import { createFileRoute, Link } 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, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { supabase } from "@/integrations/supabase/client"; import { useAuth } from "@/lib/auth"; import { Briefcase, Users, Receipt, Clock, ArrowRight } from "lucide-react"; import { formatCurrency, formatDate, statusBadgeClass } from "@/lib/format"; import { Badge } from "@/components/ui/badge"; export const Route = createFileRoute("/")({ component: () => ( ), }); interface Stats { activeCases: number; clients: number; unpaidInvoices: number; unbilledHours: number; } function Dashboard() { const { user } = useAuth(); const [stats, setStats] = useState({ activeCases: 0, clients: 0, unpaidInvoices: 0, unbilledHours: 0 }); const [recentCases, setRecentCases] = useState([]); const [recentInvoices, setRecentInvoices] = useState([]); useEffect(() => { (async () => { const [casesRes, clientsRes, invoicesRes, timeRes, recentCasesRes, recentInvRes] = await Promise.all([ supabase.from("cases").select("id", { count: "exact", head: true }).in("status", ["intake", "active", "on_hold"]), supabase.from("clients").select("id", { count: "exact", head: true }), supabase.from("invoices").select("total, amount_paid").in("status", ["sent", "overdue"]), supabase.from("time_entries").select("hours").is("invoice_id", null).eq("billable", true), supabase.from("cases").select("id, case_number, title, status, updated_at, client:clients(name)").order("updated_at", { ascending: false }).limit(5), supabase.from("invoices").select("id, invoice_number, total, status, issue_date, client:clients(name)").order("created_at", { ascending: false }).limit(5), ]); const unpaid = (invoicesRes.data ?? []).reduce( (sum, i) => sum + (Number(i.total) - Number(i.amount_paid)), 0, ); const hours = (timeRes.data ?? []).reduce((s, t) => s + Number(t.hours), 0); setStats({ activeCases: casesRes.count ?? 0, clients: clientsRes.count ?? 0, unpaidInvoices: unpaid, unbilledHours: hours, }); setRecentCases(recentCasesRes.data ?? []); setRecentInvoices(recentInvRes.data ?? []); })(); }, [user?.id]); const cards = [ { label: "Active cases", value: stats.activeCases, icon: Briefcase, to: "/cases" }, { label: "Clients", value: stats.clients, icon: Users, to: "/clients" }, { label: "Unbilled hours", value: stats.unbilledHours.toFixed(1), icon: Clock, to: "/cases" }, { label: "Outstanding A/R", value: formatCurrency(stats.unpaidInvoices), icon: Receipt, to: "/invoices" }, ]; return (
{cards.map((c) => (
{c.label}
{c.value}
))}
Recent cases {recentCases.length === 0 &&

No cases yet.

} {recentCases.map((c) => (
{c.title}
{c.case_number} · {c.client?.name}
{c.status.replace("_", " ")} ))}
Recent invoices {recentInvoices.length === 0 &&

No invoices yet.

} {recentInvoices.map((i) => (
{i.invoice_number}
{i.client?.name} · {formatDate(i.issue_date)}
{formatCurrency(i.total)} {i.status}
))}
); }