2025-09-10 18:36:28 +09:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import React from "react";
|
|
|
|
|
import { LayoutComponent, ComponentData } from "@/types/screen";
|
|
|
|
|
import { LayoutRegistry } from "./LayoutRegistry";
|
2025-09-19 02:15:21 +09:00
|
|
|
import { filterDOMProps } from "@/lib/utils/domPropsFilter";
|
2025-09-10 18:36:28 +09:00
|
|
|
|
|
|
|
|
export interface DynamicLayoutRendererProps {
|
|
|
|
|
layout: LayoutComponent;
|
|
|
|
|
allComponents: ComponentData[];
|
|
|
|
|
isDesignMode?: boolean;
|
|
|
|
|
isSelected?: boolean;
|
|
|
|
|
onClick?: (e: React.MouseEvent) => void;
|
2025-09-11 16:21:00 +09:00
|
|
|
onZoneClick?: (zoneId: string) => void;
|
|
|
|
|
onComponentDrop?: (e: React.DragEvent, zoneId: string, layoutId: string) => void;
|
2025-09-10 18:36:28 +09:00
|
|
|
onDragStart?: (e: React.DragEvent) => void;
|
|
|
|
|
onDragEnd?: (e: React.DragEvent) => void;
|
2025-09-11 12:22:39 +09:00
|
|
|
onUpdateLayout?: (updatedLayout: LayoutComponent) => void; // 레이아웃 업데이트 콜백
|
2025-09-10 18:36:28 +09:00
|
|
|
className?: string;
|
|
|
|
|
style?: React.CSSProperties;
|
2025-09-11 16:21:00 +09:00
|
|
|
[key: string]: any; // 추가 props 허용
|
2025-09-10 18:36:28 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const DynamicLayoutRenderer: React.FC<DynamicLayoutRendererProps> = ({
|
|
|
|
|
layout,
|
|
|
|
|
allComponents,
|
|
|
|
|
isDesignMode = false,
|
|
|
|
|
isSelected = false,
|
|
|
|
|
onClick,
|
|
|
|
|
onZoneClick,
|
|
|
|
|
onComponentDrop,
|
|
|
|
|
onDragStart,
|
|
|
|
|
onDragEnd,
|
2025-09-11 12:22:39 +09:00
|
|
|
onUpdateLayout,
|
2025-09-10 18:36:28 +09:00
|
|
|
className,
|
|
|
|
|
style,
|
2025-09-11 12:22:39 +09:00
|
|
|
...restProps
|
2025-09-10 18:36:28 +09:00
|
|
|
}) => {
|
|
|
|
|
console.log("🎯 DynamicLayoutRenderer:", {
|
|
|
|
|
layoutId: layout.id,
|
|
|
|
|
layoutType: layout.layoutType,
|
|
|
|
|
zonesCount: layout.zones.length,
|
|
|
|
|
allComponentsCount: allComponents.length,
|
|
|
|
|
isDesignMode,
|
|
|
|
|
isSelected,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 레지스트리에서 레이아웃 정의 조회
|
|
|
|
|
const layoutDefinition = LayoutRegistry.getLayout(layout.layoutType);
|
|
|
|
|
|
|
|
|
|
if (!layoutDefinition) {
|
|
|
|
|
console.warn(`⚠️ 등록되지 않은 레이아웃 타입: ${layout.layoutType}`);
|
|
|
|
|
|
|
|
|
|
// 폴백 렌더링 - 기본 플레이스홀더
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className={`flex h-full w-full items-center justify-center rounded border-2 border-dashed border-gray-300 bg-gray-50 p-4 ${className || ""}`}
|
|
|
|
|
style={style}
|
|
|
|
|
onClick={onClick}
|
|
|
|
|
>
|
|
|
|
|
<div className="text-center">
|
|
|
|
|
<div className="mb-2 text-sm font-medium text-gray-600">{layout.label || `레이아웃 ${layout.id}`}</div>
|
|
|
|
|
<div className="text-xs text-gray-400">미구현 레이아웃: {layout.layoutType}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 레이아웃 컴포넌트 가져오기
|
|
|
|
|
const LayoutComponent = layoutDefinition.component;
|
|
|
|
|
|
|
|
|
|
// 레이아웃 렌더링 실행
|
|
|
|
|
try {
|
2025-09-19 02:15:21 +09:00
|
|
|
// DOM 안전한 props만 필터링
|
|
|
|
|
const safeProps = filterDOMProps(restProps);
|
|
|
|
|
|
2025-09-10 18:36:28 +09:00
|
|
|
return (
|
|
|
|
|
<LayoutComponent
|
|
|
|
|
layout={layout}
|
|
|
|
|
allComponents={allComponents}
|
|
|
|
|
isDesignMode={isDesignMode}
|
|
|
|
|
isSelected={isSelected}
|
|
|
|
|
onClick={onClick}
|
|
|
|
|
onZoneClick={onZoneClick}
|
2025-09-11 16:21:00 +09:00
|
|
|
// onComponentDrop 제거
|
2025-09-10 18:36:28 +09:00
|
|
|
onDragStart={onDragStart}
|
|
|
|
|
onDragEnd={onDragEnd}
|
2025-09-11 12:22:39 +09:00
|
|
|
onUpdateLayout={onUpdateLayout}
|
2025-09-10 18:36:28 +09:00
|
|
|
className={className}
|
|
|
|
|
style={style}
|
2025-09-19 02:15:21 +09:00
|
|
|
{...safeProps}
|
2025-09-10 18:36:28 +09:00
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(`❌ 레이아웃 렌더링 실패 (${layout.layoutType}):`, error);
|
|
|
|
|
|
|
|
|
|
// 오류 발생 시 폴백 렌더링
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className={`flex h-full w-full items-center justify-center rounded border-2 border-red-300 bg-red-50 p-4 ${className || ""}`}
|
|
|
|
|
style={style}
|
|
|
|
|
onClick={onClick}
|
|
|
|
|
>
|
|
|
|
|
<div className="text-center">
|
|
|
|
|
<div className="mb-2 text-sm font-medium text-red-600">레이아웃 렌더링 오류</div>
|
|
|
|
|
<div className="text-xs text-red-400">
|
|
|
|
|
{layout.layoutType}: {error instanceof Error ? error.message : "알 수 없는 오류"}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default DynamicLayoutRenderer;
|