/** * 컴포넌트 ID로 해당 컴포넌트의 ConfigPanel을 동적으로 로드하는 유틸리티 */ import React from "react"; // 컴포넌트별 ConfigPanel 동적 import 맵 const CONFIG_PANEL_MAP: Record Promise> = { "text-input": () => import("@/lib/registry/components/text-input/TextInputConfigPanel"), "number-input": () => import("@/lib/registry/components/number-input/NumberInputConfigPanel"), "date-input": () => import("@/lib/registry/components/date-input/DateInputConfigPanel"), "textarea-basic": () => import("@/lib/registry/components/textarea-basic/TextareaBasicConfigPanel"), "select-basic": () => import("@/lib/registry/components/select-basic/SelectBasicConfigPanel"), "checkbox-basic": () => import("@/lib/registry/components/checkbox-basic/CheckboxBasicConfigPanel"), "radio-basic": () => import("@/lib/registry/components/radio-basic/RadioBasicConfigPanel"), "toggle-switch": () => import("@/lib/registry/components/toggle-switch/ToggleSwitchConfigPanel"), "file-upload": () => import("@/lib/registry/components/file-upload/FileUploadConfigPanel"), "button-primary": () => import("@/lib/registry/components/button-primary/ButtonPrimaryConfigPanel"), "text-display": () => import("@/lib/registry/components/text-display/TextDisplayConfigPanel"), "slider-basic": () => import("@/lib/registry/components/slider-basic/SliderBasicConfigPanel"), "image-display": () => import("@/lib/registry/components/image-display/ImageDisplayConfigPanel"), "divider-line": () => import("@/lib/registry/components/divider-line/DividerLineConfigPanel"), "accordion-basic": () => import("@/lib/registry/components/accordion-basic/AccordionBasicConfigPanel"), "table-list": () => import("@/lib/registry/components/table-list/TableListConfigPanel"), "card-display": () => import("@/lib/registry/components/card-display/CardDisplayConfigPanel"), "split-panel-layout": () => import("@/lib/registry/components/split-panel-layout/SplitPanelLayoutConfigPanel"), }; // ConfigPanel 컴포넌트 캐시 const configPanelCache = new Map>(); /** * 컴포넌트 ID로 ConfigPanel 컴포넌트를 동적으로 로드 */ export async function getComponentConfigPanel(componentId: string): Promise | null> { // 캐시에서 먼저 확인 if (configPanelCache.has(componentId)) { return configPanelCache.get(componentId)!; } // 매핑에서 import 함수 찾기 const importFn = CONFIG_PANEL_MAP[componentId]; if (!importFn) { console.warn(`컴포넌트 "${componentId}"에 대한 ConfigPanel을 찾을 수 없습니다.`); return null; } try { console.log(`🔧 ConfigPanel 로드 중: ${componentId}`); const module = await importFn(); // 모듈에서 ConfigPanel 컴포넌트 추출 const ConfigPanelComponent = module[`${toPascalCase(componentId)}ConfigPanel`] || module.default; if (!ConfigPanelComponent) { console.error(`컴포넌트 "${componentId}"의 ConfigPanel을 모듈에서 찾을 수 없습니다.`); return null; } // 캐시에 저장 configPanelCache.set(componentId, ConfigPanelComponent); console.log(`✅ ConfigPanel 로드 완료: ${componentId}`); return ConfigPanelComponent; } catch (error) { console.error(`컴포넌트 "${componentId}"의 ConfigPanel 로드 실패:`, error); return null; } } /** * 컴포넌트 ID가 ConfigPanel을 지원하는지 확인 */ export function hasComponentConfigPanel(componentId: string): boolean { return componentId in CONFIG_PANEL_MAP; } /** * 지원되는 모든 컴포넌트 ID 목록 조회 */ export function getSupportedConfigPanelComponents(): string[] { return Object.keys(CONFIG_PANEL_MAP); } /** * kebab-case를 PascalCase로 변환 * text-input → TextInput */ function toPascalCase(str: string): string { return str .split("-") .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(""); } /** * 컴포넌트 설정 패널을 렌더링하는 React 컴포넌트 */ export interface ComponentConfigPanelProps { componentId: string; config: Record; onChange: (config: Record) => void; screenTableName?: string; // 화면에서 지정한 테이블명 tableColumns?: any[]; // 테이블 컬럼 정보 tables?: any[]; // 전체 테이블 목록 } export const DynamicComponentConfigPanel: React.FC = ({ componentId, config, onChange, screenTableName, tableColumns, tables, }) => { console.log(`🔥 DynamicComponentConfigPanel 렌더링 시작: ${componentId}`); const [ConfigPanelComponent, setConfigPanelComponent] = React.useState | null>(null); const [loading, setLoading] = React.useState(true); const [error, setError] = React.useState(null); React.useEffect(() => { let mounted = true; async function loadConfigPanel() { try { console.log(`🔧 DynamicComponentConfigPanel: ${componentId} 로드 시작`); setLoading(true); setError(null); const component = await getComponentConfigPanel(componentId); console.log(`🔧 DynamicComponentConfigPanel: ${componentId} 로드 결과:`, component); if (mounted) { setConfigPanelComponent(() => component); setLoading(false); } } catch (err) { console.error(`❌ DynamicComponentConfigPanel: ${componentId} 로드 실패:`, err); if (mounted) { setError(err instanceof Error ? err.message : String(err)); setLoading(false); } } } loadConfigPanel(); return () => { mounted = false; }; }, [componentId]); if (loading) { return (
⏳ 로딩 중...

설정 패널을 불러오는 중입니다.

); } if (error) { return (
⚠️ 로드 실패

설정 패널을 불러올 수 없습니다: {error}

); } if (!ConfigPanelComponent) { console.warn(`⚠️ DynamicComponentConfigPanel: ${componentId} ConfigPanelComponent가 null`); return (
⚠️ 설정 패널 없음

컴포넌트 "{componentId}"에 대한 설정 패널이 없습니다.

); } console.log(`🔧 DynamicComponentConfigPanel 렌더링:`, { componentId, ConfigPanelComponent: ConfigPanelComponent?.name, config, configType: typeof config, configKeys: typeof config === "object" ? Object.keys(config || {}) : "not object", screenTableName, tableColumns: Array.isArray(tableColumns) ? tableColumns.length : tableColumns, tables: Array.isArray(tables) ? tables.length : tables, tablesType: typeof tables, }); return ( ); };