refactor: Remove debug logs and optimize toast animations

- Removed debug console logs from the UPSERT process in the DataService to clean up the code.
- Disabled animations for Sonner toast notifications to enhance performance and user experience.
- Simplified the alert and dialog components by removing unnecessary animation classes, ensuring a smoother transition.
- Updated the SelectedItemsDetailInputComponent to load all related table data in edit mode, improving data management and consistency.
This commit is contained in:
DDD1542
2026-02-09 15:37:28 +09:00
parent 423ef6231a
commit d7f900d8ae
11 changed files with 80 additions and 108 deletions

View File

@@ -223,33 +223,34 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
const additionalFields = componentConfig.additionalFields || [];
const firstRecord = dataArray[0];
// 수정 모드: 다른 sourceTable의 데이터도 추가 로드 (예: customer_item_mapping)
let mappingData: Record<string, any> | null = null;
// URL의 tableName = 이미 데이터가 로드된 테이블. 그 외 sourceTable은 추가 조회 필요
// 수정 모드: 모든 관련 테이블의 데이터를 API로 전체 로드
// sourceData는 클릭한 1개 레코드만 포함할 수 있으므로, API로 전체를 다시 가져옴
const editTableName = new URLSearchParams(window.location.search).get("tableName");
const otherTables = groups
.filter((g) => g.sourceTable && g.sourceTable !== editTableName)
.map((g) => g.sourceTable!)
.filter((v, i, a) => a.indexOf(v) === i); // 중복 제거
const allTableData: Record<string, Record<string, any>[]> = {};
if (otherTables.length > 0 && firstRecord.customer_id && firstRecord.item_id) {
if (firstRecord.customer_id && firstRecord.item_id) {
try {
const { dataApi } = await import("@/lib/api/data");
for (const otherTable of otherTables) {
// getTableData 반환: { data: any[], total, page, size } (success 필드 없음)
const response = await dataApi.getTableData(otherTable, {
// 모든 sourceTable의 데이터를 API로 전체 로드 (중복 테이블 제거)
const allTables = groups
.map((g) => g.sourceTable || editTableName)
.filter((v, i, a) => v && a.indexOf(v) === i) as string[];
for (const table of allTables) {
const response = await dataApi.getTableData(table, {
filters: {
customer_id: firstRecord.customer_id,
item_id: firstRecord.item_id,
},
sortBy: "created_date",
sortOrder: "desc",
});
if (response.data && response.data.length > 0) {
mappingData = response.data[0];
allTableData[table] = response.data;
}
}
} catch (err) {
console.error("❌ 매핑 데이터 로드 실패:", err);
console.error("❌ 편집 데이터 전체 로드 실패:", err);
}
}
@@ -263,41 +264,17 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
return;
}
// 이 그룹의 sourceTable에 따라 데이터 소스 결정
const editTableName = new URLSearchParams(window.location.search).get("tableName");
const isOtherTable = group.sourceTable && group.sourceTable !== editTableName;
// 이 그룹의 sourceTable 결정 → API에서 가져온 전체 데이터 사용
const groupTable = group.sourceTable || editTableName || "";
// 현재 테이블만 sourceData fallback 허용 (다른 테이블은 빈 배열 → id 크로스오염 방지)
const isCurrentTable = !group.sourceTable || group.sourceTable === editTableName;
const groupDataList = allTableData[groupTable] || (isCurrentTable ? dataArray : []);
if (isOtherTable && mappingData) {
// 다른 테이블 그룹 (예: customer_item_mapping) → mappingData에서 로드
const entryData: Record<string, any> = {};
groupFields.forEach((field: any) => {
let fieldValue = mappingData![field.name];
// autoFillFrom 로직
if ((fieldValue === undefined || fieldValue === null) && field.autoFillFrom) {
fieldValue = firstRecord[field.autoFillFrom] || firstRecord.item_id;
}
if (fieldValue !== undefined && fieldValue !== null) {
entryData[field.name] = fieldValue;
}
});
if (Object.keys(entryData).length > 0) {
mainFieldGroups[group.id] = [{
id: `${group.id}_entry_1`,
// DB 레코드의 고유 id(UUID PK) 보존 → 수정 시 이 id로 UPDATE
_dbRecordId: mappingData!.id || null,
...entryData,
}];
} else {
mainFieldGroups[group.id] = [];
}
} else {
// 현재 테이블 그룹 (예: customer_item_prices) → dataArray에서 로드
{
// 모든 테이블 그룹: API에서 가져온 전체 레코드를 entry로 변환
const entriesMap = new Map<string, GroupEntry>();
dataArray.forEach((record) => {
groupDataList.forEach((record) => {
const entryData: Record<string, any> = {};
groupFields.forEach((field: any) => {
@@ -355,8 +332,6 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
const entryKey = JSON.stringify(entryData);
if (!entriesMap.has(entryKey)) {
// DEBUG: record.id 확인 (추후 삭제)
console.log("🔑 [LOAD] record.id:", record.id, "record keys:", Object.keys(record));
entriesMap.set(entryKey, {
id: `${group.id}_entry_${entriesMap.size + 1}`,
// DB 레코드의 고유 id(UUID PK) 보존 → 수정 시 이 id로 UPDATE
@@ -678,37 +653,36 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
const itemParentKeys = { ...parentKeys, item_id: itemId };
// === Step 1: 메인 테이블(customer_item_mapping) 저장 ===
const mappingRecord: Record<string, any> = {};
// 여러 개의 매핑 레코드 지원 (거래처 품번/품명이 다중일 수 있음)
const mappingRecords: Record<string, any>[] = [];
mainGroups.forEach((group) => {
const entries = item.fieldGroups[group.id] || [];
const groupFields = additionalFields.filter((f) => f.groupId === group.id);
if (entries.length > 0) {
entries.forEach((entry) => {
const record: Record<string, any> = {};
groupFields.forEach((field) => {
const val = entries[0][field.name];
// 사용자가 실제 입력한 값만 포함 (빈 문자열, null 제외)
const val = entry[field.name];
if (val !== undefined && val !== null && val !== "") {
mappingRecord[field.name] = val;
record[field.name] = val;
}
});
// 기존 DB 레코드의 고유 id(PK)가 있으면 포함 → 백엔드에서 이 id로 UPDATE
if (entries[0]._dbRecordId) {
mappingRecord.id = entries[0]._dbRecordId;
if (entry._dbRecordId) {
record.id = entry._dbRecordId;
}
}
// autoFillFrom 필드 처리 (item_id 등)
// 단, item_id는 이미 정확한 itemId 변수를 사용 (autoFillFrom:"id"가 수정 모드에서 오작동 방지)
groupFields.forEach((field) => {
if (field.name === "item_id") {
// item_id는 위에서 계산된 정확한 itemId 사용
mappingRecord.item_id = itemId;
} else if (field.autoFillFrom && item.originalData) {
const value = item.originalData[field.autoFillFrom];
if (value !== undefined && value !== null) {
mappingRecord[field.name] = value;
// item_id는 정확한 itemId 변수 사용 (autoFillFrom:"id" 오작동 방지)
record.item_id = itemId;
// 나머지 autoFillFrom 필드 처리
groupFields.forEach((field) => {
if (field.name !== "item_id" && field.autoFillFrom && item.originalData) {
const value = item.originalData[field.autoFillFrom];
if (value !== undefined && value !== null && !record[field.name]) {
record[field.name] = value;
}
}
}
});
mappingRecords.push(record);
});
});
@@ -716,7 +690,7 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
const mappingResult = await dataApi.upsertGroupedRecords(
mainTable,
itemParentKeys,
[mappingRecord],
mappingRecords,
);
} catch (err) {
console.error(`${mainTable} 저장 실패:`, err);
@@ -757,8 +731,6 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
if (entry._dbRecordId) {
priceRecord.id = entry._dbRecordId;
}
// DEBUG: id 전달 확인용 (추후 삭제)
console.log("🔑 [SAVE] entry._dbRecordId:", entry._dbRecordId, "→ priceRecord.id:", priceRecord.id, "entry keys:", Object.keys(entry));
priceRecords.push(priceRecord);
}
});