Added billed time to cases

X-Lovable-Edit-ID: edt-d5bb0ae8-2204-4856-8b35-d2c2ae97bf3e
Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-04-17 00:56:20 +00:00
co-authored by renee-png
+21 -2
View File
@@ -9,7 +9,7 @@ import { supabase } from "@/integrations/supabase/client";
import { ClientFormDialog } from "@/components/clients/client-form-dialog";
import { useAuth } from "@/lib/auth";
import { ArrowLeft, Edit, Plus, Building2, User, Briefcase as Building, MapPin, Mail, Phone, Users } from "lucide-react";
import { formatDate, statusBadgeClass } from "@/lib/format";
import { formatCurrency, formatDate, statusBadgeClass } from "@/lib/format";
import { toast } from "sonner";
export const Route = createFileRoute("/clients/$clientId")({
@@ -36,8 +36,24 @@ function ClientDetail() {
supabase.from("cases").select("id, case_number, title, status, opened_at").eq("client_id", clientId).order("opened_at", { ascending: false }),
]);
if (ce) toast.error("Failed to load client", { description: ce.message });
const caseIds = (cs ?? []).map((x: any) => x.id);
let totals: Record<string, { hours: number; amount: number }> = {};
if (caseIds.length) {
const { data: te } = await supabase
.from("time_entries")
.select("case_id, hours, hourly_rate, billable")
.in("case_id", caseIds)
.eq("billable", true);
(te ?? []).forEach((t: any) => {
const h = Number(t.hours) || 0;
const r = Number(t.hourly_rate) || 0;
if (!totals[t.case_id]) totals[t.case_id] = { hours: 0, amount: 0 };
totals[t.case_id].hours += h;
totals[t.case_id].amount += h * r;
});
}
setClient(c);
setCases(cs ?? []);
setCases((cs ?? []).map((x: any) => ({ ...x, billed: totals[x.id] ?? { hours: 0, amount: 0 } })));
setLoading(false);
};
@@ -180,6 +196,9 @@ function ClientDetail() {
<div className="text-xs text-muted-foreground">
{c.case_number} · opened {formatDate(c.opened_at)}
</div>
<div className="text-xs text-muted-foreground mt-0.5">
Billed: {c.billed.hours.toFixed(1)} hr · {formatCurrency(c.billed.amount)}
</div>
</Link>
))}
</div>