feat: refactor column definitions to conditionally include action buttons based on user permissions

This commit is contained in:
Yoga Pangestu 2026-08-06 22:48:00 +07:00
parent 5ec0e9ff3b
commit 9bbb00c69f
20 changed files with 423 additions and 331 deletions

View File

@ -20,7 +20,7 @@ export function createCashAccountColumns(
): ColumnDef<CashAccount>[] { ): ColumnDef<CashAccount>[] {
const { handleEdit, handleDeleteClick, can } = params; const { handleEdit, handleDeleteClick, can } = params;
return [ const columns: ColumnDef<CashAccount>[] = [
{ {
accessorKey: 'name', accessorKey: 'name',
header: () => <span>Nama</span>, header: () => <span>Nama</span>,
@ -39,7 +39,10 @@ export function createCashAccountColumns(
</span> </span>
), ),
}, },
{ ];
if (can('cash.update') || can('cash.delete')) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -70,6 +73,8 @@ export function createCashAccountColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }

View File

@ -47,7 +47,7 @@ export function createTransactionColumns(
): ColumnDef<CashTransaction>[] { ): ColumnDef<CashTransaction>[] {
const { handleEdit, handleDeleteClick, can } = params; const { handleEdit, handleDeleteClick, can } = params;
return [ const columns: ColumnDef<CashTransaction>[] = [
{ {
accessorKey: 'formatted_created_at', accessorKey: 'formatted_created_at',
header: () => <span>Tanggal</span>, header: () => <span>Tanggal</span>,
@ -136,7 +136,10 @@ export function createTransactionColumns(
return <span>{createdBy?.user_profile?.full_name ?? '-'}</span>; return <span>{createdBy?.user_profile?.full_name ?? '-'}</span>;
}, },
}, },
{ ];
if (can('cash.update') || can('cash.delete')) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -174,6 +177,8 @@ export function createTransactionColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }

View File

@ -91,7 +91,7 @@ export function createEmployeeAdvanceColumns(
const { handleEdit, handleDeleteClick, handleApprove, handlePay, handleShowPayments, can, authUserId } = const { handleEdit, handleDeleteClick, handleApprove, handlePay, handleShowPayments, can, authUserId } =
params; params;
return [ const columns: ColumnDef<EmployeeAdvance>[] = [
{ {
accessorKey: 'formatted_created_at', accessorKey: 'formatted_created_at',
header: () => <span>Tanggal</span>, header: () => <span>Tanggal</span>,
@ -162,7 +162,16 @@ export function createEmployeeAdvanceColumns(
<span>{getStatusBadge(row.getValue('status') as string)}</span> <span>{getStatusBadge(row.getValue('status') as string)}</span>
), ),
}, },
{ ];
if (
can('employee_advances.verify') ||
can('employee_advances.pay') ||
can('employee_advances.view_payments') ||
can('employee_advances.update') ||
can('employee_advances.delete')
) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -226,6 +235,8 @@ export function createEmployeeAdvanceColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }

View File

@ -30,7 +30,7 @@ export function createExpenseColumns(
): ColumnDef<Expense>[] { ): ColumnDef<Expense>[] {
const { handleEdit, handleDeleteClick, can } = params; const { handleEdit, handleDeleteClick, can } = params;
return [ const columns: ColumnDef<Expense>[] = [
{ {
accessorKey: 'formatted_created_at', accessorKey: 'formatted_created_at',
header: () => <span>Tanggal</span>, header: () => <span>Tanggal</span>,
@ -83,7 +83,10 @@ export function createExpenseColumns(
return <span>{createdBy?.user_profile?.full_name ?? '-'}</span>; return <span>{createdBy?.user_profile?.full_name ?? '-'}</span>;
}, },
}, },
{ ];
if (can('expenses.update') || can('expenses.delete')) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -114,6 +117,8 @@ export function createExpenseColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }

View File

@ -174,58 +174,57 @@ export function createPayrollPeriodColumns(
}); });
} }
columns.push( columns.push({
{ accessorKey: 'status',
accessorKey: 'status', header: () => <span>Status</span>,
header: () => <span>Status</span>, cell: ({ row }) => (
cell: ({ row }) => ( <span>{getStatusBadge(row.getValue('status') as string)}</span>
<span>{getStatusBadge(row.getValue('status') as string)}</span> ),
), });
},
{
id: 'actions',
header: () => <span className="block text-center">Aksi</span>,
meta: {
className: 'w-[100px] text-center',
headerClassName: 'w-[100px] text-center',
},
cell: ({ row }) => {
const period = row.original;
return ( columns.push({
<RowActions id: 'actions',
actions={[ header: () => <span className="block text-center">Aksi</span>,
{ meta: {
label: 'Lihat Detail', className: 'w-[100px] text-center',
icon: <Eye className="h-4 w-4" />, headerClassName: 'w-[100px] text-center',
href: showUrl(period.id),
},
{
label: 'Tutup Periode',
icon: (
<Lock className="h-4 w-4 text-orange-600" />
),
show:
can('payroll.adjust') &&
period.status === 'open',
onClick: () => handleClose(period),
},
{
label: 'Buka Periode',
icon: (
<Unlock className="h-4 w-4 text-blue-600" />
),
show:
can('payroll.adjust') &&
period.status === 'closed',
onClick: () => handleReopen(period),
},
]}
/>
);
},
}, },
); cell: ({ row }) => {
const period = row.original;
return (
<RowActions
actions={[
{
label: 'Lihat Detail',
icon: <Eye className="h-4 w-4" />,
href: showUrl(period.id),
},
{
label: 'Tutup Periode',
icon: (
<Lock className="h-4 w-4 text-orange-600" />
),
show:
can('payroll.adjust') &&
period.status === 'open',
onClick: () => handleClose(period),
},
{
label: 'Buka Periode',
icon: (
<Unlock className="h-4 w-4 text-blue-600" />
),
show:
can('payroll.adjust') &&
period.status === 'closed',
onClick: () => handleReopen(period),
},
]}
/>
);
},
});
return columns; return columns;
} }

View File

@ -54,7 +54,7 @@ export function createEmployeeColumns(
canViewAll, canViewAll,
} = params; } = params;
return [ const columns: ColumnDef<Employee>[] = [
{ {
accessorKey: 'user_profile.full_name', accessorKey: 'user_profile.full_name',
id: 'full_name', id: 'full_name',
@ -154,7 +154,14 @@ export function createEmployeeColumns(
); );
}, },
}, },
{ ];
if (
can('employees.update') ||
can('employees.reset_password') ||
can('employees.delete')
) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -193,6 +200,8 @@ export function createEmployeeColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }

View File

@ -64,7 +64,7 @@ export function createLeaveRequestColumns(
const { handleEdit, handleDeleteClick, handleApprove, handleReject, can } = const { handleEdit, handleDeleteClick, handleApprove, handleReject, can } =
params; params;
return [ const columns: ColumnDef<LeaveRequest>[] = [
{ {
id: 'employee_name', id: 'employee_name',
header: () => <span>Oleh</span>, header: () => <span>Oleh</span>,
@ -112,7 +112,14 @@ export function createLeaveRequestColumns(
<span>{getStatusBadge(row.getValue('status') as string)}</span> <span>{getStatusBadge(row.getValue('status') as string)}</span>
), ),
}, },
{ ];
if (
can('leave_requests.verify') ||
can('leave_requests.update') ||
can('leave_requests.delete')
) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -167,6 +174,8 @@ export function createLeaveRequestColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }

View File

@ -139,25 +139,27 @@ export function CuttingCardRow({
)} )}
</div> </div>
<RowActions {(can('cuttings.update') || can('cuttings.delete')) && (
actions={[ <RowActions
{ actions={[
label: 'Edit', {
icon: <Pencil className="h-4 w-4" />, label: 'Edit',
show: can('cuttings.update'), icon: <Pencil className="h-4 w-4" />,
onClick: () => onEdit(cutting), show: can('cuttings.update'),
}, onClick: () => onEdit(cutting),
{ },
label: 'Hapus', {
icon: ( label: 'Hapus',
<Trash2 className="h-4 w-4 text-destructive" /> icon: (
), <Trash2 className="h-4 w-4 text-destructive" />
show: can('cuttings.delete'), ),
onClick: () => onDelete(cutting), show: can('cuttings.delete'),
}, onClick: () => onDelete(cutting),
]} },
wrapperClassName="flex shrink-0 items-center gap-1" ]}
/> wrapperClassName="flex shrink-0 items-center gap-1"
/>
)}
</div> </div>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -126,25 +126,27 @@ export function PurchaseCardRow({
)} )}
</div> </div>
<RowActions {(can('purchases.update') || can('purchases.delete')) && (
actions={[ <RowActions
{ actions={[
label: 'Edit', {
icon: <Pencil className="h-4 w-4" />, label: 'Edit',
show: can('purchases.update'), icon: <Pencil className="h-4 w-4" />,
onClick: () => onEdit(purchase), show: can('purchases.update'),
}, onClick: () => onEdit(purchase),
{ },
label: 'Hapus', {
icon: ( label: 'Hapus',
<Trash2 className="h-4 w-4 text-destructive" /> icon: (
), <Trash2 className="h-4 w-4 text-destructive" />
show: can('purchases.delete'), ),
onClick: () => onDelete(purchase), show: can('purchases.delete'),
}, onClick: () => onDelete(purchase),
]} },
wrapperClassName="flex shrink-0 items-center gap-1" ]}
/> wrapperClassName="flex shrink-0 items-center gap-1"
/>
)}
</div> </div>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -135,25 +135,27 @@ export function RestockCardRow({
</div> </div>
</div> </div>
<RowActions {(can('restocks.update') || can('restocks.delete')) && (
actions={[ <RowActions
{ actions={[
label: 'Edit', {
icon: <Pencil className="h-4 w-4" />, label: 'Edit',
show: can('restocks.update'), icon: <Pencil className="h-4 w-4" />,
onClick: () => onEdit(restock), show: can('restocks.update'),
}, onClick: () => onEdit(restock),
{ },
label: 'Hapus', {
icon: ( label: 'Hapus',
<Trash2 className="h-4 w-4 text-destructive" /> icon: (
), <Trash2 className="h-4 w-4 text-destructive" />
show: can('restocks.delete'), ),
onClick: () => onDelete(restock), show: can('restocks.delete'),
}, onClick: () => onDelete(restock),
]} },
wrapperClassName="flex shrink-0 items-center gap-1" ]}
/> wrapperClassName="flex shrink-0 items-center gap-1"
/>
)}
</div> </div>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -183,57 +183,59 @@ export function TransactionCardRow({
</div> </div>
</div> </div>
<RowActions {(can('orders.update') || can('orders.delete')) && (
actions={[ <RowActions
...(transaction.status === 'pending' && can('orders.update') actions={[
? [ ...(transaction.status === 'pending' && can('orders.update')
{ ? [
label: 'Kirim', {
icon: <Send className="h-4 w-4" />, label: 'Kirim',
onClick: () => onUpdateStatus(transaction, 'processing'), icon: <Send className="h-4 w-4" />,
}, onClick: () => onUpdateStatus(transaction, 'processing'),
] },
: []), ]
...((transaction.status === 'pending' || transaction.status === 'processing') && can('orders.update') : []),
? [ ...((transaction.status === 'pending' || transaction.status === 'processing') && can('orders.update')
{ ? [
label: 'Selesai', {
icon: <CheckCircle className="h-4 w-4" />, label: 'Selesai',
onClick: () => onUpdateStatus(transaction, 'completed'), icon: <CheckCircle className="h-4 w-4" />,
}, onClick: () => onUpdateStatus(transaction, 'completed'),
{ },
label: 'Dibatalkan', {
icon: <XCircle className="h-4 w-4 text-destructive" />, label: 'Dibatalkan',
onClick: () => onUpdateStatus(transaction, 'cancelled'), icon: <XCircle className="h-4 w-4 text-destructive" />,
}, onClick: () => onUpdateStatus(transaction, 'cancelled'),
] },
: []), ]
...(transaction.status === 'completed' && can('orders.update') : []),
? [ ...(transaction.status === 'completed' && can('orders.update')
{ ? [
label: 'Refund', {
icon: <XCircle className="h-4 w-4 text-destructive" />, label: 'Refund',
onClick: () => onUpdateStatus(transaction, 'refunded'), icon: <XCircle className="h-4 w-4 text-destructive" />,
}, onClick: () => onUpdateStatus(transaction, 'refunded'),
] },
: []), ]
{ : []),
label: 'Edit', {
icon: <Pencil className="h-4 w-4" />, label: 'Edit',
show: can('orders.update'), icon: <Pencil className="h-4 w-4" />,
onClick: () => onEdit(transaction), show: can('orders.update'),
}, onClick: () => onEdit(transaction),
{ },
label: 'Hapus', {
icon: ( label: 'Hapus',
<Trash2 className="h-4 w-4 text-destructive" /> icon: (
), <Trash2 className="h-4 w-4 text-destructive" />
show: can('orders.delete'), ),
onClick: () => onDelete(transaction), show: can('orders.delete'),
}, onClick: () => onDelete(transaction),
]} },
wrapperClassName="flex shrink-0 items-center gap-1" ]}
/> wrapperClassName="flex shrink-0 items-center gap-1"
/>
)}
</div> </div>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -18,7 +18,7 @@ export function createCategoryColumns(
): ColumnDef<Category>[] { ): ColumnDef<Category>[] {
const { handleEdit, handleDeleteClick, can } = params; const { handleEdit, handleDeleteClick, can } = params;
return [ const columns: ColumnDef<Category>[] = [
{ {
accessorKey: 'name', accessorKey: 'name',
header: () => <span>Nama</span>, header: () => <span>Nama</span>,
@ -28,7 +28,10 @@ export function createCategoryColumns(
</span> </span>
), ),
}, },
{ ];
if (can('categories.update') || can('categories.delete')) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -59,6 +62,8 @@ export function createCategoryColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }

View File

@ -20,7 +20,7 @@ export function createCustomerColumns(
): ColumnDef<Customer>[] { ): ColumnDef<Customer>[] {
const { handleEdit, handleDeleteClick, can } = params; const { handleEdit, handleDeleteClick, can } = params;
return [ const columns: ColumnDef<Customer>[] = [
{ {
accessorKey: 'name', accessorKey: 'name',
header: () => <span>Nama</span>, header: () => <span>Nama</span>,
@ -46,7 +46,10 @@ export function createCustomerColumns(
</span> </span>
), ),
}, },
{ ];
if (can('customers.update') || can('customers.delete')) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -77,6 +80,8 @@ export function createCustomerColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }

View File

@ -90,7 +90,7 @@ export function createProductColumns(
can, can,
} = params; } = params;
return [ const columns: ColumnDef<Product>[] = [
{ {
id: 'expand', id: 'expand',
header: '', header: '',
@ -338,7 +338,10 @@ export function createProductColumns(
); );
}, },
}, },
{ ];
if (can('products.update') || can('products.delete')) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -369,6 +372,8 @@ export function createProductColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }

View File

@ -144,25 +144,27 @@ export function ProductCardRow({
</div> </div>
</div> </div>
<RowActions {(can('products.update') || can('products.delete')) && (
actions={[ <RowActions
{ actions={[
label: 'Edit', {
icon: <Pencil className="h-4 w-4" />, label: 'Edit',
show: can('products.update'), icon: <Pencil className="h-4 w-4" />,
onClick: () => onEdit(product), show: can('products.update'),
}, onClick: () => onEdit(product),
{ },
label: 'Hapus', {
icon: ( label: 'Hapus',
<Trash2 className="h-4 w-4 text-destructive" /> icon: (
), <Trash2 className="h-4 w-4 text-destructive" />
show: can('products.delete'), ),
onClick: () => onDelete(product), show: can('products.delete'),
}, onClick: () => onDelete(product),
]} },
wrapperClassName="flex shrink-0 items-center gap-1" ]}
/> wrapperClassName="flex shrink-0 items-center gap-1"
/>
)}
</div> </div>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -34,6 +34,8 @@ export function VariantSubRow({
variant: ProductVariant; variant: ProductVariant;
} | null>(null); } | null>(null);
const canAnyAction = can('products.transfer_stock') || can('products.view_stock_mutations') || can('products.update') || can('products.delete');
return ( return (
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<Table> <Table>
@ -52,16 +54,18 @@ export function VariantSubRow({
</TableHead> </TableHead>
<TableHead className="text-center">Stok Ecer</TableHead> <TableHead className="text-center">Stok Ecer</TableHead>
<TableHead>Harga</TableHead> <TableHead>Harga</TableHead>
<TableHead className="w-[120px] text-center"> {canAnyAction && (
Aksi <TableHead className="w-[120px] text-center">
</TableHead> Aksi
</TableHead>
)}
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{variants.length === 0 ? ( {variants.length === 0 ? (
<TableRow> <TableRow>
<TableCell <TableCell
colSpan={8} colSpan={canAnyAction ? 8 : 7}
className="text-center text-muted-foreground" className="text-center text-muted-foreground"
> >
Tidak ada varian. Tidak ada varian.
@ -116,63 +120,65 @@ export function VariantSubRow({
'-' '-'
)} )}
</TableCell> </TableCell>
<TableCell> {canAnyAction && (
<RowActions <TableCell>
actions={[ <RowActions
{ actions={[
label: 'Transfer Stok', {
icon: ( label: 'Transfer Stok',
<ArrowRightLeft className="h-4 w-4" /> icon: (
), <ArrowRightLeft className="h-4 w-4" />
show: can('products.transfer_stock'), ),
onClick: () => show: can('products.transfer_stock'),
setTransferVariant({ onClick: () =>
product, setTransferVariant({
variant, product,
}), variant,
},
{
label: 'Mutasi Stok',
icon: (
<ScrollText className="h-4 w-4" />
),
show: can('products.view_stock_mutations'),
onClick: () => {
router.visit(
stockMutations.url({
product: product.id,
variant: variant.id,
}), }),
);
}, },
}, {
{ label: 'Mutasi Stok',
label: 'Edit', icon: (
icon: ( <ScrollText className="h-4 w-4" />
<Pencil className="h-4 w-4" />
),
show: can('products.update'),
onClick: () =>
onEditVariant(
product,
variant,
), ),
}, show: can('products.view_stock_mutations'),
{ onClick: () => {
label: 'Hapus', router.visit(
icon: ( stockMutations.url({
<Trash2 className="h-4 w-4 text-destructive" /> product: product.id,
), variant: variant.id,
show: can('products.delete'), }),
onClick: () => );
onDeleteVariantClick( },
product, },
variant, {
label: 'Edit',
icon: (
<Pencil className="h-4 w-4" />
), ),
}, show: can('products.update'),
]} onClick: () =>
/> onEditVariant(
</TableCell> product,
variant,
),
},
{
label: 'Hapus',
icon: (
<Trash2 className="h-4 w-4 text-destructive" />
),
show: can('products.delete'),
onClick: () =>
onDeleteVariantClick(
product,
variant,
),
},
]}
/>
</TableCell>
)}
</TableRow> </TableRow>
)) ))
)} )}

View File

@ -94,25 +94,27 @@ export function RawMaterialCardRow({
</div> </div>
</div> </div>
<RowActions {(can('raw_materials.update') || can('raw_materials.delete')) && (
actions={[ <RowActions
{ actions={[
label: 'Edit', {
icon: <Pencil className="h-4 w-4" />, label: 'Edit',
show: can('raw_materials.update'), icon: <Pencil className="h-4 w-4" />,
onClick: () => onEdit(rawMaterial), show: can('raw_materials.update'),
}, onClick: () => onEdit(rawMaterial),
{ },
label: 'Hapus', {
icon: ( label: 'Hapus',
<Trash2 className="h-4 w-4 text-destructive" /> icon: (
), <Trash2 className="h-4 w-4 text-destructive" />
show: can('raw_materials.delete'), ),
onClick: () => onDelete(rawMaterial), show: can('raw_materials.delete'),
}, onClick: () => onDelete(rawMaterial),
]} },
wrapperClassName="flex shrink-0 items-center gap-1" ]}
/> wrapperClassName="flex shrink-0 items-center gap-1"
/>
)}
</div> </div>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -47,6 +47,8 @@ export function RawMaterialVariantSubRow({
); );
} }
const canAnyAction = can('raw_materials.update') || can('raw_materials.delete');
return ( return (
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<Table> <Table>
@ -59,16 +61,18 @@ export function RawMaterialVariantSubRow({
<TableHead>Nama Varian</TableHead> <TableHead>Nama Varian</TableHead>
<TableHead>Harga</TableHead> <TableHead>Harga</TableHead>
<TableHead className="text-center">Stok</TableHead> <TableHead className="text-center">Stok</TableHead>
<TableHead className="w-[100px] text-center"> {canAnyAction && (
Aksi <TableHead className="w-[100px] text-center">
</TableHead> Aksi
</TableHead>
)}
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{variants.length === 0 ? ( {variants.length === 0 ? (
<TableRow> <TableRow>
<TableCell <TableCell
colSpan={6} colSpan={canAnyAction ? 6 : 5}
className="text-center text-muted-foreground" className="text-center text-muted-foreground"
> >
Tidak ada varian. Tidak ada varian.
@ -101,37 +105,39 @@ export function RawMaterialVariantSubRow({
<TableCell className="text-center"> <TableCell className="text-center">
{formatNumber(variant.stock)} {formatNumber(variant.stock)}
</TableCell> </TableCell>
<TableCell> {canAnyAction && (
<RowActions <TableCell>
actions={[ <RowActions
{ actions={[
label: 'Edit', {
icon: ( label: 'Edit',
<Pencil className="h-4 w-4" /> icon: (
), <Pencil className="h-4 w-4" />
show: can('raw_materials.update'), ),
onClick: () => { show: can('raw_materials.update'),
router.visit( onClick: () => {
variantEdit.url({ router.visit(
rawMaterial: variantEdit.url({
rawMaterial.id, rawMaterial:
variant: variant.id, rawMaterial.id,
}), variant: variant.id,
); }),
);
},
}, },
}, {
{ label: 'Hapus',
label: 'Hapus', icon: (
icon: ( <Trash2 className="h-4 w-4 text-destructive" />
<Trash2 className="h-4 w-4 text-destructive" /> ),
), show: can('raw_materials.delete'),
show: can('raw_materials.delete'), onClick: () =>
onClick: () => setDeletingVariant(variant),
setDeletingVariant(variant), },
}, ]}
]} />
/> </TableCell>
</TableCell> )}
</TableRow> </TableRow>
)) ))
)} )}

View File

@ -20,7 +20,7 @@ export function createSupplierColumns(
): ColumnDef<Supplier>[] { ): ColumnDef<Supplier>[] {
const { handleEdit, handleDeleteClick, can } = params; const { handleEdit, handleDeleteClick, can } = params;
return [ const columns: ColumnDef<Supplier>[] = [
{ {
accessorKey: 'name', accessorKey: 'name',
header: () => <span>Nama</span>, header: () => <span>Nama</span>,
@ -46,7 +46,10 @@ export function createSupplierColumns(
</span> </span>
), ),
}, },
{ ];
if (can('suppliers.update') || can('suppliers.delete')) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -77,6 +80,8 @@ export function createSupplierColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }

View File

@ -19,7 +19,7 @@ export function createRoleColumns(
): ColumnDef<Role>[] { ): ColumnDef<Role>[] {
const { handleEdit, handleDeleteClick, can } = params; const { handleEdit, handleDeleteClick, can } = params;
return [ const columns: ColumnDef<Role>[] = [
{ {
accessorKey: 'name', accessorKey: 'name',
header: () => <span>Nama Role</span>, header: () => <span>Nama Role</span>,
@ -44,7 +44,10 @@ export function createRoleColumns(
</span> </span>
), ),
}, },
{ ];
if (can('roles.update') || can('roles.delete')) {
columns.push({
id: 'actions', id: 'actions',
header: () => <span className="block text-center">Aksi</span>, header: () => <span className="block text-center">Aksi</span>,
meta: { meta: {
@ -75,6 +78,8 @@ export function createRoleColumns(
/> />
); );
}, },
}, });
]; }
return columns;
} }