2023-06-15 14:45:42 +02:00
import { Alert , AlertIcon , FormLabel , Stack , Tag , Text } from '@chakra-ui/react'
2023-03-03 09:01:11 +01:00
import { CodeEditor } from '@/components/inputs/CodeEditor'
2023-11-08 15:34:16 +01:00
import { SetVariableBlock , Variable } from '@typebot.io/schemas'
2023-03-03 09:01:11 +01:00
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
2023-04-14 12:11:42 +02:00
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
2023-05-11 17:17:24 -04:00
import { Select } from '@/components/inputs/Select'
2023-08-29 10:01:28 +02:00
import { WhatsAppLogo } from '@/components/logos/WhatsAppLogo'
2023-11-08 15:34:16 +01:00
import {
defaultSetVariableOptions ,
hiddenTypes ,
2024-05-15 14:24:55 +02:00
sessionOnlySetVariableOptions ,
2023-11-08 15:34:16 +01:00
valueTypes ,
} from '@typebot.io/schemas/features/blocks/logic/setVariable/constants'
2024-06-11 10:51:02 +02:00
import { TextInput , Textarea } from '@/components/inputs'
2023-11-08 15:34:16 +01:00
import { isDefined } from '@typebot.io/lib'
2024-05-02 15:11:16 +02:00
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
2024-05-15 14:24:55 +02:00
import { isInputBlock } from '@typebot.io/schemas/helpers'
2024-06-11 18:18:05 +02:00
import { RadioButtons } from '@/components/inputs/RadioButtons'
2022-01-14 07:49:24 +01:00
type Props = {
2023-11-08 15:34:16 +01:00
options : SetVariableBlock [ 'options' ]
onOptionsChange : ( options : SetVariableBlock [ 'options' ] ) = > void
2022-01-14 07:49:24 +01:00
}
2023-11-08 15:34:16 +01:00
const setVarTypes = valueTypes . filter (
( type ) = > ! hiddenTypes . includes ( type as ( typeof hiddenTypes ) [ number ] )
)
2023-08-07 14:32:30 +02:00
2022-02-02 08:05:02 +01:00
export const SetVariableSettings = ( { options , onOptionsChange } : Props ) = > {
2024-05-02 15:11:16 +02:00
const { typebot , updateVariable } = useTypebot ( )
const selectedVariable = typebot ? . variables . find (
( variable ) = > variable . id === options ? . variableId
)
const updateVariableId = ( variable? : Pick < Variable , 'id' > ) = >
2023-11-08 15:34:16 +01:00
onOptionsChange ( {
. . . options ,
variableId : variable?.id ,
} )
2023-04-14 12:11:42 +02:00
2023-05-11 17:17:24 -04:00
const updateValueType = ( type ? : string ) = >
2023-04-14 12:11:42 +02:00
onOptionsChange ( {
. . . options ,
2023-11-08 15:34:16 +01:00
type : type as NonNullable < SetVariableBlock [ 'options' ] > [ 'type' ] ,
2023-04-14 12:11:42 +02:00
} )
2024-05-02 15:11:16 +02:00
const updateIsSessionVariable = ( isSavingInResults : boolean ) = > {
if ( ! selectedVariable ? . id ) return
updateVariable ( selectedVariable . id , {
isSessionVariable : ! isSavingInResults ,
} )
}
2024-05-15 14:24:55 +02:00
const isSessionOnly =
options ? . type &&
sessionOnlySetVariableOptions . includes (
options . type as ( typeof sessionOnlySetVariableOptions ) [ number ]
)
const isLinkedToAnswer =
options ? . variableId &&
typebot ? . groups . some ( ( g ) = >
g . blocks . some (
( b ) = > isInputBlock ( b ) && b . options ? . variableId === options . variableId
)
)
2022-01-14 07:49:24 +01:00
return (
< Stack spacing = { 4 } >
< Stack >
< FormLabel mb = "0" htmlFor = "variable-search" >
Search or create variable :
< / FormLabel >
< VariableSearchInput
2023-04-14 12:11:42 +02:00
onSelectVariable = { updateVariableId }
2023-11-08 15:34:16 +01:00
initialVariableId = { options ? . variableId }
2022-01-14 07:49:24 +01:00
id = "variable-search"
/ >
< / Stack >
2023-05-11 17:17:24 -04:00
2024-05-02 15:11:16 +02:00
< Stack spacing = "4" >
< Stack >
< Text mb = "0" fontWeight = "medium" >
Value :
< / Text >
< Select
selectedItem = { options ? . type ? ? defaultSetVariableOptions . type }
items = { setVarTypes . map ( ( type ) = > ( {
label : type ,
value : type ,
icon :
type === 'Contact name' || type === 'Phone number' ? (
< WhatsAppLogo / >
) : undefined ,
} ) ) }
onSelect = { updateValueType }
/ >
< / Stack >
2024-05-15 14:24:55 +02:00
{ selectedVariable && ! isSessionOnly && ! isLinkedToAnswer && (
2024-05-02 15:11:16 +02:00
< SwitchWithLabel
key = { selectedVariable . id }
label = "Save in results?"
moreInfoContent = "By default, the variable is saved only for the user chat session. Check this option if you want to also store the variable in the typebot Results table."
initialValue = { ! selectedVariable . isSessionVariable }
onCheckChange = { updateIsSessionVariable }
/ >
) }
2023-05-11 17:17:24 -04:00
< SetVariableValue options = { options } onOptionsChange = { onOptionsChange } / >
< / Stack >
< / Stack >
)
}
const SetVariableValue = ( {
options ,
onOptionsChange ,
} : {
2023-11-08 15:34:16 +01:00
options : SetVariableBlock [ 'options' ]
onOptionsChange : ( options : SetVariableBlock [ 'options' ] ) = > void
2023-05-11 17:17:24 -04:00
} ) : JSX . Element | null = > {
const updateExpression = ( expressionToEvaluate : string ) = >
2023-11-08 15:34:16 +01:00
onOptionsChange ( {
. . . options ,
type : isDefined ( options ? . type ) ? 'Custom' : undefined ,
expressionToEvaluate ,
} )
2023-05-11 17:17:24 -04:00
const updateClientExecution = ( isExecutedOnClient : boolean ) = >
onOptionsChange ( {
. . . options ,
isExecutedOnClient ,
} )
2024-06-27 08:22:22 +02:00
const updateListVariableId = ( variable? : Pick < Variable , 'id' > ) = > {
if ( ! options || ( options . type !== 'Pop' && options . type !== 'Shift' ) ) return
onOptionsChange ( {
. . . options ,
saveItemInVariableId : variable?.id ,
} )
}
2024-05-02 15:11:16 +02:00
const updateItemVariableId = ( variable? : Pick < Variable , 'id' > ) = > {
2023-11-08 15:34:16 +01:00
if ( ! options || options . type !== 'Map item with same index' ) return
2023-05-11 17:17:24 -04:00
onOptionsChange ( {
. . . options ,
mapListItemParams : {
. . . options . mapListItemParams ,
baseItemVariableId : variable?.id ,
} ,
} )
2023-11-08 15:34:16 +01:00
}
2023-05-11 17:17:24 -04:00
2024-05-02 15:11:16 +02:00
const updateBaseListVariableId = ( variable? : Pick < Variable , 'id' > ) = > {
2023-11-08 15:34:16 +01:00
if ( ! options || options . type !== 'Map item with same index' ) return
2023-05-11 17:17:24 -04:00
onOptionsChange ( {
. . . options ,
mapListItemParams : {
. . . options . mapListItemParams ,
baseListVariableId : variable?.id ,
} ,
} )
2023-11-08 15:34:16 +01:00
}
2022-03-31 16:41:18 +02:00
2024-05-02 15:11:16 +02:00
const updateTargetListVariableId = ( variable? : Pick < Variable , 'id' > ) = > {
2023-11-08 15:34:16 +01:00
if ( ! options || options . type !== 'Map item with same index' ) return
2023-05-11 17:17:24 -04:00
onOptionsChange ( {
. . . options ,
mapListItemParams : {
. . . options . mapListItemParams ,
targetListVariableId : variable?.id ,
} ,
} )
2023-11-08 15:34:16 +01:00
}
const updateItem = ( item : string ) = > {
if ( ! options || options . type !== 'Append value(s)' ) return
onOptionsChange ( {
. . . options ,
item ,
} )
}
2023-05-11 17:17:24 -04:00
2024-06-11 18:18:05 +02:00
const updateIsCode = ( radio : 'Text' | 'Code' ) = > {
if ( options ? . type && options . type !== 'Custom' ) return
onOptionsChange ( {
. . . options ,
isCode : radio === 'Code' ,
} )
}
2023-11-08 15:34:16 +01:00
switch ( options ? . type ) {
2023-05-11 17:17:24 -04:00
case 'Custom' :
case undefined :
return (
< >
< SwitchWithLabel
label = "Execute on client?"
moreInfoContent = "Check this if you need access to client-only variables like `window` or `document`."
2023-11-08 15:34:16 +01:00
initialValue = {
options ? . isExecutedOnClient ? ?
defaultSetVariableOptions . isExecutedOnClient
}
2023-05-11 17:17:24 -04:00
onCheckChange = { updateClientExecution }
2022-03-31 16:41:18 +02:00
/ >
2024-06-11 18:18:05 +02:00
< Stack >
< RadioButtons
size = "sm"
options = { [ 'Text' , 'Code' ] }
defaultValue = {
options ? . isCode ? ? defaultSetVariableOptions . isCode
? 'Code'
: 'Text'
}
onSelect = { updateIsCode }
/ >
2024-06-24 15:03:18 +02:00
{ options ? . isCode ? (
2024-06-11 18:18:05 +02:00
< CodeEditor
defaultValue = { options ? . expressionToEvaluate ? ? '' }
onChange = { updateExpression }
lang = "javascript"
/ >
) : (
< Textarea
defaultValue = { options ? . expressionToEvaluate ? ? '' }
onChange = { updateExpression }
width = "full"
/ >
) }
< / Stack >
2023-05-11 17:17:24 -04:00
< / >
)
2024-06-27 08:22:22 +02:00
case 'Pop' :
case 'Shift' :
return (
< VariableSearchInput
initialVariableId = { options . saveItemInVariableId }
onSelectVariable = { updateListVariableId }
placeholder = {
options . type === 'Shift' ? 'Shifted item' : 'Popped item'
}
/ >
)
2023-05-11 17:17:24 -04:00
case 'Map item with same index' : {
return (
< Stack p = "2" rounded = "md" borderWidth = { 1 } >
< VariableSearchInput
initialVariableId = { options . mapListItemParams ? . baseItemVariableId }
onSelectVariable = { updateItemVariableId }
placeholder = "Base item"
/ >
< VariableSearchInput
initialVariableId = { options . mapListItemParams ? . baseListVariableId }
onSelectVariable = { updateBaseListVariableId }
placeholder = "Base list"
/ >
< VariableSearchInput
initialVariableId = { options . mapListItemParams ? . targetListVariableId }
onSelectVariable = { updateTargetListVariableId }
placeholder = "Target list"
/ >
< / Stack >
)
}
2023-11-08 15:34:16 +01:00
case 'Append value(s)' : {
2024-06-11 10:51:02 +02:00
return < Textarea defaultValue = { options . item } onChange = { updateItem } / >
2023-11-08 15:34:16 +01:00
}
2023-06-15 14:45:42 +02:00
case 'Moment of the day' : {
return (
< Alert fontSize = "sm" >
< AlertIcon / >
< Text >
Will return either < Tag size = "sm" > morning < / Tag > , { ' ' }
< Tag size = "sm" > afternoon < / Tag > , < Tag size = "sm" > evening < / Tag > or { ' ' }
< Tag size = "sm" > night < / Tag > based on the current user time .
< / Text >
< / Alert >
)
}
2023-09-26 09:50:20 +02:00
case 'Environment name' : {
return (
< Alert fontSize = "sm" >
< AlertIcon / >
< Text >
Will return either < Tag size = "sm" > web < / Tag > or { ' ' }
< Tag size = "sm" > whatsapp < / Tag > .
< / Text >
< / Alert >
)
}
2024-02-16 10:07:29 +01:00
case 'Now' :
case 'Yesterday' :
case 'Tomorrow' : {
return (
< TextInput
direction = "row"
label = "Timezone"
onChange = { ( timeZone ) = > onOptionsChange ( { . . . options , timeZone } ) }
defaultValue = { options . timeZone }
placeholder = "Europe/Paris"
/ >
)
}
2023-08-29 10:01:28 +02:00
case 'Contact name' :
case 'Phone number' :
2023-05-11 17:17:24 -04:00
case 'Random ID' :
case 'User ID' :
2024-02-16 10:07:29 +01:00
case 'Today' :
2024-02-16 11:34:54 +01:00
case 'Result ID' :
2023-05-11 17:17:24 -04:00
case 'Empty' :
2024-05-15 14:24:55 +02:00
case 'Transcript' :
2023-05-11 17:17:24 -04:00
return null
}
2022-01-14 07:49:24 +01:00
}