import { useState, useEffect, useRef, useMemo } from 'react'; import useSearchHistory from '../hooks/useSearchHistory'; import './SearchBar.css'; export default function SearchBar({ onSearch, loading, userLocation, locationLoading, locationError, requestLocation, clearLocation }) { const [query, setQuery] = useState(''); const [showSuggestions, setShowSuggestions] = useState(false); const [activeIdx, setActiveIdx] = useState(-1); const { history } = useSearchHistory(); const debounceRef = useRef(null); const wrapperRef = useRef(null); // Filter local history based on query const historySuggestions = useMemo(() => { if (!query.trim()) { return history.slice(0, 5).map(h => ({ ...h, type: 'history', text: h.query })); } const lowerQuery = query.toLowerCase(); return history .filter(h => h.query.toLowerCase().includes(lowerQuery)) .slice(0, 5) .map(h => ({ ...h, type: 'history', text: h.query })); }, [history, query]); // Only show private history suggestions const allSuggestions = useMemo(() => { return historySuggestions; }, [historySuggestions]); useEffect(() => { function handleClickOutside(e) { if (wrapperRef.current && !wrapperRef.current.contains(e.target)) { setShowSuggestions(false); } } document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); function handleInputChange(value) { setQuery(value); setActiveIdx(-1); if (debounceRef.current) clearTimeout(debounceRef.current); setShowSuggestions(true); // We stop fetching global suggestions to respect "no global searches" // and only rely on the filtered local historySuggestions. } function handleSelect(text) { if (debounceRef.current) clearTimeout(debounceRef.current); setQuery(text); setShowSuggestions(false); onSearch(text); } function handleSubmit(e) { e.preventDefault(); if (query.trim().length < 3) return; if (debounceRef.current) clearTimeout(debounceRef.current); setShowSuggestions(false); onSearch(query.trim()); } function handleKeyDown(e) { if (!showSuggestions || allSuggestions.length === 0) return; if (e.key === 'ArrowDown') { e.preventDefault(); setActiveIdx(prev => (prev < allSuggestions.length - 1 ? prev + 1 : 0)); } else if (e.key === 'ArrowUp') { e.preventDefault(); setActiveIdx(prev => (prev > 0 ? prev - 1 : allSuggestions.length - 1)); } else if (e.key === 'Enter' && activeIdx >= 0) { e.preventDefault(); handleSelect(allSuggestions[activeIdx].text); } else if (e.key === 'Escape') { setShowSuggestions(false); } else if (e.key === 'Tab') { setShowSuggestions(false); } } return (
handleInputChange(e.target.value)} onFocus={() => { setShowSuggestions(true); }} onKeyDown={handleKeyDown} disabled={loading} autoComplete="off" /> {showSuggestions && allSuggestions.length > 0 && !loading && (
    {allSuggestions.map((s, i) => (
  • handleSelect(s.text)} role="option" aria-selected={i === activeIdx} > {s.type === 'history' ? ( ) : s.type === 'place' ? '📍' : s.type === 'category' ? '📂' : '💡'} {s.text} {s.type === 'history' && ( Recent )} {s.category && ( {s.category} )}
  • ))}
)}
{userLocation ? (
Using precise GPS location
) : (
Tip: include your city in the search or use your location
Psst... try searching for something from Your Name
)}
); }