diff --git a/src/features/History/History.tsx b/src/features/History/History.tsx
index f52a091..9996022 100644
--- a/src/features/History/History.tsx
+++ b/src/features/History/History.tsx
@@ -2,10 +2,9 @@ import React from 'react';
import { IonChip, IonIcon } from '@ionic/react';
import { time } from 'ionicons/icons';
import { InfiniteScrollList, SongItem } from '../../components/common';
-import { useHistory } from '../../hooks';
+import { useHistory, useDebugLogging } from '../../hooks';
import { useAppSelector } from '../../redux';
import { selectHistory, selectIsAdmin } from '../../redux';
-import { debugLog } from '../../utils/logger';
import { formatDate } from '../../utils/dataProcessing';
import type { Song } from '../../types';
@@ -20,9 +19,15 @@ const History: React.FC = () => {
const history = useAppSelector(selectHistory);
const isAdmin = useAppSelector(selectIsAdmin);
const historyCount = Object.keys(history).length;
- // Debug logging
- debugLog('History component - history count:', historyCount);
- debugLog('History component - history items:', historyItems);
+
+ // Use unified debug logging
+ const { logData } = useDebugLogging({ componentName: 'History' });
+
+ // Log component data
+ logData({
+ 'history count': historyCount,
+ 'history items': historyItems,
+ });
// Render extra content for history items (play date)
const renderExtraContent = (item: Song) => {
diff --git a/src/features/Queue/Queue.tsx b/src/features/Queue/Queue.tsx
index 0c56fd7..760daf6 100644
--- a/src/features/Queue/Queue.tsx
+++ b/src/features/Queue/Queue.tsx
@@ -8,7 +8,7 @@ import { ActionButton, NumberDisplay, EmptyState } from '../../components/common
import { ActionButtonVariant, ActionButtonSize, ActionButtonIconSlot } from '../../types';
import { Icons } from '../../constants';
import { SongInfoDisplay } from '../../components/common/SongItem';
-import { debugLog } from '../../utils/logger';
+import { useDebugLogging } from '../../hooks';
import type { QueueItem } from '../../types';
const Queue: React.FC = () => {
@@ -32,12 +32,17 @@ const Queue: React.FC = () => {
const queueCount = useAppSelector(selectQueueLength);
- // Debug logging
- debugLog('Queue component - queue count:', queueCount);
- debugLog('Queue component - queue items:', queueItems);
- debugLog('Queue component - canReorder:', canReorder);
- debugLog('Queue component - queueMode:', queueMode);
- debugLog('Queue component - canDeleteItems:', canDeleteItems);
+ // Use unified debug logging
+ const { logData } = useDebugLogging({ componentName: 'Queue' });
+
+ // Log component data
+ logData({
+ 'queue count': queueCount,
+ 'queue items': queueItems,
+ 'canReorder': canReorder,
+ 'queueMode': queueMode,
+ 'canDeleteItems': canDeleteItems,
+ });
// Update list items when queue changes
@@ -56,8 +61,7 @@ const Queue: React.FC = () => {
};
// Render queue item
- const renderQueueItem = (queueItem: QueueItem, index: number) => {
- debugLog(`Queue item ${index}: order=${queueItem.order}, key=${queueItem.key}`);
+ const renderQueueItem = (queueItem: QueueItem) => {
const canDelete = canDeleteItems && queueMode === 'delete'; // Only allow delete in delete mode
return (
@@ -211,15 +215,15 @@ const Queue: React.FC = () => {
{/* Queue List with Reorder */}
{canReorder && queueMode === 'reorder' ? (
- {listItems.map((queueItem, index) => (
+ {listItems.map((queueItem) => (
- {renderQueueItem(queueItem, index)}
+ {renderQueueItem(queueItem)}
))}
) : (
- {listItems.map((queueItem, index) => renderQueueItem(queueItem, index))}
+ {listItems.map((queueItem) => renderQueueItem(queueItem))}
)}
diff --git a/src/features/Search/Search.tsx b/src/features/Search/Search.tsx
index 654080d..66447ea 100644
--- a/src/features/Search/Search.tsx
+++ b/src/features/Search/Search.tsx
@@ -1,10 +1,9 @@
import React from 'react';
import { IonSearchbar } from '@ionic/react';
import { InfiniteScrollList, SongItem } from '../../components/common';
-import { useSearch } from '../../hooks';
+import { useSearch, useDebugLogging } from '../../hooks';
import { useAppSelector } from '../../redux';
import { selectIsAdmin, selectSongs } from '../../redux';
-import { debugLog } from '../../utils/logger';
import type { Song } from '../../types';
const Search: React.FC = () => {
@@ -19,22 +18,16 @@ const Search: React.FC = () => {
const songs = useAppSelector(selectSongs);
const songsCount = Object.keys(songs).length;
- // Performance monitoring
- React.useEffect(() => {
- const startTime = performance.now();
-
- return () => {
- const endTime = performance.now();
- const renderTime = endTime - startTime;
- debugLog(`Search component render time: ${renderTime.toFixed(2)}ms`);
- };
- });
+ // Use unified debug logging
+ const { logData } = useDebugLogging({ componentName: 'Search' });
- // Debug logging
- debugLog('Search component - songs count:', songsCount);
- debugLog('Search component - search results:', searchResults);
- debugLog('Search component - search term:', searchTerm);
- debugLog('Search component - showing:', searchResults.songs.length, 'of', searchResults.count);
+ // Log component data
+ logData({
+ 'songs count': songsCount,
+ 'search results': searchResults,
+ 'search term': searchTerm,
+ 'showing': `${searchResults.songs.length} of ${searchResults.count}`,
+ });
return (
<>
diff --git a/src/hooks/index.ts b/src/hooks/index.ts
index 9f641c1..2649f67 100644
--- a/src/hooks/index.ts
+++ b/src/hooks/index.ts
@@ -13,5 +13,6 @@ export { useSongLists } from './useSongLists';
export { useDisabledSongs } from './useDisabledSongs';
export { useActions } from './useActions';
export { usePagination } from './usePagination';
+export { useDebugLogging } from './useDebugLogging';
export { useSongInfo } from './useSongInfo';
\ No newline at end of file
diff --git a/src/hooks/useDebugLogging.ts b/src/hooks/useDebugLogging.ts
new file mode 100644
index 0000000..fe0c3ed
--- /dev/null
+++ b/src/hooks/useDebugLogging.ts
@@ -0,0 +1,79 @@
+import { useEffect, useCallback } from 'react';
+import { debugLog } from '../utils/logger';
+
+export interface DebugLoggingConfig {
+ componentName: string;
+ enableRenderTime?: boolean;
+ enableDataLogging?: boolean;
+ enablePerformanceMonitoring?: boolean;
+}
+
+export interface DebugData {
+ [key: string]: unknown;
+}
+
+export const useDebugLogging = (config: DebugLoggingConfig) => {
+ const { componentName, enableRenderTime = true, enableDataLogging = true } = config;
+
+ // Performance monitoring for component render time
+ useEffect(() => {
+ if (!enableRenderTime) return;
+
+ const startTime = performance.now();
+
+ return () => {
+ const endTime = performance.now();
+ const renderTime = endTime - startTime;
+ debugLog(`${componentName} component render time: ${renderTime.toFixed(2)}ms`);
+ };
+ }, [componentName, enableRenderTime]);
+
+ // Log component data
+ const logData = useCallback((data: DebugData) => {
+ if (!enableDataLogging) return;
+
+ Object.entries(data).forEach(([key, value]) => {
+ debugLog(`${componentName} component - ${key}:`, value);
+ });
+ }, [componentName, enableDataLogging]);
+
+ // Log single value
+ const logValue = useCallback((key: string, value: unknown) => {
+ if (!enableDataLogging) return;
+ debugLog(`${componentName} component - ${key}:`, value);
+ }, [componentName, enableDataLogging]);
+
+ // Log hook data
+ const logHookData = useCallback((hookName: string, data: DebugData) => {
+ if (!enableDataLogging) return;
+
+ Object.entries(data).forEach(([key, value]) => {
+ debugLog(`${hookName} - ${key}:`, value);
+ });
+ }, [enableDataLogging]);
+
+ // Log hook single value
+ const logHookValue = useCallback((hookName: string, key: string, value: unknown) => {
+ if (!enableDataLogging) return;
+ debugLog(`${hookName} - ${key}:`, value);
+ }, [enableDataLogging]);
+
+ // Log component lifecycle
+ const logLifecycle = useCallback((event: string, data?: DebugData) => {
+ if (!enableDataLogging) return;
+
+ if (data) {
+ debugLog(`${componentName} component - ${event}:`, data);
+ } else {
+ debugLog(`${componentName} component - ${event}`);
+ }
+ }, [componentName, enableDataLogging]);
+
+ return {
+ logData,
+ logValue,
+ logHookData,
+ logHookValue,
+ logLifecycle,
+ };
+};
\ No newline at end of file