✨ (lp) Add custom chats and storage in pricing cards
This commit is contained in:
@ -18,15 +18,19 @@ const DashboardPage = () => {
|
|||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const subscribePlan = query.subscribePlan as Plan | undefined
|
const { subscribePlan, chats, storage } = query as {
|
||||||
|
subscribePlan: Plan | undefined
|
||||||
|
chats: string | undefined
|
||||||
|
storage: string | undefined
|
||||||
|
}
|
||||||
if (workspace && subscribePlan && user && workspace.plan === 'FREE') {
|
if (workspace && subscribePlan && user && workspace.plan === 'FREE') {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
pay({
|
pay({
|
||||||
user,
|
user,
|
||||||
plan: subscribePlan,
|
plan: subscribePlan,
|
||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
additionalChats: 0,
|
additionalChats: chats ? parseInt(chats) : 0,
|
||||||
additionalStorage: 0,
|
additionalStorage: storage ? parseInt(storage) : 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [query, user, workspace])
|
}, [query, user, workspace])
|
||||||
|
45
apps/landing-page/components/PricingPage/FreePlanCard.tsx
Normal file
45
apps/landing-page/components/PricingPage/FreePlanCard.tsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { chakra, Tooltip, Text } from '@chakra-ui/react'
|
||||||
|
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
|
||||||
|
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||||
|
import React from 'react'
|
||||||
|
import { PricingCard } from './PricingCard'
|
||||||
|
import { ActionButton } from './PricingCard/ActionButton'
|
||||||
|
|
||||||
|
export const FreePlanCard = () => (
|
||||||
|
<PricingCard
|
||||||
|
data={{
|
||||||
|
price: 'Free',
|
||||||
|
name: 'Personal',
|
||||||
|
features: [
|
||||||
|
'Unlimited typebots',
|
||||||
|
<>
|
||||||
|
<Text>
|
||||||
|
<chakra.span fontWeight="bold">300 chats</chakra.span> included
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Tooltip
|
||||||
|
hasArrow
|
||||||
|
placement="top"
|
||||||
|
label="A chat is counted whenever a user starts a discussion. It is
|
||||||
|
independant of the number of messages he sends and receives."
|
||||||
|
>
|
||||||
|
<chakra.span cursor="pointer" h="7">
|
||||||
|
<HelpCircleIcon />
|
||||||
|
</chakra.span>
|
||||||
|
</Tooltip>
|
||||||
|
</>,
|
||||||
|
'Native integrations',
|
||||||
|
'Webhooks',
|
||||||
|
'Custom Javascript & CSS',
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
button={
|
||||||
|
<NextChakraLink
|
||||||
|
href="https://app.typebot.io/register"
|
||||||
|
_hover={{ textDecor: 'none' }}
|
||||||
|
>
|
||||||
|
<ActionButton variant="outline">Get started</ActionButton>
|
||||||
|
</NextChakraLink>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
@ -42,7 +42,7 @@ export const PlanComparisonTables = ({
|
|||||||
</Th>
|
</Th>
|
||||||
<Th>Free</Th>
|
<Th>Free</Th>
|
||||||
<Th color="orange.200">Starter</Th>
|
<Th color="orange.200">Starter</Th>
|
||||||
<Th color="purple.200">Pro</Th>
|
<Th color="blue.200">Pro</Th>
|
||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
<Tbody>
|
<Tbody>
|
||||||
@ -100,7 +100,7 @@ export const PlanComparisonTables = ({
|
|||||||
</Th>
|
</Th>
|
||||||
<Th>Free</Th>
|
<Th>Free</Th>
|
||||||
<Th color="orange.200">Starter</Th>
|
<Th color="orange.200">Starter</Th>
|
||||||
<Th color="purple.200">Pro</Th>
|
<Th color="blue.200">Pro</Th>
|
||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
<Tbody>
|
<Tbody>
|
||||||
|
216
apps/landing-page/components/PricingPage/ProPlanCard.tsx
Normal file
216
apps/landing-page/components/PricingPage/ProPlanCard.tsx
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
import {
|
||||||
|
chakra,
|
||||||
|
Tooltip,
|
||||||
|
Text,
|
||||||
|
Button,
|
||||||
|
HStack,
|
||||||
|
Menu,
|
||||||
|
MenuButton,
|
||||||
|
MenuItem,
|
||||||
|
MenuList,
|
||||||
|
} from '@chakra-ui/react'
|
||||||
|
import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon'
|
||||||
|
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
|
||||||
|
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||||
|
import { Plan } from 'db'
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import {
|
||||||
|
chatsLimit,
|
||||||
|
computePrice,
|
||||||
|
formatPrice,
|
||||||
|
parseNumberWithCommas,
|
||||||
|
storageLimit,
|
||||||
|
} from 'utils'
|
||||||
|
import { PricingCard } from './PricingCard'
|
||||||
|
import { ActionButton } from './PricingCard/ActionButton'
|
||||||
|
|
||||||
|
export const ProPlanCard = () => {
|
||||||
|
const [price, setPrice] = useState('89$')
|
||||||
|
|
||||||
|
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
|
||||||
|
useState<number>(0)
|
||||||
|
const [selectedStorageLimitIndex, setSelectedStorageLimitIndex] =
|
||||||
|
useState<number>(0)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setPrice(
|
||||||
|
formatPrice(
|
||||||
|
computePrice(
|
||||||
|
Plan.PRO,
|
||||||
|
selectedChatsLimitIndex ?? 0,
|
||||||
|
selectedStorageLimitIndex ?? 0
|
||||||
|
) ?? NaN
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}, [selectedChatsLimitIndex, selectedStorageLimitIndex])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PricingCard
|
||||||
|
data={{
|
||||||
|
price,
|
||||||
|
name: 'Pro',
|
||||||
|
featureLabel: 'Everything in Personal, plus:',
|
||||||
|
features: [
|
||||||
|
<Text key="seats">
|
||||||
|
<chakra.span fontWeight="bold">5 seats</chakra.span> included
|
||||||
|
</Text>,
|
||||||
|
<HStack key="chats">
|
||||||
|
<Text>
|
||||||
|
<Menu>
|
||||||
|
<MenuButton
|
||||||
|
as={Button}
|
||||||
|
rightIcon={<ChevronDownIcon />}
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
isLoading={selectedChatsLimitIndex === undefined}
|
||||||
|
>
|
||||||
|
{selectedChatsLimitIndex !== undefined
|
||||||
|
? parseNumberWithCommas(
|
||||||
|
chatsLimit.PRO.totalIncluded +
|
||||||
|
chatsLimit.PRO.increaseStep.amount *
|
||||||
|
selectedChatsLimitIndex
|
||||||
|
)
|
||||||
|
: undefined}
|
||||||
|
</MenuButton>
|
||||||
|
<MenuList>
|
||||||
|
{selectedChatsLimitIndex !== 0 && (
|
||||||
|
<MenuItem onClick={() => setSelectedChatsLimitIndex(0)}>
|
||||||
|
{parseNumberWithCommas(chatsLimit.PRO.totalIncluded)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedChatsLimitIndex !== 1 && (
|
||||||
|
<MenuItem onClick={() => setSelectedChatsLimitIndex(1)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
chatsLimit.PRO.totalIncluded +
|
||||||
|
chatsLimit.PRO.increaseStep.amount
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedChatsLimitIndex !== 2 && (
|
||||||
|
<MenuItem onClick={() => setSelectedChatsLimitIndex(2)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
chatsLimit.PRO.totalIncluded +
|
||||||
|
chatsLimit.PRO.increaseStep.amount * 2
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedChatsLimitIndex !== 3 && (
|
||||||
|
<MenuItem onClick={() => setSelectedChatsLimitIndex(3)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
chatsLimit.PRO.totalIncluded +
|
||||||
|
chatsLimit.PRO.increaseStep.amount * 3
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedChatsLimitIndex !== 4 && (
|
||||||
|
<MenuItem onClick={() => setSelectedChatsLimitIndex(4)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
chatsLimit.PRO.totalIncluded +
|
||||||
|
chatsLimit.PRO.increaseStep.amount * 4
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
</MenuList>
|
||||||
|
</Menu>{' '}
|
||||||
|
chats/mo
|
||||||
|
</Text>
|
||||||
|
<Tooltip
|
||||||
|
hasArrow
|
||||||
|
placement="top"
|
||||||
|
label="A chat is counted whenever a user starts a discussion. It is
|
||||||
|
independant of the number of messages he sends and receives."
|
||||||
|
>
|
||||||
|
<chakra.span cursor="pointer" h="7">
|
||||||
|
<HelpCircleIcon />
|
||||||
|
</chakra.span>
|
||||||
|
</Tooltip>
|
||||||
|
</HStack>,
|
||||||
|
<HStack key="test">
|
||||||
|
<Text>
|
||||||
|
<Menu>
|
||||||
|
<MenuButton
|
||||||
|
as={Button}
|
||||||
|
rightIcon={<ChevronDownIcon />}
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
isLoading={selectedStorageLimitIndex === undefined}
|
||||||
|
>
|
||||||
|
{selectedStorageLimitIndex !== undefined
|
||||||
|
? parseNumberWithCommas(
|
||||||
|
storageLimit.PRO.totalIncluded +
|
||||||
|
storageLimit.PRO.increaseStep.amount *
|
||||||
|
selectedStorageLimitIndex
|
||||||
|
)
|
||||||
|
: undefined}
|
||||||
|
</MenuButton>
|
||||||
|
<MenuList>
|
||||||
|
{selectedStorageLimitIndex !== 0 && (
|
||||||
|
<MenuItem onClick={() => setSelectedStorageLimitIndex(0)}>
|
||||||
|
{parseNumberWithCommas(storageLimit.PRO.totalIncluded)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedStorageLimitIndex !== 1 && (
|
||||||
|
<MenuItem onClick={() => setSelectedStorageLimitIndex(1)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
storageLimit.PRO.totalIncluded +
|
||||||
|
storageLimit.PRO.increaseStep.amount
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedStorageLimitIndex !== 2 && (
|
||||||
|
<MenuItem onClick={() => setSelectedStorageLimitIndex(2)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
storageLimit.PRO.totalIncluded +
|
||||||
|
storageLimit.PRO.increaseStep.amount * 2
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedStorageLimitIndex !== 3 && (
|
||||||
|
<MenuItem onClick={() => setSelectedStorageLimitIndex(3)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
storageLimit.PRO.totalIncluded +
|
||||||
|
storageLimit.PRO.increaseStep.amount * 3
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedStorageLimitIndex !== 4 && (
|
||||||
|
<MenuItem onClick={() => setSelectedStorageLimitIndex(4)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
storageLimit.PRO.totalIncluded +
|
||||||
|
storageLimit.PRO.increaseStep.amount * 4
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
</MenuList>
|
||||||
|
</Menu>{' '}
|
||||||
|
GB of storage
|
||||||
|
</Text>
|
||||||
|
<Tooltip
|
||||||
|
hasArrow
|
||||||
|
placement="top"
|
||||||
|
label="You accumulate storage for every file that your user upload
|
||||||
|
into your bot. If you delete the result, it will free up the
|
||||||
|
space."
|
||||||
|
>
|
||||||
|
<chakra.span cursor="pointer" h="7">
|
||||||
|
<HelpCircleIcon />
|
||||||
|
</chakra.span>
|
||||||
|
</Tooltip>
|
||||||
|
</HStack>,
|
||||||
|
'Custom domains',
|
||||||
|
'In-depth analytics',
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
borderWidth="3px"
|
||||||
|
borderColor="blue.200"
|
||||||
|
button={
|
||||||
|
<NextChakraLink
|
||||||
|
href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}&chats=${selectedChatsLimitIndex}&storage=${selectedStorageLimitIndex}`}
|
||||||
|
_hover={{ textDecor: 'none' }}
|
||||||
|
>
|
||||||
|
<ActionButton>Subscribe now</ActionButton>
|
||||||
|
</NextChakraLink>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
221
apps/landing-page/components/PricingPage/StarterPlanCard.tsx
Normal file
221
apps/landing-page/components/PricingPage/StarterPlanCard.tsx
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
import {
|
||||||
|
chakra,
|
||||||
|
Tooltip,
|
||||||
|
Text,
|
||||||
|
HStack,
|
||||||
|
Menu,
|
||||||
|
MenuButton,
|
||||||
|
Button,
|
||||||
|
MenuItem,
|
||||||
|
MenuList,
|
||||||
|
} from '@chakra-ui/react'
|
||||||
|
import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon'
|
||||||
|
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
|
||||||
|
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||||
|
import { Plan } from 'db'
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import {
|
||||||
|
chatsLimit,
|
||||||
|
computePrice,
|
||||||
|
formatPrice,
|
||||||
|
parseNumberWithCommas,
|
||||||
|
storageLimit,
|
||||||
|
} from 'utils'
|
||||||
|
import { PricingCard } from './PricingCard'
|
||||||
|
import { ActionButton } from './PricingCard/ActionButton'
|
||||||
|
|
||||||
|
export const StarterPlanCard = () => {
|
||||||
|
const [price, setPrice] = useState('39$')
|
||||||
|
|
||||||
|
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
|
||||||
|
useState<number>(0)
|
||||||
|
const [selectedStorageLimitIndex, setSelectedStorageLimitIndex] =
|
||||||
|
useState<number>(0)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setPrice(
|
||||||
|
formatPrice(
|
||||||
|
computePrice(
|
||||||
|
Plan.STARTER,
|
||||||
|
selectedChatsLimitIndex ?? 0,
|
||||||
|
selectedStorageLimitIndex ?? 0
|
||||||
|
) ?? NaN
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}, [selectedChatsLimitIndex, selectedStorageLimitIndex])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PricingCard
|
||||||
|
data={{
|
||||||
|
price,
|
||||||
|
name: 'Starter',
|
||||||
|
featureLabel: 'Everything in Personal, plus:',
|
||||||
|
features: [
|
||||||
|
<Text key="seats">
|
||||||
|
<chakra.span fontWeight="bold">2 seats</chakra.span> included
|
||||||
|
</Text>,
|
||||||
|
<HStack key="chats">
|
||||||
|
<Text>
|
||||||
|
<Menu>
|
||||||
|
<MenuButton
|
||||||
|
as={Button}
|
||||||
|
rightIcon={<ChevronDownIcon />}
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
isLoading={selectedChatsLimitIndex === undefined}
|
||||||
|
colorScheme="orange"
|
||||||
|
>
|
||||||
|
{selectedChatsLimitIndex !== undefined
|
||||||
|
? parseNumberWithCommas(
|
||||||
|
chatsLimit.STARTER.totalIncluded +
|
||||||
|
chatsLimit.STARTER.increaseStep.amount *
|
||||||
|
selectedChatsLimitIndex
|
||||||
|
)
|
||||||
|
: undefined}
|
||||||
|
</MenuButton>
|
||||||
|
<MenuList>
|
||||||
|
{selectedChatsLimitIndex !== 0 && (
|
||||||
|
<MenuItem onClick={() => setSelectedChatsLimitIndex(0)}>
|
||||||
|
{parseNumberWithCommas(chatsLimit.STARTER.totalIncluded)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedChatsLimitIndex !== 1 && (
|
||||||
|
<MenuItem onClick={() => setSelectedChatsLimitIndex(1)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
chatsLimit.STARTER.totalIncluded +
|
||||||
|
chatsLimit.STARTER.increaseStep.amount
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedChatsLimitIndex !== 2 && (
|
||||||
|
<MenuItem onClick={() => setSelectedChatsLimitIndex(2)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
chatsLimit.STARTER.totalIncluded +
|
||||||
|
chatsLimit.STARTER.increaseStep.amount * 2
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedChatsLimitIndex !== 3 && (
|
||||||
|
<MenuItem onClick={() => setSelectedChatsLimitIndex(3)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
chatsLimit.STARTER.totalIncluded +
|
||||||
|
chatsLimit.STARTER.increaseStep.amount * 3
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedChatsLimitIndex !== 4 && (
|
||||||
|
<MenuItem onClick={() => setSelectedChatsLimitIndex(4)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
chatsLimit.STARTER.totalIncluded +
|
||||||
|
chatsLimit.STARTER.increaseStep.amount * 4
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
</MenuList>
|
||||||
|
</Menu>{' '}
|
||||||
|
chats/mo
|
||||||
|
</Text>
|
||||||
|
<Tooltip
|
||||||
|
hasArrow
|
||||||
|
placement="top"
|
||||||
|
label="A chat is counted whenever a user starts a discussion. It is
|
||||||
|
independant of the number of messages he sends and receives."
|
||||||
|
>
|
||||||
|
<chakra.span cursor="pointer" h="7">
|
||||||
|
<HelpCircleIcon />
|
||||||
|
</chakra.span>
|
||||||
|
</Tooltip>
|
||||||
|
</HStack>,
|
||||||
|
<HStack key="test">
|
||||||
|
<Text>
|
||||||
|
<Menu>
|
||||||
|
<MenuButton
|
||||||
|
as={Button}
|
||||||
|
rightIcon={<ChevronDownIcon />}
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
isLoading={selectedStorageLimitIndex === undefined}
|
||||||
|
colorScheme="orange"
|
||||||
|
>
|
||||||
|
{selectedStorageLimitIndex !== undefined
|
||||||
|
? parseNumberWithCommas(
|
||||||
|
storageLimit.STARTER.totalIncluded +
|
||||||
|
storageLimit.STARTER.increaseStep.amount *
|
||||||
|
selectedStorageLimitIndex
|
||||||
|
)
|
||||||
|
: undefined}
|
||||||
|
</MenuButton>
|
||||||
|
<MenuList>
|
||||||
|
{selectedStorageLimitIndex !== 0 && (
|
||||||
|
<MenuItem onClick={() => setSelectedStorageLimitIndex(0)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
storageLimit.STARTER.totalIncluded
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedStorageLimitIndex !== 1 && (
|
||||||
|
<MenuItem onClick={() => setSelectedStorageLimitIndex(1)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
storageLimit.STARTER.totalIncluded +
|
||||||
|
storageLimit.STARTER.increaseStep.amount
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedStorageLimitIndex !== 2 && (
|
||||||
|
<MenuItem onClick={() => setSelectedStorageLimitIndex(2)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
storageLimit.STARTER.totalIncluded +
|
||||||
|
storageLimit.STARTER.increaseStep.amount * 2
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedStorageLimitIndex !== 3 && (
|
||||||
|
<MenuItem onClick={() => setSelectedStorageLimitIndex(3)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
storageLimit.STARTER.totalIncluded +
|
||||||
|
storageLimit.STARTER.increaseStep.amount * 3
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{selectedStorageLimitIndex !== 4 && (
|
||||||
|
<MenuItem onClick={() => setSelectedStorageLimitIndex(4)}>
|
||||||
|
{parseNumberWithCommas(
|
||||||
|
storageLimit.STARTER.totalIncluded +
|
||||||
|
storageLimit.STARTER.increaseStep.amount * 4
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
</MenuList>
|
||||||
|
</Menu>{' '}
|
||||||
|
GB of storage
|
||||||
|
</Text>
|
||||||
|
<Tooltip
|
||||||
|
hasArrow
|
||||||
|
placement="top"
|
||||||
|
label="You accumulate storage for every file that your user upload
|
||||||
|
into your bot. If you delete the result, it will free up the
|
||||||
|
space."
|
||||||
|
>
|
||||||
|
<chakra.span cursor="pointer" h="7">
|
||||||
|
<HelpCircleIcon />
|
||||||
|
</chakra.span>
|
||||||
|
</Tooltip>
|
||||||
|
</HStack>,
|
||||||
|
'Branding removed',
|
||||||
|
'Collect files from users',
|
||||||
|
'Create folders',
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
borderWidth="1px"
|
||||||
|
borderColor="orange.200"
|
||||||
|
button={
|
||||||
|
<NextChakraLink
|
||||||
|
href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}&chats=${selectedChatsLimitIndex}&storage=${selectedStorageLimitIndex}`}
|
||||||
|
_hover={{ textDecor: 'none' }}
|
||||||
|
>
|
||||||
|
<ActionButton>Subscribe now</ActionButton>
|
||||||
|
</NextChakraLink>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
@ -11,23 +11,20 @@ import {
|
|||||||
Heading,
|
Heading,
|
||||||
VStack,
|
VStack,
|
||||||
Text,
|
Text,
|
||||||
chakra,
|
|
||||||
Tooltip,
|
|
||||||
HStack,
|
HStack,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
|
|
||||||
import { Footer } from 'components/common/Footer'
|
import { Footer } from 'components/common/Footer'
|
||||||
import { Header } from 'components/common/Header/Header'
|
import { Header } from 'components/common/Header/Header'
|
||||||
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||||
import { SocialMetaTags } from 'components/common/SocialMetaTags'
|
import { SocialMetaTags } from 'components/common/SocialMetaTags'
|
||||||
import { BackgroundPolygons } from 'components/Homepage/Hero/BackgroundPolygons'
|
import { BackgroundPolygons } from 'components/Homepage/Hero/BackgroundPolygons'
|
||||||
import { PlanComparisonTables } from 'components/PricingPage/PlanComparisonTables'
|
import { PlanComparisonTables } from 'components/PricingPage/PlanComparisonTables'
|
||||||
import { PricingCard } from 'components/PricingPage/PricingCard'
|
|
||||||
import { ActionButton } from 'components/PricingPage/PricingCard/ActionButton'
|
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { formatPrice, prices } from 'utils'
|
import { formatPrice, prices } from 'utils'
|
||||||
import { Plan } from 'db'
|
|
||||||
import { StripeClimateLogo } from 'assets/logos/StripeClimateLogo'
|
import { StripeClimateLogo } from 'assets/logos/StripeClimateLogo'
|
||||||
|
import { FreePlanCard } from 'components/PricingPage/FreePlanCard'
|
||||||
|
import { StarterPlanCard } from 'components/PricingPage/StarterPlanCard'
|
||||||
|
import { ProPlanCard } from 'components/PricingPage/ProPlanCard'
|
||||||
|
|
||||||
const Pricing = () => {
|
const Pricing = () => {
|
||||||
const [starterPrice, setStarterPrice] = useState('$39')
|
const [starterPrice, setStarterPrice] = useState('$39')
|
||||||
@ -101,166 +98,9 @@ const Pricing = () => {
|
|||||||
w="full"
|
w="full"
|
||||||
maxW="1200px"
|
maxW="1200px"
|
||||||
>
|
>
|
||||||
<PricingCard
|
<FreePlanCard />
|
||||||
data={{
|
<StarterPlanCard />
|
||||||
price: 'Free',
|
<ProPlanCard />
|
||||||
name: 'Personal',
|
|
||||||
features: [
|
|
||||||
'Unlimited typebots',
|
|
||||||
<>
|
|
||||||
<Text>
|
|
||||||
<chakra.span fontWeight="bold">300 chats</chakra.span>{' '}
|
|
||||||
included
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Tooltip
|
|
||||||
hasArrow
|
|
||||||
placement="top"
|
|
||||||
label="A chat is counted whenever a user starts a discussion. It is
|
|
||||||
independant of the number of messages he sends and receives."
|
|
||||||
>
|
|
||||||
<chakra.span cursor="pointer" h="7">
|
|
||||||
<HelpCircleIcon />
|
|
||||||
</chakra.span>
|
|
||||||
</Tooltip>
|
|
||||||
</>,
|
|
||||||
'Native integrations',
|
|
||||||
'Webhooks',
|
|
||||||
'Custom Javascript & CSS',
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
button={
|
|
||||||
<NextChakraLink
|
|
||||||
href="https://app.typebot.io/register"
|
|
||||||
_hover={{ textDecor: 'none' }}
|
|
||||||
>
|
|
||||||
<ActionButton variant="outline">Get started</ActionButton>
|
|
||||||
</NextChakraLink>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<PricingCard
|
|
||||||
data={{
|
|
||||||
price: starterPrice,
|
|
||||||
name: 'Starter',
|
|
||||||
featureLabel: 'Everything in Personal, plus:',
|
|
||||||
features: [
|
|
||||||
<Text key="seats">
|
|
||||||
<chakra.span fontWeight="bold">2 seats</chakra.span>{' '}
|
|
||||||
included
|
|
||||||
</Text>,
|
|
||||||
<>
|
|
||||||
<Text>
|
|
||||||
<chakra.span fontWeight="bold">2,000 chats</chakra.span>{' '}
|
|
||||||
included
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Tooltip
|
|
||||||
hasArrow
|
|
||||||
placement="top"
|
|
||||||
label="A chat is counted whenever a user starts a discussion. It is
|
|
||||||
independant of the number of messages he sends and receives."
|
|
||||||
>
|
|
||||||
<chakra.span cursor="pointer" h="7">
|
|
||||||
<HelpCircleIcon />
|
|
||||||
</chakra.span>
|
|
||||||
</Tooltip>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<Text>
|
|
||||||
<chakra.span fontWeight="bold">2 GB</chakra.span>{' '}
|
|
||||||
included
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Tooltip
|
|
||||||
hasArrow
|
|
||||||
placement="top"
|
|
||||||
label="You accumulate storage for every file that your user upload
|
|
||||||
into your bot. If you delete the result, it will free up the
|
|
||||||
space."
|
|
||||||
>
|
|
||||||
<chakra.span cursor="pointer" h="7">
|
|
||||||
<HelpCircleIcon />
|
|
||||||
</chakra.span>
|
|
||||||
</Tooltip>
|
|
||||||
</>,
|
|
||||||
'Branding removed',
|
|
||||||
'Collect files from users',
|
|
||||||
'Create folders',
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
borderWidth="1px"
|
|
||||||
borderColor="orange.200"
|
|
||||||
button={
|
|
||||||
<NextChakraLink
|
|
||||||
href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}`}
|
|
||||||
_hover={{ textDecor: 'none' }}
|
|
||||||
>
|
|
||||||
<ActionButton>Subscribe now</ActionButton>
|
|
||||||
</NextChakraLink>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<PricingCard
|
|
||||||
data={{
|
|
||||||
price: proPrice,
|
|
||||||
name: 'Pro',
|
|
||||||
featureLabel: 'Everything in Starter, plus:',
|
|
||||||
features: [
|
|
||||||
<Text key="seats">
|
|
||||||
<chakra.span fontWeight="bold">5 seats</chakra.span>{' '}
|
|
||||||
included
|
|
||||||
</Text>,
|
|
||||||
<>
|
|
||||||
<Text>
|
|
||||||
<chakra.span fontWeight="bold">
|
|
||||||
10,000 chats
|
|
||||||
</chakra.span>{' '}
|
|
||||||
included
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Tooltip
|
|
||||||
hasArrow
|
|
||||||
placement="top"
|
|
||||||
label="A chat is counted whenever a user starts a discussion. It is
|
|
||||||
independant of the number of messages he sends and receives."
|
|
||||||
>
|
|
||||||
<chakra.span cursor="pointer" h="7">
|
|
||||||
<HelpCircleIcon />
|
|
||||||
</chakra.span>
|
|
||||||
</Tooltip>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<Text>
|
|
||||||
<chakra.span fontWeight="bold">10 GB</chakra.span>{' '}
|
|
||||||
included
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Tooltip
|
|
||||||
hasArrow
|
|
||||||
placement="top"
|
|
||||||
label="You accumulate storage for every file that your user upload
|
|
||||||
into your bot. If you delete the result, it will free up the
|
|
||||||
space."
|
|
||||||
>
|
|
||||||
<chakra.span cursor="pointer" h="7">
|
|
||||||
<HelpCircleIcon />
|
|
||||||
</chakra.span>
|
|
||||||
</Tooltip>
|
|
||||||
</>,
|
|
||||||
'Custom domains',
|
|
||||||
'In-depth analytics',
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
borderWidth="3px"
|
|
||||||
borderColor="blue.200"
|
|
||||||
button={
|
|
||||||
<NextChakraLink
|
|
||||||
href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}`}
|
|
||||||
_hover={{ textDecor: 'none' }}
|
|
||||||
>
|
|
||||||
<ActionButton>Subscribe now</ActionButton>
|
|
||||||
</NextChakraLink>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
<Text fontSize="lg">
|
<Text fontSize="lg">
|
||||||
Need custom limits? Specific features?{' '}
|
Need custom limits? Specific features?{' '}
|
||||||
|
Reference in New Issue
Block a user