ERP-node/frontend/hooks/useConditionManager.ts

183 lines
5.8 KiB
TypeScript

"use client";
import { useState, useCallback } from "react";
import { ConditionNode } from "@/lib/api/dataflow";
import {
generateConditionId,
generateGroupId,
generateActionGroupId,
findOpenGroups,
getNextGroupLevel,
getCurrentGroupLevel,
} from "@/utils/connectionUtils";
import toast from "react-hot-toast";
export const useConditionManager = () => {
const [conditions, setConditions] = useState<ConditionNode[]>([]);
// 조건 추가
const addCondition = useCallback(() => {
const newCondition: ConditionNode = {
id: generateConditionId(),
type: "condition" as const,
field: "",
operator: "=",
value: "",
dataType: "string",
// 첫 번째 조건이 아니고, 바로 앞이 group-start가 아니면 logicalOperator 추가
...(conditions.length > 0 &&
conditions[conditions.length - 1]?.type !== "group-start" && { logicalOperator: "AND" as const }),
};
setConditions([...conditions, newCondition]);
}, [conditions]);
// 그룹 시작 추가
const addGroupStart = useCallback(() => {
const groupId = generateGroupId();
const groupLevel = getNextGroupLevel(conditions);
const groupStart: ConditionNode = {
id: generateConditionId(),
type: "group-start" as const,
groupId,
groupLevel,
// 첫 번째 그룹이 아니면 logicalOperator 추가
...(conditions.length > 0 && { logicalOperator: "AND" as const }),
};
setConditions([...conditions, groupStart]);
}, [conditions]);
// 그룹 끝 추가
const addGroupEnd = useCallback(() => {
// 가장 최근에 열린 그룹 찾기
const openGroups = findOpenGroups(conditions);
if (openGroups.length === 0) {
toast.error("닫을 그룹이 없습니다.");
return;
}
const lastOpenGroup = openGroups[openGroups.length - 1];
const groupEnd: ConditionNode = {
id: generateConditionId(),
type: "group-end" as const,
groupId: lastOpenGroup.groupId,
groupLevel: lastOpenGroup.groupLevel,
};
setConditions([...conditions, groupEnd]);
}, [conditions]);
// 조건 업데이트
const updateCondition = useCallback(
(index: number, field: keyof ConditionNode, value: string) => {
const updatedConditions = [...conditions];
updatedConditions[index] = { ...updatedConditions[index], [field]: value };
setConditions(updatedConditions);
},
[conditions],
);
// 조건 제거
const removeCondition = useCallback(
(index: number) => {
const conditionToRemove = conditions[index];
// 그룹 시작/끝을 삭제하는 경우 해당 그룹 전체 삭제
if (conditionToRemove.type === "group-start" || conditionToRemove.type === "group-end") {
const updatedConditions = conditions.filter((c) => c.groupId !== conditionToRemove.groupId);
setConditions(updatedConditions);
} else {
const updatedConditions = conditions.filter((_, i) => i !== index);
setConditions(updatedConditions);
}
},
[conditions],
);
// 그룹 전체 삭제
const removeGroup = useCallback(
(groupId: string) => {
const updatedConditions = conditions.filter((c) => c.groupId !== groupId);
setConditions(updatedConditions);
},
[conditions],
);
return {
conditions,
setConditions,
addCondition,
addGroupStart,
addGroupEnd,
updateCondition,
removeCondition,
removeGroup,
getCurrentGroupLevel: (conditionIndex: number) => getCurrentGroupLevel(conditions, conditionIndex),
};
};
// 액션별 조건 관리를 위한 헬퍼 함수들
export const useActionConditionHelpers = () => {
// 액션별 그룹 시작 추가
const addActionGroupStart = useCallback(
(actionIndex: number, dataSaveSettings: any, setDataSaveSettings: (settings: any) => void) => {
const groupId = generateActionGroupId();
const currentConditions = dataSaveSettings.actions[actionIndex].conditions || [];
const groupLevel = getNextGroupLevel(currentConditions);
const groupStart: ConditionNode = {
id: generateConditionId(),
type: "group-start" as const,
groupId,
groupLevel,
// 첫 번째 그룹이 아니면 logicalOperator 추가
...(currentConditions.length > 0 && { logicalOperator: "AND" as const }),
};
const newActions = [...dataSaveSettings.actions];
newActions[actionIndex].conditions = [...currentConditions, groupStart];
setDataSaveSettings({ ...dataSaveSettings, actions: newActions });
},
[],
);
// 액션별 그룹 끝 추가
const addActionGroupEnd = useCallback(
(actionIndex: number, dataSaveSettings: any, setDataSaveSettings: (settings: any) => void) => {
const currentConditions = dataSaveSettings.actions[actionIndex].conditions || [];
const openGroups = findOpenGroups(currentConditions);
if (openGroups.length === 0) {
toast.error("닫을 그룹이 없습니다.");
return;
}
const lastOpenGroup = openGroups[openGroups.length - 1];
const groupEnd: ConditionNode = {
id: generateConditionId(),
type: "group-end" as const,
groupId: lastOpenGroup.groupId,
groupLevel: lastOpenGroup.groupLevel,
};
const newActions = [...dataSaveSettings.actions];
newActions[actionIndex].conditions = [...currentConditions, groupEnd];
setDataSaveSettings({ ...dataSaveSettings, actions: newActions });
},
[],
);
// 액션별 현재 조건의 그룹 레벨 계산
const getActionCurrentGroupLevel = useCallback((conditions: ConditionNode[], conditionIndex: number): number => {
return getCurrentGroupLevel(conditions, conditionIndex);
}, []);
return {
addActionGroupStart,
addActionGroupEnd,
getActionCurrentGroupLevel,
};
};