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

229 lines
7.4 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Trash2 } from "lucide-react";
interface YardPlacement {
id: number;
external_material_id: string;
material_code: string;
material_name: string;
quantity: number;
unit: string;
position_x: number;
position_y: number;
position_z: number;
size_x: number;
size_y: number;
size_z: number;
color: string;
memo?: string;
}
interface MaterialEditPanelProps {
placement: YardPlacement | null;
onClose: () => void;
onUpdate: (id: number, updates: Partial<YardPlacement>) => void;
onRemove: (id: number) => void;
}
export default function MaterialEditPanel({ placement, onClose, onUpdate, onRemove }: MaterialEditPanelProps) {
const [editData, setEditData] = useState<Partial<YardPlacement>>({});
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
// placement 변경 시 editData 초기화
useEffect(() => {
if (placement) {
setEditData({
size_x: placement.size_x,
size_y: placement.size_y,
size_z: placement.size_z,
color: placement.color,
memo: placement.memo,
});
}
}, [placement]);
if (!placement) return null;
// 변경사항 적용
const handleApply = () => {
onUpdate(placement.id, editData);
};
// 배치 해제
const handleRemove = () => {
onRemove(placement.id);
setIsDeleteDialogOpen(false);
};
return (
<div className="w-80 border-l bg-white p-4">
<div className="mb-4 flex items-center justify-between">
<h3 className="text-lg font-semibold"> </h3>
<Button variant="ghost" size="sm" onClick={onClose}>
</Button>
</div>
<div className="space-y-4">
{/* 읽기 전용 정보 */}
<div className="space-y-3 rounded-lg bg-gray-50 p-3">
<div className="text-xs font-medium text-gray-500"> ( )</div>
<div>
<div className="text-xs text-gray-600"> </div>
<div className="mt-1 text-sm font-medium">{placement.material_code}</div>
</div>
<div>
<div className="text-xs text-gray-600"> </div>
<div className="mt-1 text-sm font-medium">{placement.material_name}</div>
</div>
<div>
<div className="text-xs text-gray-600"></div>
<div className="mt-1 text-sm font-medium">
{placement.quantity} {placement.unit}
</div>
</div>
</div>
{/* 배치 정보 (편집 가능) */}
<div className="space-y-3">
<div className="text-xs font-medium text-gray-500"> ( )</div>
{/* 3D 크기 */}
<div>
<Label className="text-xs"></Label>
<div className="grid grid-cols-3 gap-2">
<div>
<Label htmlFor="edit-sizeX" className="text-xs text-gray-600">
</Label>
<Input
id="edit-sizeX"
type="number"
value={editData.size_x ?? placement.size_x}
onChange={(e) => setEditData({ ...editData, size_x: parseFloat(e.target.value) || 1 })}
min="1"
step="1"
className="h-8 text-xs"
/>
</div>
<div>
<Label htmlFor="edit-sizeY" className="text-xs text-gray-600">
</Label>
<Input
id="edit-sizeY"
type="number"
value={editData.size_y ?? placement.size_y}
onChange={(e) => setEditData({ ...editData, size_y: parseFloat(e.target.value) || 1 })}
min="1"
step="1"
className="h-8 text-xs"
/>
</div>
<div>
<Label htmlFor="edit-sizeZ" className="text-xs text-gray-600">
</Label>
<Input
id="edit-sizeZ"
type="number"
value={editData.size_z ?? placement.size_z}
onChange={(e) => setEditData({ ...editData, size_z: parseFloat(e.target.value) || 1 })}
min="1"
step="1"
className="h-8 text-xs"
/>
</div>
</div>
</div>
{/* 색상 */}
<div>
<Label htmlFor="edit-color" className="text-xs">
</Label>
<div className="mt-1 flex items-center gap-2">
<input
id="edit-color"
type="color"
value={editData.color ?? placement.color}
onChange={(e) => setEditData({ ...editData, color: e.target.value })}
className="h-8 w-16 cursor-pointer rounded border"
/>
<Input
value={editData.color ?? placement.color}
onChange={(e) => setEditData({ ...editData, color: e.target.value })}
className="h-8 flex-1 text-xs"
/>
</div>
</div>
{/* 메모 */}
<div>
<Label htmlFor="edit-memo" className="text-xs">
</Label>
<Textarea
id="edit-memo"
value={editData.memo ?? placement.memo ?? ""}
onChange={(e) => setEditData({ ...editData, memo: e.target.value })}
placeholder="메모를 입력하세요"
rows={3}
className="text-xs"
/>
</div>
{/* 적용 버튼 */}
<Button onClick={handleApply} className="w-full" size="sm">
</Button>
</div>
{/* 배치 해제 */}
<div className="border-t pt-4">
<Button variant="destructive" onClick={() => setIsDeleteDialogOpen(true)} className="w-full" size="sm">
<Trash2 className="mr-2 h-4 w-4" />
</Button>
</div>
</div>
{/* 삭제 확인 모달 */}
<AlertDialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle> </AlertDialogTitle>
<AlertDialogDescription>
?
<br />
&quot;{placement.material_name}&quot; ({placement.quantity} {placement.unit})
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel></AlertDialogCancel>
<AlertDialogAction onClick={handleRemove} className="bg-red-600 hover:bg-red-700">
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
);
}