148 lines
5.8 KiB
TypeScript
148 lines
5.8 KiB
TypeScript
/**
|
|
* 生產工單完工入庫 - 選擇倉庫彈窗
|
|
*/
|
|
|
|
import React from 'react';
|
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/Components/ui/dialog";
|
|
import { Button } from "@/Components/ui/button";
|
|
import { SearchableSelect } from "@/Components/ui/searchable-select";
|
|
import { Input } from "@/Components/ui/input";
|
|
import { Label } from "@/Components/ui/label";
|
|
import { Warehouse as WarehouseIcon, Calendar as CalendarIcon, Tag, X, CheckCircle2 } from "lucide-react";
|
|
|
|
interface Warehouse {
|
|
id: number;
|
|
name: string;
|
|
}
|
|
|
|
interface WarehouseSelectionModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
onConfirm: (data: {
|
|
warehouseId: number;
|
|
batchNumber: string;
|
|
expiryDate: string;
|
|
}) => void;
|
|
warehouses: Warehouse[];
|
|
processing?: boolean;
|
|
// 新增商品資訊以利產生批號
|
|
productCode?: string;
|
|
productId?: number;
|
|
}
|
|
|
|
export default function WarehouseSelectionModal({
|
|
isOpen,
|
|
onClose,
|
|
onConfirm,
|
|
warehouses,
|
|
processing = false,
|
|
productCode,
|
|
productId,
|
|
}: WarehouseSelectionModalProps) {
|
|
const [selectedId, setSelectedId] = React.useState<number | null>(null);
|
|
const [batchNumber, setBatchNumber] = React.useState<string>("");
|
|
const [expiryDate, setExpiryDate] = React.useState<string>("");
|
|
|
|
// 當開啟時,嘗試產生成品批號 (若有資訊)
|
|
React.useEffect(() => {
|
|
if (isOpen && productCode && productId) {
|
|
const today = new Date().toISOString().split('T')[0].replace(/-/g, '');
|
|
const originCountry = 'TW';
|
|
|
|
// 先放一個預設值,實際序號由後端在儲存時再次確認或提供 API
|
|
fetch(`/api/warehouses/${selectedId || warehouses[0]?.id || 1}/inventory/batches/${productId}?originCountry=${originCountry}&arrivalDate=${new Date().toISOString().split('T')[0]}`)
|
|
.then(res => res.json())
|
|
.then(result => {
|
|
const seq = result.nextSequence || '01';
|
|
setBatchNumber(`${productCode}-${originCountry}-${today}-${seq}`);
|
|
})
|
|
.catch(() => {
|
|
setBatchNumber(`${productCode}-${originCountry}-${today}-01`);
|
|
});
|
|
}
|
|
}, [isOpen, productCode, productId]);
|
|
|
|
const handleConfirm = () => {
|
|
if (selectedId && batchNumber) {
|
|
onConfirm({
|
|
warehouseId: selectedId,
|
|
batchNumber,
|
|
expiryDate
|
|
});
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
|
<DialogContent className="sm:max-w-[425px]">
|
|
<DialogHeader>
|
|
<DialogTitle className="flex items-center gap-2 text-primary-main">
|
|
<WarehouseIcon className="h-5 w-5" />
|
|
選擇完工入庫倉庫
|
|
</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="py-6 space-y-6">
|
|
<div className="space-y-1">
|
|
<Label className="text-xs font-medium text-grey-2 flex items-center gap-1">
|
|
<WarehouseIcon className="h-3 w-3" />
|
|
完工入庫倉庫 *
|
|
</Label>
|
|
<SearchableSelect
|
|
options={warehouses.map(w => ({ value: w.id.toString(), label: w.name }))}
|
|
value={selectedId?.toString() || ""}
|
|
onValueChange={(val) => setSelectedId(parseInt(val))}
|
|
placeholder="請選擇倉庫..."
|
|
className="w-full"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-1">
|
|
<Label className="text-xs font-medium text-grey-2 flex items-center gap-1">
|
|
<Tag className="h-3 w-3" />
|
|
成品批號 *
|
|
</Label>
|
|
<Input
|
|
value={batchNumber}
|
|
onChange={(e) => setBatchNumber(e.target.value)}
|
|
placeholder="輸入成品批號"
|
|
className="h-9 font-mono"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-1">
|
|
<Label className="text-xs font-medium text-grey-2 flex items-center gap-1">
|
|
<CalendarIcon className="h-3 w-3" />
|
|
成品效期 (選填)
|
|
</Label>
|
|
<Input
|
|
type="date"
|
|
value={expiryDate}
|
|
onChange={(e) => setExpiryDate(e.target.value)}
|
|
className="h-9"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<DialogFooter>
|
|
<Button
|
|
variant="outline"
|
|
onClick={onClose}
|
|
disabled={processing}
|
|
className="gap-2 button-outlined-error"
|
|
>
|
|
<X className="h-4 w-4" />
|
|
取消
|
|
</Button>
|
|
<Button
|
|
onClick={handleConfirm}
|
|
disabled={!selectedId || !batchNumber || processing}
|
|
className="gap-2 button-filled-primary"
|
|
>
|
|
<CheckCircle2 className="h-4 w-4" />
|
|
{processing ? "處理中..." : "確認完工入庫"}
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|