80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
|
|
/**
|
||
|
|
* 조건부 표시 규칙 평가 유틸
|
||
|
|
*
|
||
|
|
* [사용처]
|
||
|
|
* - CanvasComponent.tsx : 캔버스 내 컴포넌트 조건부 표시
|
||
|
|
* - ReportPreviewModal.tsx : 미리보기 시 조건부 표시
|
||
|
|
* - ReportListPreviewModal.tsx : 목록 미리보기 시 조건부 표시
|
||
|
|
*/
|
||
|
|
|
||
|
|
import type { ConditionalRule } from "@/types/report";
|
||
|
|
export type { ConditionalRule };
|
||
|
|
|
||
|
|
type QueryResultGetter = (
|
||
|
|
queryId: string
|
||
|
|
) => { fields: string[]; rows: Record<string, unknown>[] } | null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 단일 조건 규칙을 평가한다.
|
||
|
|
* 쿼리 결과의 첫 번째 행에서 필드 값을 가져와 연산자로 비교한다.
|
||
|
|
*/
|
||
|
|
export function evaluateSingleRule(
|
||
|
|
rule: ConditionalRule,
|
||
|
|
getQueryResult: QueryResultGetter
|
||
|
|
): boolean {
|
||
|
|
const queryResult = getQueryResult(rule.queryId);
|
||
|
|
if (!queryResult?.rows?.length) return false;
|
||
|
|
|
||
|
|
const rawValue = queryResult.rows[0][rule.field];
|
||
|
|
const fieldStr =
|
||
|
|
rawValue !== null && rawValue !== undefined ? String(rawValue) : "";
|
||
|
|
const fieldNum = parseFloat(fieldStr);
|
||
|
|
const compareNum = parseFloat(rule.value);
|
||
|
|
|
||
|
|
switch (rule.operator) {
|
||
|
|
case "eq":
|
||
|
|
return fieldStr === rule.value;
|
||
|
|
case "ne":
|
||
|
|
return fieldStr !== rule.value;
|
||
|
|
case "gt":
|
||
|
|
return !isNaN(fieldNum) && !isNaN(compareNum) && fieldNum > compareNum;
|
||
|
|
case "lt":
|
||
|
|
return !isNaN(fieldNum) && !isNaN(compareNum) && fieldNum < compareNum;
|
||
|
|
case "gte":
|
||
|
|
return !isNaN(fieldNum) && !isNaN(compareNum) && fieldNum >= compareNum;
|
||
|
|
case "lte":
|
||
|
|
return !isNaN(fieldNum) && !isNaN(compareNum) && fieldNum <= compareNum;
|
||
|
|
case "contains":
|
||
|
|
return fieldStr.includes(rule.value);
|
||
|
|
case "notEmpty":
|
||
|
|
return fieldStr !== "";
|
||
|
|
case "empty":
|
||
|
|
return fieldStr === "";
|
||
|
|
default:
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 다중 조건 규칙을 AND로 평가한다.
|
||
|
|
* 모든 규칙이 충족되면 action에 따라 표시/숨김을 결정한다.
|
||
|
|
*/
|
||
|
|
export function evaluateConditionalRules(
|
||
|
|
rules: ConditionalRule[] | undefined | null,
|
||
|
|
getQueryResult: QueryResultGetter
|
||
|
|
): boolean {
|
||
|
|
if (!rules || rules.length === 0) return true;
|
||
|
|
|
||
|
|
const validRules = rules.filter(
|
||
|
|
(r) => r.queryId && r.field && r.operator
|
||
|
|
);
|
||
|
|
if (validRules.length === 0) return true;
|
||
|
|
|
||
|
|
const action = validRules[0].action || "show";
|
||
|
|
const allMet = validRules.every((r) =>
|
||
|
|
evaluateSingleRule(r, getQueryResult)
|
||
|
|
);
|
||
|
|
|
||
|
|
return action === "show" ? allMet : !allMet;
|
||
|
|
}
|