From cc079c1716e59266a786e8e7f2eec8dfba5aeebb Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 02:57:38 +0000 Subject: [PATCH] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/contacts.index.tsx | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/routes/contacts.index.tsx b/src/routes/contacts.index.tsx index 0ff1903..a41c055 100644 --- a/src/routes/contacts.index.tsx +++ b/src/routes/contacts.index.tsx @@ -86,6 +86,7 @@ function ContactsIndex() { const term = q.trim().toLowerCase(); return rows.filter((r) => { if (view === "archived" ? !r.archived_at : !!r.archived_at) return false; + if (category !== "all" && categoryOf(r.contact_type) !== category) return false; if (typeFilter !== "all" && r.contact_type !== typeFilter) return false; if (!term) return true; return ( @@ -95,11 +96,36 @@ function ContactsIndex() { (r.phone ?? "").toLowerCase().includes(term) ); }); - }, [rows, q, typeFilter, view]); + }, [rows, q, typeFilter, view, category]); + + const grouped = useMemo(() => { + const map = new Map(); + for (const r of filtered) { + const ch = (r.name?.[0] ?? "#").toUpperCase(); + const letter = /[A-Z]/.test(ch) ? ch : "#"; + if (!map.has(letter)) map.set(letter, []); + map.get(letter)!.push(r); + } + return Array.from(map.entries()).sort(([a], [b]) => { + if (a === "#") return 1; + if (b === "#") return -1; + return a.localeCompare(b); + }); + }, [filtered]); const archivedCount = rows.filter((r) => r.archived_at).length; const activeCount = rows.length - archivedCount; + const categoryCounts = useMemo(() => { + const base = rows.filter((r) => (view === "archived" ? !!r.archived_at : !r.archived_at)); + return { + all: base.length, + companies: base.filter((r) => categoryOf(r.contact_type) === "companies").length, + people: base.filter((r) => categoryOf(r.contact_type) === "people").length, + lawyers: base.filter((r) => categoryOf(r.contact_type) === "lawyers").length, + }; + }, [rows, view]); + const remove = async (id: string, name: string) => { if (!confirm(`Delete contact "${name}"? This will also remove all case and client links.`)) return; const { error } = await supabase.from("contacts").delete().eq("id", id);