import { createFileRoute, Link } from "@tanstack/react-router"; import { useEffect, useMemo, 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 { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { SearchableSelect } from "@/components/ui/searchable-select"; import { supabase } from "@/integrations/supabase/client"; import { useAuth } from "@/lib/auth"; import { Loader2, Send, ExternalLink } from "lucide-react"; import { formatDateTime } from "@/lib/format"; import { toast } from "sonner"; export const Route = createFileRoute("/status/")({ component: () => ( ), }); function nowLocal() { const d = new Date(); d.setMinutes(d.getMinutes() - d.getTimezoneOffset()); return d.toISOString().slice(0, 16); } function StatusUpdatesPage() { const { user } = useAuth(); const [cases, setCases] = useState([]); const [recent, setRecent] = useState([]); const [caseId, setCaseId] = useState(""); const [title, setTitle] = useState(nowLocal()); const [body, setBody] = useState(""); const [submitting, setSubmitting] = useState(false); const [loading, setLoading] = useState(true); const loadCases = async () => { const { data, error } = await supabase .from("cases") .select("id, case_number, title, client:clients(name)") .is("archived_at", null) .order("opened_at", { ascending: false }) .limit(500); if (error) toast.error("Could not load cases", { description: error.message }); setCases(data ?? []); }; const loadRecent = async () => { const { data, error } = await supabase .from("status_updates") .select("*, case:cases(id, case_number, title, client:clients(name))") .order("created_at", { ascending: false }) .limit(25); if (error) { toast.error("Could not load updates", { description: error.message }); setLoading(false); return; } const ids = Array.from(new Set((data ?? []).map((d: any) => d.created_by).filter(Boolean))); let profMap: Record = {}; if (ids.length) { const { data: profs } = await supabase.from("profiles").select("id, full_name, email").in("id", ids); profMap = Object.fromEntries((profs ?? []).map((p: any) => [p.id, p])); } setRecent((data ?? []).map((u: any) => ({ ...u, user: u.created_by ? profMap[u.created_by] : null }))); setLoading(false); }; useEffect(() => { loadCases(); loadRecent(); }, []); const selectedCase = useMemo(() => cases.find((c) => c.id === caseId), [cases, caseId]); const submit = async (e: React.FormEvent) => { e.preventDefault(); if (!caseId) { toast.error("Select a case"); return; } if (!title.trim() || !body.trim()) { toast.error("Date/time and details required"); return; } setSubmitting(true); const { error } = await supabase.from("status_updates").insert({ case_id: caseId, title: title.trim(), body: body.trim(), created_by: user?.id, }); setSubmitting(false); if (error) { toast.error(error.message); return; } toast.success("Update logged"); setBody(""); setTitle(nowLocal()); loadRecent(); }; return (
{/* Form */}
({ value: c.id, label: `${c.case_number} — ${c.title}${c.client?.name ? ` · ${c.client.name}` : ""}`, keywords: `${c.case_number} ${c.title} ${c.client?.name ?? ""}`, }))} /> {selectedCase && ( Open case )}
setTitle(e.target.value)} required />