ERP-node/frontend/components/dataflow/connection/ActionConditionRenderer.tsx

207 lines
7.7 KiB
TypeScript

"use client";
import React from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Trash2 } from "lucide-react";
import { ConditionNode, ColumnInfo } from "@/lib/api/dataflow";
import { DataSaveSettings } from "@/types/connectionTypes";
import { getInputTypeForDataType } from "@/utils/connectionUtils";
interface ActionConditionRendererProps {
condition: ConditionNode;
condIndex: number;
actionIndex: number;
settings: DataSaveSettings;
onSettingsChange: (settings: DataSaveSettings) => void;
fromTableColumns: ColumnInfo[];
getActionCurrentGroupLevel: (conditions: ConditionNode[], conditionIndex: number) => number;
}
export const ActionConditionRenderer: React.FC<ActionConditionRendererProps> = ({
condition,
condIndex,
actionIndex,
settings,
onSettingsChange,
fromTableColumns,
getActionCurrentGroupLevel,
}) => {
const removeConditionGroup = (groupId: string) => {
const newActions = [...settings.actions];
newActions[actionIndex].conditions = newActions[actionIndex].conditions!.filter((c) => c.groupId !== groupId);
onSettingsChange({ ...settings, actions: newActions });
};
const removeCondition = () => {
const newActions = [...settings.actions];
newActions[actionIndex].conditions = newActions[actionIndex].conditions!.filter((_, i) => i !== condIndex);
onSettingsChange({ ...settings, actions: newActions });
};
const updateCondition = (field: string, value: any) => {
const newActions = [...settings.actions];
(newActions[actionIndex].conditions![condIndex] as any)[field] = value;
onSettingsChange({ ...settings, actions: newActions });
};
const updateLogicalOperator = (targetIndex: number, value: "AND" | "OR") => {
const newActions = [...settings.actions];
newActions[actionIndex].conditions![targetIndex].logicalOperator = value;
onSettingsChange({ ...settings, actions: newActions });
};
const renderConditionValue = () => {
const selectedColumn = fromTableColumns.find((col) => col.columnName === condition.field);
const dataType = selectedColumn?.dataType?.toLowerCase() || "string";
const inputType = getInputTypeForDataType(dataType);
if (dataType.includes("bool")) {
return (
<Select value={String(condition.value || "")} onValueChange={(value) => updateCondition("value", value)}>
<SelectTrigger className="h-6 flex-1 text-xs">
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
<SelectItem value="true">TRUE</SelectItem>
<SelectItem value="false">FALSE</SelectItem>
</SelectContent>
</Select>
);
} else {
return (
<Input
type={inputType}
placeholder={inputType === "number" ? "숫자" : "값"}
value={String(condition.value || "")}
onChange={(e) => updateCondition("value", e.target.value)}
className="h-6 flex-1 text-xs"
/>
);
}
};
// 그룹 시작 렌더링
if (condition.type === "group-start") {
return (
<div className="flex items-center gap-2">
{/* 그룹 시작 앞의 논리 연산자 */}
{condIndex > 0 && (
<Select
value={settings.actions[actionIndex].conditions![condIndex - 1]?.logicalOperator || "AND"}
onValueChange={(value: "AND" | "OR") => updateLogicalOperator(condIndex - 1, value)}
>
<SelectTrigger className="h-6 w-24 border-green-200 bg-green-50 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="AND">AND</SelectItem>
<SelectItem value="OR">OR</SelectItem>
</SelectContent>
</Select>
)}
<div
className="flex items-center gap-2 rounded border-2 border-dashed border-green-300 bg-green-50/50 p-1"
style={{ marginLeft: `${(condition.groupLevel || 0) * 15}px` }}
>
<span className="font-mono text-xs text-green-600">(</span>
<span className="text-xs text-green-600"> </span>
<Button
size="sm"
variant="ghost"
onClick={() => removeConditionGroup(condition.groupId!)}
className="h-4 w-4 p-0"
>
<Trash2 className="h-2 w-2" />
</Button>
</div>
</div>
);
}
// 그룹 끝 렌더링
if (condition.type === "group-end") {
return (
<div className="flex items-center gap-2">
<div
className="flex items-center gap-2 rounded border-2 border-dashed border-green-300 bg-green-50/50 p-1"
style={{ marginLeft: `${(condition.groupLevel || 0) * 15}px` }}
>
<span className="font-mono text-xs text-green-600">)</span>
<span className="text-xs text-green-600"> </span>
<Button
size="sm"
variant="ghost"
onClick={() => removeConditionGroup(condition.groupId!)}
className="h-4 w-4 p-0"
>
<Trash2 className="h-2 w-2" />
</Button>
</div>
</div>
);
}
// 일반 조건 렌더링
return (
<div className="flex items-center gap-2">
{/* 그룹 내 첫 번째 조건이 아닐 때만 논리 연산자 표시 */}
{condIndex > 0 && settings.actions[actionIndex].conditions![condIndex - 1]?.type !== "group-start" && (
<Select
value={settings.actions[actionIndex].conditions![condIndex - 1]?.logicalOperator || "AND"}
onValueChange={(value: "AND" | "OR") => updateLogicalOperator(condIndex - 1, value)}
>
<SelectTrigger className="h-6 w-24 border-green-200 bg-green-50 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="AND">AND</SelectItem>
<SelectItem value="OR">OR</SelectItem>
</SelectContent>
</Select>
)}
<div
className="flex flex-1 items-center gap-2 rounded border bg-white p-1"
style={{
marginLeft: `${getActionCurrentGroupLevel(settings.actions[actionIndex].conditions || [], condIndex) * 15}px`,
}}
>
<Select value={condition.field || ""} onValueChange={(value) => updateCondition("field", value)}>
<SelectTrigger className="h-6 flex-1 text-xs">
<SelectValue placeholder="필드" />
</SelectTrigger>
<SelectContent>
{fromTableColumns.map((column) => (
<SelectItem key={column.columnName} value={column.columnName}>
{column.columnName}
</SelectItem>
))}
</SelectContent>
</Select>
<Select
value={condition.operator || "="}
onValueChange={(value: "=" | "!=" | ">" | "<" | ">=" | "<=" | "LIKE") => updateCondition("operator", value)}
>
<SelectTrigger className="h-6 w-20 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="=">=</SelectItem>
<SelectItem value="!=">!=</SelectItem>
<SelectItem value=">">&gt;</SelectItem>
<SelectItem value="<">&lt;</SelectItem>
<SelectItem value=">=">&gt;=</SelectItem>
<SelectItem value="<=">&lt;=</SelectItem>
<SelectItem value="LIKE">LIKE</SelectItem>
</SelectContent>
</Select>
{renderConditionValue()}
<Button size="sm" variant="ghost" onClick={removeCondition} className="h-6 w-6 p-0">
<Trash2 className="h-2 w-2" />
</Button>
</div>
</div>
);
};