일단 야드관리 3d 드래그앤 드랍까지
This commit is contained in:
@@ -0,0 +1,247 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, 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-gray-50 p-4">
|
||||
<div className="mb-2 text-sm font-medium text-gray-600">선택한 자재</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-gray-600">{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-gray-600">{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-gray-600">
|
||||
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-gray-600">
|
||||
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-gray-600">
|
||||
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-gray-600">
|
||||
너비
|
||||
</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-gray-600">
|
||||
높이
|
||||
</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-gray-600">
|
||||
깊이
|
||||
</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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user