'use client' import { memo, type ReactNode } from 'react' import { Handle, Position, type NodeProps } from '@xyflow/react' import { cn } from '@/lib/utils' import { NODE_COLORS, CONDITION_OPERATORS, LABEL_CONDITION_OPERATORS, } from '@/lib/mail-automation/node-definitions' import { actionTypeLabel, conditionFieldLabel } from '@/lib/mail-automation/domains' import { formatConditionSummary } from '@/lib/mail-automation/condition-helpers' import type { ActionsNodeData, ConditionNodeData, LabelCheckNodeData, LLMCheckNodeData, SetVarNodeData, SwitchNodeData, CallRuleNodeData, WorkflowNodeType, } from '@/lib/mail-automation/types' function fieldLabel(field: string) { return conditionFieldLabel(field) } function opLabel(op: string) { const fromString = CONDITION_OPERATORS.find((o) => o.value === op)?.label if (fromString) return fromString return LABEL_CONDITION_OPERATORS.find((o) => o.value === op)?.label ?? op } function actionLabel(type: string) { return actionTypeLabel(type) } function nodeShell( type: WorkflowNodeType, selected: boolean | undefined, className: string, children: ReactNode ) { return (
{children}
) } function BranchOutputRow({ id, label, labelClassName, handleClassName, top, }: { id: string label: string labelClassName?: string handleClassName?: string top: string }) { return ( <> {label} ) } function BranchOutputs({ branches, }: { branches: { id: string label: string labelClassName?: string handleClassName?: string }[] }) { const rowHeight = 24 const blockHeight = branches.length * rowHeight return (
{branches.map((b, i) => { const topPx = rowHeight * i + rowHeight / 2 return })}
) } export const StartNode = memo(function StartNode({ selected }: NodeProps) { return nodeShell('start', selected, 'min-w-[120px]', ( <>

Début

)) }) export const EndNode = memo(function EndNode({ selected }: NodeProps) { return nodeShell('end', selected, 'min-w-[100px]', ( <>

Fin

)) }) export const ConditionNode = memo(function ConditionNode({ data, selected }: NodeProps) { const d = data as unknown as ConditionNodeData return nodeShell('condition', selected, 'min-w-[200px]', ( <>

Si…

{formatConditionSummary(d, fieldLabel, opLabel)}

)) }) export const LabelCheckNode = memo(function LabelCheckNode({ data, selected }: NodeProps) { const d = data as unknown as LabelCheckNodeData return nodeShell('label_check', selected, 'min-w-[200px]', ( <>

Libellé

{d.operator === 'not_has' ? 'Sans' : 'A'} « {d.label || '…'} »

)) }) export const SwitchNode = memo(function SwitchNode({ data, selected }: NodeProps) { const d = data as unknown as SwitchNodeData const cases = d.cases ?? [] const caseBranches = cases.map((c, i) => ({ id: `case-${i}`, label: c.label || c.value || `Cas ${i + 1}`, labelClassName: 'text-violet-600', handleClassName: '!bg-violet-500', })) return nodeShell('switch', selected, 'min-w-[220px]', ( <>

Switch · {fieldLabel(d.field)}

)) }) export const LLMCheckNode = memo(function LLMCheckNode({ data, selected }: NodeProps) { const d = data as unknown as LLMCheckNodeData return nodeShell('llm_check', selected, 'min-w-[220px]', ( <>

LLM

{d.prompt || 'Prompt…'}

)) }) export const ActionsNode = memo(function ActionsNode({ data, selected }: NodeProps) { const d = data as unknown as ActionsNodeData const actions = d.actions ?? [] return nodeShell('actions', selected, 'min-w-[200px]', ( <>

Actions ({actions.length})

    {actions.slice(0, 4).map((a, i) => (
  • {actionLabel(a.type)} {a.value ? `: ${a.value}` : ''}
  • ))}
)) }) export const SetVarNode = memo(function SetVarNode({ data, selected }: NodeProps) { const d = data as unknown as SetVarNodeData return nodeShell('set_var', selected, 'min-w-[180px]', ( <>

Variable

{d.name || 'var'} = {d.value || '…'}

)) }) export const CallFunctionNode = memo(function CallFunctionNode({ data, selected }: NodeProps) { const d = data as unknown as CallRuleNodeData return nodeShell('call_function', selected, 'min-w-[180px]', ( <>

Fonction

{d.rule_id || 'Choisir…'}

)) }) export const CallRuleNode = memo(function CallRuleNode({ data, selected }: NodeProps) { const d = data as unknown as CallRuleNodeData return nodeShell('call_rule', selected, 'min-w-[180px]', ( <>

Règle cascade

{d.rule_id || 'Choisir…'}

)) }) export const workflowNodeTypes = { start: StartNode, end: EndNode, condition: ConditionNode, label_check: LabelCheckNode, switch: SwitchNode, llm_check: LLMCheckNode, actions: ActionsNode, set_var: SetVarNode, call_function: CallFunctionNode, call_rule: CallRuleNode, }