feat: 統一庫存管理分頁 UI 與寬度規範,並更新 SKILL 規範文件
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
|
||||
import { Head, useForm, router, Link } from '@inertiajs/react';
|
||||
import { usePermission } from '@/hooks/usePermission';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -71,7 +72,7 @@ export default function Index({ docs, warehouses, filters }: { docs: DocsPaginat
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||
const [searchQuery, setSearchQuery] = useState(filters.search || '');
|
||||
const [warehouseId, setWarehouseId] = useState(filters.warehouse_id || '');
|
||||
const [perPage, setPerPage] = useState(filters.per_page || '15');
|
||||
const [perPage, setPerPage] = useState(filters.per_page || '10');
|
||||
const [deleteId, setDeleteId] = useState<string | null>(null);
|
||||
|
||||
// For Count Doc Selection
|
||||
@@ -115,9 +116,12 @@ export default function Index({ docs, warehouses, filters }: { docs: DocsPaginat
|
||||
debouncedFilter({ search: searchQuery, warehouse_id: val, per_page: perPage });
|
||||
};
|
||||
|
||||
const handlePerPageChange = (val: string) => {
|
||||
setPerPage(val);
|
||||
debouncedFilter({ search: searchQuery, warehouse_id: warehouseId, per_page: val });
|
||||
const handlePerPageChange = (value: string) => {
|
||||
setPerPage(value);
|
||||
router.get(route('inventory.adjust.index'),
|
||||
{ ...filters, search: searchQuery, warehouse_id: warehouseId, per_page: value, page: 1 },
|
||||
{ preserveState: false, replace: true, preserveScroll: true }
|
||||
);
|
||||
};
|
||||
|
||||
const confirmDelete = (id: string, e: React.MouseEvent) => {
|
||||
@@ -134,6 +138,8 @@ export default function Index({ docs, warehouses, filters }: { docs: DocsPaginat
|
||||
}
|
||||
};
|
||||
|
||||
const { can } = usePermission();
|
||||
|
||||
const { data, setData, post, processing, reset } = useForm({
|
||||
count_doc_id: null as string | null,
|
||||
warehouse_id: '',
|
||||
@@ -229,7 +235,7 @@ export default function Index({ docs, warehouses, filters }: { docs: DocsPaginat
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="flex gap-2 w-full md:w-auto">
|
||||
<Can permission="inventory.adjust">
|
||||
<Can permission="inventory_adjust.create">
|
||||
<Button
|
||||
className="flex-1 md:flex-none button-filled-primary h-9"
|
||||
onClick={() => setIsDialogOpen(true)}
|
||||
@@ -286,30 +292,55 @@ export default function Index({ docs, warehouses, filters }: { docs: DocsPaginat
|
||||
<TableCell className="text-gray-500 text-sm">{doc.posted_at || '-'}</TableCell>
|
||||
<TableCell className="text-center">
|
||||
<div className="flex items-center justify-center gap-2" onClick={(e) => e.stopPropagation()}>
|
||||
<Link href={route('inventory.adjust.show', [doc.id])}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="button-outlined-primary"
|
||||
title={doc.status === 'posted' ? '查閱' : '編輯'}
|
||||
>
|
||||
{doc.status === 'posted' ? (
|
||||
<Eye className="w-4 h-4" />
|
||||
) : (
|
||||
<Pencil className="w-4 h-4" />
|
||||
)}
|
||||
</Button>
|
||||
</Link>
|
||||
{(() => {
|
||||
const isDraft = doc.status === 'draft';
|
||||
const canEdit = can('inventory_adjust.edit');
|
||||
const canView = can('inventory_adjust.view');
|
||||
|
||||
if (isDraft && canEdit) {
|
||||
return (
|
||||
<Link href={route('inventory.adjust.show', [doc.id])}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="button-outlined-primary"
|
||||
title="編輯"
|
||||
>
|
||||
<Pencil className="w-4 h-4 ml-0.5" />
|
||||
</Button>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
if (canView) {
|
||||
return (
|
||||
<Link href={route('inventory.adjust.show', [doc.id])}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="button-outlined-primary"
|
||||
title="查閱"
|
||||
>
|
||||
<Eye className="w-4 h-4 ml-0.5" />
|
||||
</Button>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})()}
|
||||
|
||||
{doc.status === 'draft' && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="button-outlined-error"
|
||||
title="刪除"
|
||||
onClick={(e) => confirmDelete(doc.id, e)}
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
</Button>
|
||||
<Can permission="inventory_adjust.delete">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="button-outlined-error"
|
||||
title="刪除"
|
||||
onClick={(e) => confirmDelete(doc.id, e)}
|
||||
>
|
||||
<Trash2 className="w-4 h-4 ml-0.5" />
|
||||
</Button>
|
||||
</Can>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
@@ -328,12 +359,12 @@ export default function Index({ docs, warehouses, filters }: { docs: DocsPaginat
|
||||
value={perPage}
|
||||
onValueChange={handlePerPageChange}
|
||||
options={[
|
||||
{ label: "15", value: "15" },
|
||||
{ label: "30", value: "30" },
|
||||
{ label: "10", value: "10" },
|
||||
{ label: "20", value: "20" },
|
||||
{ label: "50", value: "50" },
|
||||
{ label: "100", value: "100" }
|
||||
]}
|
||||
className="w-[100px] h-8"
|
||||
className="w-[90px] h-8"
|
||||
showSearch={false}
|
||||
/>
|
||||
<span>筆</span>
|
||||
|
||||
Reference in New Issue
Block a user