feat: 統一庫存管理分頁 UI 與寬度規範,並更新 SKILL 規範文件

This commit is contained in:
2026-02-03 17:24:34 +08:00
parent 15aaa039e4
commit bd999c7bb6
17 changed files with 357 additions and 205 deletions

View File

@@ -1,6 +1,7 @@
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import { Head, Link, useForm, router } from '@inertiajs/react';
import { Head, Link, useForm, router, usePage } from '@inertiajs/react';
import { useState, useCallback, useEffect } from 'react';
import { usePermission } from '@/hooks/usePermission';
import { debounce } from "lodash";
import { SearchableSelect } from "@/Components/ui/searchable-select";
import {
@@ -54,6 +55,8 @@ export default function Index({ auth, docs, warehouses, filters }: any) {
remarks: '',
});
const { can } = usePermission();
const [searchTerm, setSearchTerm] = useState(filters.search || "");
const [warehouseFilter, setWarehouseFilter] = useState(filters.warehouse_id || "all");
const [perPage, setPerPage] = useState(filters.per_page || "10");
@@ -207,7 +210,7 @@ export default function Index({ auth, docs, warehouses, filters }: any) {
{/* Action Buttons */}
<div className="flex gap-2 w-full md:w-auto">
<Can permission="inventory.view">
<Can permission="inventory_count.create">
<Dialog open={isCreateDialogOpen} onOpenChange={setIsCreateDialogOpen}>
<DialogTrigger asChild>
<Button className="flex-1 md:flex-none button-filled-primary">
@@ -302,22 +305,46 @@ export default function Index({ auth, docs, warehouses, filters }: any) {
<TableCell className="text-sm">{doc.created_by}</TableCell>
<TableCell className="text-center">
<div className="flex items-center justify-center gap-2">
<Can permission="inventory.view">
<Link href={route('inventory.count.show', [doc.id])}>
<Button
variant="outline"
size="sm"
className="button-outlined-primary"
title={['completed', 'adjusted'].includes(doc.status) ? '查閱' : '盤點'}
>
{['completed', 'adjusted'].includes(doc.status) ? (
<Eye className="w-4 h-4 ml-0.5" />
) : (
<Pencil className="w-4 h-4 ml-0.5" />
)}
</Button>
</Link>
{!['completed', 'adjusted'].includes(doc.status) && (
{/* Action Button Logic: Prefer Edit if allowed and status is active, otherwise fallback to View if allowed */}
{(() => {
const isEditable = !['completed', 'adjusted'].includes(doc.status);
const canEdit = can('inventory_count.edit');
const canView = can('inventory_count.view');
if (isEditable && canEdit) {
return (
<Link href={route('inventory.count.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.count.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;
})()}
{!['completed', 'adjusted'].includes(doc.status) && (
<Can permission="inventory_count.delete">
<Button
variant="outline"
size="sm"
@@ -327,8 +354,8 @@ export default function Index({ auth, docs, warehouses, filters }: any) {
>
<Trash2 className="w-4 h-4 ml-0.5" />
</Button>
)}
</Can>
</Can>
)}
</div>
</TableCell>
</TableRow>
@@ -351,7 +378,7 @@ export default function Index({ auth, docs, warehouses, filters }: any) {
{ label: "50", value: "50" },
{ label: "100", value: "100" }
]}
className="w-[100px] h-8"
className="w-[90px] h-8"
showSearch={false}
/>
<span></span>