2
0
Files
bot/packages/bot-engine/src/components/ConversationContainer.tsx

77 lines
2.4 KiB
TypeScript
Raw Normal View History

import React, { useEffect, useRef, useState } from 'react'
import { ChatBlock } from './ChatBlock/ChatBlock'
2021-12-23 09:37:42 +01:00
import { useFrame } from 'react-frame-component'
import { setCssVariablesValue } from '../services/theme'
import { useAnswers } from '../contexts/AnswersContext'
import { deepEqual } from 'fast-equals'
2022-01-15 17:30:20 +01:00
import { Answer, Block, PublicTypebot, Target } from 'models'
type Props = {
typebot: PublicTypebot
onNewBlockVisible: (blockId: string) => void
2021-12-30 10:24:16 +01:00
onNewAnswer: (answer: Answer) => void
onCompleted: () => void
}
export const ConversationContainer = ({
typebot,
onNewBlockVisible,
2021-12-30 10:24:16 +01:00
onNewAnswer,
onCompleted,
}: Props) => {
2021-12-23 09:37:42 +01:00
const { document: frameDocument } = useFrame()
2022-01-15 17:30:20 +01:00
const [displayedBlocks, setDisplayedBlocks] = useState<
{ block: Block; startStepId?: string }[]
>([])
2021-12-30 10:24:16 +01:00
const [localAnswer, setLocalAnswer] = useState<Answer | undefined>()
const { answers } = useAnswers()
const bottomAnchor = useRef<HTMLDivElement | null>(null)
2022-01-15 17:30:20 +01:00
const displayNextBlock = (target?: Target) => {
if (!target) return onCompleted()
const nextBlock = {
block: typebot.blocks.byId[target.blockId],
startStepId: target.stepId,
}
if (!nextBlock) return onCompleted()
2022-01-15 17:30:20 +01:00
onNewBlockVisible(target.blockId)
setDisplayedBlocks([...displayedBlocks, nextBlock])
}
useEffect(() => {
2022-01-06 09:40:56 +01:00
const blocks = typebot.blocks
2022-01-15 17:30:20 +01:00
const firstTarget =
2022-01-06 09:40:56 +01:00
typebot.steps.byId[blocks.byId[blocks.allIds[0]].stepIds[0]].target
2022-01-15 17:30:20 +01:00
if (firstTarget) displayNextBlock(firstTarget)
}, [])
2021-12-23 09:37:42 +01:00
useEffect(() => {
setCssVariablesValue(typebot.theme, frameDocument.body.style)
}, [typebot.theme, frameDocument])
useEffect(() => {
2021-12-30 10:24:16 +01:00
const answer = [...answers].pop()
if (!answer || deepEqual(localAnswer, answer)) return
setLocalAnswer(answer)
onNewAnswer(answer)
}, [answers])
return (
<div
className="overflow-y-scroll w-full lg:w-3/4 min-h-full rounded lg:px-5 px-3 pt-10 relative scrollable-container typebot-chat-view"
id="scrollable-container"
>
2022-01-15 17:30:20 +01:00
{displayedBlocks.map((displayedBlock, idx) => (
<ChatBlock
2022-01-15 17:30:20 +01:00
key={displayedBlock.block.id + idx}
stepIds={displayedBlock.block.stepIds}
startStepId={displayedBlock.startStepId}
onBlockEnd={displayNextBlock}
/>
))}
{/* We use a block to simulate padding because it makes iOS scroll flicker */}
<div className="w-full" ref={bottomAnchor} />
</div>
)
}