From 119afcaf42fffc520bfea4c8ab7555b805e65ea4 Mon Sep 17 00:00:00 2001 From: dohyeons Date: Tue, 25 Nov 2025 09:35:47 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B0=B0=EC=B9=98=EB=90=9C=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EB=AA=A9=EB=A1=9D=20=EA=B3=84=EC=B8=B5=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=B0=8F=20=EC=95=84=EC=BD=94=EB=94=94=EC=96=B8=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/yard-3d/DigitalTwinEditor.tsx | 134 +++++++++++++++--- 1 file changed, 112 insertions(+), 22 deletions(-) diff --git a/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx b/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx index 47902b42..b08d4fc1 100644 --- a/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx +++ b/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx @@ -1575,33 +1575,123 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi )} - {/* 배치된 객체 목록 */} -
+ {/* 배치된 객체 목록 (계층 구조) */} +

배치된 객체 ({placedObjects.length})

{placedObjects.length === 0 ? (
상단 도구를 드래그하여 배치하세요
) : ( -
- {placedObjects.map((obj) => ( -
handleObjectClick(obj.id)} - className={`cursor-pointer rounded-lg border p-3 transition-all ${ - selectedObject?.id === obj.id ? "border-primary bg-primary/10" : "hover:border-primary/50" - }`} - > -
- {obj.name} -
-
-

- 위치: ({obj.position.x.toFixed(1)}, {obj.position.z.toFixed(1)}) -

- {obj.areaKey &&

Area: {obj.areaKey}

} -
- ))} -
+ + {/* Area별로 그룹핑 */} + {(() => { + // Area 객체들 + const areaObjects = placedObjects.filter((obj) => obj.type === "area"); + + // Area가 없으면 기존 방식으로 표시 + if (areaObjects.length === 0) { + return ( +
+ {placedObjects.map((obj) => ( +
handleObjectClick(obj.id)} + className={`cursor-pointer rounded-lg border p-3 transition-all ${ + selectedObject?.id === obj.id + ? "border-primary bg-primary/10" + : "hover:border-primary/50" + }`} + > +
+ {obj.name} +
+
+

+ 위치: ({obj.position.x.toFixed(1)}, {obj.position.z.toFixed(1)}) +

+
+ ))} +
+ ); + } + + // Area별로 Location들을 그룹핑 + return areaObjects.map((areaObj) => { + // 이 Area의 자식 Location들 찾기 + const childLocations = placedObjects.filter( + (obj) => + obj.type !== "area" && + obj.areaKey === areaObj.areaKey && + (obj.parentId === areaObj.id || obj.externalKey === areaObj.externalKey), + ); + + return ( + + +
{ + e.stopPropagation(); + handleObjectClick(areaObj.id); + }} + > +
+ + {areaObj.name} +
+
+ ({childLocations.length}) +
+
+
+ + + {childLocations.length === 0 ? ( +

+ Location이 없습니다 +

+ ) : ( +
+ {childLocations.map((locationObj) => ( +
handleObjectClick(locationObj.id)} + className={`cursor-pointer rounded-lg border p-2 transition-all ${ + selectedObject?.id === locationObj.id + ? "border-primary bg-primary/10" + : "hover:border-primary/50" + }`} + > +
+
+ + {locationObj.name} +
+
+
+

+ 위치: ({locationObj.position.x.toFixed(1)}, {locationObj.position.z.toFixed(1)}) +

+ {locationObj.locaKey && ( +

+ Key: {locationObj.locaKey} +

+ )} +
+ ))} +
+ )} + + + ); + }); + })()} + )}