feat(procurement): 統一採購單按鈕樣式與術語更名為「作廢」,並加強權限控管
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Successful in 1m28s
Koori-ERP-Deploy-System / deploy-production (push) Has been skipped

This commit is contained in:
2026-02-06 15:32:12 +08:00
parent 70f1709bd0
commit 6bfdd92347
11 changed files with 318 additions and 73 deletions

View File

@@ -46,6 +46,8 @@ export default function PermissionSelector({ groupedPermissions, selectedPermiss
'view_cost': '檢視成本',
'view_logs': '檢視日誌',
'activate': '啟用/停用',
'approve': '核准/退回',
'cancel': '取消',
};
const actionText = map[action] || action;
@@ -203,6 +205,11 @@ export default function PermissionSelector({ groupedPermissions, selectedPermiss
const totalCount = group.permissions.length;
const isAllSelected = selectedCount === totalCount;
// 將權限分為「基本操作」與「狀態/進階操作」
const statusActions = ['approve', 'cancel', 'complete', 'activate'];
const normalPermissions = group.permissions.filter(p => !statusActions.includes(p.name.split('.').pop() || ''));
const specialPermissions = group.permissions.filter(p => statusActions.includes(p.name.split('.').pop() || ''));
return (
<AccordionItem
key={group.key}
@@ -210,18 +217,11 @@ export default function PermissionSelector({ groupedPermissions, selectedPermiss
className="bg-white border rounded-lg px-2 data-[state=open]:bg-gray-50/50 last:border-b"
>
<div className="flex items-center w-full">
{/* Group Selection Checkbox - Moved outside trigger to avoid bubbling issues, positioned left */}
<div className="flex items-center pl-2 pr-1">
<Checkbox
id={`group-select-${group.key}`}
checked={isAllSelected}
onCheckedChange={() => {
// Stop propagation to prevent accordion from toggling
// This is implicitly handled by the checkbox being a sibling,
// but if it were a child of AccordionTrigger, stopPropagation would be needed.
// For clarity, we can add it here if needed, but the current structure makes it unnecessary.
toggleGroup(group.permissions);
}}
onCheckedChange={() => toggleGroup(group.permissions)}
className="data-[state=checked]:bg-primary-main"
/>
</div>
@@ -241,30 +241,47 @@ export default function PermissionSelector({ groupedPermissions, selectedPermiss
</AccordionTrigger>
</div>
<AccordionContent className="px-2 pb-4">
<div className="pl-10 space-y-3 pt-1">
{/* Permissions Grid */}
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-y-3 gap-x-4">
{group.permissions.map((permission) => (
<div key={permission.id} className="flex items-start space-x-3">
<Checkbox
id={permission.name}
checked={selectedPermissions.includes(permission.name)}
onCheckedChange={() => togglePermission(permission.name)}
/>
<div className="grid gap-1.5 leading-none">
<label
htmlFor={permission.name}
className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer text-gray-700 hover:text-primary-main transition-colors"
>
{translateAction(permission.name)}
</label>
<p className="text-[10px] text-gray-400 font-mono">
{permission.name}
</p>
</div>
<div className="pl-10 space-y-6 pt-1">
{/* 基本操作 */}
{normalPermissions.length > 0 && (
<div className="space-y-3">
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider">
</div>
))}
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-y-3 gap-x-4">
{normalPermissions.map((permission) => (
<PermissionItem
key={permission.id}
permission={permission}
selectedPermissions={selectedPermissions}
onToggle={togglePermission}
translate={translateAction}
/>
))}
</div>
</div>
)}
{/* 狀態操作/進階權限 */}
{specialPermissions.length > 0 && (
<div className="space-y-3 pt-2 border-t border-gray-100 italic">
<div className="text-xs font-semibold text-amber-600/70 uppercase tracking-wider flex items-center gap-1">
<span className="w-1 h-3 bg-amber-500 rounded-full" />
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-y-3 gap-x-4">
{specialPermissions.map((permission) => (
<PermissionItem
key={permission.id}
permission={permission}
selectedPermissions={selectedPermissions}
onToggle={togglePermission}
translate={translateAction}
/>
))}
</div>
</div>
)}
</div>
</AccordionContent>
</AccordionItem>
@@ -275,3 +292,26 @@ export default function PermissionSelector({ groupedPermissions, selectedPermiss
</div>
);
}
function PermissionItem({ permission, selectedPermissions, onToggle, translate }: any) {
return (
<div className="flex items-start space-x-3">
<Checkbox
id={permission.name}
checked={selectedPermissions.includes(permission.name)}
onCheckedChange={() => onToggle(permission.name)}
/>
<div className="grid gap-1.5 leading-none">
<label
htmlFor={permission.name}
className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer text-gray-700 hover:text-primary-main transition-colors"
>
{translate(permission.name)}
</label>
<p className="text-[10px] text-gray-400 font-mono">
{permission.name}
</p>
</div>
</div>
);
}