feat(viewer): ✨ Add variables in URL support
This commit is contained in:
@ -4,7 +4,7 @@ import { useHostAvatars } from '../../../contexts/HostAvatarsContext'
|
||||
import { InputStep, InputStepType, PublicStep } from 'models'
|
||||
import { GuestBubble } from './bubbles/GuestBubble'
|
||||
import { TextForm } from './inputs/TextForm'
|
||||
import { isBubbleStep, isInputStep } from 'utils'
|
||||
import { byId, isBubbleStep, isInputStep } from 'utils'
|
||||
import { DateForm } from './inputs/DateForm'
|
||||
import { ChoiceForm } from './inputs/ChoiceForm'
|
||||
import { HostBubble } from './bubbles/HostBubble'
|
||||
@ -43,6 +43,9 @@ const InputChatStep = ({
|
||||
const { typebot } = useTypebot()
|
||||
const { addNewAvatarOffset } = useHostAvatars()
|
||||
const [answer, setAnswer] = useState<string>()
|
||||
const { variableId } = step.options
|
||||
const defaultValue =
|
||||
variableId && typebot.variables.find(byId(variableId))?.value
|
||||
|
||||
useEffect(() => {
|
||||
addNewAvatarOffset()
|
||||
@ -71,7 +74,13 @@ const InputChatStep = ({
|
||||
case InputStepType.EMAIL:
|
||||
case InputStepType.URL:
|
||||
case InputStepType.PHONE:
|
||||
return <TextForm step={step} onSubmit={handleSubmit} />
|
||||
return (
|
||||
<TextForm
|
||||
step={step}
|
||||
onSubmit={handleSubmit}
|
||||
defaultValue={defaultValue}
|
||||
/>
|
||||
)
|
||||
case InputStepType.DATE:
|
||||
return <DateForm options={step.options} onSubmit={handleSubmit} />
|
||||
case InputStepType.CHOICE:
|
||||
|
@ -17,10 +17,11 @@ type TextFormProps = {
|
||||
| UrlInputStep
|
||||
| PhoneNumberInputStep
|
||||
onSubmit: (value: string) => void
|
||||
defaultValue?: string
|
||||
}
|
||||
|
||||
export const TextForm = ({ step, onSubmit }: TextFormProps) => {
|
||||
const [inputValue, setInputValue] = useState('')
|
||||
export const TextForm = ({ step, onSubmit, defaultValue }: TextFormProps) => {
|
||||
const [inputValue, setInputValue] = useState(defaultValue ?? '')
|
||||
|
||||
const handleChange = (inputValue: string) => setInputValue(inputValue)
|
||||
|
||||
@ -38,7 +39,11 @@ export const TextForm = ({ step, onSubmit }: TextFormProps) => {
|
||||
onSubmit={handleSubmit}
|
||||
data-testid="input"
|
||||
>
|
||||
<TextInput step={step} onChange={handleChange} />
|
||||
<TextInput
|
||||
step={step}
|
||||
onChange={handleChange}
|
||||
defaultValue={defaultValue ?? ''}
|
||||
/>
|
||||
<SendButton
|
||||
label={step.options?.labels?.button ?? 'Send'}
|
||||
isDisabled={inputValue === ''}
|
||||
|
@ -22,10 +22,11 @@ type TextInputProps = {
|
||||
| NumberInputStep
|
||||
| UrlInputStep
|
||||
| PhoneNumberInputStep
|
||||
defaultValue: string
|
||||
onChange: (value: string) => void
|
||||
}
|
||||
|
||||
export const TextInput = ({ step, onChange }: TextInputProps) => {
|
||||
export const TextInput = ({ step, defaultValue, onChange }: TextInputProps) => {
|
||||
const inputRef = useRef<HTMLInputElement & HTMLTextAreaElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
@ -49,6 +50,7 @@ export const TextInput = ({ step, onChange }: TextInputProps) => {
|
||||
placeholder={
|
||||
step.options?.labels?.placeholder ?? 'Type your answer...'
|
||||
}
|
||||
defaultValue={defaultValue}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
) : (
|
||||
@ -57,6 +59,7 @@ export const TextInput = ({ step, onChange }: TextInputProps) => {
|
||||
placeholder={
|
||||
step.options?.labels?.placeholder ?? 'Type your answer...'
|
||||
}
|
||||
defaultValue={defaultValue}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
)
|
||||
@ -68,6 +71,7 @@ export const TextInput = ({ step, onChange }: TextInputProps) => {
|
||||
placeholder={
|
||||
step.options?.labels?.placeholder ?? 'Type your email...'
|
||||
}
|
||||
defaultValue={defaultValue}
|
||||
onChange={handleInputChange}
|
||||
type="email"
|
||||
/>
|
||||
@ -80,6 +84,7 @@ export const TextInput = ({ step, onChange }: TextInputProps) => {
|
||||
placeholder={
|
||||
step.options?.labels?.placeholder ?? 'Type your answer...'
|
||||
}
|
||||
defaultValue={defaultValue}
|
||||
onChange={handleInputChange}
|
||||
type="number"
|
||||
style={{ appearance: 'auto' }}
|
||||
@ -94,6 +99,7 @@ export const TextInput = ({ step, onChange }: TextInputProps) => {
|
||||
<ShortTextInput
|
||||
ref={inputRef}
|
||||
placeholder={step.options?.labels?.placeholder ?? 'Type your URL...'}
|
||||
defaultValue={defaultValue}
|
||||
onChange={handleInputChange}
|
||||
type="url"
|
||||
/>
|
||||
@ -105,6 +111,7 @@ export const TextInput = ({ step, onChange }: TextInputProps) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
ref={inputRef as any}
|
||||
onChange={handlePhoneNumberChange}
|
||||
defaultValue={defaultValue}
|
||||
placeholder={
|
||||
step.options?.labels?.placeholder ?? 'Your phone number...'
|
||||
}
|
||||
@ -131,7 +138,11 @@ const ShortTextInput = React.forwardRef(
|
||||
|
||||
const LongTextInput = React.forwardRef(
|
||||
(
|
||||
props: { placeholder: string; onChange: ChangeEventHandler },
|
||||
props: {
|
||||
placeholder: string
|
||||
defaultValue: string
|
||||
onChange: ChangeEventHandler
|
||||
},
|
||||
ref: React.ForwardedRef<HTMLTextAreaElement>
|
||||
) => (
|
||||
<textarea
|
||||
|
@ -22,7 +22,7 @@ export const ConversationContainer = ({
|
||||
onNewAnswer,
|
||||
onCompleted,
|
||||
}: Props) => {
|
||||
const { typebot } = useTypebot()
|
||||
const { typebot, updateVariableValue } = useTypebot()
|
||||
const { document: frameDocument } = useFrame()
|
||||
const [displayedBlocks, setDisplayedBlocks] = useState<
|
||||
{ block: PublicBlock; startStepIndex: number }[]
|
||||
@ -48,10 +48,21 @@ export const ConversationContainer = ({
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
injectUrlParamsIntoVariables()
|
||||
displayNextBlock(typebot.blocks[0].steps[0].outgoingEdgeId)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
const injectUrlParamsIntoVariables = () => {
|
||||
const urlParams = new URLSearchParams(location.search)
|
||||
urlParams.forEach((value, key) => {
|
||||
const matchingVariable = typebot.variables.find(
|
||||
(v) => v.name.toLowerCase() === key.toLowerCase()
|
||||
)
|
||||
if (matchingVariable) updateVariableValue(matchingVariable?.id, value)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setCssVariablesValue(theme, frameDocument.body.style)
|
||||
}, [theme, frameDocument])
|
||||
|
@ -31,7 +31,10 @@ export const TypebotContext = ({
|
||||
const [localTypebot, setLocalTypebot] = useState<PublicTypebot>(typebot)
|
||||
|
||||
useEffect(() => {
|
||||
setLocalTypebot({ ...localTypebot, theme: typebot.theme })
|
||||
setLocalTypebot((localTypebot) => ({
|
||||
...localTypebot,
|
||||
theme: typebot.theme,
|
||||
}))
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [typebot.theme])
|
||||
|
||||
|
Reference in New Issue
Block a user