"use client"; import { useEffect, useRef, useState } from "react"; import { useRouter } from "next/navigation"; import { IconSearch, IconPin } from "./icons"; type Suggest = { places: { kind: string; name: string; region: string | null; nSale: number; nRent: number }[]; addresses: { uid: string; address: string; city: string; market: string }[] }; export function SearchBar({ market = "achat", placeholder = "Ville, quartier ou adresse", autoFocus = false, size = "lg", onPick }: { market?: "achat" | "location"; placeholder?: string; autoFocus?: boolean; size?: "lg" | "md"; onPick?: (city: string) => void }) { const [q, setQ] = useState(""); const [sug, setSug] = useState(null); const [open, setOpen] = useState(false); const [active, setActive] = useState(-1); const router = useRouter(); const box = useRef(null); useEffect(() => { if (q.trim().length < 2) { setSug(null); return; } const ctl = new AbortController(); const t = setTimeout(() => { fetch(`/api/suggest?q=${encodeURIComponent(q)}`, { signal: ctl.signal }).then((r) => r.json()).then((d) => { setSug(d); setOpen(true); setActive(-1); }).catch(() => {}); }, 150); return () => { clearTimeout(t); ctl.abort(); }; }, [q]); useEffect(() => { const h = (e: MouseEvent) => { if (!box.current?.contains(e.target as Node)) setOpen(false); }; document.addEventListener("mousedown", h); return () => document.removeEventListener("mousedown", h); }, []); const items = [...(sug?.places ?? []).map((p) => ({ type: "place" as const, ...p })), ...(sug?.addresses ?? []).map((a) => ({ type: "address" as const, ...a }))]; const go = (i: number) => { const it = items[i]; if (!it) { if (q.trim()) router.push(`/recherche?marche=${market}&q=${encodeURIComponent(q.trim())}`); return; } setOpen(false); if (it.type === "place") { if (onPick) { onPick(it.name); return; } router.push(it.kind === "region" ? `/recherche?marche=${market}®ion=${encodeURIComponent(it.name)}` : `/recherche?marche=${market}&ville=${encodeURIComponent(it.name)}`); } else router.push(`/annonce/${encodeURIComponent(it.uid)}`); }; return (
{ e.preventDefault(); go(active); }} className="relative"> setQ(e.target.value)} onFocus={() => sug && setOpen(true)} autoFocus={autoFocus} placeholder={placeholder} aria-label="Rechercher une ville, un quartier ou une adresse" aria-expanded={open} aria-controls="tv-suggest" role="combobox" aria-autocomplete="list" onKeyDown={(e) => { if (e.key === "ArrowDown") { e.preventDefault(); setActive((a) => Math.min(a + 1, items.length - 1)); } else if (e.key === "ArrowUp") { e.preventDefault(); setActive((a) => Math.max(a - 1, -1)); } else if (e.key === "Escape") setOpen(false); }} className={`tv-input ${size === "lg" ? "py-3.5 text-base pr-28" : "text-sm pr-24"}`} /> {open && items.length > 0 && (
    {items.map((it, i) => (
  • ))}
)}
); }