리피터 컨테이너 기능 추가: ScreenDesigner 컴포넌트에 리피터 컨테이너 내부 드롭 처리 로직을 추가하여, 드롭 시 새로운 자식 컴포넌트를 생성하고 레이아웃을 업데이트합니다. 또한, TableListComponent에서 리피터 컨테이너와 집계 위젯 연동을 위한 커스텀 이벤트를 발생시켜 데이터 변경 사항을 처리할 수 있도록 개선하였습니다.

This commit is contained in:
kjs
2026-01-16 15:12:22 +09:00
parent 28f67cb0b6
commit 9d74baf60a
8 changed files with 1859 additions and 2 deletions

View File

@@ -2222,6 +2222,56 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
return;
}
}
// 🎯 리피터 컨테이너 내부 드롭 처리
const dropTarget = e.target as HTMLElement;
const repeatContainer = dropTarget.closest('[data-repeat-container="true"]');
if (repeatContainer) {
const containerId = repeatContainer.getAttribute("data-component-id");
if (containerId) {
console.log("리피터 컨테이너 내부 드롭 감지:", { containerId, component });
// 해당 리피터 컨테이너 찾기
const targetComponent = layout.components.find((c) => c.id === containerId);
if (targetComponent && (targetComponent as any).componentType === "repeat-container") {
const currentConfig = (targetComponent as any).componentConfig || {};
const currentChildren = currentConfig.children || [];
// 새 자식 컴포넌트 생성
const newChild = {
id: `slot_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
componentType: component.id || component.componentType || "text-display",
label: component.name || component.label || "새 컴포넌트",
fieldName: "",
position: { x: 0, y: currentChildren.length * 40 },
size: component.defaultSize || { width: 200, height: 32 },
componentConfig: component.defaultConfig || {},
};
// 컴포넌트 업데이트
const updatedComponent = {
...targetComponent,
componentConfig: {
...currentConfig,
children: [...currentChildren, newChild],
},
};
const newLayout = {
...layout,
components: layout.components.map((c) =>
c.id === containerId ? updatedComponent : c
),
};
setLayout(newLayout);
saveToHistory(newLayout);
console.log("리피터 컨테이너에 컴포넌트 추가 완료:", newChild);
return; // 리피터 컨테이너 처리 완료
}
}
}
const rect = canvasRef.current?.getBoundingClientRect();
if (!rect) return;
@@ -2562,6 +2612,52 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
const dropTarget = e.target as HTMLElement;
const formContainer = dropTarget.closest('[data-form-container="true"]');
// 🎯 리피터 컨테이너 내부에 컬럼 드롭 시 처리
const repeatContainer = dropTarget.closest('[data-repeat-container="true"]');
if (repeatContainer && type === "column" && column) {
const containerId = repeatContainer.getAttribute("data-component-id");
if (containerId) {
console.log("리피터 컨테이너 내부에 컬럼 드롭:", { containerId, column });
const targetComponent = layout.components.find((c) => c.id === containerId);
if (targetComponent && (targetComponent as any).componentType === "repeat-container") {
const currentConfig = (targetComponent as any).componentConfig || {};
const currentChildren = currentConfig.children || [];
// 새 자식 컴포넌트 생성 (컬럼 기반)
const newChild = {
id: `slot_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
componentType: column.widgetType || "text-display",
label: column.columnLabel || column.columnName,
fieldName: column.columnName,
position: { x: 0, y: currentChildren.length * 40 },
size: { width: 200, height: 32 },
componentConfig: {},
};
const updatedComponent = {
...targetComponent,
componentConfig: {
...currentConfig,
children: [...currentChildren, newChild],
},
};
const newLayout = {
...layout,
components: layout.components.map((c) =>
c.id === containerId ? updatedComponent : c
),
};
setLayout(newLayout);
saveToHistory(newLayout);
console.log("리피터 컨테이너에 컬럼 기반 컴포넌트 추가 완료:", newChild);
return;
}
}
}
const rect = canvasRef.current?.getBoundingClientRect();
if (!rect) return;
@@ -4687,9 +4783,10 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
e.preventDefault();
e.dataTransfer.dropEffect = "copy";
}}
onDrop={(e) => {
onDropCapture={(e) => {
// 캡처 단계에서 드롭 이벤트를 처리하여 자식 요소 드롭도 감지
e.preventDefault();
// console.log("🎯 캔버스 드롭 이벤트 발생");
console.log("🎯 캔버스 드롭 이벤트 (캡처), target:", (e.target as HTMLElement).tagName, (e.target as HTMLElement).getAttribute("data-repeat-container"));
handleDrop(e);
}}
>