Files
vexplor/frontend/lib/registry/components/modal-repeater-table/useCalculation.ts
SeongHyun Kim d5d267e63a feat(modal-repeater-table): 컬럼 매핑 및 계산 규칙 UI 대폭 개선
새로운 기능
- 컬럼별 독립적인 소스 테이블 선택 기능
- SourceColumnSelector, ReferenceColumnSelector 컴포넌트 추가
- 계산 규칙 자동 동기화 로직 (cleanupInitialConfig)

UI/UX 개선
- 컬럼 설정 UI를 세로 레이아웃으로 재구성 (h-10 통일)
- 매핑 타입별 색상 구분 (파란색/보라색/초록색)
- 계산 규칙 섹션 재디자인 (안내 박스, 번호 배지, 빈 상태)
- 현재 설정 시각화 (코드 스타일 표시)

버그 수정
- 계산 규칙 삭제 시 컬럼이 수정 불가능 상태로 남는 문제 해결
- 결과 필드 변경 시 이전 필드의 calculated 속성 제거
- 초기 로드 시 계산 규칙과 컬럼 속성 동기화

개선 사항
- 모든 입력 필드의 높이와 텍스트 크기 일관성 확보
- 섹션별 명확한 제목과 설명 추가
- 접근성 향상 (ARIA 레이블, 포커스 스타일)
2025-11-19 17:09:12 +09:00

68 lines
2.0 KiB
TypeScript

import { useCallback } from "react";
import { CalculationRule } from "./types";
/**
* 계산 필드 자동 업데이트 훅
*/
export function useCalculation(calculationRules: CalculationRule[] = []) {
/**
* 단일 행의 계산 필드 업데이트
*/
const calculateRow = useCallback(
(row: any): any => {
if (calculationRules.length === 0) return row;
const updatedRow = { ...row };
for (const rule of calculationRules) {
try {
// formula에서 필드명 자동 추출 (영문자, 숫자, 언더스코어로 구성된 단어)
let formula = rule.formula;
const fieldMatches = formula.match(/[a-zA-Z_][a-zA-Z0-9_]*/g) || [];
// 추출된 필드명들을 사용 (dependencies가 없으면 자동 추출 사용)
const dependencies = rule.dependencies && rule.dependencies.length > 0
? rule.dependencies
: fieldMatches;
// 필드명을 실제 값으로 대체
for (const dep of dependencies) {
// 결과 필드는 제외
if (dep === rule.result) continue;
const value = parseFloat(row[dep]) || 0;
// 정확한 필드명만 대체 (단어 경계 사용)
formula = formula.replace(new RegExp(`\\b${dep}\\b`, "g"), value.toString());
}
// 계산 실행 (Function 사용)
const result = new Function(`return ${formula}`)();
updatedRow[rule.result] = result;
} catch (error) {
console.error(`계산 오류 (${rule.formula}):`, error);
updatedRow[rule.result] = 0;
}
}
return updatedRow;
},
[calculationRules]
);
/**
* 전체 데이터의 계산 필드 업데이트
*/
const calculateAll = useCallback(
(data: any[]): any[] => {
return data.map((row) => calculateRow(row));
},
[calculateRow]
);
return {
calculateRow,
calculateAll,
};
}