Removed category tabs on /contacts
X-Lovable-Edit-ID: edt-e5168799-dc2f-49ab-a708-0da1ec7d01db Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
@@ -11,6 +11,8 @@ import { toast } from "sonner";
|
||||
import { Loader2 } from "lucide-react";
|
||||
|
||||
export const CONTACT_TYPES = [
|
||||
{ value: "client", label: "Client" },
|
||||
{ value: "staff", label: "Staff" },
|
||||
{ value: "opposing_counsel", label: "Opposing counsel" },
|
||||
{ value: "co_counsel", label: "Co-counsel" },
|
||||
{ value: "expert", label: "Expert" },
|
||||
|
||||
@@ -14,21 +14,6 @@ import { Plus, Search, Mail, Phone, Building2, ChevronRight, Edit, Trash2, Brief
|
||||
import { ContactFormDialog, CONTACT_TYPES, type ContactRecord } from "@/components/contacts/contact-form-dialog";
|
||||
import { setArchived } from "@/lib/archive";
|
||||
|
||||
type Category = "all" | "companies" | "people" | "lawyers";
|
||||
|
||||
const CATEGORY_TYPES: Record<Exclude<Category, "all">, string[]> = {
|
||||
lawyers: ["opposing_counsel", "co_counsel"],
|
||||
companies: ["vendor", "court"],
|
||||
people: ["expert", "witness", "process_server", "client_contact", "other"],
|
||||
};
|
||||
|
||||
function categoryOf(type: string | null | undefined): Exclude<Category, "all"> {
|
||||
const t = type ?? "other";
|
||||
if (CATEGORY_TYPES.lawyers.includes(t)) return "lawyers";
|
||||
if (CATEGORY_TYPES.companies.includes(t)) return "companies";
|
||||
return "people";
|
||||
}
|
||||
|
||||
export const Route = createFileRoute("/contacts/")({
|
||||
component: () => (
|
||||
<ProtectedLayout>
|
||||
@@ -52,7 +37,6 @@ function ContactsIndex() {
|
||||
const [q, setQ] = useState("");
|
||||
const [typeFilter, setTypeFilter] = useState<string>("all");
|
||||
const [view, setView] = useState<"active" | "archived">("active");
|
||||
const [category, setCategory] = useState<Category>("all");
|
||||
const [editing, setEditing] = useState<ContactRecord | null>(null);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
@@ -86,7 +70,6 @@ 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 (
|
||||
@@ -96,7 +79,7 @@ function ContactsIndex() {
|
||||
(r.phone ?? "").toLowerCase().includes(term)
|
||||
);
|
||||
});
|
||||
}, [rows, q, typeFilter, view, category]);
|
||||
}, [rows, q, typeFilter, view]);
|
||||
|
||||
const grouped = useMemo(() => {
|
||||
const map = new Map<string, ContactRow[]>();
|
||||
@@ -116,14 +99,13 @@ function ContactsIndex() {
|
||||
const archivedCount = rows.filter((r) => r.archived_at).length;
|
||||
const activeCount = rows.length - archivedCount;
|
||||
|
||||
const categoryCounts = useMemo(() => {
|
||||
const typeCounts = 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,
|
||||
};
|
||||
const counts: Record<string, number> = { all: base.length };
|
||||
for (const t of CONTACT_TYPES) {
|
||||
counts[t.value] = base.filter((r) => (r.contact_type ?? "other") === t.value).length;
|
||||
}
|
||||
return counts;
|
||||
}, [rows, view]);
|
||||
|
||||
const remove = async (id: string, name: string) => {
|
||||
@@ -192,14 +174,25 @@ function ContactsIndex() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Tabs value={category} onValueChange={(v) => setCategory(v as Category)} className="mb-4">
|
||||
<TabsList>
|
||||
<TabsTrigger value="all">All ({categoryCounts.all})</TabsTrigger>
|
||||
<TabsTrigger value="companies">Companies ({categoryCounts.companies})</TabsTrigger>
|
||||
<TabsTrigger value="people">People ({categoryCounts.people})</TabsTrigger>
|
||||
<TabsTrigger value="lawyers">Lawyers ({categoryCounts.lawyers})</TabsTrigger>
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
<div className="mb-4 flex flex-wrap gap-1.5">
|
||||
<Button
|
||||
size="sm"
|
||||
variant={typeFilter === "all" ? "default" : "outline"}
|
||||
onClick={() => setTypeFilter("all")}
|
||||
>
|
||||
All ({typeCounts.all ?? 0})
|
||||
</Button>
|
||||
{CONTACT_TYPES.map((t) => (
|
||||
<Button
|
||||
key={t.value}
|
||||
size="sm"
|
||||
variant={typeFilter === t.value ? "default" : "outline"}
|
||||
onClick={() => setTypeFilter(t.value)}
|
||||
>
|
||||
{t.label} ({typeCounts[t.value] ?? 0})
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
|
||||
Reference in New Issue
Block a user