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 (