@@ -1,47 +1,26 @@
|
|||||||
import { chakra, useColorModeValue } from '@chakra-ui/react'
|
import { chakra, useColorModeValue } from '@chakra-ui/react'
|
||||||
import { Popup } from '@typebot.io/nextjs'
|
import { Popup } from '@typebot.io/nextjs'
|
||||||
import { useUser } from '@/features/account/hooks/useUser'
|
import { useUser } from '@/features/account/hooks/useUser'
|
||||||
import { Typebot } from '@typebot.io/schemas'
|
|
||||||
import React, { useEffect, useRef, useState } from 'react'
|
import React, { useEffect, useRef, useState } from 'react'
|
||||||
import { sendRequest } from '@typebot.io/lib'
|
|
||||||
import confetti from 'canvas-confetti'
|
import confetti from 'canvas-confetti'
|
||||||
import { useToast } from '@/hooks/useToast'
|
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
type Props = { totalTypebots: number }
|
type Props = { totalTypebots: number }
|
||||||
|
|
||||||
export const OnboardingModal = ({ totalTypebots }: Props) => {
|
export const OnboardingModal = ({ totalTypebots }: Props) => {
|
||||||
const { push } = useRouter()
|
const { push } = useRouter()
|
||||||
const botPath = useColorModeValue(
|
|
||||||
'/bots/onboarding.json',
|
|
||||||
'/bots/onboarding-dark.json'
|
|
||||||
)
|
|
||||||
const backgroundColor = useColorModeValue('white', '#171923')
|
const backgroundColor = useColorModeValue('white', '#171923')
|
||||||
const { user, updateUser } = useUser()
|
const { user, updateUser } = useUser()
|
||||||
const [typebot, setTypebot] = useState<Typebot>()
|
|
||||||
const confettiCanvaContainer = useRef<HTMLCanvasElement | null>(null)
|
const confettiCanvaContainer = useRef<HTMLCanvasElement | null>(null)
|
||||||
const confettiCanon = useRef<confetti.CreateTypes>()
|
const confettiCanon = useRef<confetti.CreateTypes>()
|
||||||
const [chosenCategories, setChosenCategories] = useState<string[]>([])
|
const [chosenCategories, setChosenCategories] = useState<string[]>([])
|
||||||
|
|
||||||
const { showToast } = useToast()
|
|
||||||
|
|
||||||
const isNewUser =
|
const isNewUser =
|
||||||
user &&
|
user &&
|
||||||
new Date(user?.createdAt as unknown as string).toDateString() ===
|
new Date(user?.createdAt as unknown as string).toDateString() ===
|
||||||
new Date().toDateString() &&
|
new Date().toDateString() &&
|
||||||
totalTypebots === 0
|
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(() => {
|
useEffect(() => {
|
||||||
initConfettis()
|
initConfettis()
|
||||||
}, [])
|
}, [])
|
||||||
@@ -68,12 +47,11 @@ export const OnboardingModal = ({ totalTypebots }: Props) => {
|
|||||||
const isCompany = answer.blockId === 'cl126jioz000v2e6dwrk1f2cb'
|
const isCompany = answer.blockId === 'cl126jioz000v2e6dwrk1f2cb'
|
||||||
const isCategories = answer.blockId === 'cl126lb8v00142e6duv5qe08l'
|
const isCategories = answer.blockId === 'cl126lb8v00142e6duv5qe08l'
|
||||||
const isOtherCategories = answer.blockId === 'cl126pv7n001o2e6dajltc4qz'
|
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 (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) {
|
if (isCategories) {
|
||||||
const onboardingCategories = answer.message.split(', ')
|
const onboardingCategories = answer.message.split(', ')
|
||||||
updateUser({ onboardingCategories })
|
updateUser({ onboardingCategories })
|
||||||
@@ -97,14 +75,16 @@ export const OnboardingModal = ({ totalTypebots }: Props) => {
|
|||||||
zIndex={9999}
|
zIndex={9999}
|
||||||
pointerEvents="none"
|
pointerEvents="none"
|
||||||
/>
|
/>
|
||||||
{typebot && (
|
{user?.email && (
|
||||||
<Popup
|
<Popup
|
||||||
typebot={typebot}
|
typebot="onboarding-typebot"
|
||||||
prefilledVariables={{
|
prefilledVariables={{
|
||||||
Name: user?.name?.split(' ')[0] ?? undefined,
|
Name: user.name?.split(' ')[0] ?? undefined,
|
||||||
|
Email: user.email ?? undefined,
|
||||||
}}
|
}}
|
||||||
theme={{
|
theme={{
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
|
zIndex: 100,
|
||||||
}}
|
}}
|
||||||
defaultOpen={isNewUser}
|
defaultOpen={isNewUser}
|
||||||
onAnswer={handleNewAnswer}
|
onAnswer={handleNewAnswer}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import { TypebotCardOverlay } from './TypebotButtonOverlay'
|
|||||||
import { useI18n } from '@/locales'
|
import { useI18n } from '@/locales'
|
||||||
import { useTypebots } from '@/features/dashboard/hooks/useTypebots'
|
import { useTypebots } from '@/features/dashboard/hooks/useTypebots'
|
||||||
import { TypebotInDashboard } from '@/features/dashboard/types'
|
import { TypebotInDashboard } from '@/features/dashboard/types'
|
||||||
|
import { isCloudProdInstance } from '@/helpers/isCloudProdInstance'
|
||||||
|
|
||||||
type Props = { folder: DashboardFolder | null }
|
type Props = { folder: DashboardFolder | null }
|
||||||
|
|
||||||
@@ -160,7 +161,9 @@ export const FolderContent = ({ folder }: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex w="full" flex="1" justify="center">
|
<Flex w="full" flex="1" justify="center">
|
||||||
{typebots && <OnboardingModal totalTypebots={typebots.length} />}
|
{typebots && isCloudProdInstance && (
|
||||||
|
<OnboardingModal totalTypebots={typebots.length} />
|
||||||
|
)}
|
||||||
<Stack w="1000px" spacing={6}>
|
<Stack w="1000px" spacing={6}>
|
||||||
<Skeleton isLoaded={folder?.name !== undefined}>
|
<Skeleton isLoaded={folder?.name !== undefined}>
|
||||||
<Heading as="h1">{folder?.name}</Heading>
|
<Heading as="h1">{folder?.name}</Heading>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/js",
|
"name": "@typebot.io/js",
|
||||||
"version": "0.1.7",
|
"version": "0.1.8",
|
||||||
"description": "Javascript library to display typebots on your website",
|
"description": "Javascript library to display typebots on your website",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export const Popup = (props: PopupProps) => {
|
|||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
style={{
|
style={{
|
||||||
'z-index': 42424242,
|
'z-index': props.theme?.zIndex ?? 42424242,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<style>{styles}</style>
|
<style>{styles}</style>
|
||||||
|
|||||||
@@ -3,5 +3,6 @@ export type PopupParams = {
|
|||||||
theme?: {
|
theme?: {
|
||||||
width?: string
|
width?: string
|
||||||
backgroundColor?: string
|
backgroundColor?: string
|
||||||
|
zIndex?: number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/nextjs",
|
"name": "@typebot.io/nextjs",
|
||||||
"version": "0.1.7",
|
"version": "0.1.8",
|
||||||
"description": "Convenient library to display typebots on your Next.js website",
|
"description": "Convenient library to display typebots on your Next.js website",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/react",
|
"name": "@typebot.io/react",
|
||||||
"version": "0.1.7",
|
"version": "0.1.8",
|
||||||
"description": "Convenient library to display typebots on your Next.js website",
|
"description": "Convenient library to display typebots on your Next.js website",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|||||||
@@ -18,22 +18,29 @@ declare global {
|
|||||||
type BubbleElement = HTMLElement & Props
|
type BubbleElement = HTMLElement & Props
|
||||||
|
|
||||||
export const Bubble = (props: Props) => {
|
export const Bubble = (props: Props) => {
|
||||||
const ref = useRef<BubbleElement | null>(null)
|
const bubbleElement = useRef<BubbleElement | null>(null)
|
||||||
|
|
||||||
const attachBubbleToDom = useCallback((props: Props) => {
|
const attachBubbleToDom = useCallback((props: Props) => {
|
||||||
const bubbleElement = document.createElement(
|
const newBubbleElement = document.createElement(
|
||||||
'typebot-bubble'
|
'typebot-bubble'
|
||||||
) as BubbleElement
|
) as BubbleElement
|
||||||
ref.current = bubbleElement
|
bubbleElement.current = newBubbleElement
|
||||||
injectPropsToElement(ref.current, props)
|
injectPropsToElement(bubbleElement.current, props)
|
||||||
document.body.append(ref.current)
|
document.body.append(bubbleElement.current)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ref.current) attachBubbleToDom(props)
|
if (!bubbleElement.current) attachBubbleToDom(props)
|
||||||
injectPropsToElement(ref.current as BubbleElement, props)
|
injectPropsToElement(bubbleElement.current as BubbleElement, props)
|
||||||
}, [attachBubbleToDom, props])
|
}, [attachBubbleToDom, props])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
bubbleElement.current?.remove()
|
||||||
|
bubbleElement.current = null
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
const injectPropsToElement = (element: BubbleElement, props: Props) => {
|
const injectPropsToElement = (element: BubbleElement, props: Props) => {
|
||||||
Object.assign(element, props)
|
Object.assign(element, props)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,25 +18,39 @@ declare global {
|
|||||||
type PopupElement = HTMLElement & Props
|
type PopupElement = HTMLElement & Props
|
||||||
|
|
||||||
export const Popup = (props: 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
|
const popupElement = document.createElement('typebot-popup') as PopupElement
|
||||||
ref.current = popupElement
|
popupRef.current = popupElement
|
||||||
injectPropsToElement(ref.current, props)
|
injectPropsToElement(popupRef.current, props)
|
||||||
document.body.append(ref.current)
|
if (!containerRef.current) {
|
||||||
|
console.warn(
|
||||||
|
'Could not attach popup to container because containerRef.current is null'
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
containerRef.current?.append(popupRef.current)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ref.current) attachPopupToDom(props)
|
if (!popupRef.current) attachPopupToContainer(props)
|
||||||
injectPropsToElement(ref.current as PopupElement, props)
|
injectPropsToElement(popupRef.current as PopupElement, props)
|
||||||
}, [attachPopupToDom, props])
|
}, [attachPopupToContainer, props])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
popupRef.current?.remove()
|
||||||
|
popupRef.current = null
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
const injectPropsToElement = (element: PopupElement, props: Props) => {
|
const injectPropsToElement = (element: PopupElement, props: Props) => {
|
||||||
Object.assign(element, props)
|
Object.assign(element, props)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return <div ref={containerRef} />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Popup
|
export default Popup
|
||||||
|
|||||||
Reference in New Issue
Block a user