import type { ColumnDef } from '@tanstack/react-table'; import { format, isBefore, startOfDay } from 'date-fns'; import { CreditCard, Pencil, Trash2 } from 'lucide-react'; import { RowActions } from '@/components/row-actions'; import { Badge } from '@/components/ui/badge'; import { formatRupiah } from '@/lib/currency'; import { cn } from '@/lib/utils'; import { index as paymentsIndex } from '@/routes/admin/finances/tuition-invoices/payments'; import { formatAcademicTermLabel } from '@/types/academic-term'; import type { TuitionInvoice } from '@/types/tuition-invoice'; export type { TuitionInvoice } from '@/types/tuition-invoice'; type CreateColumnsParams = { handleEdit: (invoice: TuitionInvoice) => void; handleDeleteClick: (invoice: TuitionInvoice) => void; canUpdate: boolean; canDelete: boolean; canViewPayments: boolean; }; export function createTuitionInvoiceColumns( params: CreateColumnsParams, ): ColumnDef[] { const { handleEdit, handleDeleteClick, canUpdate, canDelete, canViewPayments, } = params; return [ { accessorKey: 'student.student_number', header: () => Mahasiswa, cell: ({ row }) => { const student = row.original.student; return (

{student?.user?.profile?.full_name ?? 'N/A'}

{student?.student_number} ·{' '} {student?.department?.name ?? '-'}

); }, }, { accessorKey: 'academic_term.name', header: () => Periode, cell: ({ row }) => { const term = row.original.academic_term; return term ? formatAcademicTermLabel(term) : '-'; }, }, { accessorKey: 'amount_due', header: () => Tagihan, cell: ({ row }) => formatRupiah(row.getValue('amount_due')), }, { accessorKey: 'paid_total', header: () => Status Bayar, cell: ({ row }) => { const invoice = row.original; const paidTotal = Number(invoice.paid_total ?? 0); const amountDue = Number(invoice.amount_due); const variant = paidTotal >= amountDue && amountDue > 0 ? 'default' : paidTotal > 0 ? 'secondary' : 'outline'; const label = paidTotal >= amountDue && amountDue > 0 ? 'Lunas' : paidTotal > 0 ? 'Sebagian' : 'Belum Bayar'; return (
{label} {formatRupiah(paidTotal)} /{' '} {formatRupiah(amountDue)}
); }, }, { accessorKey: 'due_date', header: () => Jatuh Tempo, cell: ({ row }) => { const invoice = row.original; const dueDate = row.getValue('due_date') as string | null; if (!dueDate) { return '-'; } const paidTotal = Number(invoice.paid_total ?? 0); const amountDue = Number(invoice.amount_due); const isOverdue = paidTotal < amountDue && isBefore(new Date(dueDate), startOfDay(new Date())); return ( {format(new Date(dueDate), 'd MMM yyyy')} ); }, }, { id: 'actions', header: () => Aksi, meta: { className: 'w-[130px] text-center', headerClassName: 'w-[130px] text-center', }, cell: ({ row }) => { const invoice = row.original; return ( , show: canViewPayments, href: paymentsIndex.url(invoice.id), }, { label: 'Edit', icon: , show: canUpdate, onClick: () => handleEdit(invoice), }, { label: 'Hapus', icon: ( ), show: canDelete, onClick: () => handleDeleteClick(invoice), }, ]} /> ); }, }, ]; }