119 lines
3.6 KiB
TypeScript
119 lines
3.6 KiB
TypeScript
/**
|
|
* 조건부 표시 평가 유틸리티
|
|
* 컴포넌트의 조건부 표시 설정을 평가하여 visible/disabled 상태를 반환합니다.
|
|
*/
|
|
|
|
import { ComponentData } from "@/types/screen";
|
|
|
|
export interface ConditionalResult {
|
|
visible: boolean;
|
|
disabled: boolean;
|
|
}
|
|
|
|
export interface ConditionalConfig {
|
|
enabled: boolean;
|
|
field: string;
|
|
operator: "=" | "!=" | ">" | "<" | "in" | "notIn" | "isEmpty" | "isNotEmpty";
|
|
value: string | string[];
|
|
action: "show" | "hide" | "enable" | "disable";
|
|
}
|
|
|
|
/**
|
|
* 조건부 표시를 평가합니다.
|
|
* @param conditional - 컴포넌트의 조건부 설정
|
|
* @param formData - 현재 폼 데이터
|
|
* @param allComponents - 화면의 모든 컴포넌트 (필드 참조용)
|
|
* @returns visible/disabled 상태
|
|
*/
|
|
export function evaluateConditional(
|
|
conditional: ConditionalConfig | undefined,
|
|
formData: Record<string, any>,
|
|
allComponents: ComponentData[],
|
|
): ConditionalResult {
|
|
// 조건부 설정이 없거나 비활성화된 경우 기본값 반환
|
|
if (!conditional || !conditional.enabled) {
|
|
return { visible: true, disabled: false };
|
|
}
|
|
|
|
const { field, operator, value, action } = conditional;
|
|
|
|
// 필드가 설정되지 않은 경우 기본값 반환
|
|
if (!field) {
|
|
console.warn("[evaluateConditional] 조건 필드가 설정되지 않음");
|
|
return { visible: true, disabled: false };
|
|
}
|
|
|
|
// 참조 필드의 현재 값 가져오기
|
|
// field 값은 columnName 또는 id일 수 있으므로 양쪽으로 찾기
|
|
const refComponent = allComponents.find((c) => {
|
|
const columnName = (c as any)?.columnName;
|
|
return c.id === field || columnName === field;
|
|
});
|
|
|
|
// formData에서 값 조회: columnName 우선, 없으면 field 값 직접 사용
|
|
const fieldName = (refComponent as any)?.columnName || field;
|
|
const fieldValue = formData[fieldName];
|
|
|
|
// 조건 평가
|
|
let conditionMet = false;
|
|
switch (operator) {
|
|
case "=":
|
|
conditionMet = fieldValue === value || String(fieldValue) === String(value);
|
|
break;
|
|
case "!=":
|
|
conditionMet = fieldValue !== value && String(fieldValue) !== String(value);
|
|
break;
|
|
case ">":
|
|
conditionMet = Number(fieldValue) > Number(value);
|
|
break;
|
|
case "<":
|
|
conditionMet = Number(fieldValue) < Number(value);
|
|
break;
|
|
case "in":
|
|
if (Array.isArray(value)) {
|
|
conditionMet = value.includes(fieldValue) || value.map(String).includes(String(fieldValue));
|
|
}
|
|
break;
|
|
case "notIn":
|
|
if (Array.isArray(value)) {
|
|
conditionMet = !value.includes(fieldValue) && !value.map(String).includes(String(fieldValue));
|
|
} else {
|
|
conditionMet = true;
|
|
}
|
|
break;
|
|
case "isEmpty":
|
|
conditionMet =
|
|
fieldValue === null ||
|
|
fieldValue === undefined ||
|
|
fieldValue === "" ||
|
|
(Array.isArray(fieldValue) && fieldValue.length === 0);
|
|
break;
|
|
case "isNotEmpty":
|
|
conditionMet =
|
|
fieldValue !== null &&
|
|
fieldValue !== undefined &&
|
|
fieldValue !== "" &&
|
|
!(Array.isArray(fieldValue) && fieldValue.length === 0);
|
|
break;
|
|
default:
|
|
conditionMet = true;
|
|
}
|
|
|
|
// 액션에 따른 결과 반환
|
|
switch (action) {
|
|
case "show":
|
|
// 조건이 참이면 표시, 거짓이면 숨김
|
|
return { visible: conditionMet, disabled: false };
|
|
case "hide":
|
|
// 조건이 참이면 숨김, 거짓이면 표시
|
|
return { visible: !conditionMet, disabled: false };
|
|
case "enable":
|
|
return { visible: true, disabled: !conditionMet };
|
|
case "disable":
|
|
return { visible: true, disabled: conditionMet };
|
|
default:
|
|
return { visible: true, disabled: false };
|
|
}
|
|
}
|
|
|