Files
star-erp/resources/js/Components/Warehouse/Inventory/InventoryImportDialog.tsx

204 lines
9.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React from "react";
import { useForm } from "@inertiajs/react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/Components/ui/dialog";
import { Button } from "@/Components/ui/button";
import { Input } from "@/Components/ui/input";
import { Label } from "@/Components/ui/label";
import { Download, FileUp, Loader2, AlertCircle, FileSpreadsheet, Info } from "lucide-react";
import { toast } from "sonner";
import { Alert, AlertDescription } from "@/Components/ui/alert";
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/Components/ui/accordion";
interface Props {
open: boolean;
onOpenChange: (open: boolean) => void;
warehouseId: string;
}
export default function InventoryImportDialog({ open, onOpenChange, warehouseId }: Props) {
const { data, setData, post, processing, errors, reset, clearErrors } = useForm({
file: null as File | null,
inboundDate: new Date().toISOString().split('T')[0],
notes: "Excel 匯入",
});
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
post(route("warehouses.inventory.import", warehouseId), {
forceFormData: true,
onSuccess: () => {
toast.success("庫存匯入完成");
onOpenChange(false);
reset();
},
onError: (err) => {
console.error("Import error:", err);
toast.error("匯入失敗,請檢查檔案格式");
}
});
};
const handleDownloadTemplate = () => {
window.location.href = route("warehouses.inventory.template");
};
return (
<Dialog open={open} onOpenChange={(val) => {
onOpenChange(val);
if (!val) {
reset();
clearErrors();
}
}}>
<DialogContent className="sm:max-w-[550px]">
<DialogHeader>
<DialogTitle></DialogTitle>
<DialogDescription>
</DialogDescription>
</DialogHeader>
<form onSubmit={handleSubmit} className="space-y-6">
{/* 步驟 1: 下載範本 */}
<div className="space-y-2 p-4 bg-gray-50 rounded-lg border border-gray-100">
<Label className="font-medium flex items-center gap-2">
<FileSpreadsheet className="w-4 h-4 text-green-600" />
1
</Label>
<div className="text-sm text-gray-500 mb-2">
</div>
<Button
type="button"
variant="outline"
size="sm"
onClick={handleDownloadTemplate}
className="w-full sm:w-auto button-outlined-primary"
>
<Download className="w-4 h-4 mr-2" />
(.xlsx)
</Button>
</div>
{/* 步驟 2: 設定資訊 */}
<div className="space-y-2">
<Label className="font-medium flex items-center gap-2">
<Info className="w-4 h-4 text-primary-main" />
2
</Label>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="inboundDate" className="text-sm text-gray-700 flex items-center gap-1.5 align-middle">
<span className="text-red-500">*</span>
</Label>
<Input
id="inboundDate"
type="date"
value={data.inboundDate}
onChange={e => setData('inboundDate', e.target.value)}
required
className="cursor-pointer"
/>
</div>
<div className="space-y-2">
<Label htmlFor="notes" className="text-sm text-gray-700 flex items-center gap-1.5">
</Label>
<Input
id="notes"
placeholder="選填備註"
value={data.notes}
onChange={e => setData('notes', e.target.value)}
/>
</div>
</div>
</div>
{/* 步驟 3: 上傳檔案 */}
<div className="space-y-2">
<Label className="font-medium flex items-center gap-2">
<FileUp className="w-4 h-4 text-blue-600" />
3
</Label>
<div className="grid w-full max-w-sm items-center gap-1.5">
<Input
id="file"
type="file"
accept=".xlsx,.xls,.csv"
onChange={e => setData('file', e.target.files ? e.target.files[0] : null)}
required
className="cursor-pointer"
/>
</div>
{errors.file && (
<Alert variant="destructive" className="mt-2">
<AlertCircle className="h-4 w-4" />
<AlertDescription className="whitespace-pre-wrap">
{errors.file}
</AlertDescription>
</Alert>
)}
</div>
{/* 欄位說明 */}
<Accordion type="single" collapsible className="w-full border rounded-lg px-2">
<AccordionItem value="rules" className="border-b-0">
<AccordionTrigger className="text-sm text-gray-500 hover:no-underline py-3">
<div className="flex items-center gap-2">
<Info className="h-4 w-4" />
</div>
</AccordionTrigger>
<AccordionContent>
<div className="text-sm text-gray-600 space-y-2 pb-2 pl-6">
<ul className="list-disc space-y-1">
<li><span className="font-medium text-gray-700"></span>使</li>
<li><span className="font-medium text-gray-700"></span> Excel <span className="underline"></span></li>
<li><span className="font-medium text-gray-700"></span>2026/12/31</li>
<li><span className="font-medium text-gray-700"></span>使</li>
</ul>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
<DialogFooter>
<Button
type="button"
variant="outline"
onClick={() => onOpenChange(false)}
disabled={processing}
className="button-outlined-primary"
>
</Button>
<Button
type="submit"
disabled={processing || !data.file}
className="button-filled-primary"
>
{processing ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
...
</>
) : (
"開始匯入"
)}
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
);
}