feat(warehouse): 合併撥補單至調撥單流程並移除舊組件

This commit is contained in:
2026-02-02 10:07:36 +08:00
parent 313b95ceb9
commit 1748eb007e
2 changed files with 88 additions and 371 deletions

View File

@@ -1,10 +1,20 @@
import { useState } from "react";
import { Plus, Warehouse as WarehouseIcon } from 'lucide-react';
import { SearchableSelect } from "@/Components/ui/searchable-select";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogFooter,
DialogDescription,
} from "@/Components/ui/dialog";
import { Label } from "@/Components/ui/label";
import { Loader2, Plus, Warehouse as WarehouseIcon } from 'lucide-react';
import { Card, CardContent } from "@/Components/ui/card";
import { Button } from "@/Components/ui/button";
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
import { Head, router } from "@inertiajs/react";
import WarehouseDialog from "@/Components/Warehouse/WarehouseDialog";
import TransferOrderDialog from "@/Components/Warehouse/TransferOrderDialog";
import SearchToolbar from "@/Components/shared/SearchToolbar";
import WarehouseCard from "@/Components/Warehouse/WarehouseCard";
import WarehouseEmptyState from "@/Components/Warehouse/WarehouseEmptyState";
@@ -13,7 +23,6 @@ import Pagination from "@/Components/shared/Pagination";
import { toast } from "sonner";
import { getBreadcrumbs } from "@/utils/breadcrumb";
import { Can } from "@/Components/Permission/Can";
import { Card, CardContent } from "@/Components/ui/card";
interface PageProps {
warehouses: {
@@ -39,7 +48,12 @@ export default function WarehouseIndex({ warehouses, totals, filters }: PageProp
// 對話框狀態
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [editingWarehouse, setEditingWarehouse] = useState<Warehouse | null>(null);
const [transferOrderDialogOpen, setTransferOrderDialogOpen] = useState(false);
// 調撥單單建立狀態
const [isTransferCreateOpen, setIsTransferCreateOpen] = useState(false);
const [sourceWarehouseId, setSourceWarehouseId] = useState("");
const [targetWarehouseId, setTargetWarehouseId] = useState("");
const [creating, setCreating] = useState(false);
// 搜尋處理
const handleSearch = (term: string) => {
@@ -93,18 +107,33 @@ export default function WarehouseIndex({ warehouses, totals, filters }: PageProp
};
const handleAddTransferOrder = () => {
setTransferOrderDialogOpen(true);
setIsTransferCreateOpen(true);
};
const handleSaveTransferOrder = (data: any) => {
router.post(route('inventory.transfer.store'), data, {
const handleCreateTransferOrder = () => {
if (!sourceWarehouseId) {
toast.error("請選擇來源倉庫");
return;
}
if (!targetWarehouseId) {
toast.error("請選擇目的倉庫");
return;
}
if (sourceWarehouseId === targetWarehouseId) {
toast.error("來源與目的倉庫不能相同");
return;
}
setCreating(true);
router.post(route('inventory.transfer.store'), {
from_warehouse_id: sourceWarehouseId,
to_warehouse_id: targetWarehouseId
}, {
onFinish: () => setCreating(false),
onSuccess: () => {
toast.success('撥補單已建立且庫存已轉移');
setTransferOrderDialogOpen(false);
},
onError: (errors) => {
toast.error('建立撥補單失敗');
console.error(errors);
setIsTransferCreateOpen(false);
setSourceWarehouseId("");
setTargetWarehouseId("");
toast.success('調撥單已建立');
}
});
};
@@ -170,7 +199,7 @@ export default function WarehouseIndex({ warehouses, totals, filters }: PageProp
className="flex-1 md:flex-initial button-outlined-primary"
>
<Plus className="mr-2 h-4 w-4" />
調
</Button>
</Can>
<Can permission="warehouses.create">
@@ -222,14 +251,51 @@ export default function WarehouseIndex({ warehouses, totals, filters }: PageProp
onDelete={handleDeleteWarehouse}
/>
{/* 撥補單對話框 */}
<TransferOrderDialog
open={transferOrderDialogOpen}
onOpenChange={setTransferOrderDialogOpen}
order={null}
onSave={handleSaveTransferOrder}
warehouses={warehouses.data}
/>
{/* 調撥單建立對話框 */}
<Dialog open={isTransferCreateOpen} onOpenChange={setIsTransferCreateOpen}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>調</DialogTitle>
<DialogDescription>
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="space-y-2">
<Label></Label>
<SearchableSelect
value={sourceWarehouseId}
onValueChange={setSourceWarehouseId}
options={warehouses.data.map((w: any) => ({ label: w.name, value: w.id.toString() }))}
placeholder="請選擇來源倉庫"
className="h-9"
/>
</div>
<div className="space-y-2">
<Label></Label>
<SearchableSelect
value={targetWarehouseId}
onValueChange={setTargetWarehouseId}
options={warehouses.data
.filter((w: any) => w.id.toString() !== sourceWarehouseId)
.map((w: any) => ({ label: w.name, value: w.id.toString() }))
}
placeholder="請選擇目的倉庫"
className="h-9"
/>
</div>
</div>
<DialogFooter>
<Button type="button" variant="outline" className="button-outlined-primary" onClick={() => setIsTransferCreateOpen(false)}>
</Button>
<Button onClick={handleCreateTransferOrder} className="button-filled-primary" disabled={creating || !sourceWarehouseId || !targetWarehouseId}>
{creating && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
</AuthenticatedLayout>
);