import { Head, Link, router } from '@inertiajs/react'; import type { ColumnDef } from '@tanstack/react-table'; import { format } from 'date-fns'; import { ArrowLeft, Paperclip, Pencil, Plus, Trash2 } from 'lucide-react'; import { useState } from 'react'; import { DataTable } from '@/components/data-table'; import { DateTimeField } from '@/components/datetime-field'; import { DeleteConfirmDialog } from '@/components/delete-confirm-dialog'; import { FileUploadField } from '@/components/file-upload-field'; import { FormDialog } from '@/components/form-dialog'; import InputError from '@/components/input-error'; import { PageHeader } from '@/components/page-header'; import { RowActions } from '@/components/row-actions'; import { RupiahInput } from '@/components/rupiah-input'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Label } from '@/components/ui/label'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { Textarea } from '@/components/ui/textarea'; import { usePermissions } from '@/hooks/use-permissions'; import { formatRupiah } from '@/lib/currency'; import { index as tuitionInvoiceIndex } from '@/routes/admin/finances/tuition-invoices'; import { destroy, store, update, } from '@/routes/admin/finances/tuition-invoices/payments'; import { formatAcademicTermLabel } from '@/types/academic-term'; import type { TuitionInvoice } from '@/types/tuition-invoice'; import type { TuitionPayment } from '@/types/tuition-payment'; import { PaymentMethodLabels, PaymentMethods, PaymentStatusLabels, } from '@/types/tuition-payment'; type Props = { invoice: TuitionInvoice; payments: TuitionPayment[]; }; export default function TuitionPaymentIndex({ invoice, payments }: Props) { const [createOpen, setCreateOpen] = useState(false); const [editing, setEditing] = useState(null); const [deleting, setDeleting] = useState(null); const { hasPermission } = usePermissions(); const canCreate = hasPermission('create-tuition-payments'); const canUpdate = hasPermission('update-tuition-payments'); const canDelete = hasPermission('delete-tuition-payments'); function handleDelete() { if (!deleting) { return; } router.delete(destroy([invoice.id, deleting.id]), { onSuccess: () => setDeleting(null), }); } const paidTotal = payments.reduce( (sum, payment) => sum + Number(payment.amount_paid), 0, ); const amountDue = Number(invoice.amount_due); const isFullyPaid = paidTotal >= amountDue; const columns: ColumnDef[] = [ { accessorKey: 'paid_at', header: () => Tanggal Bayar, cell: ({ row }) => format(new Date(row.original.paid_at), 'd MMM yyyy, HH:mm'), }, { accessorKey: 'amount_paid', header: () => Jumlah, cell: ({ row }) => formatRupiah(row.getValue('amount_paid')), }, { accessorKey: 'payment_method', header: () => Metode, cell: ({ row }) => { const method = row.getValue('payment_method') as keyof typeof PaymentMethodLabels | null; return method ? PaymentMethodLabels[method] : '-'; }, }, { accessorKey: 'status', header: () => Status, meta: { className: 'w-[120px] text-center', headerClassName: 'w-[120px] text-center', }, cell: ({ row }) => { const status = row.getValue('status') as keyof typeof PaymentStatusLabels | null; return (
{status ? ( {PaymentStatusLabels[status]} ) : ( - )}
); }, }, { accessorKey: 'recorder.full_name', header: () => Dicatat Oleh, cell: ({ row }) => row.original.recorder?.full_name ?? '-', }, { accessorKey: 'proof_name', header: () => Bukti, cell: ({ row }) => { const payment = row.original; if (!payment.proof_url) { return -; } return ( {payment.proof_name} ); }, }, { id: 'actions', header: () => Aksi, meta: { className: 'w-[100px] text-center', headerClassName: 'w-[100px] text-center', }, cell: ({ row }) => ( , show: canUpdate, onClick: () => setEditing(row.original), }, { label: 'Hapus', icon: ( ), show: canDelete, onClick: () => setDeleting(row.original), }, ]} /> ), }, ]; return ( <>
Kembali } /> {invoice.student?.user?.profile?.full_name ?? 'N/A'}

NIM: {invoice.student?.student_number} ·{' '} {invoice.student?.department?.name ?? '-'}

Periode:{' '} {invoice.academic_term ? formatAcademicTermLabel(invoice.academic_term) : '-'}

Jumlah Tagihan: {formatRupiah(invoice.amount_due)}

Total Terbayar: {formatRupiah(paidTotal)}{' '} {isFullyPaid ? ( Lunas ) : paidTotal > 0 ? ( Sebagian ) : ( Belum Bayar )}

Riwayat Pembayaran

{!isFullyPaid && canCreate && ( )}
{ if (!open) { setEditing(null); } }} invoiceId={invoice.id} editing={editing} remaining={ editing ? amountDue - (paidTotal - Number(editing.amount_paid)) : 0 } /> { if (!open) { setDeleting(null); } }} title="Hapus Pembayaran" description={() => 'Apakah Anda yakin ingin menghapus data pembayaran ini? Tindakan ini tidak dapat dibatalkan.' } onConfirm={handleDelete} />
); } function CreateForm({ open, onOpenChange, invoiceId, remaining, }: { open: boolean; onOpenChange: (open: boolean) => void; invoiceId: number; remaining: number; }) { return ( onOpenChange(false)} > {({ errors }) => (
)}
); } function EditForm({ open, onOpenChange, invoiceId, editing, remaining, }: { open: boolean; onOpenChange: (open: boolean) => void; invoiceId: number; editing: TuitionPayment | null; remaining: number; }) { return ( onOpenChange(false)} > {({ errors }) => editing && (
) }
); } function PaymentFields({ errors, editing, resetKey, remaining, }: { errors: Record; editing?: TuitionPayment; resetKey?: string; remaining: number; }) { return ( <>

Sisa tagihan: {formatRupiah(remaining)}

{PaymentMethods.map((method) => (
))}