diff --git a/resources/js/Components/Warehouse/TransferOrderDialog.tsx b/resources/js/Components/Warehouse/TransferOrderDialog.tsx deleted file mode 100644 index 51b48f7..0000000 --- a/resources/js/Components/Warehouse/TransferOrderDialog.tsx +++ /dev/null @@ -1,349 +0,0 @@ - -/** - * 撥補單對話框元件 - * 重構後:加入驗證邏輯模組化 - */ - -import { useState, useEffect } from "react"; -import { getCurrentDateTime } from "@/utils/format"; -import axios from "axios"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from "@/Components/ui/dialog"; -import { Label } from "@/Components/ui/label"; -import { Input } from "@/Components/ui/input"; -import { Button } from "@/Components/ui/button"; -import { SearchableSelect } from "@/Components/ui/searchable-select"; -import { Textarea } from "@/Components/ui/textarea"; -import { toast } from "sonner"; -import { Warehouse, TransferOrder, TransferOrderStatus } from "@/types/warehouse"; -import { validateTransferOrder, validateTransferQuantity } from "@/utils/validation"; -import { usePermission } from "@/hooks/usePermission"; - -export type { TransferOrder }; - -interface TransferOrderDialogProps { - open: boolean; - onOpenChange: (open: boolean) => void; - order: TransferOrder | null; - warehouses: Warehouse[]; - // inventories: WarehouseInventory[]; // 因從 API 獲取而移除 - onSave: (order: Omit) => void; -} - -interface AvailableProduct { - productId: string; - productName: string; - batchNumber: string; - availableQty: number; - unit: string; - expiryDate: string | null; - unitCost: number; // 新增 - totalValue: number; // 新增 -} - -export default function TransferOrderDialog({ - open, - onOpenChange, - order, - warehouses, - // inventories, - onSave, -}: TransferOrderDialogProps) { - const { can } = usePermission(); - const canViewCost = can('inventory.view_cost'); - - const [formData, setFormData] = useState({ - sourceWarehouseId: "", - targetWarehouseId: "", - productId: "", - productName: "", - batchNumber: "", - quantity: 0, - transferDate: getCurrentDateTime(), - status: "待處理" as TransferOrderStatus, - notes: "", - }); - - const [availableProducts, setAvailableProducts] = useState([]); - - // 當對話框開啟或訂單變更時,重置表單 - useEffect(() => { - if (order) { - setFormData({ - sourceWarehouseId: order.sourceWarehouseId, - targetWarehouseId: order.targetWarehouseId, - productId: order.productId, - productName: order.productName, - batchNumber: order.batchNumber, - quantity: order.quantity, - transferDate: order.transferDate, - status: order.status, - notes: order.notes || "", - }); - } else { - setFormData({ - sourceWarehouseId: "", - targetWarehouseId: "", - productId: "", - productName: "", - batchNumber: "", - quantity: 0, - transferDate: getCurrentDateTime(), - status: "待處理", - notes: "", - }); - } - }, [order, open]); - - // 當來源倉庫變更時,從 API 更新可用商品列表 - useEffect(() => { - if (formData.sourceWarehouseId) { - axios.get(route('api.warehouses.inventories', formData.sourceWarehouseId)) - .then(response => { - const mappedData = response.data.map((item: any) => ({ - productId: item.product_id, - productName: item.product_name, - batchNumber: item.batch_number, - availableQty: item.quantity, - unit: item.unit_name, - expiryDate: item.expiry_date, - unitCost: item.unit_cost, // 映射 - totalValue: item.total_value, // 映射 - })); - setAvailableProducts(mappedData); - }) - .catch(error => { - console.error("Failed to fetch inventories:", error); - toast.error("無法取得倉庫庫存資訊"); - setAvailableProducts([]); - }); - } else { - setAvailableProducts([]); - } - }, [formData.sourceWarehouseId]); - - const handleSubmit = () => { - // 基本驗證 - const validation = validateTransferOrder(formData); - if (!validation.isValid) { - toast.error(validation.error); - return; - } - - // 檢查可用數量 - const selectedProduct = availableProducts.find( - (p) => p.productId === formData.productId && p.batchNumber === formData.batchNumber - ); - - if (selectedProduct) { - const quantityValidation = validateTransferQuantity( - formData.quantity, - selectedProduct.availableQty - ); - if (!quantityValidation.isValid) { - toast.error(quantityValidation.error); - return; - } - } - - onSave({ - from_warehouse_id: formData.sourceWarehouseId, - to_warehouse_id: formData.targetWarehouseId, - product_id: formData.productId, - quantity: formData.quantity, - batch_number: formData.batchNumber, - notes: formData.notes, - instant_post: true, - } as any); - }; - - const handleProductChange = (productKey: string) => { - const [productId, batchNumber] = productKey.split("|||"); - const product = availableProducts.find( - (p) => p.productId === productId && p.batchNumber === batchNumber - ); - if (product) { - setFormData({ - ...formData, - productId: product.productId, - productName: product.productName, - batchNumber: product.batchNumber, - quantity: 0, - }); - } - }; - - const selectedProduct = availableProducts.find( - (p) => p.productId === formData.productId && p.batchNumber === formData.batchNumber - ); - - return ( - - - - {order ? "編輯撥補單" : "新增撥補單"} - 填寫撥補單資訊 - - -
- {/* 來源倉庫和目標倉庫 */} -
-
- - - setFormData({ - ...formData, - sourceWarehouseId: value, - productId: "", - productName: "", - batchNumber: "", - quantity: 0, - }) - } - disabled={!!order} - options={warehouses.map((warehouse) => ({ label: warehouse.name, value: warehouse.id }))} - placeholder="選擇來源倉庫" - searchPlaceholder="搜尋倉庫..." - /> -
- -
- - - setFormData({ ...formData, targetWarehouseId: value }) - } - disabled={!!order} - options={warehouses - .filter((w) => w.id !== formData.sourceWarehouseId) - .map((warehouse) => ({ label: warehouse.name, value: warehouse.id }))} - placeholder="選擇目標倉庫" - searchPlaceholder="搜尋倉庫..." - /> -
-
- - {/* 商品選擇 */} -
- - ({ - label: `${product.productName} | 批號: ${product.batchNumber || '-'} | 效期: ${product.expiryDate || '-'} (庫存: ${product.availableQty} ${product.unit})${canViewCost ? ` | 成本: $${product.unitCost?.toLocaleString()}` : ''}`, - value: `${product.productId}|||${product.batchNumber}`, - }))} - placeholder="選擇商品與批號" - searchPlaceholder="搜尋商品..." - emptyText={formData.sourceWarehouseId ? "該倉庫無可用庫存" : "請先選擇來源倉庫"} - /> -
- - {/* 數量和日期 */} -
-
- - - setFormData({ ...formData, quantity: Number(e.target.value) }) - } - /> -
- {selectedProduct && ( -

- 可用庫存: {selectedProduct.availableQty} {selectedProduct.unit} -

- )} -
-
- -
- - - setFormData({ ...formData, transferDate: e.target.value }) - } - /> -
-
- - {/* 狀態(僅編輯時顯示) */} - {order && ( -
- - - setFormData({ ...formData, status: value as TransferOrderStatus }) - } - options={[ - { label: "待處理", value: "待處理" }, - { label: "處理中", value: "處理中" }, - { label: "已完成", value: "已完成" }, - { label: "已取消", value: "已取消" }, - ]} - /> -
- )} - - {/* 備註 */} -
- -