diff --git a/src/routes/cases.$caseId.tsx b/src/routes/cases.$caseId.tsx index ab9c829..b7cd29b 100644 --- a/src/routes/cases.$caseId.tsx +++ b/src/routes/cases.$caseId.tsx @@ -1,5 +1,5 @@ import { createFileRoute, Link } from "@tanstack/react-router"; -import { useEffect, useState, useCallback } from "react"; +import { useEffect, useState, useCallback, useMemo } from "react"; import { ProtectedLayout } from "@/components/protected-layout"; import { PageContainer, PageHeader } from "@/components/app-shell"; import { Button } from "@/components/ui/button"; @@ -7,8 +7,10 @@ import { Card, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; import { supabase } from "@/integrations/supabase/client"; -import { ArrowLeft, FileText, Clock, DollarSign, Activity, Receipt, Scale, Users, Contact, Phone, Tag, Archive, ArchiveRestore } from "lucide-react"; +import { ArrowLeft, FileText, Clock, DollarSign, Activity, Receipt, Scale, Users, Contact, Phone, Tag, Archive, ArchiveRestore, ArrowRightLeft, Search } from "lucide-react"; import { ContactsLinkTab } from "@/components/contacts/contacts-link-tab"; import { CaseCallLogsTab } from "@/components/cases/call-logs-tab"; import { formatCurrency, formatDate, statusBadgeClass } from "@/lib/format"; @@ -38,19 +40,26 @@ function CaseDetail() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [users, setUsers] = useState([]); + const [clients, setClients] = useState([]); + const [reassignOpen, setReassignOpen] = useState(false); + const [clientSearch, setClientSearch] = useState(""); + const [selectedClientId, setSelectedClientId] = useState(""); + const [reassigning, setReassigning] = useState(false); const load = useCallback(async () => { - const [{ data: c, error }, { data: us }] = await Promise.all([ + const [{ data: c, error }, { data: us }, { data: cl }] = await Promise.all([ supabase .from("cases") .select("*, client:clients(id, name, client_type, annual_interest_rate), assignee:profiles!cases_assigned_attorney_id_fkey(id, full_name, email)") .eq("id", caseId) .maybeSingle(), supabase.from("profiles").select("id, full_name, email"), + supabase.from("clients").select("id, name, client_type").is("archived_at", null).order("name"), ]); if (error) toast.error("Failed to load case", { description: error.message }); setData(c); setUsers(us ?? []); + setClients(cl ?? []); setLoading(false); }, [caseId]); @@ -76,6 +85,30 @@ function CaseDetail() { else { toast.success("Assignee updated"); load(); } }; + const filteredClients = useMemo(() => { + const q = clientSearch.trim().toLowerCase(); + if (!q) return clients.slice(0, 50); + return clients.filter((c) => c.name.toLowerCase().includes(q)).slice(0, 50); + }, [clients, clientSearch]); + + const reassignClient = async () => { + if (!selectedClientId || selectedClientId === data.client?.id) { + setReassignOpen(false); + return; + } + setReassigning(true); + const { error } = await supabase.from("cases").update({ client_id: selectedClientId }).eq("id", caseId); + setReassigning(false); + if (error) toast.error("Could not reassign", { description: error.message }); + else { + toast.success("Case reassigned to new client"); + setReassignOpen(false); + setClientSearch(""); + setSelectedClientId(""); + load(); + } + }; + if (loading) return

Loading…

; if (!data) { return ( @@ -134,6 +167,15 @@ function CaseDetail() { Closed + + )) + )} + + + + + + + + + {data.description && (