From 93d9df3e5afd24a48e9ff893c2ace88b952320fe Mon Sep 17 00:00:00 2001 From: kjs Date: Wed, 4 Mar 2026 16:41:51 +0900 Subject: [PATCH] feat: Refactor category mapping logic in TableListComponent - Introduced a helper function to flatten tree structures for category mappings, improving code readability and maintainability. - Removed redundant checks for empty category columns, streamlining the data fetching process. - Enhanced error handling for category value loading, ensuring clearer logging of failures. - Updated the mapping logic to utilize the new flattening function, ensuring consistent handling of category data across components. --- .../table-list/TableListComponent.tsx | 71 +++++++---------- .../v2-table-list/TableListComponent.tsx | 78 ++++++------------- 2 files changed, 52 insertions(+), 97 deletions(-) diff --git a/frontend/lib/registry/components/table-list/TableListComponent.tsx b/frontend/lib/registry/components/table-list/TableListComponent.tsx index d8c2a0b3..c14f28f6 100644 --- a/frontend/lib/registry/components/table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/table-list/TableListComponent.tsx @@ -1262,62 +1262,54 @@ export const TableListComponent: React.FC = ({ return; } - if (categoryColumns.length === 0) { - setCategoryMappings({}); - return; - } - try { const mappings: Record> = {}; const apiClient = (await import("@/lib/api/client")).apiClient; + // 트리 구조를 평탄화하는 헬퍼 함수 (메인 테이블 + 엔티티 조인 공통 사용) + const flattenTree = (items: any[], mapping: Record) => { + items.forEach((item: any) => { + if (item.valueCode) { + mapping[String(item.valueCode)] = { + label: item.valueLabel, + color: item.color, + }; + } + if (item.valueId !== undefined && item.valueId !== null) { + mapping[String(item.valueId)] = { + label: item.valueLabel, + color: item.color, + }; + } + if (item.children && Array.isArray(item.children) && item.children.length > 0) { + flattenTree(item.children, mapping); + } + }); + }; + for (const columnName of categoryColumns) { try { - // 🆕 엔티티 조인 컬럼 처리: "테이블명.컬럼명" 형태인지 확인 let targetTable = tableConfig.selectedTable; let targetColumn = columnName; if (columnName.includes(".")) { const parts = columnName.split("."); - targetTable = parts[0]; // 조인된 테이블명 (예: item_info) - targetColumn = parts[1]; // 실제 컬럼명 (예: material) + targetTable = parts[0]; + targetColumn = parts[1]; } const response = await apiClient.get(`/table-categories/${targetTable}/${targetColumn}/values`); if (response.data.success && response.data.data && Array.isArray(response.data.data)) { const mapping: Record = {}; - - response.data.data.forEach((item: any) => { - // valueCode를 문자열로 변환하여 키로 사용 - const key = String(item.valueCode); - mapping[key] = { - label: item.valueLabel, - color: item.color, - }; - }); + flattenTree(response.data.data, mapping); if (Object.keys(mapping).length > 0) { - // 🆕 원래 컬럼명(item_info.material)으로 매핑 저장 mappings[columnName] = mapping; - } else { - console.warn(`⚠️ [TableList] 매핑 데이터가 비어있음 [${columnName}]`); } - } else { - console.warn(`⚠️ [TableList] 카테고리 값 없음 [${columnName}]:`, { - success: response.data.success, - hasData: !!response.data.data, - isArray: Array.isArray(response.data.data), - response: response.data, - }); } } catch (error: any) { - console.error(`❌ [TableList] 카테고리 값 로드 실패 [${columnName}]:`, { - error: error.message, - stack: error.stack, - response: error.response?.data, - status: error.response?.status, - }); + console.error(`[TableList] 카테고리 값 로드 실패 [${columnName}]:`, error.message); } } @@ -1393,14 +1385,7 @@ export const TableListComponent: React.FC = ({ if (response.data.success && response.data.data && Array.isArray(response.data.data)) { const mapping: Record = {}; - - response.data.data.forEach((item: any) => { - const key = String(item.valueCode); - mapping[key] = { - label: item.valueLabel, - color: item.color, - }; - }); + flattenTree(response.data.data, mapping); if (Object.keys(mapping).length > 0) { mappings[col.columnName] = mapping; @@ -1449,8 +1434,8 @@ export const TableListComponent: React.FC = ({ // 연쇄관계 매핑이 없는 경우 무시 (404 등) } + setCategoryMappings(mappings); if (Object.keys(mappings).length > 0) { - setCategoryMappings(mappings); setCategoryMappingsKey((prev) => prev + 1); } } catch (error) { @@ -1464,7 +1449,7 @@ export const TableListComponent: React.FC = ({ categoryColumns.length, JSON.stringify(categoryColumns), JSON.stringify(tableConfig.columns), - ]); // 더 명확한 의존성 + ]); // ======================================== // 데이터 가져오기 diff --git a/frontend/lib/registry/components/v2-table-list/TableListComponent.tsx b/frontend/lib/registry/components/v2-table-list/TableListComponent.tsx index 7b3ace6d..eae50795 100644 --- a/frontend/lib/registry/components/v2-table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/v2-table-list/TableListComponent.tsx @@ -1396,15 +1396,31 @@ export const TableListComponent: React.FC = ({ return; } - if (categoryColumns.length === 0) { - setCategoryMappings({}); - return; - } - try { const mappings: Record> = {}; const apiClient = (await import("@/lib/api/client")).apiClient; + // 트리 구조를 평탄화하는 헬퍼 함수 (메인 테이블 + 엔티티 조인 공통 사용) + const flattenTree = (items: any[], mapping: Record) => { + items.forEach((item: any) => { + if (item.valueCode) { + mapping[String(item.valueCode)] = { + label: item.valueLabel, + color: item.color, + }; + } + if (item.valueId !== undefined && item.valueId !== null) { + mapping[String(item.valueId)] = { + label: item.valueLabel, + color: item.color, + }; + } + if (item.children && Array.isArray(item.children) && item.children.length > 0) { + flattenTree(item.children, mapping); + } + }); + }; + for (const columnName of categoryColumns) { try { let targetTable = tableConfig.selectedTable; @@ -1429,39 +1445,10 @@ export const TableListComponent: React.FC = ({ if (response.data.success && response.data.data && Array.isArray(response.data.data)) { const mapping: Record = {}; - - // 트리 구조를 평탄화하는 헬퍼 함수 - const flattenTree = (items: any[]) => { - items.forEach((item: any) => { - // valueCode를 문자열로 변환하여 키로 사용 - if (item.valueCode) { - const key = String(item.valueCode); - mapping[key] = { - label: item.valueLabel, - color: item.color, - }; - } - // valueId도 키로 추가 (숫자 ID 저장 시 라벨 표시용) - if (item.valueId !== undefined && item.valueId !== null) { - mapping[String(item.valueId)] = { - label: item.valueLabel, - color: item.color, - }; - } - // 자식 노드도 재귀적으로 처리 - if (item.children && Array.isArray(item.children) && item.children.length > 0) { - flattenTree(item.children); - } - }); - }; - - flattenTree(response.data.data); + flattenTree(response.data.data, mapping); if (Object.keys(mapping).length > 0) { - // 🆕 원래 컬럼명(item_info.material)으로 매핑 저장 mappings[columnName] = mapping; - } else { - // 매핑 데이터가 비어있음 - 해당 컬럼에 카테고리 값이 없음 } } } catch { @@ -1541,24 +1528,7 @@ export const TableListComponent: React.FC = ({ if (response.data.success && response.data.data && Array.isArray(response.data.data)) { const mapping: Record = {}; - - response.data.data.forEach((item: any) => { - // valueCode로 매핑 - if (item.valueCode) { - const key = String(item.valueCode); - mapping[key] = { - label: item.valueLabel, - color: item.color, - }; - } - // valueId도 키로 추가 (숫자 ID 저장 시 라벨 표시용) - if (item.valueId !== undefined && item.valueId !== null) { - mapping[String(item.valueId)] = { - label: item.valueLabel, - color: item.color, - }; - } - }); + flattenTree(response.data.data, mapping); if (Object.keys(mapping).length > 0) { mappings[col.columnName] = mapping; @@ -1608,8 +1578,8 @@ export const TableListComponent: React.FC = ({ // 연쇄관계 매핑이 없는 경우 무시 } + setCategoryMappings(mappings); if (Object.keys(mappings).length > 0) { - setCategoryMappings(mappings); setCategoryMappingsKey((prev) => prev + 1); } } catch {