refactor: 코드 정리 및 가독성 향상
- numberingRuleController.ts에서 API 엔드포인트의 코드 스타일을 일관되게 정리하여 가독성을 높였습니다. - 불필요한 줄바꿈을 제거하고, 코드 블록을 명확하게 정리하여 유지보수성을 개선했습니다. - tableManagementService.ts와 ButtonConfigPanel.tsx에서 코드 정리를 통해 일관성을 유지하고, 가독성을 향상시켰습니다. - 전반적으로 코드의 깔끔함을 유지하고, 향후 개발 시 이해하기 쉽게 개선했습니다.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
* - modal: 엔티티 선택 (FK 저장) + 추가 입력 컬럼
|
||||
*
|
||||
* RepeaterTable 및 ItemSelectionModal 재사용
|
||||
*
|
||||
*
|
||||
* 데이터 전달 인터페이스:
|
||||
* - DataProvidable: 선택된 데이터 제공
|
||||
* - DataReceivable: 외부에서 데이터 수신
|
||||
@@ -124,83 +124,91 @@ export const UnifiedRepeater: React.FC<UnifiedRepeaterProps> = ({
|
||||
// DataProvidable 인터페이스 구현
|
||||
// 다른 컴포넌트에서 이 리피터의 데이터를 가져갈 수 있게 함
|
||||
// ============================================================
|
||||
const dataProvider: DataProvidable = useMemo(() => ({
|
||||
componentId: parentId || config.fieldName || "unified-repeater",
|
||||
componentType: "unified-repeater",
|
||||
|
||||
// 선택된 행 데이터 반환
|
||||
getSelectedData: () => {
|
||||
return Array.from(selectedRows).map((idx) => data[idx]).filter(Boolean);
|
||||
},
|
||||
|
||||
// 전체 데이터 반환
|
||||
getAllData: () => {
|
||||
return [...data];
|
||||
},
|
||||
|
||||
// 선택 초기화
|
||||
clearSelection: () => {
|
||||
setSelectedRows(new Set());
|
||||
},
|
||||
}), [parentId, config.fieldName, data, selectedRows]);
|
||||
const dataProvider: DataProvidable = useMemo(
|
||||
() => ({
|
||||
componentId: parentId || config.fieldName || "unified-repeater",
|
||||
componentType: "unified-repeater",
|
||||
|
||||
// 선택된 행 데이터 반환
|
||||
getSelectedData: () => {
|
||||
return Array.from(selectedRows)
|
||||
.map((idx) => data[idx])
|
||||
.filter(Boolean);
|
||||
},
|
||||
|
||||
// 전체 데이터 반환
|
||||
getAllData: () => {
|
||||
return [...data];
|
||||
},
|
||||
|
||||
// 선택 초기화
|
||||
clearSelection: () => {
|
||||
setSelectedRows(new Set());
|
||||
},
|
||||
}),
|
||||
[parentId, config.fieldName, data, selectedRows],
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// DataReceivable 인터페이스 구현
|
||||
// 외부에서 이 리피터로 데이터를 전달받을 수 있게 함
|
||||
// ============================================================
|
||||
const dataReceiver: DataReceivable = useMemo(() => ({
|
||||
componentId: parentId || config.fieldName || "unified-repeater",
|
||||
componentType: "repeater",
|
||||
|
||||
// 데이터 수신 (append, replace, merge 모드 지원)
|
||||
receiveData: async (incomingData: any[], receiverConfig: DataReceiverConfig) => {
|
||||
if (!incomingData || incomingData.length === 0) return;
|
||||
const dataReceiver: DataReceivable = useMemo(
|
||||
() => ({
|
||||
componentId: parentId || config.fieldName || "unified-repeater",
|
||||
componentType: "repeater",
|
||||
|
||||
// 매핑 규칙 적용
|
||||
const mappedData = incomingData.map((item, index) => {
|
||||
const newRow: any = { _id: `received_${Date.now()}_${index}` };
|
||||
|
||||
if (receiverConfig.mappingRules && receiverConfig.mappingRules.length > 0) {
|
||||
receiverConfig.mappingRules.forEach((rule) => {
|
||||
const sourceValue = item[rule.sourceField];
|
||||
newRow[rule.targetField] = sourceValue !== undefined ? sourceValue : rule.defaultValue;
|
||||
});
|
||||
} else {
|
||||
// 매핑 규칙 없으면 그대로 복사
|
||||
Object.assign(newRow, item);
|
||||
// 데이터 수신 (append, replace, merge 모드 지원)
|
||||
receiveData: async (incomingData: any[], receiverConfig: DataReceiverConfig) => {
|
||||
if (!incomingData || incomingData.length === 0) return;
|
||||
|
||||
// 매핑 규칙 적용
|
||||
const mappedData = incomingData.map((item, index) => {
|
||||
const newRow: any = { _id: `received_${Date.now()}_${index}` };
|
||||
|
||||
if (receiverConfig.mappingRules && receiverConfig.mappingRules.length > 0) {
|
||||
receiverConfig.mappingRules.forEach((rule) => {
|
||||
const sourceValue = item[rule.sourceField];
|
||||
newRow[rule.targetField] = sourceValue !== undefined ? sourceValue : rule.defaultValue;
|
||||
});
|
||||
} else {
|
||||
// 매핑 규칙 없으면 그대로 복사
|
||||
Object.assign(newRow, item);
|
||||
}
|
||||
|
||||
return newRow;
|
||||
});
|
||||
|
||||
// 모드에 따라 데이터 처리
|
||||
switch (receiverConfig.mode) {
|
||||
case "replace":
|
||||
setData(mappedData);
|
||||
onDataChange?.(mappedData);
|
||||
break;
|
||||
case "merge":
|
||||
// 중복 제거 후 병합 (id 또는 _id 기준)
|
||||
const existingIds = new Set(data.map((row) => row.id || row._id));
|
||||
const newItems = mappedData.filter((row) => !existingIds.has(row.id || row._id));
|
||||
const mergedData = [...data, ...newItems];
|
||||
setData(mergedData);
|
||||
onDataChange?.(mergedData);
|
||||
break;
|
||||
case "append":
|
||||
default:
|
||||
const appendedData = [...data, ...mappedData];
|
||||
setData(appendedData);
|
||||
onDataChange?.(appendedData);
|
||||
break;
|
||||
}
|
||||
|
||||
return newRow;
|
||||
});
|
||||
},
|
||||
|
||||
// 모드에 따라 데이터 처리
|
||||
switch (receiverConfig.mode) {
|
||||
case "replace":
|
||||
setData(mappedData);
|
||||
onDataChange?.(mappedData);
|
||||
break;
|
||||
case "merge":
|
||||
// 중복 제거 후 병합 (id 또는 _id 기준)
|
||||
const existingIds = new Set(data.map((row) => row.id || row._id));
|
||||
const newItems = mappedData.filter((row) => !existingIds.has(row.id || row._id));
|
||||
const mergedData = [...data, ...newItems];
|
||||
setData(mergedData);
|
||||
onDataChange?.(mergedData);
|
||||
break;
|
||||
case "append":
|
||||
default:
|
||||
const appendedData = [...data, ...mappedData];
|
||||
setData(appendedData);
|
||||
onDataChange?.(appendedData);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// 현재 데이터 반환
|
||||
getData: () => {
|
||||
return [...data];
|
||||
},
|
||||
}), [parentId, config.fieldName, data, onDataChange]);
|
||||
// 현재 데이터 반환
|
||||
getData: () => {
|
||||
return [...data];
|
||||
},
|
||||
}),
|
||||
[parentId, config.fieldName, data, onDataChange],
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// ScreenContext에 DataProvider/DataReceiver 등록
|
||||
@@ -208,7 +216,7 @@ export const UnifiedRepeater: React.FC<UnifiedRepeaterProps> = ({
|
||||
useEffect(() => {
|
||||
if (screenContext && (parentId || config.fieldName)) {
|
||||
const componentId = parentId || config.fieldName || "unified-repeater";
|
||||
|
||||
|
||||
screenContext.registerDataProvider(componentId, dataProvider);
|
||||
screenContext.registerDataReceiver(componentId, dataReceiver);
|
||||
|
||||
@@ -231,7 +239,9 @@ export const UnifiedRepeater: React.FC<UnifiedRepeaterProps> = ({
|
||||
componentId: parentId || config.fieldName || "unified-repeater",
|
||||
tableName: config.dataSource?.tableName || "",
|
||||
data: data,
|
||||
selectedData: Array.from(selectedRows).map((idx) => data[idx]).filter(Boolean),
|
||||
selectedData: Array.from(selectedRows)
|
||||
.map((idx) => data[idx])
|
||||
.filter(Boolean),
|
||||
});
|
||||
prevDataLengthRef.current = data.length;
|
||||
}
|
||||
@@ -701,19 +711,22 @@ export const UnifiedRepeater: React.FC<UnifiedRepeaterProps> = ({
|
||||
|
||||
// 🆕 채번 API 호출 (비동기)
|
||||
// 🆕 수동 입력 부분 지원을 위해 userInputCode 파라미터 추가
|
||||
const generateNumberingCode = useCallback(async (ruleId: string, userInputCode?: string, formData?: Record<string, any>): Promise<string> => {
|
||||
try {
|
||||
const result = await allocateNumberingCode(ruleId, userInputCode, formData);
|
||||
if (result.success && result.data?.generatedCode) {
|
||||
return result.data.generatedCode;
|
||||
const generateNumberingCode = useCallback(
|
||||
async (ruleId: string, userInputCode?: string, formData?: Record<string, any>): Promise<string> => {
|
||||
try {
|
||||
const result = await allocateNumberingCode(ruleId, userInputCode, formData);
|
||||
if (result.success && result.data?.generatedCode) {
|
||||
return result.data.generatedCode;
|
||||
}
|
||||
console.error("채번 실패:", result.error);
|
||||
return "";
|
||||
} catch (error) {
|
||||
console.error("채번 API 호출 실패:", error);
|
||||
return "";
|
||||
}
|
||||
console.error("채번 실패:", result.error);
|
||||
return "";
|
||||
} catch (error) {
|
||||
console.error("채번 API 호출 실패:", error);
|
||||
return "";
|
||||
}
|
||||
}, []);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
// 🆕 행 추가 (inline 모드 또는 모달 열기) - 비동기로 변경
|
||||
const handleAddRow = useCallback(async () => {
|
||||
|
||||
Reference in New Issue
Block a user