diff --git a/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx b/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx
index 88e844d3..ac9aac19 100644
--- a/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx
+++ b/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx
@@ -25,6 +25,7 @@ import {
import type { MaterialData } from "@/types/digitalTwin";
import { ExternalDbConnectionAPI } from "@/lib/api/externalDbConnection";
import HierarchyConfigPanel, { HierarchyConfig } from "./HierarchyConfigPanel";
+import { OBJECT_COLORS, DEFAULT_COLOR } from "./constants";
import { validateSpatialContainment, updateChildrenPositions, getAllDescendants } from "./spatialContainment";
// 백엔드 DB 객체 타입 (snake_case)
@@ -702,7 +703,7 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
name: objectName,
position: { x, y: yPosition, z },
size: defaults.size || { x: 5, y: 5, z: 5 },
- color: defaults.color || "#9ca3af",
+ color: OBJECT_COLORS[draggedTool] || DEFAULT_COLOR, // 타입별 기본 색상
areaKey,
locaKey,
locType,
@@ -1169,8 +1170,8 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
도구:
{[
{ type: "area" as ToolType, label: "영역", icon: Grid3x3, color: "text-blue-500" },
- { type: "location-bed" as ToolType, label: "베드", icon: Package, color: "text-emerald-500" },
- { type: "location-stp" as ToolType, label: "정차", icon: Move, color: "text-orange-500" },
+ { type: "location-bed" as ToolType, label: "베드", icon: Package, color: "text-blue-600" },
+ { type: "location-stp" as ToolType, label: "정차", icon: Move, color: "text-gray-500" },
// { type: "crane-gantry" as ToolType, label: "겐트리", icon: Combine, color: "text-green-500" },
{ type: "crane-mobile" as ToolType, label: "크레인", icon: Truck, color: "text-yellow-500" },
{ type: "rack" as ToolType, label: "랙", icon: Box, color: "text-purple-500" },
@@ -1221,54 +1222,6 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
- {/* 창고 테이블 및 컬럼 매핑 */}
- {selectedDbConnection && (
-
-
-
- {/* 이 레이아웃의 창고 선택 */}
- {hierarchyConfig?.warehouse?.tableName && hierarchyConfig?.warehouse?.keyColumn && (
-
-
- {loadingWarehouses ? (
-
-
-
- ) : (
-
- )}
-
- )}
-
- )}
-
{/* 계층 설정 패널 (신규) */}
{selectedDbConnection && (
)}
+ {/* 창고 선택 (HierarchyConfigPanel 아래로 이동) */}
+ {selectedDbConnection && hierarchyConfig?.warehouse?.tableName && hierarchyConfig?.warehouse?.keyColumn && (
+
+
+
+
+
+ {loadingWarehouses ? (
+
+
+
+ ) : (
+
+ )}
+
+
+ )}
+
{/* Area 목록 */}
{selectedDbConnection && selectedWarehouse && (
@@ -1605,7 +1605,7 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
handleObjectUpdate({ name: e.target.value })}
className="mt-1.5 h-9 text-sm"
/>
@@ -1622,7 +1622,7 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
handleObjectUpdate({
position: {
@@ -1641,7 +1641,7 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
handleObjectUpdate({
position: {
@@ -1669,7 +1669,7 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
type="number"
step="5"
min="5"
- value={selectedObject.size.x}
+ value={selectedObject.size?.x || 5}
onChange={(e) =>
handleObjectUpdate({
size: {
@@ -1688,7 +1688,7 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
handleObjectUpdate({
size: {
@@ -1709,7 +1709,7 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
type="number"
step="5"
min="5"
- value={selectedObject.size.z}
+ value={selectedObject.size?.z || 5}
onChange={(e) =>
handleObjectUpdate({
size: {
@@ -1732,7 +1732,7 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
handleObjectUpdate({ color: e.target.value })}
className="mt-1.5 h-9"
/>
diff --git a/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinViewer.tsx b/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinViewer.tsx
index 3945a692..94ef98fb 100644
--- a/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinViewer.tsx
+++ b/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinViewer.tsx
@@ -10,6 +10,7 @@ import dynamic from "next/dynamic";
import { useToast } from "@/hooks/use-toast";
import type { PlacedObject, MaterialData } from "@/types/digitalTwin";
import { getLayoutById, getMaterials } from "@/lib/api/digitalTwin";
+import { OBJECT_COLORS, DEFAULT_COLOR } from "./constants";
const Yard3DCanvas = dynamic(() => import("./Yard3DCanvas"), {
ssr: false,
@@ -81,7 +82,7 @@ export default function DigitalTwinViewer({ layoutId }: DigitalTwinViewerProps)
z: parseFloat(obj.size_z),
},
rotation: obj.rotation ? parseFloat(obj.rotation) : 0,
- color: getObjectColor(objectType), // 타입별 기본 색상 사용
+ color: getObjectColor(objectType, obj.color), // 저장된 색상 우선, 없으면 타입별 기본 색상
areaKey: obj.area_key,
locaKey: obj.loca_key,
locType: obj.loc_type,
@@ -225,17 +226,11 @@ export default function DigitalTwinViewer({ layoutId }: DigitalTwinViewerProps)
// 객체 타입별 기본 색상 (useMemo로 최적화)
const getObjectColor = useMemo(() => {
- return (type: string): string => {
- const colorMap: Record
= {
- area: "#3b82f6", // 파란색
- "location-bed": "#2563eb", // 진한 파란색
- "location-stp": "#6b7280", // 회색
- "location-temp": "#f59e0b", // 주황색
- "location-dest": "#10b981", // 초록색
- "crane-mobile": "#8b5cf6", // 보라색
- rack: "#ef4444", // 빨간색
- };
- return colorMap[type] || "#3b82f6";
+ return (type: string, savedColor?: string): string => {
+ // 저장된 색상이 있으면 우선 사용
+ if (savedColor) return savedColor;
+ // 없으면 타입별 기본 색상 사용
+ return OBJECT_COLORS[type] || DEFAULT_COLOR;
};
}, []);
@@ -383,7 +378,7 @@ export default function DigitalTwinViewer({ layoutId }: DigitalTwinViewerProps)
{typeLabel}
diff --git a/frontend/components/admin/dashboard/widgets/yard-3d/HierarchyConfigPanel.tsx b/frontend/components/admin/dashboard/widgets/yard-3d/HierarchyConfigPanel.tsx
index 8a6f4bfd..d309c92f 100644
--- a/frontend/components/admin/dashboard/widgets/yard-3d/HierarchyConfigPanel.tsx
+++ b/frontend/components/admin/dashboard/widgets/yard-3d/HierarchyConfigPanel.tsx
@@ -257,7 +257,7 @@ export default function HierarchyConfigPanel({
handleLevelChange(level.level, "name", e.target.value)}
className="h-7 w-32 text-xs"
placeholder="레벨명"
@@ -276,7 +276,7 @@ export default function HierarchyConfigPanel({