import { useState, useCallback, useRef } from 'react'; import { Search, Loader2, FileText, CheckSquare, Calendar } from 'lucide-react'; import { useDebounce } from '@yetanother/hooks'; interface SearchResult { id: string; title: string; type: string; plainText: string; updatedAt: string; } export function SearchBar() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const [open, setOpen] = useState(false); const debouncedQuery = useDebounce(query, 300); const inputRef = useRef(null); const handleSearch = useCallback(async (q: string) => { if (!q.trim()) { setResults([]); return; } setLoading(true); try { const res = await fetch(`/api/v1/search?q=${encodeURIComponent(q)}`); const data = await res.json() as { results: SearchResult[] }; setResults(data.results); } catch { setResults([]); } finally { setLoading(false); } }, []); useState(() => { if (debouncedQuery) handleSearch(debouncedQuery); }); const typeIcons: Record = { note: , task: , event: , }; return (
{ setQuery(e.target.value); setOpen(true); }} onFocus={() => setOpen(true)} onBlur={() => setTimeout(() => setOpen(false), 200)} placeholder="Search anything..." className="w-64 pl-9 pr-3 py-2 text-sm rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-ring" /> {loading && }
{open && results.length > 0 && (
{results.map((r) => ( ))}
)}
); }