import { useState, useRef, useEffect } from 'react'; interface SearchResult { id: string; slug: string; name: string; brand: string; colorway: string; image: string; lowestPrice: number; shopCount: number; } interface Suggestion { brands: Array<{ name: string; slug: string; count: number }>; models: Array<{ name: string; brand: string; brand_slug: string; slug: string; count: number }>; products: Array<{ id: string; slug: string; name: string; brand: string; price: number; shops: number }>; } export default function SearchBar({ large = false }: { large?: boolean }) { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [suggestions, setSuggestions] = useState(null); const [open, setOpen] = useState(false); const ref = useRef(null); const debounceRef = useRef>(); useEffect(() => { if (query.length < 2) { setResults([]); setSuggestions(null); return; } clearTimeout(debounceRef.current); debounceRef.current = setTimeout(async () => { try { // Fetch both search results and suggestions in parallel const [searchRes, suggestRes] = await Promise.all([ fetch(`/api/search?q=${encodeURIComponent(query)}`), fetch(`/api/search/suggest?q=${encodeURIComponent(query)}`), ]); if (searchRes.ok) setResults(await searchRes.json()); if (suggestRes.ok) setSuggestions(await suggestRes.json()); } catch {} }, 200); return () => clearTimeout(debounceRef.current); }, [query]); useEffect(() => { const handler = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false); }; document.addEventListener('mousedown', handler); return () => document.removeEventListener('mousedown', handler); }, []); const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && query.trim().length >= 2) { window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'search', search_term: query.trim() }); setOpen(false); window.location.href = `/zoeken?q=${encodeURIComponent(query.trim())}`; } }; const searchUrl = `/zoeken?q=${encodeURIComponent(query.trim())}`; const hasSuggestions = suggestions && (suggestions.brands.length > 0 || suggestions.models.length > 0); const hasResults = results.length > 0; const showDropdown = open && (hasSuggestions || hasResults); return (
{ setQuery(e.target.value); setOpen(true); }} onFocus={() => setOpen(true)} onKeyDown={handleKeyDown} placeholder="Zoek sneakers, merken of modellen..." className={`w-full bg-transparent text-[var(--text)] placeholder-[var(--text-muted)] outline-none ${large ? 'text-lg' : 'text-sm'}`} aria-label="Zoek sneakers" /> {query && ( )}
{showDropdown && (
{/* Brand suggestions */} {suggestions && suggestions.brands.length > 0 && (

Merken

{suggestions.brands.map(b => ( {b.name} {b.count} ))}
)} {/* Model suggestions */} {suggestions && suggestions.models.length > 0 && (

Modellen

{suggestions.models.map(m => ( {m.brand} {m.name} {m.count} varianten ))}
)} {/* Product results */} {hasResults && ( )} { window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'search', search_term: query.trim() }); }} className="flex items-center justify-center gap-2 border-t border-[var(--border)] px-4 py-3 text-sm font-semibold text-[var(--accent)] transition-colors hover:bg-[var(--bg-hover)]" > Bekijk alle resultaten
)}
); }