diff --git a/src/components/clients/contact-picker-popover.tsx b/src/components/clients/contact-picker-popover.tsx index 9717edc..e89d8fb 100644 --- a/src/components/clients/contact-picker-popover.tsx +++ b/src/components/clients/contact-picker-popover.tsx @@ -30,29 +30,44 @@ export function ContactPickerPopover({ const [open, setOpen] = useState(false); const [q, setQ] = useState(""); const [rows, setRows] = useState([]); + const [loading, setLoading] = useState(false); useEffect(() => { if (!open) return; setQ(""); - supabase - .from("contacts") - .select("id, name, email, phone, title, company, contact_type") - .is("archived_at", null) - .order("name") - .limit(200) - .then(({ data }) => setRows((data ?? []) as PickResult[])); }, [open]); - const filtered = useMemo(() => { - const term = q.trim().toLowerCase(); - if (!term) return rows; - return rows.filter( - (r) => - r.name.toLowerCase().includes(term) || - (r.company ?? "").toLowerCase().includes(term) || - (r.email ?? "").toLowerCase().includes(term), - ); - }, [rows, q]); + useEffect(() => { + if (!open) return; + let cancelled = false; + const term = q.trim(); + setLoading(true); + const handle = setTimeout(async () => { + let query = supabase + .from("contacts") + .select("id, name, email, phone, title, company, contact_type") + .is("archived_at", null) + .order("name") + .limit(50); + if (term) { + const esc = term.replace(/[%,]/g, " "); + query = query.or( + `name.ilike.%${esc}%,company.ilike.%${esc}%,email.ilike.%${esc}%`, + ); + } + const { data } = await query; + if (!cancelled) { + setRows((data ?? []) as PickResult[]); + setLoading(false); + } + }, 200); + return () => { + cancelled = true; + clearTimeout(handle); + }; + }, [open, q]); + + const filtered = rows; return (