dstpabuaran.com/resources/js/pages/admin/manage/stock-mutation/columns.tsx

179 lines
5.0 KiB
TypeScript

import type { ColumnDef } from '@tanstack/react-table';
import { ArrowDown, ArrowUp } from 'lucide-react';
export type StockMutation = {
id: number;
type: 'in' | 'out';
quantity: number;
formatted_quantity: string;
stock_before: number;
stock_after: number;
formatted_stock_before: string;
formatted_stock_after: string;
stock_quality: 'good' | 'reject' | 'retail';
description: string | null;
created_at: string;
formatted_created_at: string;
stockable: {
id: number;
name: string;
product: {
id: number;
name: string;
} | null;
} | null;
user: {
id: number;
username: string;
email: string;
user_profile?: {
full_name: string;
};
} | null;
};
function getQualityLabel(quality: string): string {
const labels: Record<string, string> = {
good: 'Bagus',
reject: 'Reject',
retail: 'Ecer',
};
return labels[quality] ?? quality;
}
function getQualityColor(quality: string): string {
const colors: Record<string, string> = {
good: 'bg-green-100 text-green-800',
reject: 'bg-red-100 text-red-800',
retail: 'bg-blue-100 text-blue-800',
};
return colors[quality] ?? 'bg-gray-100 text-gray-800';
}
export const columns: ColumnDef<StockMutation>[] = [
{
accessorKey: 'formatted_created_at',
header: () => <span>Tanggal</span>,
cell: ({ row }) => (
<span className="whitespace-nowrap">
{row.getValue('formatted_created_at') as string}
</span>
),
},
{
id: 'product',
header: () => <span>Produk</span>,
cell: ({ row }) => {
const stockable = row.original.stockable;
return (
<div className="flex flex-col">
<span className="font-medium">
{stockable?.product?.name ?? '-'}
</span>
<span className="text-xs text-muted-foreground">
{stockable?.name ?? '-'}
</span>
</div>
);
},
},
{
id: 'type',
header: () => <span>Tipe</span>,
cell: ({ row }) => {
const mutation = row.original;
const isIn = mutation.type === 'in';
return (
<span
className={`inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-xs font-medium ${
isIn
? 'bg-green-100 text-green-800'
: 'bg-red-100 text-red-800'
}`}
>
{isIn ? (
<ArrowUp className="h-3 w-3" />
) : (
<ArrowDown className="h-3 w-3" />
)}
{isIn ? 'Masuk' : 'Keluar'}
</span>
);
},
},
{
id: 'stock_quality',
header: () => <span>Kualitas</span>,
cell: ({ row }) => {
const quality = row.original.stock_quality;
return (
<span
className={`inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium ${getQualityColor(quality)}`}
>
{getQualityLabel(quality)}
</span>
);
},
},
{
id: 'quantity',
header: () => <span>Qty</span>,
cell: ({ row }) => {
const mutation = row.original;
const isPositive = mutation.quantity > 0;
return (
<span
className={
isPositive
? 'font-medium text-green-600'
: 'font-medium text-red-600'
}
>
{isPositive ? '+' : ''}
{mutation.formatted_quantity}
</span>
);
},
},
{
id: 'stock_change',
header: () => <span>Stok</span>,
cell: ({ row }) => {
const mutation = row.original;
return (
<span className="whitespace-nowrap text-muted-foreground">
{mutation.formatted_stock_before} {' '}
{mutation.formatted_stock_after}
</span>
);
},
},
{
accessorKey: 'description',
header: () => <span>Keterangan</span>,
cell: ({ row }) => (
<span className="block max-w-[220px]">
{(row.getValue('description') as string | null) ?? '-'}
</span>
),
},
{
id: 'user',
header: () => <span>Oleh</span>,
cell: ({ row }) => {
const user = row.original.user;
return (
<span>{user?.user_profile?.full_name ?? user?.username ?? '-'}</span>
);
},
},
];