2
0

⚗️ Implement bot v2 MVP (#194)

Closes #190
This commit is contained in:
Baptiste Arnaud
2022-12-22 17:02:34 +01:00
committed by GitHub
parent e55823e011
commit 1a3869ae6d
202 changed files with 8060 additions and 1152 deletions

View File

@@ -8,6 +8,10 @@ import { ErrorPage } from './ErrorPage'
import { createResultQuery, updateResultQuery } from '@/features/results'
import { upsertAnswerQuery } from '@/features/answers'
import { gtmBodyElement } from '@/lib/google-tag-manager'
import {
getExistingResultFromSession,
setResultInSession,
} from '@/utils/sessionStorage'
export type TypebotPageProps = {
publishedTypebot: Omit<PublicTypebot, 'createdAt' | 'updatedAt'> & {
@@ -18,8 +22,6 @@ export type TypebotPageProps = {
customHeadCode: string | null
}
const sessionStorageKey = 'resultId'
export const TypebotPage = ({
publishedTypebot,
isIE,
@@ -153,15 +155,3 @@ export const TypebotPage = ({
</div>
)
}
const getExistingResultFromSession = () => {
try {
return sessionStorage.getItem(sessionStorageKey)
} catch {}
}
const setResultInSession = (resultId: string) => {
try {
return sessionStorage.setItem(sessionStorageKey, resultId)
} catch {}
}

View File

@@ -0,0 +1,110 @@
import { getInitialChatReplyQuery } from '@/queries/getInitialChatReplyQuery'
import {
getExistingResultFromSession,
setResultInSession,
} from '@/utils/sessionStorage'
import Bot from '@typebot.io/react'
import { BackgroundType, InitialChatReply, Typebot } from 'models'
import { useRouter } from 'next/router'
import { useCallback, useEffect, useState } from 'react'
import { ErrorPage } from './ErrorPage'
import { SEO } from './Seo'
export type TypebotPageV2Props = {
url: string
typebot: Pick<
Typebot,
'settings' | 'theme' | 'id' | 'name' | 'isClosed' | 'isArchived'
>
}
let hasInitializedChat = false
export const TypebotPageV2 = ({ url, typebot }: TypebotPageV2Props) => {
const { asPath, push } = useRouter()
const [initialChatReply, setInitialChatReply] = useState<InitialChatReply>()
const [error, setError] = useState<Error | undefined>(undefined)
const background = typebot.theme.general.background
const clearQueryParamsIfNecessary = useCallback(() => {
const hasQueryParams = asPath.includes('?')
if (
!hasQueryParams ||
!(typebot.settings.general.isHideQueryParamsEnabled ?? true)
)
return
push(asPath.split('?')[0], undefined, { shallow: true })
}, [asPath, push, typebot.settings.general.isHideQueryParamsEnabled])
useEffect(() => {
clearQueryParamsIfNecessary()
}, [clearQueryParamsIfNecessary])
useEffect(() => {
if (hasInitializedChat) return
hasInitializedChat = true
const prefilledVariables = extractPrefilledVariables()
const existingResultId = getExistingResultFromSession() ?? undefined
getInitialChatReplyQuery({
typebotId: typebot.id,
resultId:
typebot.settings.general.isNewResultOnRefreshEnabled ?? false
? undefined
: existingResultId,
prefilledVariables,
}).then(({ data, error }) => {
if (error && 'code' in error && error.code === 'FORBIDDEN') {
setError(new Error('This bot is now closed.'))
return
}
if (!data) return setError(new Error("Couldn't initiate the chat"))
setInitialChatReply(data)
setResultInSession(data.resultId)
})
}, [
initialChatReply,
typebot.id,
typebot.settings.general.isNewResultOnRefreshEnabled,
])
if (error) {
return <ErrorPage error={error} />
}
return (
<div
style={{
height: '100vh',
// Set background color to avoid SSR flash
backgroundColor:
background.type === BackgroundType.COLOR
? background.content
: 'white',
}}
>
<SEO
url={url}
typebotName={typebot.name}
metadata={typebot.settings.metadata}
/>
{initialChatReply && (
<Bot.Standard
typebotId={typebot.id}
initialChatReply={initialChatReply}
/>
)}
</div>
)
}
const extractPrefilledVariables = () => {
const urlParams = new URLSearchParams(location.search)
const prefilledVariables: { [key: string]: string } = {}
urlParams.forEach((value, key) => {
prefilledVariables[key] = value
})
return prefilledVariables
}