"use client"; import Link from "next/link"; import { useRouter } from "next/navigation"; import type { ColumnDef } from "@tanstack/react-table"; import { Button } from "~/components/ui/button"; import { StatusBadge, type StatusType } from "~/components/data/status-badge"; import { PDFDownloadButton } from "~/app/dashboard/invoices/[id]/_components/pdf-download-button"; import { DataTable, DataTableColumnHeader } from "~/components/data/data-table"; import { Eye, Edit } from "lucide-react"; // Type for invoice data interface Invoice { id: string; invoiceNumber: string; clientId: string; businessId: string | null; issueDate: Date; dueDate: Date; status: string; totalAmount: number; taxRate: number; notes: string | null; createdById: string; createdAt: Date; updatedAt: Date | null; client?: { id: string; name: string; email: string | null; phone: string | null; } | null; business?: { id: string; name: string; email: string | null; phone: string | null; } | null; items?: Array<{ id: string; invoiceId: string; date: Date; description: string; hours: number; rate: number; amount: number; position: number; createdAt: Date; }> | null; } interface InvoicesDataTableProps { invoices: Invoice[]; } const getStatusType = (invoice: Invoice): StatusType => { if (invoice.status === "paid") return "paid"; if (invoice.status === "draft") return "draft"; if (invoice.status === "overdue") return "overdue"; if (invoice.status === "sent") { const dueDate = new Date(invoice.dueDate); return dueDate < new Date() ? "overdue" : "sent"; } return "draft"; }; const formatDate = (date: Date) => { return new Intl.DateTimeFormat("en-US", { month: "short", day: "2-digit", year: "numeric", }).format(new Date(date)); }; const formatCurrency = (amount: number) => { return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", }).format(amount); }; export function InvoicesDataTable({ invoices }: InvoicesDataTableProps) { const router = useRouter(); const handleRowClick = (invoice: Invoice) => { router.push(`/dashboard/invoices/${invoice.id}`); }; const columns: ColumnDef[] = [ { accessorKey: "client.name", header: ({ column }) => ( ), cell: ({ row }) => { const invoice = row.original; return (

{invoice.client?.name ?? "—"}

{invoice.invoiceNumber}

); }, }, { accessorKey: "issueDate", header: ({ column }) => ( ), cell: ({ row }) => { const date = row.getValue("issueDate"); return (

{formatDate(date as Date)}

Due {formatDate(new Date(row.original.dueDate))}

); }, }, { accessorKey: "status", header: ({ column }) => ( ), cell: ({ row }) => { const invoice = row.original; return ; }, filterFn: (row, id, value: string[]) => { const invoice = row.original; const status = getStatusType(invoice); return value.includes(status); }, meta: { headerClassName: "hidden sm:table-cell", cellClassName: "hidden sm:table-cell", }, }, { accessorKey: "totalAmount", header: ({ column }) => ( ), cell: ({ row }) => { const amount = row.getValue("totalAmount"); return (

{formatCurrency(amount as number)}

{row.original.items?.length ?? 0} items

); }, meta: { headerClassName: "hidden sm:table-cell", cellClassName: "hidden sm:table-cell", }, }, { id: "actions", cell: ({ row }) => { const invoice = row.original; return (
{invoice.items && invoice.client && (
)}
); }, }, ]; const filterableColumns = [ { id: "status", title: "Status", options: [ { label: "Draft", value: "draft" }, { label: "Sent", value: "sent" }, { label: "Paid", value: "paid" }, { label: "Overdue", value: "overdue" }, ], }, ]; return ( ); }