first commit
This commit is contained in:
148
resources/js/Pages/Warehouse/SafetyStockSettings.tsx
Normal file
148
resources/js/Pages/Warehouse/SafetyStockSettings.tsx
Normal file
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* 安全庫存設定頁面
|
||||
* Last Updated: 2025-12-29
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { ArrowLeft, Plus } from "lucide-react";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
|
||||
import { Head, Link, router } from "@inertiajs/react";
|
||||
import { SafetyStockSetting, WarehouseInventory, Warehouse, Product } from "@/types/warehouse";
|
||||
import SafetyStockList from "@/Components/Warehouse/SafetyStock/SafetyStockList";
|
||||
import AddSafetyStockDialog from "@/Components/Warehouse/SafetyStock/AddSafetyStockDialog";
|
||||
import EditSafetyStockDialog from "@/Components/Warehouse/SafetyStock/EditSafetyStockDialog";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
warehouse: Warehouse;
|
||||
safetyStockSettings: SafetyStockSetting[];
|
||||
inventories: WarehouseInventory[];
|
||||
availableProducts: Product[];
|
||||
}
|
||||
|
||||
export default function SafetyStockPage({
|
||||
warehouse,
|
||||
safetyStockSettings: initialSettings = [],
|
||||
inventories = [],
|
||||
availableProducts = [],
|
||||
}: Props) {
|
||||
const [settings, setSettings] = useState<SafetyStockSetting[]>(initialSettings);
|
||||
const [showAddDialog, setShowAddDialog] = useState(false);
|
||||
const [editingSetting, setEditingSetting] = useState<SafetyStockSetting | null>(null);
|
||||
|
||||
|
||||
// 當 Props 更新時同步本地 State
|
||||
useEffect(() => {
|
||||
setSettings(initialSettings);
|
||||
}, [initialSettings]);
|
||||
|
||||
const handleAdd = (newSettings: SafetyStockSetting[]) => {
|
||||
router.post(route('warehouses.safety-stock.store', warehouse.id), {
|
||||
settings: newSettings.map(s => ({
|
||||
productId: s.productId,
|
||||
quantity: s.safetyStock
|
||||
})),
|
||||
}, {
|
||||
onSuccess: () => {
|
||||
setShowAddDialog(false);
|
||||
toast.success(`成功新增 ${newSettings.length} 項安全庫存設定`);
|
||||
},
|
||||
onError: (errors) => {
|
||||
const firstError = Object.values(errors)[0];
|
||||
toast.error(typeof firstError === 'string' ? firstError : "新增失敗");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleEdit = (updatedSetting: SafetyStockSetting) => {
|
||||
router.put(route('warehouses.safety-stock.update', [warehouse.id, updatedSetting.id]), {
|
||||
safetyStock: updatedSetting.safetyStock,
|
||||
}, {
|
||||
onSuccess: () => {
|
||||
setEditingSetting(null);
|
||||
toast.success(`成功更新 ${updatedSetting.productName} 的安全庫存`);
|
||||
},
|
||||
onError: (errors) => {
|
||||
const firstError = Object.values(errors)[0];
|
||||
toast.error(typeof firstError === 'string' ? firstError : "更新失敗");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleDelete = (id: string) => {
|
||||
router.delete(route('warehouses.safety-stock.destroy', [warehouse.id, id]), {
|
||||
onSuccess: () => {
|
||||
toast.success("已刪除安全庫存設定");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (!warehouse) {
|
||||
return <div className="p-8 text-center text-muted-foreground">正在載入倉庫資料...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout>
|
||||
<Head title={`安全庫存設定 - ${warehouse.name}`} />
|
||||
<div className="container mx-auto p-6 max-w-7xl">
|
||||
{/* 頁面標題與導航 */}
|
||||
<div className="mb-6">
|
||||
<Link href={route('warehouses.inventory.index', warehouse.id)}>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="gap-2 button-outlined-primary mb-6"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
返回庫存管理
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="mb-2">安全庫存設定 - {warehouse.name}</h1>
|
||||
<p className="text-gray-600 font-medium">
|
||||
設定商品的安全庫存量,當庫存低於安全值時將發出警告
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => setShowAddDialog(true)}
|
||||
className="button-filled-primary"
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
新增安全庫存
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 安全庫存列表 */}
|
||||
<SafetyStockList
|
||||
settings={settings}
|
||||
inventories={inventories}
|
||||
onEdit={setEditingSetting}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
|
||||
{/* 新增對話框 */}
|
||||
<AddSafetyStockDialog
|
||||
open={showAddDialog}
|
||||
onOpenChange={setShowAddDialog}
|
||||
warehouseId={warehouse.id}
|
||||
existingSettings={settings}
|
||||
availableProducts={availableProducts}
|
||||
onAdd={handleAdd}
|
||||
/>
|
||||
|
||||
{/* 編輯對話框 */}
|
||||
{editingSetting && (
|
||||
<EditSafetyStockDialog
|
||||
open={!!editingSetting}
|
||||
onOpenChange={(open) => !open && setEditingSetting(null)}
|
||||
setting={editingSetting}
|
||||
onSave={handleEdit}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</AuthenticatedLayout>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user