'use client' import { useCallback, useMemo, useState } from 'react' import Combobox from '@/components/editor/Combobox' import type { ComboboxItem } from '@/components/editor/Combobox' import { useEditorContext } from '@/components/editor/EditorContext' import type { Condition } from '@/types/flowchart' type ConditionEditorProps = { edgeId: string condition: Condition | undefined onChange: (edgeId: string, condition: Condition | undefined) => void onClose: () => void } export default function ConditionEditor({ edgeId, condition, onChange, onClose, }: ConditionEditorProps) { const { variables, onAddVariable } = useEditorContext() const [showAddForm, setShowAddForm] = useState(false) const [newName, setNewName] = useState('') const [newType, setNewType] = useState<'numeric' | 'string' | 'boolean'>('numeric') const variableItems: ComboboxItem[] = useMemo( () => variables.map((v) => ({ id: v.id, label: v.name, badge: v.type, })), [variables] ) const selectedVariable = useMemo(() => { if (!condition?.variableId) return undefined return variables.find((v) => v.id === condition.variableId) }, [condition?.variableId, variables]) const hasInvalidReference = useMemo(() => { if (!condition?.variableId) return false return !variables.some((v) => v.id === condition.variableId) }, [condition?.variableId, variables]) // Determine operators based on variable type const availableOperators = useMemo(() => { if (!selectedVariable || selectedVariable.type === 'numeric') { return [ { value: '==', label: '==' }, { value: '!=', label: '!=' }, { value: '>', label: '>' }, { value: '<', label: '<' }, { value: '>=', label: '>=' }, { value: '<=', label: '<=' }, ] as const } // string and boolean only support == and != return [ { value: '==', label: '==' }, { value: '!=', label: '!=' }, ] as const }, [selectedVariable]) const handleVariableSelect = useCallback( (variableId: string) => { const variable = variables.find((v) => v.id === variableId) const defaultValue = variable ? variable.type === 'numeric' ? 0 : variable.type === 'boolean' ? false : '' : 0 // Reset operator if current one is not valid for new type const validOperator = variable && variable.type !== 'numeric' && condition?.operator && !['==', '!='].includes(condition.operator) ? '==' : condition?.operator || '==' onChange(edgeId, { variableName: variable?.name || '', variableId, operator: validOperator as Condition['operator'], value: defaultValue, }) }, [variables, condition?.operator, edgeId, onChange] ) const handleOperatorChange = useCallback( (operator: string) => { if (!condition) return onChange(edgeId, { ...condition, operator: operator as Condition['operator'], }) }, [condition, edgeId, onChange] ) const handleValueChange = useCallback( (value: number | string | boolean) => { if (!condition) return onChange(edgeId, { ...condition, value, }) }, [condition, edgeId, onChange] ) const handleRemoveCondition = useCallback(() => { onChange(edgeId, undefined) onClose() }, [edgeId, onChange, onClose]) const handleAddNew = useCallback(() => { setShowAddForm(true) setNewName('') setNewType('numeric') }, []) const handleSubmitNew = useCallback(() => { if (!newName.trim()) return const defaultValue = newType === 'numeric' ? 0 : newType === 'boolean' ? false : '' const newId = onAddVariable(newName.trim(), newType, defaultValue) onChange(edgeId, { variableName: newName.trim(), variableId: newId, operator: '==', value: defaultValue, }) setShowAddForm(false) }, [newName, newType, onAddVariable, edgeId, onChange]) const handleCancelNew = useCallback(() => { setShowAddForm(false) }, []) // Render value input based on variable type const renderValueInput = () => { const varType = selectedVariable?.type || 'numeric' if (varType === 'boolean') { return ( ) } if (varType === 'string') { return ( handleValueChange(e.target.value)} placeholder="Value..." className="w-full rounded border border-zinc-300 bg-white px-2 py-1 text-sm focus:border-blue-500 focus:outline-none dark:border-zinc-600 dark:bg-zinc-700 dark:text-white dark:placeholder-zinc-400" /> ) } // numeric return ( handleValueChange(parseFloat(e.target.value) || 0)} className="w-full rounded border border-zinc-300 bg-white px-2 py-1 text-sm focus:border-blue-500 focus:outline-none dark:border-zinc-600 dark:bg-zinc-700 dark:text-white" /> ) } return (