ERP-node/frontend/components/admin/dashboard/widgets/yard-3d/MaterialAddModal.tsx

255 lines
7.6 KiB
TypeScript

"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Loader2 } from "lucide-react";
interface TempMaterial {
id: number;
material_code: string;
material_name: string;
category: string;
unit: string;
default_color: string;
description: string;
}
interface MaterialAddModalProps {
isOpen: boolean;
material: TempMaterial | null;
onClose: () => void;
onAdd: (placementData: any) => Promise<void>;
}
export default function MaterialAddModal({ isOpen, material, onClose, onAdd }: MaterialAddModalProps) {
const [quantity, setQuantity] = useState("1");
const [positionX, setPositionX] = useState("0");
const [positionY, setPositionY] = useState("0");
const [positionZ, setPositionZ] = useState("0");
const [sizeX, setSizeX] = useState("5");
const [sizeY, setSizeY] = useState("5");
const [sizeZ, setSizeZ] = useState("5");
const [color, setColor] = useState("");
const [isAdding, setIsAdding] = useState(false);
// 모달이 열릴 때 기본값 설정
const handleOpen = (open: boolean) => {
if (open && material) {
setColor(material.default_color);
setQuantity("1");
setPositionX("0");
setPositionY("0");
setPositionZ("0");
setSizeX("5");
setSizeY("5");
setSizeZ("5");
}
};
// 자재 추가
const handleAdd = async () => {
if (!material) return;
setIsAdding(true);
try {
await onAdd({
external_material_id: `TEMP-${Date.now()}`,
material_code: material.material_code,
material_name: material.material_name,
quantity: parseInt(quantity) || 1,
unit: material.unit,
position_x: parseFloat(positionX) || 0,
position_y: parseFloat(positionY) || 0,
position_z: parseFloat(positionZ) || 0,
size_x: parseFloat(sizeX) || 5,
size_y: parseFloat(sizeY) || 5,
size_z: parseFloat(sizeZ) || 5,
color: color || material.default_color,
});
onClose();
} catch (error) {
console.error("자재 추가 실패:", error);
} finally {
setIsAdding(false);
}
};
if (!material) return null;
return (
<Dialog
open={isOpen}
onOpenChange={(open) => {
handleOpen(open);
if (!open) onClose();
}}
>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle> </DialogTitle>
</DialogHeader>
<div className="space-y-4">
{/* 자재 정보 */}
<div className="rounded-lg bg-muted p-4">
<div className="mb-2 text-sm font-medium text-foreground"> </div>
<div className="flex items-center gap-4">
<div className="h-10 w-10 rounded border" style={{ backgroundColor: material.default_color }} />
<div>
<div className="font-medium">{material.material_name}</div>
<div className="text-sm text-foreground">{material.material_code}</div>
</div>
</div>
</div>
{/* 수량 */}
<div className="space-y-2">
<Label htmlFor="quantity"></Label>
<div className="flex items-center gap-2">
<Input
id="quantity"
type="number"
value={quantity}
onChange={(e) => setQuantity(e.target.value)}
min="1"
className="flex-1"
/>
<span className="text-sm text-foreground">{material.unit}</span>
</div>
</div>
{/* 3D 위치 */}
<div className="space-y-2">
<Label>3D </Label>
<div className="grid grid-cols-3 gap-2">
<div>
<Label htmlFor="posX" className="text-xs text-foreground">
X ()
</Label>
<Input
id="posX"
type="number"
value={positionX}
onChange={(e) => setPositionX(e.target.value)}
step="0.5"
/>
</div>
<div>
<Label htmlFor="posY" className="text-xs text-foreground">
Y ()
</Label>
<Input
id="posY"
type="number"
value={positionY}
onChange={(e) => setPositionY(e.target.value)}
step="0.5"
/>
</div>
<div>
<Label htmlFor="posZ" className="text-xs text-foreground">
Z ()
</Label>
<Input
id="posZ"
type="number"
value={positionZ}
onChange={(e) => setPositionZ(e.target.value)}
step="0.5"
/>
</div>
</div>
</div>
{/* 3D 크기 */}
<div className="space-y-2">
<Label>3D </Label>
<div className="grid grid-cols-3 gap-2">
<div>
<Label htmlFor="sizeX" className="text-xs text-foreground">
</Label>
<Input
id="sizeX"
type="number"
value={sizeX}
onChange={(e) => setSizeX(e.target.value)}
min="1"
step="0.5"
/>
</div>
<div>
<Label htmlFor="sizeY" className="text-xs text-foreground">
</Label>
<Input
id="sizeY"
type="number"
value={sizeY}
onChange={(e) => setSizeY(e.target.value)}
min="1"
step="0.5"
/>
</div>
<div>
<Label htmlFor="sizeZ" className="text-xs text-foreground">
</Label>
<Input
id="sizeZ"
type="number"
value={sizeZ}
onChange={(e) => setSizeZ(e.target.value)}
min="1"
step="0.5"
/>
</div>
</div>
</div>
{/* 색상 */}
<div className="space-y-2">
<Label htmlFor="color"></Label>
<div className="flex items-center gap-2">
<input
id="color"
type="color"
value={color}
onChange={(e) => setColor(e.target.value)}
className="h-10 w-20 cursor-pointer rounded border"
/>
<Input value={color} onChange={(e) => setColor(e.target.value)} className="flex-1" />
</div>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={onClose} disabled={isAdding}>
</Button>
<Button onClick={handleAdd} disabled={isAdding}>
{isAdding ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
...
</>
) : (
"배치"
)}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}