feat: Ajouter logs de debug pour la recherche globale
- Logs détaillés dans GlobalSearchBar pour fetchSuggestions
- Logs pour chaque étape de la recherche (tracks, playlists, users)
- Logs de performance avec durée des requêtes
- Logs dans Search component pour interactions utilisateur
- Logs pour navigation et sélection de résultats
- Utilisation de console.log avec préfixes [🔍] pour faciliter le filtrage dans DevTools
This commit is contained in:
parent
52ace207fc
commit
b5d6bc2f12
2 changed files with 186 additions and 4 deletions
|
|
@ -33,11 +33,21 @@ export function GlobalSearchBar({
|
|||
// Fetch autocomplete suggestions
|
||||
const fetchSuggestions = useCallback(
|
||||
async (query: string): Promise<SearchResult[]> => {
|
||||
console.log('[🔍 GlobalSearchBar] fetchSuggestions called', { query });
|
||||
logger.debug('Fetching search suggestions', { query, component: 'GlobalSearchBar' });
|
||||
|
||||
if (!query.trim()) {
|
||||
console.log('[🔍 GlobalSearchBar] Empty query, returning empty results');
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const startTime = performance.now();
|
||||
console.log('[🔍 GlobalSearchBar] Starting parallel search requests', {
|
||||
query,
|
||||
playlistSearchEnabled: isFeatureEnabled('PLAYLIST_SEARCH'),
|
||||
});
|
||||
|
||||
// Fetch suggestions from all sources in parallel
|
||||
// FIX: Gérer les feature flags (PLAYLIST_SEARCH peut être désactivé)
|
||||
const searchPromises: Array<Promise<any>> = [
|
||||
|
|
@ -47,10 +57,12 @@ export function GlobalSearchBar({
|
|||
|
||||
// Ajouter la recherche de playlists seulement si la feature est activée
|
||||
if (isFeatureEnabled('PLAYLIST_SEARCH')) {
|
||||
console.log('[🔍 GlobalSearchBar] Playlist search enabled, adding to promises');
|
||||
searchPromises.push(
|
||||
playlistsApi.search({ q: query, page: 1, limit: 3 }),
|
||||
);
|
||||
} else {
|
||||
console.log('[🔍 GlobalSearchBar] Playlist search disabled, using empty result');
|
||||
// Si désactivé, retourner une promesse résolue avec un résultat vide
|
||||
searchPromises.push(Promise.resolve({ playlists: [], total: 0 }));
|
||||
}
|
||||
|
|
@ -59,11 +71,21 @@ export function GlobalSearchBar({
|
|||
searchPromises,
|
||||
);
|
||||
|
||||
const duration = performance.now() - startTime;
|
||||
console.log('[🔍 GlobalSearchBar] Search requests completed', {
|
||||
duration: `${duration.toFixed(2)}ms`,
|
||||
tracksStatus: tracksData.status,
|
||||
usersStatus: usersData.status,
|
||||
playlistsStatus: playlistsData.status,
|
||||
});
|
||||
|
||||
const results: SearchResult[] = [];
|
||||
|
||||
// Add track suggestions
|
||||
// FIX: searchTracks retourne PaginatedResponse<Track> avec propriété 'data'
|
||||
if (tracksData.status === 'fulfilled' && tracksData.value?.data) {
|
||||
const tracksCount = tracksData.value.data.length;
|
||||
console.log('[🔍 GlobalSearchBar] Adding track suggestions', { count: tracksCount });
|
||||
tracksData.value.data.forEach((track: any) => {
|
||||
results.push({
|
||||
id: track.id,
|
||||
|
|
@ -73,6 +95,12 @@ export function GlobalSearchBar({
|
|||
image: track.cover_url || track.cover || track.thumbnail_url,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.log('[🔍 GlobalSearchBar] No track suggestions', {
|
||||
status: tracksData.status,
|
||||
hasData: tracksData.status === 'fulfilled' && !!tracksData.value?.data,
|
||||
error: tracksData.status === 'rejected' ? tracksData.reason : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
// Add playlist suggestions (seulement si la feature est activée)
|
||||
|
|
@ -81,6 +109,8 @@ export function GlobalSearchBar({
|
|||
playlistsData.status === 'fulfilled' &&
|
||||
playlistsData.value?.playlists
|
||||
) {
|
||||
const playlistsCount = playlistsData.value.playlists.length;
|
||||
console.log('[🔍 GlobalSearchBar] Adding playlist suggestions', { count: playlistsCount });
|
||||
playlistsData.value.playlists.forEach((playlist: any) => {
|
||||
results.push({
|
||||
id: playlist.id,
|
||||
|
|
@ -90,10 +120,18 @@ export function GlobalSearchBar({
|
|||
image: playlist.cover_url || playlist.thumbnail_url,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.log('[🔍 GlobalSearchBar] No playlist suggestions', {
|
||||
featureEnabled: isFeatureEnabled('PLAYLIST_SEARCH'),
|
||||
status: playlistsData.status,
|
||||
hasData: playlistsData.status === 'fulfilled' && !!playlistsData.value?.playlists,
|
||||
});
|
||||
}
|
||||
|
||||
// Add user suggestions
|
||||
if (usersData.status === 'fulfilled' && usersData.value?.users) {
|
||||
const usersCount = usersData.value.users.length;
|
||||
console.log('[🔍 GlobalSearchBar] Adding user suggestions', { count: usersCount });
|
||||
usersData.value.users.forEach((user: any) => {
|
||||
results.push({
|
||||
id: user.id,
|
||||
|
|
@ -103,13 +141,44 @@ export function GlobalSearchBar({
|
|||
image: user.avatar_url,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.log('[🔍 GlobalSearchBar] No user suggestions', {
|
||||
status: usersData.status,
|
||||
hasData: usersData.status === 'fulfilled' && !!usersData.value?.users,
|
||||
error: usersData.status === 'rejected' ? usersData.reason : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
return results.slice(0, 8); // Limit to 8 total suggestions
|
||||
const finalResults = results.slice(0, 8); // Limit to 8 total suggestions
|
||||
console.log('[🔍 GlobalSearchBar] Final suggestions', {
|
||||
total: results.length,
|
||||
limited: finalResults.length,
|
||||
breakdown: {
|
||||
tracks: finalResults.filter((r) => r.type === 'track').length,
|
||||
playlists: finalResults.filter((r) => r.type === 'playlist').length,
|
||||
users: finalResults.filter((r) => r.type === 'user').length,
|
||||
},
|
||||
});
|
||||
logger.debug('Search suggestions fetched', {
|
||||
query,
|
||||
totalResults: results.length,
|
||||
limitedResults: finalResults.length,
|
||||
component: 'GlobalSearchBar',
|
||||
});
|
||||
|
||||
return finalResults;
|
||||
} catch (error) {
|
||||
console.error('[🔍 GlobalSearchBar] Error fetching suggestions', {
|
||||
error,
|
||||
query,
|
||||
errorMessage: error instanceof Error ? error.message : String(error),
|
||||
errorStack: error instanceof Error ? error.stack : undefined,
|
||||
});
|
||||
logger.error('Error fetching search suggestions', {
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
query,
|
||||
component: 'GlobalSearchBar',
|
||||
});
|
||||
return [];
|
||||
}
|
||||
|
|
@ -120,9 +189,15 @@ export function GlobalSearchBar({
|
|||
// Handle search action - navigation vers la page de recherche
|
||||
const handleSearch = useCallback(
|
||||
(query: string) => {
|
||||
console.log('[🔍 GlobalSearchBar] handleSearch called', { query });
|
||||
if (query.trim()) {
|
||||
navigate(`/search?q=${encodeURIComponent(query)}`);
|
||||
const searchUrl = `/search?q=${encodeURIComponent(query)}`;
|
||||
console.log('[🔍 GlobalSearchBar] Navigating to search page', { searchUrl });
|
||||
navigate(searchUrl);
|
||||
onSearch?.(query);
|
||||
logger.debug('Search submitted', { query, component: 'GlobalSearchBar' });
|
||||
} else {
|
||||
console.log('[🔍 GlobalSearchBar] Empty query, skipping navigation');
|
||||
}
|
||||
},
|
||||
[navigate, onSearch],
|
||||
|
|
@ -131,6 +206,17 @@ export function GlobalSearchBar({
|
|||
// Handle result selection
|
||||
const handleResultSelect = useCallback(
|
||||
(result: SearchResult) => {
|
||||
console.log('[🔍 GlobalSearchBar] handleResultSelect called', {
|
||||
type: result.type,
|
||||
id: result.id,
|
||||
title: result.title,
|
||||
});
|
||||
logger.debug('Search result selected', {
|
||||
type: result.type,
|
||||
id: result.id,
|
||||
component: 'GlobalSearchBar',
|
||||
});
|
||||
|
||||
switch (result.type) {
|
||||
case 'track':
|
||||
navigate(`/tracks/${result.id}`);
|
||||
|
|
|
|||
|
|
@ -67,28 +67,72 @@ export function Search({
|
|||
// Debounce de la query pour la recherche
|
||||
const debouncedQuery = useDebounce(query, debounceDelay);
|
||||
|
||||
// Log query changes
|
||||
useEffect(() => {
|
||||
console.log('[🔍 Search] Query changed', {
|
||||
rawQuery: query,
|
||||
debouncedQuery,
|
||||
debounceDelay,
|
||||
});
|
||||
}, [query, debouncedQuery, debounceDelay]);
|
||||
|
||||
// Fetch suggestions lorsque la query change
|
||||
useEffect(() => {
|
||||
console.log('[🔍 Search] useEffect triggered for suggestions', {
|
||||
debouncedQuery,
|
||||
hasFetchSuggestions: !!fetchSuggestions,
|
||||
showSuggestions,
|
||||
});
|
||||
|
||||
if (!debouncedQuery.trim() || !fetchSuggestions || !showSuggestions) {
|
||||
console.log('[🔍 Search] Skipping suggestions fetch', {
|
||||
reason: !debouncedQuery.trim()
|
||||
? 'empty query'
|
||||
: !fetchSuggestions
|
||||
? 'no fetchSuggestions'
|
||||
: 'showSuggestions disabled',
|
||||
});
|
||||
setSuggestions([]);
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[🔍 Search] Starting suggestions fetch', { debouncedQuery });
|
||||
setIsLoading(true);
|
||||
const loadSuggestions = async () => {
|
||||
const startTime = performance.now();
|
||||
try {
|
||||
const results = await Promise.resolve(fetchSuggestions(debouncedQuery));
|
||||
const duration = performance.now() - startTime;
|
||||
console.log('[🔍 Search] Suggestions fetched', {
|
||||
count: results.length,
|
||||
duration: `${duration.toFixed(2)}ms`,
|
||||
results: results.map((r) => ({ type: r.type, title: r.title })),
|
||||
});
|
||||
setSuggestions(results);
|
||||
logger.debug('Suggestions loaded', {
|
||||
query: debouncedQuery,
|
||||
count: results.length,
|
||||
component: 'Search',
|
||||
});
|
||||
} catch (error) {
|
||||
const duration = performance.now() - startTime;
|
||||
console.error('[🔍 Search] Error fetching suggestions', {
|
||||
error,
|
||||
query: debouncedQuery,
|
||||
duration: `${duration.toFixed(2)}ms`,
|
||||
errorMessage: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
logger.error('Error fetching suggestions', {
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
query: debouncedQuery,
|
||||
component: 'Search',
|
||||
});
|
||||
setSuggestions([]);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
console.log('[🔍 Search] Suggestions fetch completed', { isLoading: false });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -120,12 +164,18 @@ export function Search({
|
|||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
console.log('[🔍 Search] Input changed', { value, length: value.length });
|
||||
setQuery(value);
|
||||
setShowDropdown(true);
|
||||
setActiveIndex(-1);
|
||||
};
|
||||
|
||||
const handleInputFocus = () => {
|
||||
console.log('[🔍 Search] Input focused', {
|
||||
query,
|
||||
hasHistory: showHistory && history.length > 0,
|
||||
historyCount: history.length,
|
||||
});
|
||||
if (query.trim() || (showHistory && history.length > 0)) {
|
||||
setShowDropdown(true);
|
||||
}
|
||||
|
|
@ -137,17 +187,33 @@ export function Search({
|
|||
...suggestions,
|
||||
];
|
||||
|
||||
console.log('[🔍 Search] Key pressed', {
|
||||
key: e.key,
|
||||
activeIndex,
|
||||
itemsCount: items.length,
|
||||
query,
|
||||
});
|
||||
|
||||
switch (e.key) {
|
||||
case 'ArrowDown':
|
||||
e.preventDefault();
|
||||
setActiveIndex((prev) => (prev < items.length - 1 ? prev + 1 : prev));
|
||||
const newIndexDown = activeIndex < items.length - 1 ? activeIndex + 1 : activeIndex;
|
||||
console.log('[🔍 Search] ArrowDown', { previousIndex: activeIndex, newIndex: newIndexDown });
|
||||
setActiveIndex(newIndexDown);
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
e.preventDefault();
|
||||
setActiveIndex((prev) => (prev > 0 ? prev - 1 : -1));
|
||||
const newIndexUp = activeIndex > 0 ? activeIndex - 1 : -1;
|
||||
console.log('[🔍 Search] ArrowUp', { previousIndex: activeIndex, newIndex: newIndexUp });
|
||||
setActiveIndex(newIndexUp);
|
||||
break;
|
||||
case 'Enter':
|
||||
e.preventDefault();
|
||||
console.log('[🔍 Search] Enter pressed', {
|
||||
activeIndex,
|
||||
itemsCount: items.length,
|
||||
query,
|
||||
});
|
||||
if (activeIndex >= 0 && activeIndex < items.length) {
|
||||
if (
|
||||
activeIndex <
|
||||
|
|
@ -155,6 +221,7 @@ export function Search({
|
|||
) {
|
||||
// C'est un item de l'historique
|
||||
const historyItem = history[activeIndex];
|
||||
console.log('[🔍 Search] Selecting history item', { historyItem, index: activeIndex });
|
||||
setQuery(historyItem);
|
||||
handleSearch(historyItem);
|
||||
} else {
|
||||
|
|
@ -165,13 +232,19 @@ export function Search({
|
|||
? Math.min(history.length, 5)
|
||||
: 0);
|
||||
const result = suggestions[suggestionIndex];
|
||||
console.log('[🔍 Search] Selecting suggestion', {
|
||||
suggestionIndex,
|
||||
result: result ? { type: result.type, title: result.title } : null,
|
||||
});
|
||||
handleResultSelect(result);
|
||||
}
|
||||
} else if (query.trim()) {
|
||||
console.log('[🔍 Search] Submitting query directly', { query });
|
||||
handleSearch(query);
|
||||
}
|
||||
break;
|
||||
case 'Escape':
|
||||
console.log('[🔍 Search] Escape pressed, closing dropdown');
|
||||
setShowDropdown(false);
|
||||
setActiveIndex(-1);
|
||||
inputRef.current?.blur();
|
||||
|
|
@ -181,6 +254,7 @@ export function Search({
|
|||
|
||||
const handleSearch = useCallback(
|
||||
(searchQuery: string) => {
|
||||
console.log('[🔍 Search] handleSearch called', { searchQuery });
|
||||
if (searchQuery.trim()) {
|
||||
// Ajouter à l'historique
|
||||
if (showHistory) {
|
||||
|
|
@ -190,11 +264,23 @@ export function Search({
|
|||
0,
|
||||
maxHistoryItems,
|
||||
);
|
||||
console.log('[🔍 Search] History updated', {
|
||||
previousCount: prev.length,
|
||||
newCount: updated.length,
|
||||
added: searchQuery,
|
||||
});
|
||||
return updated;
|
||||
});
|
||||
}
|
||||
setShowDropdown(false);
|
||||
console.log('[🔍 Search] Calling onSearch callback', { searchQuery });
|
||||
onSearch(searchQuery);
|
||||
logger.debug('Search submitted from Search component', {
|
||||
query: searchQuery,
|
||||
component: 'Search',
|
||||
});
|
||||
} else {
|
||||
console.log('[🔍 Search] Empty search query, skipping');
|
||||
}
|
||||
},
|
||||
[onSearch, showHistory, setHistory, maxHistoryItems],
|
||||
|
|
@ -202,10 +288,20 @@ export function Search({
|
|||
|
||||
const handleResultSelect = useCallback(
|
||||
(result: SearchResult) => {
|
||||
console.log('[🔍 Search] handleResultSelect called', {
|
||||
type: result.type,
|
||||
id: result.id,
|
||||
title: result.title,
|
||||
});
|
||||
setQuery(result.title);
|
||||
setShowDropdown(false);
|
||||
setActiveIndex(-1);
|
||||
onResultSelect?.(result);
|
||||
logger.debug('Search result selected from Search component', {
|
||||
type: result.type,
|
||||
id: result.id,
|
||||
component: 'Search',
|
||||
});
|
||||
},
|
||||
[onResultSelect],
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue