From ff394f6f570e2b8221ba344fb73bf544eece074a 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 18:43:04 +0000 Subject: [PATCH] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/invoices.index.tsx | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/routes/invoices.index.tsx b/src/routes/invoices.index.tsx index 3dff250..a9ff543 100644 --- a/src/routes/invoices.index.tsx +++ b/src/routes/invoices.index.tsx @@ -206,6 +206,47 @@ function InvoicesIndex() { } }; + const refreshInvoices = async () => { + const { data } = await supabase + .from("invoices") + .select("*, client:clients(id, name), case:cases(id, case_number, title)") + .order("created_at", { ascending: false }); + setInvoices(data ?? []); + setPlaceholderIds(new Set( + (data ?? []) + .filter((i: any) => + typeof i.invoice_number === "string" && + (i.invoice_number.startsWith("MARKED-INVOICED-") || i.invoice_number.startsWith("IMPORT-PREBILLED-")) + ) + .map((i: any) => i.id), + )); + }; + + const bulkInvoiceAction = async (action: "delete" | "sent" | "void") => { + if (selectedInvoices.size === 0) { toast.error("Select at least one invoice"); return; } + const ids = Array.from(selectedInvoices); + const verb = action === "delete" ? "delete" : `mark as ${action}`; + if (!confirm(`${verb.charAt(0).toUpperCase() + verb.slice(1)} ${ids.length} invoice(s)?`)) return; + setWorking(true); + try { + if (action === "delete") { + const { error } = await supabase.from("invoices").delete().in("id", ids); + if (error) throw error; + toast.success(`Deleted ${ids.length} invoice(s)`); + } else { + const { error } = await supabase.from("invoices").update({ status: action }).in("id", ids); + if (error) throw error; + toast.success(`Marked ${ids.length} invoice(s) as ${action}`); + } + setSelectedInvoices(new Set()); + await refreshInvoices(); + } catch (err: any) { + toast.error(err?.message ?? "Bulk action failed"); + } finally { + setWorking(false); + } + }; + return (