2
0

🚸 (templates) Add category and description in templates modal

This commit is contained in:
Baptiste Arnaud
2023-04-20 10:49:25 +02:00
parent b614544909
commit 4d1fe4c1de
15 changed files with 214 additions and 93 deletions

View File

@ -228,7 +228,7 @@
}, },
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,
"isNewResultOnRefreshEnabled": true "isNewResultOnRefreshEnabled": true

View File

@ -787,7 +787,7 @@
"selectedThemeTemplateId": null, "selectedThemeTemplateId": null,
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,
"isNewResultOnRefreshEnabled": true "isNewResultOnRefreshEnabled": true

View File

@ -429,7 +429,7 @@
}, },
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isResultSavingEnabled": true, "isResultSavingEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,

View File

@ -447,7 +447,7 @@
}, },
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isResultSavingEnabled": true, "isResultSavingEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,

View File

@ -528,7 +528,7 @@
}, },
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isResultSavingEnabled": true, "isResultSavingEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,

View File

@ -333,7 +333,7 @@
}, },
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isResultSavingEnabled": true, "isResultSavingEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,

View File

@ -583,7 +583,7 @@
"selectedThemeTemplateId": null, "selectedThemeTemplateId": null,
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,
"isNewResultOnRefreshEnabled": true "isNewResultOnRefreshEnabled": true

View File

@ -760,7 +760,7 @@
}, },
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isResultSavingEnabled": true, "isResultSavingEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,

View File

@ -620,7 +620,7 @@
}, },
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,
"isNewResultOnRefreshEnabled": true "isNewResultOnRefreshEnabled": true

View File

@ -697,7 +697,7 @@
}, },
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isResultSavingEnabled": true, "isResultSavingEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,

View File

@ -441,7 +441,7 @@
}, },
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isResultSavingEnabled": true, "isResultSavingEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,

View File

@ -907,7 +907,7 @@
}, },
"settings": { "settings": {
"general": { "general": {
"isBrandingEnabled": true, "isBrandingEnabled": false,
"isInputPrefillEnabled": true, "isInputPrefillEnabled": true,
"isResultSavingEnabled": true, "isResultSavingEnabled": true,
"isHideQueryParamsEnabled": true, "isHideQueryParamsEnabled": true,

View File

@ -1,9 +1,7 @@
import { import {
Button, Button,
chakra,
Divider,
Heading,
HStack, HStack,
Heading,
Modal, Modal,
ModalBody, ModalBody,
ModalContent, ModalContent,
@ -11,9 +9,9 @@ import {
Stack, Stack,
Tag, Tag,
Text, Text,
Tooltip, chakra,
useColorModeValue,
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { ExternalLinkIcon } from '@/components/icons'
import { Standard } from '@typebot.io/react' import { Standard } from '@typebot.io/react'
import { Typebot } from '@typebot.io/schemas' import { Typebot } from '@typebot.io/schemas'
import React, { useCallback, useEffect, useState } from 'react' import React, { useCallback, useEffect, useState } from 'react'
@ -29,6 +27,7 @@ type Props = {
} }
export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => { export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
const templateCardBackgroundColor = useColorModeValue(undefined, 'gray.800')
const [typebot, setTypebot] = useState<Typebot>() const [typebot, setTypebot] = useState<Typebot>()
const [selectedTemplate, setSelectedTemplate] = useState<TemplateProps>( const [selectedTemplate, setSelectedTemplate] = useState<TemplateProps>(
templates[0] templates[0]
@ -64,17 +63,140 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
<Modal <Modal
isOpen={isOpen} isOpen={isOpen}
onClose={onClose} onClose={onClose}
size="6xl"
blockScrollOnMount={false} blockScrollOnMount={false}
size="6xl"
> >
<ModalOverlay /> <ModalOverlay />
<ModalContent h="85vh"> <ModalContent h="85vh">
<ModalBody h="full" as={HStack} p="0" spacing="0"> <ModalBody h="full" as={HStack} p="0" spacing="0">
<Stack w="full" h="full" spacing="4"> <Stack
<Heading pl="10" pt="4" fontSize="2xl"> h="full"
{selectedTemplate.emoji}{' '} w="300px"
<chakra.span ml="2">{selectedTemplate.name}</chakra.span> py="4"
</Heading> px="2"
borderRightWidth={1}
justify="space-between"
flexShrink={0}
>
<Stack spacing={5}>
<Stack spacing={2}>
<Text
fontSize="xs"
fontWeight="semibold"
pl="1"
color="gray.500"
>
Marketing
</Text>
{templates
.filter((template) => template.category === 'marketing')
.map((template) => (
<Button
size="sm"
key={template.name}
onClick={() => fetchTemplate(template)}
w="full"
variant={
selectedTemplate.name === template.name
? 'solid'
: 'ghost'
}
isDisabled={template.isComingSoon}
>
<HStack overflow="hidden" fontSize="sm" w="full">
<Text>{template.emoji}</Text>
<Text>{template.name}</Text>
{template.isNew && (
<Tag colorScheme="orange" size="sm" flexShrink={0}>
New
</Tag>
)}
</HStack>
</Button>
))}
</Stack>
<Stack spacing={2}>
<Text
fontSize="xs"
fontWeight="semibold"
pl="1"
color="gray.500"
>
Product
</Text>
{templates
.filter((template) => template.category === 'product')
.map((template) => (
<Button
size="sm"
key={template.name}
onClick={() => fetchTemplate(template)}
w="full"
variant={
selectedTemplate.name === template.name
? 'solid'
: 'ghost'
}
isDisabled={template.isComingSoon}
>
<HStack overflow="hidden" fontSize="sm" w="full">
<Text>{template.emoji}</Text>
<Text>{template.name}</Text>
{template.isNew && (
<Tag colorScheme="orange" size="sm" flexShrink={0}>
New
</Tag>
)}
</HStack>
</Button>
))}
</Stack>
<Stack spacing={2}>
<Text
fontSize="xs"
fontWeight="semibold"
pl="1"
color="gray.500"
>
Other
</Text>
{templates
.filter((template) => template.category === undefined)
.map((template) => (
<Button
size="sm"
key={template.name}
onClick={() => fetchTemplate(template)}
w="full"
variant={
selectedTemplate.name === template.name
? 'solid'
: 'ghost'
}
isDisabled={template.isComingSoon}
>
<HStack overflow="hidden" fontSize="sm" w="full">
<Text>{template.emoji}</Text>
<Text>{template.name}</Text>
{template.isNew && (
<Tag colorScheme="orange" size="sm" flexShrink={0}>
New
</Tag>
)}
</HStack>
</Button>
))}
</Stack>
</Stack>
</Stack>
<Stack
w="full"
h="full"
spacing="4"
align="center"
pb="4"
bgColor="white"
>
{typebot && ( {typebot && (
<Standard <Standard
key={typebot.id} key={typebot.id}
@ -85,17 +207,21 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
}} }}
/> />
)} )}
</Stack> <HStack
p="6"
<Stack borderWidth={1}
h="full" rounded="md"
py="6" w="95%"
w="300px" spacing={4}
px="4" bgColor={templateCardBackgroundColor}
borderLeftWidth={1} >
justify="space-between" <Stack flex="1" spacing={4}>
> <Heading fontSize="2xl">
<Stack spacing={4}> {selectedTemplate.emoji}{' '}
<chakra.span ml="2">{selectedTemplate.name}</chakra.span>
</Heading>
<Text>{selectedTemplate.description}</Text>
</Stack>
<Button <Button
colorScheme="blue" colorScheme="blue"
onClick={onUseThisTemplateClick} onClick={onUseThisTemplateClick}
@ -103,61 +229,7 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
> >
Use this template Use this template
</Button> </Button>
<Divider /> </HStack>
<Stack>
{templates.map((template) => (
<Tooltip
key={template.name}
isDisabled={!template.isComingSoon}
label="Coming soon!"
>
<span>
<Button
onClick={() => fetchTemplate(template)}
w="full"
variant={
selectedTemplate.name === template.name
? 'solid'
: 'ghost'
}
isDisabled={template.isComingSoon}
>
<HStack justifyContent="space-between" w="full">
<HStack overflow="hidden">
<Text>{template.emoji}</Text>
<Text noOfLines={0} display="block">
{template.name}
</Text>
</HStack>
{template.isNew && (
<Tag colorScheme="orange" size="sm" flexShrink={0}>
New
</Tag>
)}
</HStack>
</Button>
</span>
</Tooltip>
))}
</Stack>
</Stack>
<Stack>
<Divider />
<Tooltip label="Coming soon!" placement="top">
<span>
<Button
w="full"
variant="ghost"
isDisabled
leftIcon={<ExternalLinkIcon />}
>
Community templates
</Button>
</span>
</Tooltip>
</Stack>
</Stack> </Stack>
</ModalBody> </ModalBody>
</ModalContent> </ModalContent>

View File

@ -1,50 +1,97 @@
import { TemplateProps } from './types' import { TemplateProps } from './types'
export const templates: TemplateProps[] = [ export const templates: TemplateProps[] = [
{ name: 'Lead Generation', emoji: '🤝', fileName: 'lead-gen.json' }, {
{ name: 'Customer Support', emoji: '😍', fileName: 'customer-support.json' }, name: 'Lead Generation',
{ name: 'Quiz', emoji: '🕹️', fileName: 'quiz.json' }, emoji: '🤝',
{ name: 'Lead Scoring', emoji: '🏆', fileName: 'lead-scoring.json' }, fileName: 'lead-gen.json',
category: 'marketing',
description:
'You are a marketing agency and this bot allows you generate new leads interested in your services',
},
{
name: 'Customer Support',
emoji: '😍',
fileName: 'customer-support.json',
category: 'product',
description:
'A bot whose job is to collect user feedback: questions, bugs and feature requests.',
},
{
name: 'Quiz',
emoji: '🕹️',
fileName: 'quiz.json',
category: 'marketing',
description:
'A fun quizz to engage with your users and collect their emails',
},
{
name: 'Lead Scoring',
emoji: '🏆',
fileName: 'lead-scoring.json',
category: 'marketing',
description:
'Compute a score alongside lead qualification questions to rank your new prospects',
},
{ {
name: 'Lead magnet', name: 'Lead magnet',
emoji: '🧲', emoji: '🧲',
fileName: 'lead-magnet.json', fileName: 'lead-magnet.json',
category: 'marketing',
isNew: true, isNew: true,
description:
'Provide a free content to your prospects in exchange for their contact information.',
}, },
{ {
name: 'NPS Survey', name: 'NPS Survey',
emoji: '⭐', emoji: '⭐',
fileName: 'nps.json', fileName: 'nps.json',
category: 'product',
description:
'A simple NPS survey to measure your customer satisfaction and improve your product',
}, },
{ {
name: 'User Onboarding', name: 'User Onboarding',
emoji: '🧑‍🚀', emoji: '🧑‍🚀',
fileName: 'onboarding.json', fileName: 'onboarding.json',
category: 'product',
description:
'A bot that asks for new user information before he start using your product',
}, },
{ {
name: 'Digital Product Payment', name: 'Digital Product Payment',
emoji: '🖼️', emoji: '🖼️',
fileName: 'digital-product-payment.json', fileName: 'digital-product-payment.json',
description:
'A bot that allows you to sell digital products (ebooks, courses, etc.) and only provide the content after the payment is confirmed',
}, },
{ {
name: 'FAQ', name: 'FAQ',
emoji: '💬', emoji: '💬',
fileName: 'faq.json', fileName: 'faq.json',
category: 'product',
description:
'A bot that answers frequently asked questions about your product or service',
}, },
{ {
name: 'Movie Recommendation', name: 'Movie Recommendation',
emoji: '🍿', emoji: '🍿',
fileName: 'movie-recommendation.json', fileName: 'movie-recommendation.json',
description: 'A bot that recommends movies based on the user preferences',
}, },
{ {
name: 'Basic ChatGPT', name: 'Basic ChatGPT',
emoji: '🤖', emoji: '🤖',
fileName: 'basic-chat-gpt.json', fileName: 'basic-chat-gpt.json',
description:
'A bot that uses the ChatGPT model to generate responses based on the user input',
}, },
{ {
name: 'ChatGPT personas', name: 'ChatGPT personas',
emoji: '🎭', emoji: '🎭',
fileName: 'chat-gpt-personas.json', fileName: 'chat-gpt-personas.json',
isNew: true, isNew: true,
description:
'A bot that uses the ChatGPT model to generate responses based on the user input and the selected persona',
}, },
] ]

View File

@ -2,6 +2,8 @@ export type TemplateProps = {
name: string name: string
emoji: string emoji: string
fileName: string fileName: string
description: string
category?: 'marketing' | 'product'
isComingSoon?: boolean isComingSoon?: boolean
isNew?: boolean isNew?: boolean
} }