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.
This commit is contained in:
kjs
2026-03-04 16:41:51 +09:00
parent ea8b4ce5dc
commit 93d9df3e5a
2 changed files with 52 additions and 97 deletions

View File

@@ -1262,62 +1262,54 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
return;
}
if (categoryColumns.length === 0) {
setCategoryMappings({});
return;
}
try {
const mappings: Record<string, Record<string, { label: string; color?: string }>> = {};
const apiClient = (await import("@/lib/api/client")).apiClient;
// 트리 구조를 평탄화하는 헬퍼 함수 (메인 테이블 + 엔티티 조인 공통 사용)
const flattenTree = (items: any[], mapping: Record<string, { label: string; color?: string }>) => {
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<string, { label: string; color?: string }> = {};
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<TableListComponentProps> = ({
if (response.data.success && response.data.data && Array.isArray(response.data.data)) {
const mapping: Record<string, { label: string; color?: string }> = {};
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<TableListComponentProps> = ({
// 연쇄관계 매핑이 없는 경우 무시 (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<TableListComponentProps> = ({
categoryColumns.length,
JSON.stringify(categoryColumns),
JSON.stringify(tableConfig.columns),
]); // 더 명확한 의존성
]);
// ========================================
// 데이터 가져오기

View File

@@ -1396,15 +1396,31 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
return;
}
if (categoryColumns.length === 0) {
setCategoryMappings({});
return;
}
try {
const mappings: Record<string, Record<string, { label: string; color?: string }>> = {};
const apiClient = (await import("@/lib/api/client")).apiClient;
// 트리 구조를 평탄화하는 헬퍼 함수 (메인 테이블 + 엔티티 조인 공통 사용)
const flattenTree = (items: any[], mapping: Record<string, { label: string; color?: string }>) => {
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<TableListComponentProps> = ({
if (response.data.success && response.data.data && Array.isArray(response.data.data)) {
const mapping: Record<string, { label: string; color?: string }> = {};
// 트리 구조를 평탄화하는 헬퍼 함수
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<TableListComponentProps> = ({
if (response.data.success && response.data.data && Array.isArray(response.data.data)) {
const mapping: Record<string, { label: string; color?: string }> = {};
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<TableListComponentProps> = ({
// 연쇄관계 매핑이 없는 경우 무시
}
setCategoryMappings(mappings);
if (Object.keys(mappings).length > 0) {
setCategoryMappings(mappings);
setCategoryMappingsKey((prev) => prev + 1);
}
} catch {