@ -1,26 +1,16 @@
|
||||
import { Flex } from '@chakra-ui/react'
|
||||
import { DropdownList } from '@/components/DropdownList'
|
||||
import {
|
||||
Comparison,
|
||||
ConditionItem,
|
||||
ConditionBlock,
|
||||
LogicalOperator,
|
||||
} from 'models'
|
||||
import { Comparison, ConditionItem, LogicalOperator } from 'models'
|
||||
import React from 'react'
|
||||
import { ComparisonItem } from './ComparisonsItem'
|
||||
import { ComparisonItem } from './ComparisonItem'
|
||||
import { TableList } from '@/components/TableList'
|
||||
|
||||
type ConditionSettingsBodyProps = {
|
||||
block: ConditionBlock
|
||||
type Props = {
|
||||
itemContent: ConditionItem['content']
|
||||
onItemChange: (updates: Partial<ConditionItem>) => void
|
||||
}
|
||||
|
||||
export const ConditionSettingsBody = ({
|
||||
block,
|
||||
onItemChange,
|
||||
}: ConditionSettingsBodyProps) => {
|
||||
const itemContent = block.items[0].content
|
||||
|
||||
export const ConditionItemForm = ({ itemContent, onItemChange }: Props) => {
|
||||
const handleComparisonsChange = (comparisons: Comparison[]) =>
|
||||
onItemChange({ content: { ...itemContent, comparisons } })
|
||||
const handleLogicalOperatorChange = (logicalOperator: LogicalOperator) =>
|
@ -0,0 +1 @@
|
||||
export * from './ConditionItemForm'
|
@ -0,0 +1,180 @@
|
||||
import {
|
||||
Stack,
|
||||
Tag,
|
||||
Text,
|
||||
Flex,
|
||||
Wrap,
|
||||
Fade,
|
||||
IconButton,
|
||||
PopoverTrigger,
|
||||
Popover,
|
||||
Portal,
|
||||
PopoverContent,
|
||||
PopoverArrow,
|
||||
PopoverBody,
|
||||
useEventListener,
|
||||
} from '@chakra-ui/react'
|
||||
import { useTypebot } from '@/features/editor'
|
||||
import {
|
||||
Comparison,
|
||||
ConditionItem,
|
||||
ComparisonOperators,
|
||||
ItemType,
|
||||
ItemIndices,
|
||||
} from 'models'
|
||||
import React, { useRef } from 'react'
|
||||
import { byId, isNotDefined } from 'utils'
|
||||
import { PlusIcon } from '@/components/icons'
|
||||
import { ConditionItemForm } from './ConditionItemForm'
|
||||
import { useGraph } from '@/features/graph'
|
||||
import cuid from 'cuid'
|
||||
|
||||
type Props = {
|
||||
item: ConditionItem
|
||||
isMouseOver: boolean
|
||||
indices: ItemIndices
|
||||
}
|
||||
|
||||
export const ConditionItemNode = ({ item, isMouseOver, indices }: Props) => {
|
||||
const { typebot, createItem, updateItem } = useTypebot()
|
||||
const { openedItemId, setOpenedItemId } = useGraph()
|
||||
const ref = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
const handleMouseDown = (e: React.MouseEvent) => e.stopPropagation()
|
||||
|
||||
const openPopover = () => {
|
||||
setOpenedItemId(item.id)
|
||||
}
|
||||
|
||||
const handleItemChange = (updates: Partial<ConditionItem>) => {
|
||||
updateItem(indices, { ...item, ...updates })
|
||||
}
|
||||
|
||||
const handlePlusClick = (event: React.MouseEvent) => {
|
||||
event.stopPropagation()
|
||||
const itemIndex = indices.itemIndex + 1
|
||||
const newItemId = cuid()
|
||||
createItem(
|
||||
{
|
||||
blockId: item.blockId,
|
||||
type: ItemType.CONDITION,
|
||||
id: newItemId,
|
||||
},
|
||||
{ ...indices, itemIndex }
|
||||
)
|
||||
setOpenedItemId(newItemId)
|
||||
}
|
||||
|
||||
const handleMouseWheel = (e: WheelEvent) => {
|
||||
e.stopPropagation()
|
||||
}
|
||||
useEventListener('wheel', handleMouseWheel, ref.current)
|
||||
|
||||
return (
|
||||
<Popover
|
||||
placement="left"
|
||||
isLazy
|
||||
isOpen={openedItemId === item.id}
|
||||
closeOnBlur={false}
|
||||
>
|
||||
<PopoverTrigger>
|
||||
<Flex p={3} pos="relative" w="full" onClick={openPopover}>
|
||||
{item.content.comparisons.length === 0 ||
|
||||
comparisonIsEmpty(item.content.comparisons[0]) ? (
|
||||
<Text color={'gray.500'}>Configure...</Text>
|
||||
) : (
|
||||
<Stack maxW="170px">
|
||||
{item.content.comparisons.map((comparison, idx) => {
|
||||
const variable = typebot?.variables.find(
|
||||
byId(comparison.variableId)
|
||||
)
|
||||
return (
|
||||
<Wrap key={comparison.id} spacing={1} noOfLines={1}>
|
||||
{idx > 0 && (
|
||||
<Text>{item.content.logicalOperator ?? ''}</Text>
|
||||
)}
|
||||
{variable?.name && (
|
||||
<Tag bgColor="orange.400" color="white">
|
||||
{variable.name}
|
||||
</Tag>
|
||||
)}
|
||||
{comparison.comparisonOperator && (
|
||||
<Text>
|
||||
{parseComparisonOperatorSymbol(
|
||||
comparison.comparisonOperator
|
||||
)}
|
||||
</Text>
|
||||
)}
|
||||
{comparison?.value && (
|
||||
<Tag bgColor={'gray.200'}>
|
||||
<Text noOfLines={1}>{comparison.value}</Text>
|
||||
</Tag>
|
||||
)}
|
||||
</Wrap>
|
||||
)
|
||||
})}
|
||||
</Stack>
|
||||
)}
|
||||
<Fade
|
||||
in={isMouseOver}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: '-15px',
|
||||
zIndex: 3,
|
||||
left: '90px',
|
||||
}}
|
||||
unmountOnExit
|
||||
>
|
||||
<IconButton
|
||||
aria-label="Add item"
|
||||
icon={<PlusIcon />}
|
||||
size="xs"
|
||||
shadow="md"
|
||||
colorScheme="gray"
|
||||
onClick={handlePlusClick}
|
||||
/>
|
||||
</Fade>
|
||||
</Flex>
|
||||
</PopoverTrigger>
|
||||
<Portal>
|
||||
<PopoverContent pos="relative" onMouseDown={handleMouseDown}>
|
||||
<PopoverArrow />
|
||||
<PopoverBody
|
||||
py="6"
|
||||
overflowY="scroll"
|
||||
maxH="400px"
|
||||
shadow="lg"
|
||||
ref={ref}
|
||||
>
|
||||
<ConditionItemForm
|
||||
itemContent={item.content}
|
||||
onItemChange={handleItemChange}
|
||||
/>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Portal>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
const comparisonIsEmpty = (comparison: Comparison) =>
|
||||
isNotDefined(comparison.comparisonOperator) &&
|
||||
isNotDefined(comparison.value) &&
|
||||
isNotDefined(comparison.variableId)
|
||||
|
||||
const parseComparisonOperatorSymbol = (operator: ComparisonOperators) => {
|
||||
switch (operator) {
|
||||
case ComparisonOperators.CONTAINS:
|
||||
return 'contains'
|
||||
case ComparisonOperators.EQUAL:
|
||||
return '='
|
||||
case ComparisonOperators.GREATER:
|
||||
return '>'
|
||||
case ComparisonOperators.IS_SET:
|
||||
return 'is set'
|
||||
case ComparisonOperators.LESS:
|
||||
return '<'
|
||||
case ComparisonOperators.NOT_EQUAL:
|
||||
return '!='
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
import { Stack, Tag, Text, Flex, Wrap } from '@chakra-ui/react'
|
||||
import { useTypebot } from '@/features/editor'
|
||||
import { Comparison, ConditionItem, ComparisonOperators } from 'models'
|
||||
import React from 'react'
|
||||
import { byId, isNotDefined } from 'utils'
|
||||
|
||||
type Props = {
|
||||
item: ConditionItem
|
||||
}
|
||||
|
||||
export const ConditionNodeContent = ({ item }: Props) => {
|
||||
const { typebot } = useTypebot()
|
||||
return (
|
||||
<Flex px={2} py={2}>
|
||||
{item.content.comparisons.length === 0 ||
|
||||
comparisonIsEmpty(item.content.comparisons[0]) ? (
|
||||
<Text color={'gray.500'}>Configure...</Text>
|
||||
) : (
|
||||
<Stack maxW="170px">
|
||||
{item.content.comparisons.map((comparison, idx) => {
|
||||
const variable = typebot?.variables.find(
|
||||
byId(comparison.variableId)
|
||||
)
|
||||
return (
|
||||
<Wrap key={comparison.id} spacing={1} noOfLines={1}>
|
||||
{idx > 0 && <Text>{item.content.logicalOperator ?? ''}</Text>}
|
||||
{variable?.name && (
|
||||
<Tag bgColor="orange.400" color="white">
|
||||
{variable.name}
|
||||
</Tag>
|
||||
)}
|
||||
{comparison.comparisonOperator && (
|
||||
<Text>
|
||||
{parseComparisonOperatorSymbol(
|
||||
comparison.comparisonOperator
|
||||
)}
|
||||
</Text>
|
||||
)}
|
||||
{comparison?.value && (
|
||||
<Tag bgColor={'gray.200'}>
|
||||
<Text noOfLines={1}>{comparison.value}</Text>
|
||||
</Tag>
|
||||
)}
|
||||
</Wrap>
|
||||
)
|
||||
})}
|
||||
</Stack>
|
||||
)}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
const comparisonIsEmpty = (comparison: Comparison) =>
|
||||
isNotDefined(comparison.comparisonOperator) &&
|
||||
isNotDefined(comparison.value) &&
|
||||
isNotDefined(comparison.variableId)
|
||||
|
||||
const parseComparisonOperatorSymbol = (operator: ComparisonOperators) => {
|
||||
switch (operator) {
|
||||
case ComparisonOperators.CONTAINS:
|
||||
return 'contains'
|
||||
case ComparisonOperators.EQUAL:
|
||||
return '='
|
||||
case ComparisonOperators.GREATER:
|
||||
return '>'
|
||||
case ComparisonOperators.IS_SET:
|
||||
return 'is set'
|
||||
case ComparisonOperators.LESS:
|
||||
return '<'
|
||||
case ComparisonOperators.NOT_EQUAL:
|
||||
return '!='
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export { ConditionSettingsBody } from './ConditonSettingsBody'
|
@ -1,3 +1,2 @@
|
||||
export { ConditionSettingsBody } from './components/ConditionSettingsBody'
|
||||
export { ConditionNodeContent } from './components/ConditionNodeContent'
|
||||
export { ConditionIcon } from './components/ConditionIcon'
|
||||
export * from './components/ConditionItemNode'
|
||||
export * from './components/ConditionIcon'
|
||||
|
Reference in New Issue
Block a user