dress/resources/js/pages/admin/finance/payroll/partials/columns.tsx

134 lines
5.5 KiB
TypeScript

import { ColumnDef } from '@tanstack/react-table';
import { Payroll } from '@/types';
import { DataTableColumnHeader } from '@/components/data-table-column-header';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import { Button } from '@/components/ui/button';
import { Switch } from '@/components/ui/switch';
import { Badge } from '@/components/ui/badge';
import { PencilRuler, Trash2 } from 'lucide-react';
interface ColumnProps {
onEdit: (payroll: Payroll) => void;
onDelete: (payroll: Payroll) => void;
onTogglePaid: (id: number) => void;
}
export const getColumns = ({ onEdit, onDelete, onTogglePaid }: ColumnProps): ColumnDef<Payroll>[] => [
{
accessorKey: "user.name",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Pegawai" />
),
cell: ({ row }) => row.original.user?.name || '-',
meta: { title: "Pegawai" },
},
{
accessorKey: "period_month",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Periode" />
),
cell: ({ row }) => row.original.period_month_formatted,
meta: { title: "Periode" },
},
{
accessorKey: "total_salary",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Rincian Gaji" />
),
cell: ({ row }) => {
const payroll = row.original;
return (
<div className="flex flex-col gap-1 py-1 min-w-[200px]">
<div className="flex justify-between text-[10px] text-muted-foreground uppercase tracking-tighter">
<span>Gaji Pokok</span>
<span className="font-medium text-foreground">{payroll.base_salary_formatted}</span>
</div>
{payroll.adjustments && payroll.adjustments.length > 0 && (
<div className="space-y-0.5">
{payroll.adjustments.map((adj, idx) => (
<div key={idx} className="flex justify-between text-[9px] text-muted-foreground italic">
<span className="line-clamp-1 max-w-[120px]">{adj.description}</span>
<span className={adj.type === 'bonus' ? 'text-green-600' : 'text-red-500'}>
{adj.type === 'bonus' ? '+' : '-'}{adj.amount_formatted}
</span>
</div>
))}
</div>
)}
<div className="flex justify-between text-xs font-bold pt-1 border-t border-dashed mt-1">
<span className="uppercase text-[10px]">Gaji Bersih</span>
<span className="text-primary">{payroll.total_salary_formatted}</span>
</div>
</div>
);
},
meta: { title: "Total Gaji" },
},
{
accessorKey: "is_paid",
header: "Status",
cell: ({ row }) => {
const payroll = row.original;
return (
<div className="flex items-center gap-2">
<Switch
checked={payroll.is_paid}
onCheckedChange={() => onTogglePaid(payroll.id)}
/>
<Badge
variant={payroll.is_paid ? 'default' : 'outline'}
className={payroll.is_paid ? 'bg-green-500/10 text-green-600 border-green-200 dark:bg-green-500/20 dark:text-green-400 dark:border-green-900' : ''}
>
{payroll.is_paid ? 'Dibayar' : 'Pending'}
</Badge>
</div>
);
},
meta: { title: "Status" },
},
{
id: "actions",
header: "Aksi",
cell: ({ row }) => {
const payroll = row.original;
return (
<div className="flex items-center gap-2">
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
className='text-yellow-600'
onClick={() => onEdit(payroll)}
>
<PencilRuler className="size-4" />
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Ubah / Sesuaikan</p>
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
className='text-red-600'
onClick={() => onDelete(payroll)}
>
<Trash2 className="size-4" />
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Hapus</p>
</TooltipContent>
</Tooltip>
</div>
);
},
meta: { title: "Aksi" },
},
];