2
0

🚸 Update onboarding bot

Closes #400
This commit is contained in:
Baptiste Arnaud
2023-07-25 09:12:53 +02:00
parent b17177f35f
commit 283c55c1a4
9 changed files with 55 additions and 50 deletions

View File

@ -1,47 +1,26 @@
import { chakra, useColorModeValue } from '@chakra-ui/react'
import { Popup } from '@typebot.io/nextjs'
import { useUser } from '@/features/account/hooks/useUser'
import { Typebot } from '@typebot.io/schemas'
import React, { useEffect, useRef, useState } from 'react'
import { sendRequest } from '@typebot.io/lib'
import confetti from 'canvas-confetti'
import { useToast } from '@/hooks/useToast'
import { useRouter } from 'next/router'
type Props = { totalTypebots: number }
export const OnboardingModal = ({ totalTypebots }: Props) => {
const { push } = useRouter()
const botPath = useColorModeValue(
'/bots/onboarding.json',
'/bots/onboarding-dark.json'
)
const backgroundColor = useColorModeValue('white', '#171923')
const { user, updateUser } = useUser()
const [typebot, setTypebot] = useState<Typebot>()
const confettiCanvaContainer = useRef<HTMLCanvasElement | null>(null)
const confettiCanon = useRef<confetti.CreateTypes>()
const [chosenCategories, setChosenCategories] = useState<string[]>([])
const { showToast } = useToast()
const isNewUser =
user &&
new Date(user?.createdAt as unknown as string).toDateString() ===
new Date().toDateString() &&
totalTypebots === 0
useEffect(() => {
const fetchTemplate = async () => {
const { data, error } = await sendRequest(botPath)
if (error)
return showToast({ title: error.name, description: error.message })
setTypebot(data as Typebot)
}
fetchTemplate()
}, [botPath, showToast])
useEffect(() => {
initConfettis()
}, [])
@ -68,12 +47,11 @@ export const OnboardingModal = ({ totalTypebots }: Props) => {
const isCompany = answer.blockId === 'cl126jioz000v2e6dwrk1f2cb'
const isCategories = answer.blockId === 'cl126lb8v00142e6duv5qe08l'
const isOtherCategories = answer.blockId === 'cl126pv7n001o2e6dajltc4qz'
const answeredAllQuestions =
isOtherCategories || (isCategories && !answer.message.includes('Other'))
if (answeredAllQuestions && confettiCanon.current)
shootConfettis(confettiCanon.current)
if (isName) updateUser({ name: answer.message })
if (isCompany) updateUser({ company: answer.message })
if (isCompany) {
updateUser({ company: answer.message })
if (confettiCanon.current) shootConfettis(confettiCanon.current)
}
if (isCategories) {
const onboardingCategories = answer.message.split(', ')
updateUser({ onboardingCategories })
@ -97,14 +75,16 @@ export const OnboardingModal = ({ totalTypebots }: Props) => {
zIndex={9999}
pointerEvents="none"
/>
{typebot && (
{user?.email && (
<Popup
typebot={typebot}
typebot="onboarding-typebot"
prefilledVariables={{
Name: user?.name?.split(' ')[0] ?? undefined,
Name: user.name?.split(' ')[0] ?? undefined,
Email: user.email ?? undefined,
}}
theme={{
backgroundColor,
zIndex: 100,
}}
defaultOpen={isNewUser}
onAnswer={handleNewAnswer}

View File

@ -26,6 +26,7 @@ import { TypebotCardOverlay } from './TypebotButtonOverlay'
import { useI18n } from '@/locales'
import { useTypebots } from '@/features/dashboard/hooks/useTypebots'
import { TypebotInDashboard } from '@/features/dashboard/types'
import { isCloudProdInstance } from '@/helpers/isCloudProdInstance'
type Props = { folder: DashboardFolder | null }
@ -160,7 +161,9 @@ export const FolderContent = ({ folder }: Props) => {
return (
<Flex w="full" flex="1" justify="center">
{typebots && <OnboardingModal totalTypebots={typebots.length} />}
{typebots && isCloudProdInstance && (
<OnboardingModal totalTypebots={typebots.length} />
)}
<Stack w="1000px" spacing={6}>
<Skeleton isLoaded={folder?.name !== undefined}>
<Heading as="h1">{folder?.name}</Heading>

View File

@ -1,6 +1,6 @@
{
"name": "@typebot.io/js",
"version": "0.1.7",
"version": "0.1.8",
"description": "Javascript library to display typebots on your website",
"type": "module",
"main": "dist/index.js",

View File

@ -112,7 +112,7 @@ export const Popup = (props: PopupProps) => {
role="dialog"
aria-modal="true"
style={{
'z-index': 42424242,
'z-index': props.theme?.zIndex ?? 42424242,
}}
>
<style>{styles}</style>

View File

@ -3,5 +3,6 @@ export type PopupParams = {
theme?: {
width?: string
backgroundColor?: string
zIndex?: number
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@typebot.io/nextjs",
"version": "0.1.7",
"version": "0.1.8",
"description": "Convenient library to display typebots on your Next.js website",
"main": "dist/index.js",
"types": "dist/index.d.ts",

View File

@ -1,6 +1,6 @@
{
"name": "@typebot.io/react",
"version": "0.1.7",
"version": "0.1.8",
"description": "Convenient library to display typebots on your Next.js website",
"main": "dist/index.js",
"types": "dist/index.d.ts",

View File

@ -18,22 +18,29 @@ declare global {
type BubbleElement = HTMLElement & Props
export const Bubble = (props: Props) => {
const ref = useRef<BubbleElement | null>(null)
const bubbleElement = useRef<BubbleElement | null>(null)
const attachBubbleToDom = useCallback((props: Props) => {
const bubbleElement = document.createElement(
const newBubbleElement = document.createElement(
'typebot-bubble'
) as BubbleElement
ref.current = bubbleElement
injectPropsToElement(ref.current, props)
document.body.append(ref.current)
bubbleElement.current = newBubbleElement
injectPropsToElement(bubbleElement.current, props)
document.body.append(bubbleElement.current)
}, [])
useEffect(() => {
if (!ref.current) attachBubbleToDom(props)
injectPropsToElement(ref.current as BubbleElement, props)
if (!bubbleElement.current) attachBubbleToDom(props)
injectPropsToElement(bubbleElement.current as BubbleElement, props)
}, [attachBubbleToDom, props])
useEffect(() => {
return () => {
bubbleElement.current?.remove()
bubbleElement.current = null
}
}, [])
const injectPropsToElement = (element: BubbleElement, props: Props) => {
Object.assign(element, props)
}

View File

@ -18,25 +18,39 @@ declare global {
type PopupElement = HTMLElement & Props
export const Popup = (props: Props) => {
const ref = useRef<PopupElement | null>(null)
const containerRef = useRef<HTMLDivElement | null>(null)
const popupRef = useRef<PopupElement | null>(null)
const attachPopupToDom = useCallback((props: Props) => {
const attachPopupToContainer = useCallback((props: Props) => {
const popupElement = document.createElement('typebot-popup') as PopupElement
ref.current = popupElement
injectPropsToElement(ref.current, props)
document.body.append(ref.current)
popupRef.current = popupElement
injectPropsToElement(popupRef.current, props)
if (!containerRef.current) {
console.warn(
'Could not attach popup to container because containerRef.current is null'
)
return
}
containerRef.current?.append(popupRef.current)
}, [])
useEffect(() => {
if (!ref.current) attachPopupToDom(props)
injectPropsToElement(ref.current as PopupElement, props)
}, [attachPopupToDom, props])
if (!popupRef.current) attachPopupToContainer(props)
injectPropsToElement(popupRef.current as PopupElement, props)
}, [attachPopupToContainer, props])
useEffect(() => {
return () => {
popupRef.current?.remove()
popupRef.current = null
}
}, [])
const injectPropsToElement = (element: PopupElement, props: Props) => {
Object.assign(element, props)
}
return null
return <div ref={containerRef} />
}
export default Popup