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 { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Textarea } from '@/components/ui/textarea'; 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 { PaymentStatusLabels, PaymentStatuses } 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); 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 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 }) => (row.getValue('payment_method') as string | null) ?? '-', }, { 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 }) => ( , onClick: () => setEditing(row.original), }, { label: 'Hapus', icon: ( ), 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)}{' '} {paidTotal >= Number(invoice.amount_due) ? ( Lunas ) : paidTotal > 0 ? ( Sebagian ) : ( Belum Bayar )}

Riwayat Pembayaran

{ if (!open) { setEditing(null); } }} invoiceId={invoice.id} editing={editing} /> { 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, }: { open: boolean; onOpenChange: (open: boolean) => void; invoiceId: number; }) { return ( onOpenChange(false)} > {({ errors }) => (
)}
); } function EditForm({ open, onOpenChange, invoiceId, editing, }: { open: boolean; onOpenChange: (open: boolean) => void; invoiceId: number; editing: TuitionPayment | null; }) { return ( onOpenChange(false)} > {({ errors }) => editing && (
) }
); } function PaymentFields({ errors, editing, resetKey, }: { errors: Record; editing?: TuitionPayment; resetKey?: string; }) { return ( <>