diff --git a/frontend/components/v2/V2Input.tsx b/frontend/components/v2/V2Input.tsx index 17183050..dac766d5 100644 --- a/frontend/components/v2/V2Input.tsx +++ b/frontend/components/v2/V2Input.tsx @@ -771,9 +771,15 @@ export const V2Input = forwardRef((props, ref) => ); case "number": + // DB에서 문자열("325")로 반환되는 경우도 숫자로 변환하여 표시 + const numValue = typeof displayValue === "number" + ? displayValue + : (displayValue !== undefined && displayValue !== null && displayValue !== "" && !isNaN(Number(displayValue))) + ? Number(displayValue) + : undefined; return ( { setAutoGeneratedValue(null); onChange?.(v ?? 0); @@ -802,9 +808,15 @@ export const V2Input = forwardRef((props, ref) => ); case "slider": + // DB에서 문자열로 반환되는 경우도 숫자로 변환 + const sliderValue = typeof displayValue === "number" + ? displayValue + : (displayValue !== undefined && displayValue !== null && displayValue !== "" && !isNaN(Number(displayValue))) + ? Number(displayValue) + : (config.min ?? 0); return ( { setAutoGeneratedValue(null); onChange?.(v); diff --git a/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx b/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx index 05c16943..53e91e71 100644 --- a/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx +++ b/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx @@ -2105,22 +2105,16 @@ export const SplitPanelLayoutComponent: React.FC const editButtonConfig = componentConfig.leftPanel?.editButton; if (editButtonConfig?.mode === "modal" && editButtonConfig?.modalScreenId) { const leftTableName = componentConfig.leftPanel?.tableName || ""; - const sourceColumn = componentConfig.leftPanel?.itemAddConfig?.sourceColumn || "id"; - // Primary Key 찾기 - let primaryKeyName = sourceColumn; - let primaryKeyValue = item[sourceColumn]; + // Primary Key 찾기 - 실제 DB의 id 컬럼 값을 우선 사용 + let primaryKeyValue = item.id || item.ID; if (primaryKeyValue === undefined || primaryKeyValue === null) { - if (item.id !== undefined && item.id !== null) { - primaryKeyName = "id"; - primaryKeyValue = item.id; - } else if (item.ID !== undefined && item.ID !== null) { - primaryKeyName = "ID"; - primaryKeyValue = item.ID; - } else { + // id가 없으면 sourceColumn 시도, 마지막으로 첫 번째 키 + const sourceColumn = componentConfig.leftPanel?.itemAddConfig?.sourceColumn || "id"; + primaryKeyValue = item[sourceColumn]; + if (primaryKeyValue === undefined || primaryKeyValue === null) { const firstKey = Object.keys(item)[0]; - primaryKeyName = firstKey; primaryKeyValue = item[firstKey]; } } @@ -2147,7 +2141,6 @@ export const SplitPanelLayoutComponent: React.FC console.log("✅ [SplitPanel] 좌측 수정 모달 화면 열기:", { screenId: editButtonConfig.modalScreenId, tableName: leftTableName, - primaryKeyName, primaryKeyValue, }); return; @@ -2282,9 +2275,8 @@ export const SplitPanelLayoutComponent: React.FC return; } - // Primary Key 찾기 - const sourceColumn = componentConfig.leftPanel?.itemAddConfig?.sourceColumn || "id"; - const primaryKey = selectedLeftItem[sourceColumn] || selectedLeftItem.id || selectedLeftItem.ID; + // Primary Key 찾기 - 실제 DB의 id 컬럼 값을 사용 (sourceColumn은 관계 연결용이므로 PK로 사용하지 않음) + const primaryKey = selectedLeftItem.id || selectedLeftItem.ID; if (!primaryKey) { toast({ @@ -2307,7 +2299,7 @@ export const SplitPanelLayoutComponent: React.FC cleanData.company_code = companyCode; } - console.log("📝 [SplitPanel] 커스텀 우측 패널 저장:", { tableName, sourceColumn, primaryKey, data: cleanData }); + console.log("📝 [SplitPanel] 커스텀 우측 패널 저장:", { tableName, primaryKey, data: cleanData }); const response = await dataApi.updateRecord(tableName, primaryKey, cleanData); @@ -2529,7 +2521,8 @@ export const SplitPanelLayoutComponent: React.FC if (deleteModalPanel === "left") { loadLeftData(); // 삭제된 항목이 선택되어 있었으면 선택 해제 - if (selectedLeftItem && selectedLeftItem[sourceColumn] === primaryKey) { + const deletedId = deleteModalItem?.id || deleteModalItem?.ID; + if (selectedLeftItem && (selectedLeftItem.id === deletedId || selectedLeftItem.ID === deletedId)) { setSelectedLeftItem(null); setRightData(null); } @@ -2968,6 +2961,7 @@ export const SplitPanelLayoutComponent: React.FC const displayHeight = isResizingComp && resizeSize ? resizeSize.height : (comp.size?.height || 100); // 컴포넌트 데이터를 DynamicComponentRenderer 형식으로 변환 + // componentConfig의 주요 속성을 최상위로 펼침 (일반 화면의 overrides 플래트닝과 동일) const componentData = { id: comp.id, type: "component" as const, @@ -2977,6 +2971,11 @@ export const SplitPanelLayoutComponent: React.FC size: { width: displayWidth, height: displayHeight }, componentConfig: comp.componentConfig || {}, style: comp.style || {}, + // 파일 업로드/미디어 등이 component.tableName, component.columnName을 직접 참조하므로 펼침 + tableName: comp.componentConfig?.tableName, + columnName: comp.componentConfig?.columnName, + webType: comp.componentConfig?.webType, + inputType: comp.inputType || comp.componentConfig?.inputType, }; if (isDesignMode) { @@ -3981,6 +3980,15 @@ export const SplitPanelLayoutComponent: React.FC })() ) : componentConfig.rightPanel?.displayMode === "custom" ? ( // 🆕 커스텀 모드: 패널 안에 자유롭게 컴포넌트 배치 + // 실행 모드에서 좌측 미선택 시 안내 메시지 표시 + !isDesignMode && !selectedLeftItem ? ( +
+
+

좌측에서 항목을 선택하세요

+

선택한 항목의 상세 정보가 여기에 표시됩니다

+
+
+ ) : (
const displayHeight = isResizingComp && resizeSize ? resizeSize.height : (comp.size?.height || 100); // 컴포넌트 데이터를 DynamicComponentRenderer 형식으로 변환 + // componentConfig의 주요 속성을 최상위로 펼침 (일반 화면의 overrides 플래트닝과 동일) const componentData = { id: comp.id, type: "component" as const, @@ -4011,6 +4020,11 @@ export const SplitPanelLayoutComponent: React.FC size: { width: displayWidth, height: displayHeight }, componentConfig: comp.componentConfig || {}, style: comp.style || {}, + // 파일 업로드/미디어 등이 component.tableName, component.columnName을 직접 참조하므로 펼침 + tableName: comp.componentConfig?.tableName, + columnName: comp.componentConfig?.columnName, + webType: comp.componentConfig?.webType, + inputType: comp.inputType || comp.componentConfig?.inputType, }; if (isDesignMode) { @@ -4201,6 +4215,7 @@ export const SplitPanelLayoutComponent: React.FC
)} + ) ) : isLoadingRight ? ( // 로딩 중