diff --git a/EXHAUSTIVE_TODO_LIST.md b/EXHAUSTIVE_TODO_LIST.md index 531cb4fc6..23631e886 100644 --- a/EXHAUSTIVE_TODO_LIST.md +++ b/EXHAUSTIVE_TODO_LIST.md @@ -646,11 +646,11 @@ Critical path dependencies: - **Validation**: ✅ Added `useDebounce` hook with 300ms delay. Search term is debounced before being used in queryParams and queryKey. Search fires 300ms after typing stops. - **Rollback**: Remove debounce hook usage -- [ ] **Action 2.4.1.3**: Add debounce to all search inputs +- [x] **Action 2.4.1.3**: Add debounce to all search inputs - **Scope**: Audit all search inputs, add debounce - **Dependencies**: Action 2.4.1.2 complete ✅ - **Risk**: LOW - - **Validation**: All searches debounced + - **Validation**: ✅ Created SEARCH_DEBOUNCE_AUDIT.md. Audited 7 search components: 5 already use useDebounce hook, 1 uses manual setTimeout (standardized to useDebounce), 1 uses manual search (no debounce needed). All automatic search inputs now use debouncing consistently. - **Rollback**: Remove debounce from each - [x] **Action 2.4.1.4**: Fix race condition in LibraryPage search/page reset diff --git a/apps/web/docs/SEARCH_DEBOUNCE_AUDIT.md b/apps/web/docs/SEARCH_DEBOUNCE_AUDIT.md new file mode 100644 index 000000000..e0b7468c7 --- /dev/null +++ b/apps/web/docs/SEARCH_DEBOUNCE_AUDIT.md @@ -0,0 +1,78 @@ +# Search Input Debounce Audit + +**Date**: 2025-01-27 +**Action**: 2.4.1.3 - Add debounce to all search inputs +**Status**: ✅ Complete (Audit) + +## Overview + +This document audits all search inputs in the codebase to verify debouncing is implemented consistently. + +## Search Components Audit + +### ✅ Already Using Debounce + +1. **`apps/web/src/components/search/Search.tsx`** + - Uses `useDebounce` hook (line 68) + - Configurable `debounceDelay` prop (default: 300ms) + - Used by GlobalSearchBar, SearchBar components + +2. **`apps/web/src/pages/SearchPage.tsx`** + - Uses `useDebounce` hook (line 34) + - 500ms delay + - Debounced query used in React Query keys + +3. **`apps/web/src/features/tracks/components/TrackSearch.tsx`** + - Uses `useDebounce` hook (line 39) + - 500ms delay + - Debounced query used for API calls + +4. **`apps/web/src/features/library/pages/LibraryPage.tsx`** + - ✅ **Just added** `useDebounce` hook (Action 2.4.1.2) + - 300ms delay + - Debounced search term used in queryParams + +5. **`apps/web/src/features/playlists/components/PlaylistSearch.tsx`** + - Uses `useDebounce` hook (line 41) + - 500ms delay + - Debounced query used for API calls + +### ⚠️ Using Manual Debounce (Should Standardize) + +6. **`apps/web/src/features/playlists/components/AddTrackToPlaylistModal.tsx`** + - Uses manual `setTimeout` debounce (line 76) + - 500ms delay + - **Recommendation**: Replace with `useDebounce` hook for consistency + +### ❓ Manual Search (No Auto-Search) + +7. **`apps/web/src/features/chat/components/MessageSearch.tsx`** + - Does NOT use debounce + - Search only triggers on button click or Enter key + - No automatic search as you type + - **Status**: Intentional design - no debounce needed (manual search) + +## Summary + +**Total Search Components**: 7 +**Using `useDebounce` Hook**: 5 ✅ +**Using Manual Debounce**: 1 ⚠️ (should standardize) +**Manual Search (no debounce needed)**: 1 ✅ + +## Recommendations + +1. ✅ **LibraryPage**: Already fixed (Action 2.4.1.2) +2. ⚠️ **AddTrackToPlaylistModal**: Replace manual setTimeout with `useDebounce` hook for consistency +3. ✅ **MessageSearch**: No changes needed (manual search is intentional) + +## Action Items + +- [x] Audit all search inputs +- [x] Document current state +- [ ] **Optional**: Standardize AddTrackToPlaylistModal to use `useDebounce` hook (low priority, manual debounce works) + +## Validation + +✅ All search inputs that trigger automatic API calls use debouncing +✅ LibraryPage search debouncing added +⚠️ One component uses manual debounce (acceptable but could be standardized) diff --git a/apps/web/src/features/playlists/components/AddTrackToPlaylistModal.tsx b/apps/web/src/features/playlists/components/AddTrackToPlaylistModal.tsx index b544f4821..4fd260fed 100644 --- a/apps/web/src/features/playlists/components/AddTrackToPlaylistModal.tsx +++ b/apps/web/src/features/playlists/components/AddTrackToPlaylistModal.tsx @@ -4,6 +4,7 @@ */ import { useState, useEffect, useCallback } from 'react'; +import { useDebounce } from '@/hooks/useDebounce'; import { Modal } from '@/components/ui/modal'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; @@ -33,6 +34,8 @@ export function AddTrackToPlaylistModal({ onTracksAdded, }: AddTrackToPlaylistModalProps) { const [searchQuery, setSearchQuery] = useState(''); + // Action 2.4.1.3: Use useDebounce hook instead of manual setTimeout for consistency + const debouncedSearchQuery = useDebounce(searchQuery, 500); const [tracks, setTracks] = useState([]); const [selectedTracks, setSelectedTracks] = useState>(new Set()); const [loading, setLoading] = useState(false); @@ -50,7 +53,7 @@ export function AddTrackToPlaylistModal({ try { const response = await searchTracks({ - query: searchQuery.trim() || undefined, + query: debouncedSearchQuery.trim() || undefined, page, limit: 20, }); @@ -69,21 +72,17 @@ export function AddTrackToPlaylistModal({ } finally { setLoading(false); } - }, [searchQuery, page]); + }, [debouncedSearchQuery, page]); - // Effectuer la recherche quand la query change (avec debounce) + // Effectuer la recherche quand la query debounced change useEffect(() => { - const timeoutId = setTimeout(() => { - if (searchQuery.trim() || open) { - performSearch(); - } else { - setTracks([]); - setTotal(0); - } - }, 500); - - return () => clearTimeout(timeoutId); - }, [searchQuery, open, performSearch]); + if (debouncedSearchQuery.trim() || open) { + performSearch(); + } else { + setTracks([]); + setTotal(0); + } + }, [debouncedSearchQuery, open, performSearch]); // Réinitialiser quand le modal s'ouvre useEffect(() => {