import React, { useState, useEffect, useRef, useCallback } from 'react' const SEARCH_API = '/api/search/artworks' const DEBOUNCE_MS = 280 function useDebounce(value, delay) { const [debounced, setDebounced] = useState(value) useEffect(() => { const id = setTimeout(() => setDebounced(value), delay) return () => clearTimeout(id) }, [value, delay]) return debounced } export default function SearchBar({ placeholder = 'Search artworks, artists, tagsā¦' }) { const [query, setQuery] = useState('') const [suggestions, setSuggestions] = useState([]) const [loading, setLoading] = useState(false) const [open, setOpen] = useState(false) const inputRef = useRef(null) const wrapperRef = useRef(null) const abortRef = useRef(null) const debouncedQuery = useDebounce(query, DEBOUNCE_MS) const fetchSuggestions = useCallback(async (q) => { if (!q || q.length < 2) { setSuggestions([]) setOpen(false) return } if (abortRef.current) abortRef.current.abort() abortRef.current = new AbortController() setLoading(true) try { const url = `${SEARCH_API}?q=${encodeURIComponent(q)}&per_page=6` const res = await fetch(url, { signal: abortRef.current.signal }) if (!res.ok) return const json = await res.json() const items = json.data ?? json ?? [] setSuggestions(Array.isArray(items) ? items.slice(0, 6) : []) setOpen(true) } catch (e) { if (e.name !== 'AbortError') console.error('SearchBar fetch error', e) } finally { setLoading(false) } }, []) useEffect(() => { fetchSuggestions(debouncedQuery) }, [debouncedQuery, fetchSuggestions]) // Close suggestions on outside click useEffect(() => { function handler(e) { if (wrapperRef.current && !wrapperRef.current.contains(e.target)) { setOpen(false) } } document.addEventListener('mousedown', handler) return () => document.removeEventListener('mousedown', handler) }, []) function handleSubmit(e) { e.preventDefault() if (query.trim()) { window.location.href = `/search?q=${encodeURIComponent(query.trim())}` } } function handleSelect(item) { window.location.href = item.urls?.web ?? `/${item.slug ?? ''}` } function handleKeyDown(e) { if (e.key === 'Escape') { setOpen(false) inputRef.current?.blur() } } return (