diff --git a/src/components/app-shell.tsx b/src/components/app-shell.tsx index 5c30484..9044bf2 100644 --- a/src/components/app-shell.tsx +++ b/src/components/app-shell.tsx @@ -38,23 +38,23 @@ interface NavItem { } const NAV: NavItem[] = [ - { to: "/", label: "Dashboard", icon: LayoutDashboard }, + { to: "/admin/users", label: "Users", icon: ShieldCheck, adminOnly: true }, { to: "/calendar", label: "Calendar", icon: CalendarIcon }, - { to: "/clients", label: "Clients", icon: Users }, - { to: "/contacts", label: "Contacts", icon: UserPlus }, { to: "/cases", label: "Cases", icon: Briefcase }, - { to: "/tasks", label: "Tasks", icon: CheckSquare }, - { to: "/messages", label: "Messages", icon: MessageSquare }, - { to: "/inbox", label: "Inbox", icon: InboxIcon }, - { to: "/status", label: "Status Updates", icon: Activity }, + { to: "/clients", label: "Clients", icon: Users }, { to: "/collections", label: "Collections", icon: DollarSign }, - { to: "/documents", label: "Pleadings", icon: FolderOpen }, + { to: "/contacts", label: "Contacts", icon: UserPlus }, + { to: "/", label: "Dashboard", icon: LayoutDashboard }, { to: "/files", label: "Files", icon: FilesIcon }, { to: "/forms", label: "Forms", icon: ClipboardList }, + { to: "/inbox", label: "Inbox", icon: InboxIcon }, { to: "/invoices", label: "Invoices", icon: Receipt }, + { to: "/messages", label: "Messages", icon: MessageSquare }, + { to: "/documents", label: "Pleadings", icon: FolderOpen }, { to: "/settings", label: "Settings", icon: SettingsIcon }, - { to: "/admin/users", label: "Users", icon: ShieldCheck, adminOnly: true }, -]; + { to: "/status", label: "Status Updates", icon: Activity }, + { to: "/tasks", label: "Tasks", icon: CheckSquare }, +].sort((a, b) => a.label.localeCompare(b.label)); void FileText; export function AppShell({ children }: { children: ReactNode }) { diff --git a/src/routes/contacts.index.tsx b/src/routes/contacts.index.tsx index 0a17e9a..f3aba33 100644 --- a/src/routes/contacts.index.tsx +++ b/src/routes/contacts.index.tsx @@ -44,6 +44,7 @@ function ContactsIndex() { const [selected, setSelected] = useState>(new Set()); const [bulkType, setBulkType] = useState(""); const [letter, setLetter] = useState("all"); + const [visibleLimit, setVisibleLimit] = useState(100); const load = async () => { setLoading(true); @@ -140,9 +141,17 @@ function ContactsIndex() { return preLetterFiltered.filter((r) => letterOf(r.name) === letter); }, [preLetterFiltered, letter]); + // Reset paging window when filters change + useEffect(() => { + setVisibleLimit(100); + }, [q, typeFilter, view, letter]); + + const visibleRows = useMemo(() => filtered.slice(0, visibleLimit), [filtered, visibleLimit]); + const hasMore = filtered.length > visibleRows.length; + const grouped = useMemo(() => { const map = new Map(); - for (const r of filtered) { + for (const r of visibleRows) { const l = letterOf(r.name); if (!map.has(l)) map.set(l, []); map.get(l)!.push(r); @@ -152,7 +161,7 @@ function ContactsIndex() { if (b === "#") return -1; return a.localeCompare(b); }); - }, [filtered]); + }, [visibleRows]); const archivedCount = rows.filter((r) => r.archived_at).length; const activeCount = rows.length - archivedCount; @@ -199,12 +208,12 @@ function ContactsIndex() { }); }; const toggleAllVisible = () => { - const visibleIds = filtered.map((r) => r.id); - const allSelected = visibleIds.every((id) => selected.has(id)); + const ids = visibleRows.map((r) => r.id); + const allSelected = ids.every((id) => selected.has(id)); setSelected((s) => { const next = new Set(s); - if (allSelected) visibleIds.forEach((id) => next.delete(id)); - else visibleIds.forEach((id) => next.add(id)); + if (allSelected) ids.forEach((id) => next.delete(id)); + else ids.forEach((id) => next.add(id)); return next; }); }; @@ -253,7 +262,7 @@ function ContactsIndex() { load(); }; - const visibleIds = filtered.map((r) => r.id); + const visibleIds = visibleRows.map((r) => r.id); const allVisibleSelected = visibleIds.length > 0 && visibleIds.every((id) => selected.has(id)); const someVisibleSelected = visibleIds.some((id) => selected.has(id)); @@ -387,7 +396,7 @@ function ContactsIndex() { aria-label="Select all visible" /> - Select all {filtered.length} visible + Showing {visibleRows.length} of {filtered.length} )} @@ -468,6 +477,13 @@ function ContactsIndex() { ))} )} + {!loading && hasMore && ( +
+ +
+ )}