import { createFileRoute, Link, useNavigate } from "@tanstack/react-router"; import { useEffect, useState } from "react"; import { ProtectedLayout } from "@/components/protected-layout"; import { PageContainer, PageHeader } from "@/components/app-shell"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { supabase } from "@/integrations/supabase/client"; import { useAuth } from "@/lib/auth"; import { toast } from "sonner"; import { ArrowLeft, Edit, Trash2, Mail, Phone, MapPin, Building2, Briefcase, Users, Archive, ArchiveRestore } from "lucide-react"; import { ContactFormDialog, CONTACT_TYPES } from "@/components/contacts/contact-form-dialog"; import { setArchived } from "@/lib/archive"; export const Route = createFileRoute("/contacts/$contactId")({ component: () => ( ), }); function ContactDetail() { const { contactId } = Route.useParams(); const navigate = useNavigate(); const { user, isAdmin } = useAuth(); const [contact, setContact] = useState(null); const [cases, setCases] = useState([]); const [clients, setClients] = useState([]); const [loading, setLoading] = useState(true); const [editOpen, setEditOpen] = useState(false); const load = async () => { setLoading(true); const [{ data: c, error }, { data: cc }, { data: clc }] = await Promise.all([ supabase.from("contacts").select("*").eq("id", contactId).maybeSingle(), supabase.from("case_contacts").select("role, case:cases(id, case_number, title, status)").eq("contact_id", contactId), supabase.from("client_contacts").select("role, client:clients(id, name, client_type)").eq("contact_id", contactId), ]); if (error) toast.error(error.message); setContact(c); setCases(((cc ?? []) as any[]).filter((r) => r.case)); setClients(((clc ?? []) as any[]).filter((r) => r.client)); setLoading(false); }; useEffect(() => { load(); }, [contactId]); const remove = async () => { if (!contact) return; if (!confirm(`Delete contact "${contact.name}"?`)) return; const { error } = await supabase.from("contacts").delete().eq("id", contactId); if (error) { toast.error(error.message); return; } toast.success("Contact deleted"); navigate({ to: "/contacts" }); }; if (loading) { return Loading…; } if (!contact) { return ( Contact not found. Back to contacts ); } const canEdit = isAdmin || contact.created_by === user?.id; const typeLabel = CONTACT_TYPES.find((t) => t.value === contact.contact_type)?.label ?? contact.contact_type; const addr = [contact.address_line1, contact.address_line2, contact.city, contact.state, contact.postal_code].filter(Boolean).join(", "); return ( All contacts {contact.archived_at && ( Archived )} {canEdit && ( <> setEditOpen(true)}> Edit { if (await setArchived("contacts", contact.id, !contact.archived_at)) load(); }} > {contact.archived_at ? ( <> Restore> ) : ( <> Archive> )} Delete > )} > } /> {typeLabel} {contact.notes && ( Notes {contact.notes} )} Cases ({cases.length}) {cases.length === 0 ? ( Not linked to any cases. ) : ( {cases.map((row, i) => ( {row.case.title} {row.case.case_number} ))} )} Clients ({clients.length}) {clients.length === 0 ? ( Not linked to any clients. ) : ( {clients.map((row, i) => ( {row.client.name} {row.client.client_type} ))} )} load()} /> ); } function DetailRow({ label, value, icon: Icon }: { label: string; value: any; icon?: any }) { return ( <> {label} {Icon && value && } {value || —} > ); }
Loading…
Contact not found.
{contact.notes}
Not linked to any cases.
Not linked to any clients.