import { useNotify, useRefresh, useShowContext, useTranslate, useUpdate, useDataProvider, } from "ra-core"; import { Check, Download, Printer, Send, XCircle } from "lucide-react"; import { Button } from "@/components/ds/ui/button"; import { Card, CardContent, CardHeader, CardTitle, } from "@/components/ds/ui/card"; import { DateField } from "@/components/ds/admin/date-field"; import { ReferenceField } from "@/components/ds/admin/reference-field"; import { TextField } from "@/components/ds/admin/text-field"; import { EditButton } from "@/components/ds/admin/edit-button"; import { InvoiceEmailModal } from "./InvoiceEmailModal"; import { DownloadPDFButton } from "./DownloadPDFButton"; import type { Invoice } from "../types"; export const InvoiceAside = () => { const { record, isPending } = useShowContext(); const translate = useTranslate(); if (isPending || !record) return null; return (
{/* Quick Actions */} {translate("resources.invoices.section.actions")} {record.status === "draft" && ( } record={record} /> )} {(record.status === "draft" || record.status === "sent" || record.status === "overdue") && ( } record={record} /> )} {record.status !== "cancelled" && record.status !== "paid" && ( } record={record} /> )} {/* Invoice Details */} {translate("resources.invoices.section.details")}

{translate("resources.invoices.fields.invoice_number")}

{record.invoice_number}

{record.reference && (

{translate("resources.invoices.fields.reference")}

{record.reference}

)}

{translate("resources.invoices.fields.currency")}

{record.currency}

{translate("resources.invoices.fields.created_at")}

{record.sent_at && (

{translate("resources.invoices.fields.sent_at")}

)} {record.viewed_at && (

{translate("resources.invoices.fields.viewed_at")}

)}
{/* Assigned To */} {record.sales_id && ( {translate("resources.invoices.section.assigned_to")}
{" "}
)}
); }; const ExportCSVButton = ({ record }: { record: Invoice }) => { const translate = useTranslate(); const dataProvider = useDataProvider(); const notify = useNotify(); const handleExport = async () => { try { // Fetch invoice items const { data: items } = await dataProvider.getList("invoice_items", { filter: { invoice_id: record.id }, pagination: { page: 1, perPage: 100 }, sort: { field: "sort_order", order: "ASC" }, }); // Prepare CSV content const header = [ "Invoice Number", "Reference", "Issue Date", "Due Date", "Status", "Currency", "Subtotal", "Discount", "Tax Total", "Total", "Item Name", "Item Qty", "Item Price", "Item Total", ]; const rows = items.map((item: any) => [ record.invoice_number, record.reference || "", record.issue_date, record.due_date, record.status, record.currency, record.subtotal, record.discount, record.tax_total, record.total, item.description, item.quantity, item.unit_price, item.line_total_with_tax, ]); const csvContent = [ header.join(","), ...rows.map((row: any[]) => row.map((v) => `"${String(v).replace(/"/g, '""')}"`).join(","), ), ].join("\n"); // Download CSV const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.setAttribute("href", url); link.setAttribute("download", `invoice-${record.invoice_number}.csv`); link.style.visibility = "hidden"; document.body.appendChild(link); link.click(); document.body.removeChild(link); } catch (error: any) { notify(error.message, { type: "warning" }); } }; return ( ); }; const ActionButton = ({ label, status, icon, record, variant = "default", }: { label: string; status: Invoice["status"]; icon: React.ReactNode; record: Invoice; variant?: | "default" | "outline" | "secondary" | "ghost" | "link" | "destructive"; }) => { const translate = useTranslate(); const notify = useNotify(); const refresh = useRefresh(); const [update, { isPending }] = useUpdate(); const handleUpdate = () => { update( "invoices", { id: record.id, data: { status, ...(status === "paid" ? { paid_at: new Date().toISOString() } : {}), ...(status === "sent" ? { sent_at: new Date().toISOString() } : {}), }, }, { onSuccess: () => { notify("resources.invoices.notification.status_updated", { type: "info", messageArgs: { status: translate(`resources.invoices.status.${status}`), }, }); refresh(); }, onError: (error: any) => notify(error.message, { type: "warning" }), }, ); }; return ( ); };