115 lines
4.2 KiB
TypeScript
115 lines
4.2 KiB
TypeScript
import { Link } from '@inertiajs/react';
|
|
import type { ColumnDef } from '@tanstack/react-table';
|
|
import { format } from 'date-fns';
|
|
import { id } from 'date-fns/locale';
|
|
import { Pencil, Trash2 } from 'lucide-react';
|
|
import { DataTableColumnHeader } from '@/components/data-table-column-header';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
|
import purchaseRoutes from '@/routes/purchase';
|
|
import type { Purchase } from '@/types';
|
|
|
|
interface ColumnProps {
|
|
onDelete: (purchase: Purchase) => void;
|
|
}
|
|
|
|
export const getColumns = ({ onDelete }: ColumnProps): ColumnDef<Purchase>[] => [
|
|
{
|
|
accessorKey: "purchase_date",
|
|
header: ({ column }) => (
|
|
<DataTableColumnHeader column={column} title="Tanggal" />
|
|
),
|
|
cell: ({ row }) => {
|
|
const date = row.original.purchase_date;
|
|
|
|
return format(new Date(date), 'dd MMMM yyyy', { locale: id });
|
|
},
|
|
meta: { title: "Tanggal" },
|
|
},
|
|
{
|
|
accessorKey: "items",
|
|
header: ({ column }) => (
|
|
<DataTableColumnHeader column={column} title="Item" />
|
|
),
|
|
cell: ({ row }) => {
|
|
const purchase = row.original;
|
|
const items = purchase.items;
|
|
|
|
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
return <span className="text-muted-foreground text-xs italic">-</span>;
|
|
}
|
|
|
|
return (
|
|
<div className="flex flex-col gap-1">
|
|
{items.map((item, i) => (
|
|
<div key={i} className="text-xs whitespace-nowrap">
|
|
<span className="text-muted-foreground">{item.product?.name || 'Produk N/A'}:</span>{' '}
|
|
<span className="font-medium text-primary">{item.quantity} x {item.unit_price_formatted}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
},
|
|
meta: { title: "Item" },
|
|
},
|
|
{
|
|
accessorKey: "total",
|
|
header: ({ column }) => (
|
|
<DataTableColumnHeader column={column} title="Total" />
|
|
),
|
|
cell: ({ row }) => {
|
|
return (
|
|
<span className="font-bold text-primary">
|
|
{row.original.total_formatted}
|
|
</span>
|
|
);
|
|
},
|
|
meta: { title: "Total" },
|
|
},
|
|
{
|
|
accessorKey: "note",
|
|
header: "Catatan",
|
|
cell: ({ row }) => (
|
|
<span className="text-muted-foreground text-sm truncate max-w-[200px] block">
|
|
{row.original.note || '-'}
|
|
</span>
|
|
),
|
|
meta: { title: "Catatan" },
|
|
},
|
|
{
|
|
id: "actions",
|
|
header: "Aksi",
|
|
cell: ({ row }) => {
|
|
const purchase = row.original;
|
|
|
|
return (
|
|
<div className="flex items-center gap-2">
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<Link href={purchaseRoutes.edit(purchase.id).url}>
|
|
<Button variant="ghost" size="icon" className='text-yellow-600 hover:text-yellow-700 hover:bg-yellow-50 dark:hover:bg-yellow-950/20'>
|
|
<Pencil className="size-4" />
|
|
</Button>
|
|
</Link>
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<p>Ubah</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<Button variant="ghost" size="icon" className='text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-950/20' onClick={() => onDelete(purchase)}>
|
|
<Trash2 className="size-4" />
|
|
</Button>
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<p>Hapus</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
);
|
|
},
|
|
meta: { title: "Aksi" },
|
|
},
|
|
];
|