import type { ColumnDef } from '@tanstack/react-table'; import { ArrowUpDown, CircleDollarSign, Pencil, Trash2, XCircle, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '@/components/ui/tooltip'; import { formatCurrency } from '@/lib/utils'; export type Payroll = { id: number; base_salary: number; bonus_amount: number; deduction_amount: number; total_amount: number; status: 'unpaid' | 'paid' | 'cancelled'; paid_at: string | null; employee: { user: { user_profile: { full_name: string; }; }; }; payroll_adjustments?: PayrollAdjustment[]; }; export type PayrollAdjustment = { id: number; type: 'bonus' | 'deduction'; amount: number; description: string; created_at: string; }; function getStatusBadge(status: string) { const statusConfig: Record = { unpaid: { label: 'Belum Dibayar', className: 'bg-yellow-100 text-yellow-800 hover:bg-yellow-100', }, paid: { label: 'Dibayar', className: 'bg-green-100 text-green-800 hover:bg-green-100', }, cancelled: { label: 'Dibatalkan', className: 'bg-red-100 text-red-800 hover:bg-red-100', }, }; const config = statusConfig[status] ?? statusConfig.unpaid; return ( {config.label} ); } type CreateColumnsParams = { handlePay: (payroll: Payroll) => void; handleCancel: (payroll: Payroll) => void; handleAddAdjustment: (payroll: Payroll) => void; handleDeleteAdjustment: ( adjustment: PayrollAdjustment, payrollId: number, ) => void; }; export function createPayrollColumns( params: CreateColumnsParams, ): ColumnDef[] { const { handlePay, handleCancel, handleAddAdjustment, handleDeleteAdjustment, } = params; return [ { id: 'no', header: () => No, cell: ({ row }) => ( {row.index + 1} ), meta: { className: 'w-[50px] text-center', headerClassName: 'w-[50px] text-center', }, }, { id: 'employee_name', header: () => Nama Karyawan, cell: ({ row }) => { const employee = row.original.employee; return ( {employee?.user?.user_profile?.full_name ?? '-'} ); }, }, { accessorKey: 'base_salary', header: ({ column }) => ( ), cell: ({ row }) => ( {formatCurrency(row.getValue('base_salary') as number)} ), }, { accessorKey: 'bonus_amount', header: ({ column }) => ( ), cell: ({ row }) => { const value = row.getValue('bonus_amount') as number; return ( 0 ? 'font-medium text-green-600' : '' } > {value > 0 ? '+ ' : ''} {formatCurrency(value)} ); }, }, { accessorKey: 'deduction_amount', header: ({ column }) => ( ), cell: ({ row }) => { const value = row.getValue('deduction_amount') as number; return ( 0 ? 'font-medium text-red-600' : ''} > {value > 0 ? '- ' : ''} {formatCurrency(value)} ); }, }, { accessorKey: 'total_amount', header: ({ column }) => ( ), cell: ({ row }) => ( {formatCurrency(row.getValue('total_amount') as number)} ), }, { accessorKey: 'status', header: () => Status, cell: ({ row }) => ( {getStatusBadge(row.getValue('status') as string)} ), }, { id: 'adjustments', header: () => Penyesuaian, cell: ({ row }) => { const payroll = row.original; const adjustments = payroll.payroll_adjustments ?? []; if (adjustments.length === 0) { return -; } return (
{adjustments.map((adj: PayrollAdjustment) => (
{adj.type === 'bonus' ? '+' : '-'}{' '} {formatCurrency(adj.amount)} {adj.description} {payroll.status === 'unpaid' && ( )}
))}
); }, }, { id: 'actions', header: () => Aksi, meta: { className: 'w-[120px] text-center', headerClassName: 'w-[120px] text-center', }, cell: ({ row }) => { const payroll = row.original; return (
{payroll.status === 'unpaid' && ( <> Tambah Adjustment Tandai Dibayar Batalkan )}
); }, }, ]; }