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, }; }