import React, { useCallback, useEffect, useRef, useState } from 'react'; import { Card } from '@/components/ui/Card'; import Spinner from '@/components/ui/Spinner'; import { useTranslation } from '@/hooks/useI18n'; import { useKeyboard } from '@/hooks/useKeyboard'; import { Search } from 'lucide-react'; interface SearchSuggestionsProps { suggestions: string[]; isLoading: boolean; error?: string | null; onSelect: (suggestion: string) => void; searchTerm: string; } const SearchSuggestions = ({ suggestions, isLoading, error, onSelect, searchTerm, }: SearchSuggestionsProps) => { const { t } = useTranslation(); const [selectedIndex, setSelectedIndex] = useState(-1); const suggestionRefs = useRef<(HTMLButtonElement | null)[]>([]); const containerRef = useRef(null); const showSuggestions = isLoading || error || (suggestions && suggestions.length > 0); const hasResults = suggestions && suggestions.length > 0; // Reset selected index when suggestions change useEffect(() => { setSelectedIndex(-1); }, [suggestions]); // Handle keyboard navigation const handleKeyDown = useCallback( (e: KeyboardEvent) => { if (!showSuggestions) return; switch (e.key) { case 'ArrowDown': e.preventDefault(); setSelectedIndex((prev) => (prev < suggestions.length - 1 ? prev + 1 : prev)); break; case 'ArrowUp': e.preventDefault(); setSelectedIndex((prev) => (prev > -1 ? prev - 1 : -1)); break; case 'Enter': if (selectedIndex >= 0 && suggestions[selectedIndex]) { e.preventDefault(); onSelect(suggestions[selectedIndex]); } break; case 'Escape': // Let parent handle escape to close suggestions break; } }, [showSuggestions, suggestions, selectedIndex, onSelect] ); useKeyboard(handleKeyDown); // Scroll selected item into view useEffect(() => { if (selectedIndex >= 0 && suggestionRefs.current[selectedIndex]) { suggestionRefs.current[selectedIndex]?.scrollIntoView({ block: 'nearest', behavior: 'smooth', }); } }, [selectedIndex]); if (!showSuggestions) { return null; } return ( {/* Loading State */} {isLoading && (
{t('searchSuggestions.searching', 'Searching...')}
)} {/* Error State */} {error && !isLoading && (
{error}
)} {/* No Results State */} {!isLoading && !error && !hasResults && searchTerm.length >= 2 && (

{t('searchSuggestions.noResults', 'No results found')}

{t('searchSuggestions.tryDifferent', 'Try a different search term')}

)} {/* Suggestions List */} {!isLoading && !error && hasResults && (

{t('searchSuggestions.suggestions', 'Suggestions')}

    {suggestions.map((suggestion, index) => { const isSelected = index === selectedIndex; return (
  • ); })}
)} {/* Footer with keyboard hints */} {!isLoading && hasResults && (

{t( 'searchSuggestions.keyboardHint', 'Use ↑↓ to navigate, Enter to select, Esc to close' )}

)}
); }; export default React.memo(SearchSuggestions);