import { useCallback, useMemo } from 'react' import produce from 'immer' import { useStoreApi } from 'reactflow' import type { ValueSelector, Var } from '../../types' import { VarType } from '../../types' import { getOperators } from '../if-else/utils' import { OrderBy } from './types' import type { Condition, Limit, ListFilterNodeType } from './types' import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud' import { useIsChatMode, useNodesReadOnly, useWorkflow, useWorkflowVariables, } from '@/app/components/workflow/hooks' const useConfig = (id: string, payload: ListFilterNodeType) => { const { nodesReadOnly: readOnly } = useNodesReadOnly() const isChatMode = useIsChatMode() const store = useStoreApi() const { getBeforeNodesInSameBranch } = useWorkflow() const { getNodes, } = store.getState() const currentNode = getNodes().find(n => n.id === id) const isInIteration = payload.isInIteration const iterationNode = isInIteration ? getNodes().find(n => n.id === currentNode!.parentId) : null const availableNodes = useMemo(() => { return getBeforeNodesInSameBranch(id) }, [getBeforeNodesInSameBranch, id]) const { inputs, setInputs } = useNodeCrud(id, payload) const { getCurrentVariableType } = useWorkflowVariables() const getType = useCallback((variable?: ValueSelector) => { const varType = getCurrentVariableType({ parentNode: iterationNode, valueSelector: variable || inputs.variable || [], availableNodes, isChatMode, isConstant: false, }) let itemVarType = VarType.string switch (varType) { case VarType.arrayNumber: itemVarType = VarType.number break case VarType.arrayString: itemVarType = VarType.string break case VarType.arrayFile: itemVarType = VarType.file break case VarType.arrayObject: itemVarType = VarType.object break default: itemVarType = varType } return { varType, itemVarType } }, [availableNodes, getCurrentVariableType, inputs.variable, isChatMode, iterationNode]) const { varType, itemVarType } = getType() const itemVarTypeShowName = useMemo(() => { if (!inputs.variable) return '?' return [(itemVarType || VarType.string).substring(0, 1).toUpperCase(), (itemVarType || VarType.string).substring(1)].join('') }, [inputs.variable, itemVarType]) const hasSubVariable = [VarType.arrayFile].includes(varType) const handleVarChanges = useCallback((variable: ValueSelector | string) => { const newInputs = produce(inputs, (draft) => { draft.variable = variable as ValueSelector const { varType, itemVarType } = getType(draft.variable) const isFileArray = varType === VarType.arrayFile draft.var_type = varType draft.item_var_type = itemVarType draft.filter_by.conditions = [{ key: (isFileArray && !draft.filter_by.conditions[0]?.key) ? 'name' : '', comparison_operator: getOperators(itemVarType, isFileArray ? { key: 'name' } : undefined)[0], value: '', }] if (isFileArray && draft.order_by.enabled && !draft.order_by.key) draft.order_by.key = 'name' }) setInputs(newInputs) }, [getType, inputs, setInputs]) const filterVar = useCallback((varPayload: Var) => { // Don't know the item struct of VarType.arrayObject, so not support it return [VarType.arrayNumber, VarType.arrayString, VarType.arrayFile].includes(varPayload.type) }, []) const handleFilterEnabledChange = useCallback((enabled: boolean) => { const newInputs = produce(inputs, (draft) => { draft.filter_by.enabled = enabled if (enabled && !draft.filter_by.conditions) draft.filter_by.conditions = [] }) setInputs(newInputs) }, [hasSubVariable, inputs, setInputs]) const handleFilterChange = useCallback((condition: Condition) => { const newInputs = produce(inputs, (draft) => { draft.filter_by.conditions[0] = condition }) setInputs(newInputs) }, [inputs, setInputs]) const handleLimitChange = useCallback((limit: Limit) => { const newInputs = produce(inputs, (draft) => { draft.limit = limit }) setInputs(newInputs) }, [inputs, setInputs]) const handleExtractsEnabledChange = useCallback((enabled: boolean) => { const newInputs = produce(inputs, (draft) => { draft.extract_by.enabled = enabled if (enabled) draft.extract_by.serial = '1' }) setInputs(newInputs) }, [inputs, setInputs]) const handleExtractsChange = useCallback((value: string) => { const newInputs = produce(inputs, (draft) => { draft.extract_by.serial = value }) setInputs(newInputs) }, [inputs, setInputs]) const handleOrderByEnabledChange = useCallback((enabled: boolean) => { const newInputs = produce(inputs, (draft) => { draft.order_by.enabled = enabled if (enabled) { draft.order_by.value = OrderBy.ASC if (hasSubVariable && !draft.order_by.key) draft.order_by.key = 'name' } }) setInputs(newInputs) }, [hasSubVariable, inputs, setInputs]) const handleOrderByKeyChange = useCallback((key: string) => { const newInputs = produce(inputs, (draft) => { draft.order_by.key = key }) setInputs(newInputs) }, [inputs, setInputs]) const handleOrderByTypeChange = useCallback((type: OrderBy) => { return () => { const newInputs = produce(inputs, (draft) => { draft.order_by.value = type }) setInputs(newInputs) } }, [inputs, setInputs]) return { readOnly, inputs, filterVar, varType, itemVarType, itemVarTypeShowName, hasSubVariable, handleVarChanges, handleFilterEnabledChange, handleFilterChange, handleLimitChange, handleOrderByEnabledChange, handleOrderByKeyChange, handleOrderByTypeChange, handleExtractsEnabledChange, handleExtractsChange, } } export default useConfig