From 57821307b7de08e620cc01ffcaf5428686cfba1e Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 19 Apr 2026 17:00:39 +0000 Subject: [PATCH] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/cases/expenses-tab.tsx | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/components/cases/expenses-tab.tsx b/src/components/cases/expenses-tab.tsx index b10f787..685d798 100644 --- a/src/components/cases/expenses-tab.tsx +++ b/src/components/cases/expenses-tab.tsx @@ -55,6 +55,35 @@ export function CaseExpensesTab({ caseId }: { caseId: string }) { useEffect(() => { load(); }, [caseId]); + // Load case client_id for placeholder invoice creation + useEffect(() => { + (async () => { + const { data } = await supabase.from("cases").select("client_id").eq("id", caseId).maybeSingle(); + setClientId((data as any)?.client_id ?? null); + })(); + }, [caseId]); + + const toggleInvoiced = async (item: any) => { + if (item.invoice_id) { + const { error } = await supabase.from("expenses").update({ invoice_id: null }).eq("id", item.id); + if (error) { toast.error(error.message); return; } + toast.success("Marked as unbilled"); + load(); + } else { + if (!user?.id) { toast.error("Not signed in"); return; } + if (!clientId) { toast.error("Case has no client to invoice against"); return; } + try { + const invId = await ensureMarkedInvoicedPlaceholder(clientId, caseId, user.id); + const { error } = await supabase.from("expenses").update({ invoice_id: invId }).eq("id", item.id); + if (error) throw error; + toast.success("Marked as invoiced"); + load(); + } catch (err: any) { + toast.error(err?.message ?? "Could not mark as invoiced"); + } + } + }; + useEffect(() => { (async () => { const { data } = await supabase