2
0

✏️ (lp) Fix incorrect additional limits price

This commit is contained in:
Baptiste Arnaud
2022-11-03 19:39:42 +01:00
parent 570a780db1
commit c62e20f81a
26 changed files with 434 additions and 481 deletions

View File

@ -18,8 +18,8 @@ export const StripeClimateLogo = (props: IconProps) => (
y2="7.8394" y2="7.8394"
gradientTransform="matrix(1 0 0 -1 0 34)" gradientTransform="matrix(1 0 0 -1 0 34)"
> >
<stop offset="0" stop-color="#00d924" /> <stop offset="0" stopColor="#00d924" />
<stop offset="1" stop-color="#00cb1b" /> <stop offset="1" stopColor="#00cb1b" />
</linearGradient> </linearGradient>
<path <path
d="M0 10.82h32c0 8.84-7.16 16-16 16s-16-7.16-16-16z" d="M0 10.82h32c0 8.84-7.16 16-16 16s-16-7.16-16-16z"
@ -34,8 +34,8 @@ export const StripeClimateLogo = (props: IconProps) => (
y2="17.2443" y2="17.2443"
gradientTransform="matrix(1 0 0 -1 0 34)" gradientTransform="matrix(1 0 0 -1 0 34)"
> >
<stop offset=".1562" stop-color="#009c00" /> <stop offset=".1562" stopColor="#009c00" />
<stop offset="1" stop-color="#00be20" /> <stop offset="1" stopColor="#00be20" />
</linearGradient> </linearGradient>
<path <path
d="M32 10.82c0 2.21-1.49 4.65-5.41 4.65-3.42 0-7.27-2.37-10.59-4.65 3.52-2.43 7.39-5.63 10.59-5.63C29.86 5.18 32 8.17 32 10.82z" d="M32 10.82c0 2.21-1.49 4.65-5.41 4.65-3.42 0-7.27-2.37-10.59-4.65 3.52-2.43 7.39-5.63 10.59-5.63C29.86 5.18 32 8.17 32 10.82z"
@ -50,8 +50,8 @@ export const StripeClimateLogo = (props: IconProps) => (
y2="29.1239" y2="29.1239"
gradientTransform="matrix(1 0 0 -1 0 34)" gradientTransform="matrix(1 0 0 -1 0 34)"
> >
<stop offset="0" stop-color="#ffe37d" /> <stop offset="0" stopColor="#ffe37d" />
<stop offset="1" stop-color="#ffc900" /> <stop offset="1" stopColor="#ffc900" />
</linearGradient> </linearGradient>
<path <path
d="M0 10.82c0 2.21 1.49 4.65 5.41 4.65 3.42 0 7.27-2.37 10.59-4.65-3.52-2.43-7.39-5.64-10.59-5.64C2.14 5.18 0 8.17 0 10.82z" d="M0 10.82c0 2.21 1.49 4.65 5.41 4.65 3.42 0 7.27-2.37 10.59-4.65-3.52-2.43-7.39-5.64-10.59-5.64C2.14 5.18 0 8.17 0 10.82z"

View File

@ -16,7 +16,7 @@ export const BillingContent = () => {
return ( return (
<Stack spacing="10" w="full"> <Stack spacing="10" w="full">
<UsageContent workspace={workspace} /> <UsageContent workspace={workspace} />
<Stack gap="2"> <Stack spacing="2">
<CurrentSubscriptionContent <CurrentSubscriptionContent
plan={workspace.plan} plan={workspace.plan}
stripeId={workspace.stripeId} stripeId={workspace.stripeId}

View File

@ -44,7 +44,7 @@ export const CurrentSubscriptionContent = ({
const isSubscribed = (plan === Plan.STARTER || plan === Plan.PRO) && stripeId const isSubscribed = (plan === Plan.STARTER || plan === Plan.PRO) && stripeId
return ( return (
<Stack gap="2"> <Stack spacing="2">
<Heading fontSize="3xl">Subscription</Heading> <Heading fontSize="3xl">Subscription</Heading>
<HStack data-testid="current-subscription"> <HStack data-testid="current-subscription">
<Text>Current workspace subscription: </Text> <Text>Current workspace subscription: </Text>
@ -70,7 +70,7 @@ export const CurrentSubscriptionContent = ({
{isSubscribed && !isCancelling && ( {isSubscribed && !isCancelling && (
<> <>
<Stack gap="1"> <Stack spacing="1">
<Text fontSize="sm"> <Text fontSize="sm">
Need to change payment method or billing information? Head over to Need to change payment method or billing information? Head over to
your billing portal: your billing portal:

View File

@ -127,13 +127,6 @@ export const UsageContent = ({ workspace }: Props) => {
</Tooltip> </Tooltip>
)} )}
</HStack> </HStack>
<Heading
fontSize="xl"
as="h3"
display="inline-flex"
alignItems="center"
gap="2"
></Heading>
<HStack> <HStack>
<Skeleton <Skeleton
fontWeight="bold" fontWeight="bold"

View File

@ -93,7 +93,7 @@ export const MembersList = () => {
}) })
return ( return (
<Stack w="full" gap="3"> <Stack w="full" spacing={3}>
{!canInviteNewMember && ( {!canInviteNewMember && (
<UnlockPlanInfo <UnlockPlanInfo
contentLabel={` contentLabel={`

View File

@ -0,0 +1,10 @@
import Icon, { IconProps } from '@chakra-ui/icon'
import { featherIconsBaseProps } from './HamburgerIcon'
export const ExternalLinkIcon = (props: IconProps) => (
<Icon viewBox="0 0 24 24" {...featherIconsBaseProps} {...props} margin="0">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
<polyline points="15 3 21 3 21 9"></polyline>
<line x1="10" y1="14" x2="21" y2="3"></line>
</Icon>
)

View File

@ -18,8 +18,8 @@ export const StripeClimateLogo = (props: IconProps) => (
y2="7.8394" y2="7.8394"
gradientTransform="matrix(1 0 0 -1 0 34)" gradientTransform="matrix(1 0 0 -1 0 34)"
> >
<stop offset="0" stop-color="#00d924" /> <stop offset="0" stopColor="#00d924" />
<stop offset="1" stop-color="#00cb1b" /> <stop offset="1" stopColor="#00cb1b" />
</linearGradient> </linearGradient>
<path <path
d="M0 10.82h32c0 8.84-7.16 16-16 16s-16-7.16-16-16z" d="M0 10.82h32c0 8.84-7.16 16-16 16s-16-7.16-16-16z"
@ -34,8 +34,8 @@ export const StripeClimateLogo = (props: IconProps) => (
y2="17.2443" y2="17.2443"
gradientTransform="matrix(1 0 0 -1 0 34)" gradientTransform="matrix(1 0 0 -1 0 34)"
> >
<stop offset=".1562" stop-color="#009c00" /> <stop offset=".1562" stopColor="#009c00" />
<stop offset="1" stop-color="#00be20" /> <stop offset="1" stopColor="#00be20" />
</linearGradient> </linearGradient>
<path <path
d="M32 10.82c0 2.21-1.49 4.65-5.41 4.65-3.42 0-7.27-2.37-10.59-4.65 3.52-2.43 7.39-5.63 10.59-5.63C29.86 5.18 32 8.17 32 10.82z" d="M32 10.82c0 2.21-1.49 4.65-5.41 4.65-3.42 0-7.27-2.37-10.59-4.65 3.52-2.43 7.39-5.63 10.59-5.63C29.86 5.18 32 8.17 32 10.82z"
@ -50,8 +50,8 @@ export const StripeClimateLogo = (props: IconProps) => (
y2="29.1239" y2="29.1239"
gradientTransform="matrix(1 0 0 -1 0 34)" gradientTransform="matrix(1 0 0 -1 0 34)"
> >
<stop offset="0" stop-color="#ffe37d" /> <stop offset="0" stopColor="#ffe37d" />
<stop offset="1" stop-color="#ffc900" /> <stop offset="1" stopColor="#ffc900" />
</linearGradient> </linearGradient>
<path <path
d="M0 10.82c0 2.21 1.49 4.65 5.41 4.65 3.42 0 7.27-2.37 10.59-4.65-3.52-2.43-7.39-5.64-10.59-5.64C2.14 5.18 0 8.17 0 10.82z" d="M0 10.82c0 2.21 1.49 4.65 5.41 4.65 3.42 0 7.27-2.37 10.59-4.65-3.52-2.43-7.39-5.64-10.59-5.64C2.14 5.18 0 8.17 0 10.82z"

View File

@ -2,9 +2,9 @@ import { Flex, Stack, Heading, Box, Text, Button } from '@chakra-ui/react'
import React from 'react' import React from 'react'
import Image from 'next/image' import Image from 'next/image'
import builderDndSrc from 'public/images/homepage/builder-dnd.png' import builderDndSrc from 'public/images/homepage/builder-dnd.png'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { ArrowRight } from 'assets/icons/ArrowRight' import { ArrowRight } from 'assets/icons/ArrowRight'
import { Flare } from 'assets/illustrations/Flare' import { Flare } from 'assets/illustrations/Flare'
import Link from 'next/link'
export const EasyBuildingExperience = () => { export const EasyBuildingExperience = () => {
return ( return (
@ -41,7 +41,7 @@ export const EasyBuildingExperience = () => {
</Text> </Text>
<Flex> <Flex>
<Button <Button
as={NextChakraLink} as={Link}
rightIcon={<ArrowRight />} rightIcon={<ArrowRight />}
href={`https://app.typebot.io/register`} href={`https://app.typebot.io/register`}
variant="ghost" variant="ghost"

View File

@ -2,9 +2,9 @@ import { Flex, Stack, Heading, Box, Text, Button } from '@chakra-ui/react'
import React from 'react' import React from 'react'
import Image from 'next/image' import Image from 'next/image'
import nativeFeelingSrc from 'public/images/homepage/native-feeling.png' import nativeFeelingSrc from 'public/images/homepage/native-feeling.png'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { ArrowRight } from 'assets/icons/ArrowRight' import { ArrowRight } from 'assets/icons/ArrowRight'
import { Flare } from 'assets/illustrations/Flare' import { Flare } from 'assets/illustrations/Flare'
import Link from 'next/link'
export const EasyEmbed = () => { export const EasyEmbed = () => {
return ( return (
@ -42,7 +42,7 @@ export const EasyEmbed = () => {
</Text> </Text>
<Flex data-aos="fade"> <Flex data-aos="fade">
<Button <Button
as={NextChakraLink} as={Link}
rightIcon={<ArrowRight />} rightIcon={<ArrowRight />}
href={`https://app.typebot.io/register`} href={`https://app.typebot.io/register`}
variant="ghost" variant="ghost"

View File

@ -1,5 +1,5 @@
import { Heading, Button, Text, Flex, VStack } from '@chakra-ui/react' import { Heading, Button, Text, Flex, VStack } from '@chakra-ui/react'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink' import Link from 'next/link'
import React from 'react' import React from 'react'
import { BackgroundPolygons } from './Hero/BackgroundPolygons' import { BackgroundPolygons } from './Hero/BackgroundPolygons'
@ -31,7 +31,7 @@ export const EndCta = () => {
</Heading> </Heading>
<Flex> <Flex>
<Button <Button
as={NextChakraLink} as={Link}
href="https://app.typebot.io/register" href="https://app.typebot.io/register"
size="lg" size="lg"
colorScheme="orange" colorScheme="orange"

View File

@ -8,13 +8,13 @@ import {
Text, Text,
VStack, VStack,
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import * as React from 'react' import * as React from 'react'
import { Header } from '../../common/Header/Header' import { Header } from '../../common/Header/Header'
import { BackgroundPolygons } from './BackgroundPolygons' import { BackgroundPolygons } from './BackgroundPolygons'
import * as Logos from './Brands' import * as Logos from './Brands'
import Image from 'next/image' import Image from 'next/image'
import builderScreenshotSrc from 'public/images/homepage/builder.png' import builderScreenshotSrc from 'public/images/homepage/builder.png'
import Link from 'next/link'
export const Hero = () => { export const Hero = () => {
return ( return (
@ -52,7 +52,7 @@ export const Hero = () => {
data-aos-delay="200" data-aos-delay="200"
> >
<Button <Button
as={NextChakraLink} as={Link}
href="https://app.typebot.io/register" href="https://app.typebot.io/register"
colorScheme="orange" colorScheme="orange"
size="lg" size="lg"

View File

@ -1,8 +1,8 @@
import { Flex, Stack, Heading, Text, Button, VStack } from '@chakra-ui/react' import { Flex, Stack, Heading, Text, Button, VStack } from '@chakra-ui/react'
import { ArrowRight } from 'assets/icons/ArrowRight' import { ArrowRight } from 'assets/icons/ArrowRight'
import { TypebotViewer } from 'bot-engine' import { TypebotViewer } from 'bot-engine'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { PublicTypebot, Typebot } from 'models' import { PublicTypebot, Typebot } from 'models'
import Link from 'next/link'
import React, { useEffect, useRef, useState } from 'react' import React, { useEffect, useRef, useState } from 'react'
import { sendRequest } from 'utils' import { sendRequest } from 'utils'
@ -72,7 +72,7 @@ export const RealTimeResults = () => {
</Text> </Text>
<Flex> <Flex>
<Button <Button
as={NextChakraLink} as={Link}
rightIcon={<ArrowRight />} rightIcon={<ArrowRight />}
href={`https://app.typebot.io/register`} href={`https://app.typebot.io/register`}
variant="ghost" variant="ghost"

View File

@ -1,9 +1,8 @@
import { chakra, Tooltip, Text } from '@chakra-ui/react' import { chakra, Tooltip, Text, Button } from '@chakra-ui/react'
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon' import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink' import Link from 'next/link'
import React from 'react' import React from 'react'
import { PricingCard } from './PricingCard' import { PricingCard } from './PricingCard'
import { ActionButton } from './PricingCard/ActionButton'
export const FreePlanCard = () => ( export const FreePlanCard = () => (
<PricingCard <PricingCard
@ -34,12 +33,18 @@ export const FreePlanCard = () => (
], ],
}} }}
button={ button={
<NextChakraLink <Button
as={Link}
href="https://app.typebot.io/register" href="https://app.typebot.io/register"
_hover={{ textDecor: 'none' }} variant="outline"
colorScheme="blue"
size="lg"
w="full"
fontWeight="extrabold"
py={{ md: '8' }}
> >
<ActionButton variant="outline">Get started</ActionButton> Get started
</NextChakraLink> </Button>
} }
/> />
) )

View File

@ -17,9 +17,10 @@ import {
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { CheckIcon } from 'assets/icons/CheckIcon' import { CheckIcon } from 'assets/icons/CheckIcon'
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon' import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { Plan } from 'db' import { Plan } from 'db'
import React from 'react' import Link from 'next/link'
import React, { useEffect, useState } from 'react'
import { chatsLimit, formatPrice, storageLimit } from 'utils'
type Props = { type Props = {
starterPrice: string starterPrice: string
@ -31,6 +32,20 @@ export const PlanComparisonTables = ({
proPrice, proPrice,
...props ...props
}: Props) => { }: Props) => {
const [additionalChatsPrice, setAdditionalChatsPrice] = useState(
`$${chatsLimit.STARTER.increaseStep.price}`
)
const [additionalStoragePrice, setAdditionalStoragePrice] = useState(
`$${storageLimit.STARTER.increaseStep.price}`
)
useEffect(() => {
setAdditionalChatsPrice(formatPrice(chatsLimit.STARTER.increaseStep.price))
setAdditionalStoragePrice(
formatPrice(storageLimit.STARTER.increaseStep.price)
)
}, [])
return ( return (
<Stack spacing="12" {...props}> <Stack spacing="12" {...props}>
<TableContainer> <TableContainer>
@ -61,8 +76,8 @@ export const PlanComparisonTables = ({
<Tr> <Tr>
<Td>Additional Chats</Td> <Td>Additional Chats</Td>
<Td /> <Td />
<Td>$10 per 500</Td> <Td>{additionalChatsPrice} per 500</Td>
<Td>$10 per 1,000</Td> <Td>{additionalChatsPrice} per 1,000</Td>
</Tr> </Tr>
<Tr> <Tr>
<Td>Storage</Td> <Td>Storage</Td>
@ -73,8 +88,8 @@ export const PlanComparisonTables = ({
<Tr> <Tr>
<Td>Additional Storage</Td> <Td>Additional Storage</Td>
<Td /> <Td />
<Td>$5 per 1 GB</Td> <Td>{additionalStoragePrice} per 1 GB</Td>
<Td>$5 per 1 GB</Td> <Td>{additionalStoragePrice} per 1 GB</Td>
</Tr> </Tr>
<Tr> <Tr>
<Td>Members</Td> <Td>Members</Td>
@ -331,12 +346,9 @@ export const PlanComparisonTables = ({
Personal Personal
</Heading> </Heading>
<Heading as="h3">Free</Heading> <Heading as="h3">Free</Heading>
<NextChakraLink <Link href="https://app.typebot.io/register">
href="https://app.typebot.io/register"
_hover={{ textDecor: 'none' }}
>
<Button variant="outline">Get started</Button> <Button variant="outline">Get started</Button>
</NextChakraLink> </Link>
</Stack> </Stack>
<Stack spacing={4}> <Stack spacing={4}>
<Heading as="h3" size="md" color="orange.200"> <Heading as="h3" size="md" color="orange.200">
@ -345,12 +357,11 @@ export const PlanComparisonTables = ({
<Heading as="h3"> <Heading as="h3">
{starterPrice} <chakra.span fontSize="lg">/ month</chakra.span> {starterPrice} <chakra.span fontSize="lg">/ month</chakra.span>
</Heading> </Heading>
<NextChakraLink <Link
href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}`} href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}`}
_hover={{ textDecor: 'none' }}
> >
<Button>Subscribe</Button> <Button>Subscribe</Button>
</NextChakraLink> </Link>
</Stack> </Stack>
<Stack spacing={4}> <Stack spacing={4}>
<Heading as="h3" size="md" color="blue.200"> <Heading as="h3" size="md" color="blue.200">
@ -359,12 +370,11 @@ export const PlanComparisonTables = ({
<Heading as="h3"> <Heading as="h3">
{proPrice} <chakra.span fontSize="lg">/ month</chakra.span> {proPrice} <chakra.span fontSize="lg">/ month</chakra.span>
</Heading> </Heading>
<NextChakraLink <Link
href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}`} href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}`}
_hover={{ textDecor: 'none' }}
> >
<Button>Subscribe</Button> <Button>Subscribe</Button>
</NextChakraLink> </Link>
</Stack> </Stack>
</Stack> </Stack>
</Stack> </Stack>
@ -378,12 +388,12 @@ const TdWithTooltip = ({
text: string text: string
tooltip: string tooltip: string
}) => ( }) => (
<Td as={HStack}> <HStack as={Td}>
<Text>{text}</Text> <Text>{text}</Text>
<Tooltip hasArrow placement="top" label={tooltip}> <Tooltip hasArrow placement="top" label={tooltip}>
<chakra.span cursor="pointer"> <chakra.span cursor="pointer">
<HelpCircleIcon /> <HelpCircleIcon />
</chakra.span> </chakra.span>
</Tooltip> </Tooltip>
</Td> </HStack>
) )

View File

@ -1,13 +0,0 @@
import { Button, ButtonProps } from '@chakra-ui/react'
import * as React from 'react'
export const ActionButton = (props: ButtonProps) => (
<Button
colorScheme="blue"
size="lg"
w="full"
fontWeight="extrabold"
py={{ md: '8' }}
{...props}
/>
)

View File

@ -9,13 +9,15 @@ import {
VStack, VStack,
} from '@chakra-ui/react' } from '@chakra-ui/react'
import * as React from 'react' import * as React from 'react'
import { useEffect, useState } from 'react'
import { formatPrice } from 'utils'
import { CheckCircleIcon } from '../../../assets/icons/CheckCircleIcon' import { CheckCircleIcon } from '../../../assets/icons/CheckCircleIcon'
import { Card, CardProps } from './Card' import { Card, CardProps } from './Card'
export interface PricingCardData { export interface PricingCardData {
features: React.ReactNode[] features: React.ReactNode[]
name: string name: string
price: string price: number | string
featureLabel?: string featureLabel?: string
} }
@ -32,8 +34,13 @@ export const PricingCard = ({
...rest ...rest
}: PricingCardProps) => { }: PricingCardProps) => {
const { features, price, name } = data const { features, price, name } = data
const [formattedPrice, setFormattedPrice] = useState(price)
const accentColor = useColorModeValue('blue.500', 'white') const accentColor = useColorModeValue('blue.500', 'white')
useEffect(() => {
setFormattedPrice(typeof price === 'number' ? formatPrice(price) : price)
}, [price])
return ( return (
<Card rounded="xl" bgColor="gray.800" {...rest}> <Card rounded="xl" bgColor="gray.800" {...rest}>
<Flex justifyContent="space-between" flexDir="column" h="full"> <Flex justifyContent="space-between" flexDir="column" h="full">
@ -52,9 +59,9 @@ export const PricingCard = ({
my="8" my="8"
> >
<Heading size="2xl" fontWeight="inherit" lineHeight="0.9em"> <Heading size="2xl" fontWeight="inherit" lineHeight="0.9em">
{price} {formattedPrice}
</Heading> </Heading>
{(price.includes('$') || price.includes('€')) && ( {typeof price === 'number' && (
<Text fontWeight="inherit" fontSize="xl"> <Text fontWeight="inherit" fontSize="xl">
/ month / month
</Text> </Text>

View File

@ -11,21 +11,19 @@ import {
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon' import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon'
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon' import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { Plan } from 'db' import { Plan } from 'db'
import Link from 'next/link'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { import {
chatsLimit, chatsLimit,
computePrice, computePrice,
formatPrice,
parseNumberWithCommas, parseNumberWithCommas,
storageLimit, storageLimit,
} from 'utils' } from 'utils'
import { PricingCard } from './PricingCard' import { PricingCard } from './PricingCard'
import { ActionButton } from './PricingCard/ActionButton'
export const ProPlanCard = () => { export const ProPlanCard = () => {
const [price, setPrice] = useState('89$') const [price, setPrice] = useState(89)
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] = const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
useState<number>(0) useState<number>(0)
@ -34,13 +32,11 @@ export const ProPlanCard = () => {
useEffect(() => { useEffect(() => {
setPrice( setPrice(
formatPrice( computePrice(
computePrice( Plan.PRO,
Plan.PRO, selectedChatsLimitIndex ?? 0,
selectedChatsLimitIndex ?? 0, selectedStorageLimitIndex ?? 0
selectedStorageLimitIndex ?? 0 ) ?? NaN
) ?? NaN
)
) )
}, [selectedChatsLimitIndex, selectedStorageLimitIndex]) }, [selectedChatsLimitIndex, selectedStorageLimitIndex])
@ -54,66 +50,64 @@ export const ProPlanCard = () => {
<Text key="seats"> <Text key="seats">
<chakra.span fontWeight="bold">5 seats</chakra.span> included <chakra.span fontWeight="bold">5 seats</chakra.span> included
</Text>, </Text>,
<HStack key="chats"> <HStack key="chats" spacing={1.5}>
<Text> <Menu>
<Menu> <MenuButton
<MenuButton as={Button}
as={Button} rightIcon={<ChevronDownIcon />}
rightIcon={<ChevronDownIcon />} size="sm"
size="sm" variant="outline"
variant="outline" isLoading={selectedChatsLimitIndex === undefined}
isLoading={selectedChatsLimitIndex === undefined} >
> {selectedChatsLimitIndex !== undefined
{selectedChatsLimitIndex !== undefined ? parseNumberWithCommas(
? parseNumberWithCommas( chatsLimit.PRO.totalIncluded +
chatsLimit.PRO.totalIncluded + chatsLimit.PRO.increaseStep.amount *
chatsLimit.PRO.increaseStep.amount * selectedChatsLimitIndex
selectedChatsLimitIndex )
) : undefined}
: undefined} </MenuButton>
</MenuButton> <MenuList>
<MenuList> {selectedChatsLimitIndex !== 0 && (
{selectedChatsLimitIndex !== 0 && ( <MenuItem onClick={() => setSelectedChatsLimitIndex(0)}>
<MenuItem onClick={() => setSelectedChatsLimitIndex(0)}> {parseNumberWithCommas(chatsLimit.PRO.totalIncluded)}
{parseNumberWithCommas(chatsLimit.PRO.totalIncluded)} </MenuItem>
</MenuItem> )}
)} {selectedChatsLimitIndex !== 1 && (
{selectedChatsLimitIndex !== 1 && ( <MenuItem onClick={() => setSelectedChatsLimitIndex(1)}>
<MenuItem onClick={() => setSelectedChatsLimitIndex(1)}> {parseNumberWithCommas(
{parseNumberWithCommas( chatsLimit.PRO.totalIncluded +
chatsLimit.PRO.totalIncluded + chatsLimit.PRO.increaseStep.amount
chatsLimit.PRO.increaseStep.amount )}
)} </MenuItem>
</MenuItem> )}
)} {selectedChatsLimitIndex !== 2 && (
{selectedChatsLimitIndex !== 2 && ( <MenuItem onClick={() => setSelectedChatsLimitIndex(2)}>
<MenuItem onClick={() => setSelectedChatsLimitIndex(2)}> {parseNumberWithCommas(
{parseNumberWithCommas( chatsLimit.PRO.totalIncluded +
chatsLimit.PRO.totalIncluded + chatsLimit.PRO.increaseStep.amount * 2
chatsLimit.PRO.increaseStep.amount * 2 )}
)} </MenuItem>
</MenuItem> )}
)} {selectedChatsLimitIndex !== 3 && (
{selectedChatsLimitIndex !== 3 && ( <MenuItem onClick={() => setSelectedChatsLimitIndex(3)}>
<MenuItem onClick={() => setSelectedChatsLimitIndex(3)}> {parseNumberWithCommas(
{parseNumberWithCommas( chatsLimit.PRO.totalIncluded +
chatsLimit.PRO.totalIncluded + chatsLimit.PRO.increaseStep.amount * 3
chatsLimit.PRO.increaseStep.amount * 3 )}
)} </MenuItem>
</MenuItem> )}
)} {selectedChatsLimitIndex !== 4 && (
{selectedChatsLimitIndex !== 4 && ( <MenuItem onClick={() => setSelectedChatsLimitIndex(4)}>
<MenuItem onClick={() => setSelectedChatsLimitIndex(4)}> {parseNumberWithCommas(
{parseNumberWithCommas( chatsLimit.PRO.totalIncluded +
chatsLimit.PRO.totalIncluded + chatsLimit.PRO.increaseStep.amount * 4
chatsLimit.PRO.increaseStep.amount * 4 )}
)} </MenuItem>
</MenuItem> )}
)} </MenuList>
</MenuList> </Menu>{' '}
</Menu>{' '} <Text>chats/mo</Text>
chats/mo
</Text>
<Tooltip <Tooltip
hasArrow hasArrow
placement="top" placement="top"
@ -125,66 +119,64 @@ export const ProPlanCard = () => {
</chakra.span> </chakra.span>
</Tooltip> </Tooltip>
</HStack>, </HStack>,
<HStack key="test"> <HStack key="storage" spacing={1.5}>
<Text> <Menu>
<Menu> <MenuButton
<MenuButton as={Button}
as={Button} rightIcon={<ChevronDownIcon />}
rightIcon={<ChevronDownIcon />} size="sm"
size="sm" variant="outline"
variant="outline" isLoading={selectedStorageLimitIndex === undefined}
isLoading={selectedStorageLimitIndex === undefined} >
> {selectedStorageLimitIndex !== undefined
{selectedStorageLimitIndex !== undefined ? parseNumberWithCommas(
? parseNumberWithCommas( storageLimit.PRO.totalIncluded +
storageLimit.PRO.totalIncluded + storageLimit.PRO.increaseStep.amount *
storageLimit.PRO.increaseStep.amount * selectedStorageLimitIndex
selectedStorageLimitIndex )
) : undefined}
: undefined} </MenuButton>
</MenuButton> <MenuList>
<MenuList> {selectedStorageLimitIndex !== 0 && (
{selectedStorageLimitIndex !== 0 && ( <MenuItem onClick={() => setSelectedStorageLimitIndex(0)}>
<MenuItem onClick={() => setSelectedStorageLimitIndex(0)}> {parseNumberWithCommas(storageLimit.PRO.totalIncluded)}
{parseNumberWithCommas(storageLimit.PRO.totalIncluded)} </MenuItem>
</MenuItem> )}
)} {selectedStorageLimitIndex !== 1 && (
{selectedStorageLimitIndex !== 1 && ( <MenuItem onClick={() => setSelectedStorageLimitIndex(1)}>
<MenuItem onClick={() => setSelectedStorageLimitIndex(1)}> {parseNumberWithCommas(
{parseNumberWithCommas( storageLimit.PRO.totalIncluded +
storageLimit.PRO.totalIncluded + storageLimit.PRO.increaseStep.amount
storageLimit.PRO.increaseStep.amount )}
)} </MenuItem>
</MenuItem> )}
)} {selectedStorageLimitIndex !== 2 && (
{selectedStorageLimitIndex !== 2 && ( <MenuItem onClick={() => setSelectedStorageLimitIndex(2)}>
<MenuItem onClick={() => setSelectedStorageLimitIndex(2)}> {parseNumberWithCommas(
{parseNumberWithCommas( storageLimit.PRO.totalIncluded +
storageLimit.PRO.totalIncluded + storageLimit.PRO.increaseStep.amount * 2
storageLimit.PRO.increaseStep.amount * 2 )}
)} </MenuItem>
</MenuItem> )}
)} {selectedStorageLimitIndex !== 3 && (
{selectedStorageLimitIndex !== 3 && ( <MenuItem onClick={() => setSelectedStorageLimitIndex(3)}>
<MenuItem onClick={() => setSelectedStorageLimitIndex(3)}> {parseNumberWithCommas(
{parseNumberWithCommas( storageLimit.PRO.totalIncluded +
storageLimit.PRO.totalIncluded + storageLimit.PRO.increaseStep.amount * 3
storageLimit.PRO.increaseStep.amount * 3 )}
)} </MenuItem>
</MenuItem> )}
)} {selectedStorageLimitIndex !== 4 && (
{selectedStorageLimitIndex !== 4 && ( <MenuItem onClick={() => setSelectedStorageLimitIndex(4)}>
<MenuItem onClick={() => setSelectedStorageLimitIndex(4)}> {parseNumberWithCommas(
{parseNumberWithCommas( storageLimit.PRO.totalIncluded +
storageLimit.PRO.totalIncluded + storageLimit.PRO.increaseStep.amount * 4
storageLimit.PRO.increaseStep.amount * 4 )}
)} </MenuItem>
</MenuItem> )}
)} </MenuList>
</MenuList> </Menu>{' '}
</Menu>{' '} <Text>GB of storage</Text>
GB of storage
</Text>
<Tooltip <Tooltip
hasArrow hasArrow
placement="top" placement="top"
@ -204,12 +196,17 @@ export const ProPlanCard = () => {
borderWidth="3px" borderWidth="3px"
borderColor="blue.200" borderColor="blue.200"
button={ button={
<NextChakraLink <Button
as={Link}
href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}&chats=${selectedChatsLimitIndex}&storage=${selectedStorageLimitIndex}`} href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}&chats=${selectedChatsLimitIndex}&storage=${selectedStorageLimitIndex}`}
_hover={{ textDecor: 'none' }} colorScheme="blue"
size="lg"
w="full"
fontWeight="extrabold"
py={{ md: '8' }}
> >
<ActionButton>Subscribe now</ActionButton> Subscribe now
</NextChakraLink> </Button>
} }
/> />
) )

View File

@ -11,8 +11,8 @@ import {
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon' import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon'
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon' import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { Plan } from 'db' import { Plan } from 'db'
import Link from 'next/link'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { import {
chatsLimit, chatsLimit,
@ -22,10 +22,9 @@ import {
storageLimit, storageLimit,
} from 'utils' } from 'utils'
import { PricingCard } from './PricingCard' import { PricingCard } from './PricingCard'
import { ActionButton } from './PricingCard/ActionButton'
export const StarterPlanCard = () => { export const StarterPlanCard = () => {
const [price, setPrice] = useState('39$') const [price, setPrice] = useState(39)
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] = const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
useState<number>(0) useState<number>(0)
@ -34,13 +33,11 @@ export const StarterPlanCard = () => {
useEffect(() => { useEffect(() => {
setPrice( setPrice(
formatPrice( computePrice(
computePrice( Plan.STARTER,
Plan.STARTER, selectedChatsLimitIndex ?? 0,
selectedChatsLimitIndex ?? 0, selectedStorageLimitIndex ?? 0
selectedStorageLimitIndex ?? 0 ) ?? NaN
) ?? NaN
)
) )
}, [selectedChatsLimitIndex, selectedStorageLimitIndex]) }, [selectedChatsLimitIndex, selectedStorageLimitIndex])
@ -54,67 +51,62 @@ export const StarterPlanCard = () => {
<Text key="seats"> <Text key="seats">
<chakra.span fontWeight="bold">2 seats</chakra.span> included <chakra.span fontWeight="bold">2 seats</chakra.span> included
</Text>, </Text>,
<HStack key="chats"> <HStack key="chats" spacing={1.5}>
<Text> <Menu>
<Menu> <MenuButton
<MenuButton as={Button}
as={Button} rightIcon={<ChevronDownIcon />}
rightIcon={<ChevronDownIcon />} size="sm"
size="sm" variant="outline"
variant="outline" colorScheme="orange"
isLoading={selectedChatsLimitIndex === undefined} >
colorScheme="orange" {parseNumberWithCommas(
> chatsLimit.STARTER.totalIncluded +
{selectedChatsLimitIndex !== undefined chatsLimit.STARTER.increaseStep.amount *
? parseNumberWithCommas( selectedChatsLimitIndex
chatsLimit.STARTER.totalIncluded + )}
chatsLimit.STARTER.increaseStep.amount * </MenuButton>
selectedChatsLimitIndex <MenuList>
) {selectedChatsLimitIndex !== 0 && (
: undefined} <MenuItem onClick={() => setSelectedChatsLimitIndex(0)}>
</MenuButton> {parseNumberWithCommas(chatsLimit.STARTER.totalIncluded)}
<MenuList> </MenuItem>
{selectedChatsLimitIndex !== 0 && ( )}
<MenuItem onClick={() => setSelectedChatsLimitIndex(0)}> {selectedChatsLimitIndex !== 1 && (
{parseNumberWithCommas(chatsLimit.STARTER.totalIncluded)} <MenuItem onClick={() => setSelectedChatsLimitIndex(1)}>
</MenuItem> {parseNumberWithCommas(
)} chatsLimit.STARTER.totalIncluded +
{selectedChatsLimitIndex !== 1 && ( chatsLimit.STARTER.increaseStep.amount
<MenuItem onClick={() => setSelectedChatsLimitIndex(1)}> )}
{parseNumberWithCommas( </MenuItem>
chatsLimit.STARTER.totalIncluded + )}
chatsLimit.STARTER.increaseStep.amount {selectedChatsLimitIndex !== 2 && (
)} <MenuItem onClick={() => setSelectedChatsLimitIndex(2)}>
</MenuItem> {parseNumberWithCommas(
)} chatsLimit.STARTER.totalIncluded +
{selectedChatsLimitIndex !== 2 && ( chatsLimit.STARTER.increaseStep.amount * 2
<MenuItem onClick={() => setSelectedChatsLimitIndex(2)}> )}
{parseNumberWithCommas( </MenuItem>
chatsLimit.STARTER.totalIncluded + )}
chatsLimit.STARTER.increaseStep.amount * 2 {selectedChatsLimitIndex !== 3 && (
)} <MenuItem onClick={() => setSelectedChatsLimitIndex(3)}>
</MenuItem> {parseNumberWithCommas(
)} chatsLimit.STARTER.totalIncluded +
{selectedChatsLimitIndex !== 3 && ( chatsLimit.STARTER.increaseStep.amount * 3
<MenuItem onClick={() => setSelectedChatsLimitIndex(3)}> )}
{parseNumberWithCommas( </MenuItem>
chatsLimit.STARTER.totalIncluded + )}
chatsLimit.STARTER.increaseStep.amount * 3 {selectedChatsLimitIndex !== 4 && (
)} <MenuItem onClick={() => setSelectedChatsLimitIndex(4)}>
</MenuItem> {parseNumberWithCommas(
)} chatsLimit.STARTER.totalIncluded +
{selectedChatsLimitIndex !== 4 && ( chatsLimit.STARTER.increaseStep.amount * 4
<MenuItem onClick={() => setSelectedChatsLimitIndex(4)}> )}
{parseNumberWithCommas( </MenuItem>
chatsLimit.STARTER.totalIncluded + )}
chatsLimit.STARTER.increaseStep.amount * 4 </MenuList>
)} </Menu>{' '}
</MenuItem> <Text>chats/mo</Text>
)}
</MenuList>
</Menu>{' '}
chats/mo
</Text>
<Tooltip <Tooltip
hasArrow hasArrow
placement="top" placement="top"
@ -126,69 +118,65 @@ export const StarterPlanCard = () => {
</chakra.span> </chakra.span>
</Tooltip> </Tooltip>
</HStack>, </HStack>,
<HStack key="test"> <HStack key="storage" spacing={1.5}>
<Text> <Menu>
<Menu> <MenuButton
<MenuButton as={Button}
as={Button} rightIcon={<ChevronDownIcon />}
rightIcon={<ChevronDownIcon />} size="sm"
size="sm" variant="outline"
variant="outline" isLoading={selectedStorageLimitIndex === undefined}
isLoading={selectedStorageLimitIndex === undefined} colorScheme="orange"
colorScheme="orange" >
> {selectedStorageLimitIndex !== undefined
{selectedStorageLimitIndex !== undefined ? parseNumberWithCommas(
? parseNumberWithCommas( storageLimit.STARTER.totalIncluded +
storageLimit.STARTER.totalIncluded + storageLimit.STARTER.increaseStep.amount *
storageLimit.STARTER.increaseStep.amount * selectedStorageLimitIndex
selectedStorageLimitIndex )
) : undefined}
: undefined} </MenuButton>
</MenuButton> <MenuList>
<MenuList> {selectedStorageLimitIndex !== 0 && (
{selectedStorageLimitIndex !== 0 && ( <MenuItem onClick={() => setSelectedStorageLimitIndex(0)}>
<MenuItem onClick={() => setSelectedStorageLimitIndex(0)}> {parseNumberWithCommas(storageLimit.STARTER.totalIncluded)}
{parseNumberWithCommas( </MenuItem>
storageLimit.STARTER.totalIncluded )}
)} {selectedStorageLimitIndex !== 1 && (
</MenuItem> <MenuItem onClick={() => setSelectedStorageLimitIndex(1)}>
)} {parseNumberWithCommas(
{selectedStorageLimitIndex !== 1 && ( storageLimit.STARTER.totalIncluded +
<MenuItem onClick={() => setSelectedStorageLimitIndex(1)}> storageLimit.STARTER.increaseStep.amount
{parseNumberWithCommas( )}
storageLimit.STARTER.totalIncluded + </MenuItem>
storageLimit.STARTER.increaseStep.amount )}
)} {selectedStorageLimitIndex !== 2 && (
</MenuItem> <MenuItem onClick={() => setSelectedStorageLimitIndex(2)}>
)} {parseNumberWithCommas(
{selectedStorageLimitIndex !== 2 && ( storageLimit.STARTER.totalIncluded +
<MenuItem onClick={() => setSelectedStorageLimitIndex(2)}> storageLimit.STARTER.increaseStep.amount * 2
{parseNumberWithCommas( )}
storageLimit.STARTER.totalIncluded + </MenuItem>
storageLimit.STARTER.increaseStep.amount * 2 )}
)} {selectedStorageLimitIndex !== 3 && (
</MenuItem> <MenuItem onClick={() => setSelectedStorageLimitIndex(3)}>
)} {parseNumberWithCommas(
{selectedStorageLimitIndex !== 3 && ( storageLimit.STARTER.totalIncluded +
<MenuItem onClick={() => setSelectedStorageLimitIndex(3)}> storageLimit.STARTER.increaseStep.amount * 3
{parseNumberWithCommas( )}
storageLimit.STARTER.totalIncluded + </MenuItem>
storageLimit.STARTER.increaseStep.amount * 3 )}
)} {selectedStorageLimitIndex !== 4 && (
</MenuItem> <MenuItem onClick={() => setSelectedStorageLimitIndex(4)}>
)} {parseNumberWithCommas(
{selectedStorageLimitIndex !== 4 && ( storageLimit.STARTER.totalIncluded +
<MenuItem onClick={() => setSelectedStorageLimitIndex(4)}> storageLimit.STARTER.increaseStep.amount * 4
{parseNumberWithCommas( )}
storageLimit.STARTER.totalIncluded + </MenuItem>
storageLimit.STARTER.increaseStep.amount * 4 )}
)} </MenuList>
</MenuItem> </Menu>{' '}
)} <Text>GB of storage</Text>
</MenuList>
</Menu>{' '}
GB of storage
</Text>
<Tooltip <Tooltip
hasArrow hasArrow
placement="top" placement="top"
@ -209,12 +197,17 @@ export const StarterPlanCard = () => {
borderWidth="1px" borderWidth="1px"
borderColor="orange.200" borderColor="orange.200"
button={ button={
<NextChakraLink <Button
as={Link}
href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}&chats=${selectedChatsLimitIndex}&storage=${selectedStorageLimitIndex}`} href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}&chats=${selectedChatsLimitIndex}&storage=${selectedStorageLimitIndex}`}
_hover={{ textDecor: 'none' }} colorScheme="blue"
size="lg"
w="full"
fontWeight="extrabold"
py={{ md: '8' }}
> >
<ActionButton>Subscribe now</ActionButton> Subscribe now
</NextChakraLink> </Button>
} }
/> />
) )

View File

@ -9,8 +9,8 @@ import {
Stack, Stack,
Text, Text,
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { NextChakraLink } from './nextChakraAdapters/NextChakraLink'
import { Logo } from 'assets/icons/Logo' import { Logo } from 'assets/icons/Logo'
import { TextLink } from './TextLink'
const facebookGroupUrl = 'https://www.facebook.com/groups/typebot' const facebookGroupUrl = 'https://www.facebook.com/groups/typebot'
const typebotLinkedInUrl = 'https://www.linkedin.com/company/typebot' const typebotLinkedInUrl = 'https://www.linkedin.com/company/typebot'
@ -35,64 +35,40 @@ export const Footer = () => {
</HStack> </HStack>
<Text> <Text>
Made with by{' '} Made with by{' '}
<NextChakraLink href={baptisteTwitterUrl} color="gray.400"> <TextLink href={baptisteTwitterUrl}>@baptisteArno</TextLink>
@baptisteArno
</NextChakraLink>
</Text> </Text>
</Stack> </Stack>
<Stack align={'flex-start'}> <Stack align={'flex-start'}>
<ListHeader>Product</ListHeader> <ListHeader>Product</ListHeader>
<NextChakraLink <TextLink href={documentationLink} isExternal>
href={documentationLink}
isExternal
color="gray.400"
>
Documentation Documentation
</NextChakraLink> </TextLink>
<NextChakraLink href={roadmapLink} isExternal color="gray.400"> <TextLink href={roadmapLink} isExternal>
Roadmap Roadmap
</NextChakraLink> </TextLink>
<NextChakraLink href={'/pricing'} color="gray.400"> <TextLink href={'/pricing'}>Pricing</TextLink>
Pricing
</NextChakraLink>
</Stack> </Stack>
<Stack align={'flex-start'}> <Stack align={'flex-start'}>
<ListHeader>Community</ListHeader> <ListHeader>Community</ListHeader>
<NextChakraLink href={githubRepoLink} isExternal color="gray.400"> <TextLink href={githubRepoLink} isExternal>
GitHub repository GitHub repository
</NextChakraLink> </TextLink>
<NextChakraLink href={facebookGroupUrl} isExternal color="gray.400"> <TextLink href={facebookGroupUrl} isExternal>
Facebook Group Facebook Group
</NextChakraLink> </TextLink>
<NextChakraLink <TextLink href={typebotTwitterUrl} isExternal>
href={typebotTwitterUrl}
isExternal
color="gray.400"
>
Twitter Twitter
</NextChakraLink> </TextLink>
<NextChakraLink <TextLink href={typebotLinkedInUrl} isExternal>
href={typebotLinkedInUrl}
isExternal
color="gray.400"
>
LinkedIn LinkedIn
</NextChakraLink> </TextLink>
</Stack> </Stack>
<Stack align={'flex-start'}> <Stack align={'flex-start'}>
<ListHeader>Company</ListHeader> <ListHeader>Company</ListHeader>
<NextChakraLink href="/about" color="gray.400"> <TextLink href="/about">About</TextLink>
About <TextLink href="mailto:baptiste@typebot.io">Contact</TextLink>
</NextChakraLink> <TextLink href={'/terms-of-service'}>Terms of Service</TextLink>
<NextChakraLink href="mailto:baptiste@typebot.io" color="gray.400"> <TextLink href={'/privacy-policies'}>Privacy Policy</TextLink>
Contact
</NextChakraLink>
<NextChakraLink href={'/terms-of-service'} color="gray.400">
Terms of Service
</NextChakraLink>
<NextChakraLink href={'/privacy-policies'} color="gray.400">
Privacy Policy
</NextChakraLink>
</Stack> </Stack>
</SimpleGrid> </SimpleGrid>
</Container> </Container>

View File

@ -7,13 +7,13 @@ import {
useColorModeValue as mode, useColorModeValue as mode,
useDisclosure, useDisclosure,
Box, Box,
Link,
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { HamburgerIcon } from 'assets/icons' import { HamburgerIcon } from 'assets/icons'
import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon' import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon'
import { CloseIcon } from 'assets/icons/CloseIcon' import { CloseIcon } from 'assets/icons/CloseIcon'
import { Logo } from 'assets/icons/Logo' import { Logo } from 'assets/icons/Logo'
import * as React from 'react' import * as React from 'react'
import { NextChakraLink } from '../nextChakraAdapters/NextChakraLink'
import { MobileMenu } from './MobileMenu' import { MobileMenu } from './MobileMenu'
import { ResourcesMenu } from './ResourcesMenu' import { ResourcesMenu } from './ResourcesMenu'
@ -40,7 +40,7 @@ export const Header = () => {
className="nav-content__mobile" className="nav-content__mobile"
color={mode('white', 'white')} color={mode('white', 'white')}
> >
<HStack as={NextChakraLink} href="/" rel="home" ml="2"> <HStack as={Link} href="/" rel="home" ml="2">
<Logo boxSize="35px" /> <Logo boxSize="35px" />
<Heading as="p" fontSize="lg"> <Heading as="p" fontSize="lg">
Typebot Typebot
@ -77,7 +77,7 @@ export const Header = () => {
<ResourcesMenu isOpen={isOpen} /> <ResourcesMenu isOpen={isOpen} />
</Flex> </Flex>
<Button <Button
as={NextChakraLink} as={Link}
href="/pricing" href="/pricing"
variant="ghost" variant="ghost"
colorScheme="gray" colorScheme="gray"
@ -86,7 +86,7 @@ export const Header = () => {
Pricing Pricing
</Button> </Button>
<Button <Button
as={NextChakraLink} as={Link}
href="https://app.typebot.io/signin" href="https://app.typebot.io/signin"
colorScheme="blue" colorScheme="blue"
variant="outline" variant="outline"
@ -95,7 +95,7 @@ export const Header = () => {
Sign in Sign in
</Button> </Button>
<Button <Button
as={NextChakraLink} as={Link}
href="https://app.typebot.io/register" href="https://app.typebot.io/register"
colorScheme="orange" colorScheme="orange"
fontWeight={700} fontWeight={700}

View File

@ -1,5 +1,5 @@
import { Collapse, Stack, Button, Text } from '@chakra-ui/react' import { Collapse, Stack, Button, Text } from '@chakra-ui/react'
import { NextChakraLink } from '../nextChakraAdapters/NextChakraLink' import Link from 'next/link'
import { links } from './_data' import { links } from './_data'
type Props = { isOpen: boolean } type Props = { isOpen: boolean }
@ -15,7 +15,7 @@ export const MobileMenu = ({ isOpen }: Props) => (
spacing={4} spacing={4}
> >
<Button <Button
as={NextChakraLink} as={Link}
href="https://app.typebot.io/signin" href="https://app.typebot.io/signin"
colorScheme="blue" colorScheme="blue"
variant="outline" variant="outline"
@ -24,7 +24,7 @@ export const MobileMenu = ({ isOpen }: Props) => (
Sign in Sign in
</Button> </Button>
<Button <Button
as={NextChakraLink} as={Link}
href="https://app.typebot.io/register" href="https://app.typebot.io/register"
colorScheme="orange" colorScheme="orange"
fontWeight={700} fontWeight={700}
@ -32,7 +32,7 @@ export const MobileMenu = ({ isOpen }: Props) => (
Create a typebot Create a typebot
</Button> </Button>
<Button <Button
as={NextChakraLink} as={Link}
href="/pricing" href="/pricing"
variant="outline" variant="outline"
colorScheme="gray" colorScheme="gray"
@ -43,7 +43,7 @@ export const MobileMenu = ({ isOpen }: Props) => (
<Text fontWeight="700">Resources:</Text> <Text fontWeight="700">Resources:</Text>
{links[0].children?.map((link, idx) => ( {links[0].children?.map((link, idx) => (
<Button <Button
as={NextChakraLink} as={Link}
href={link.href} href={link.href}
key={idx} key={idx}
variant="outline" variant="outline"

View File

@ -8,8 +8,8 @@ import {
useColorModeValue as mode, useColorModeValue as mode,
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { ChevronRightIcon } from 'assets/icons/ChevronRightIcon' import { ChevronRightIcon } from 'assets/icons/ChevronRightIcon'
import Link from 'next/link'
import * as React from 'react' import * as React from 'react'
import { NextChakraLink } from '../nextChakraAdapters/NextChakraLink'
import { links } from './_data' import { links } from './_data'
type Props = { isOpen: boolean } type Props = { isOpen: boolean }
@ -29,7 +29,8 @@ export const ResourcesMenu = ({ isOpen }: Props) => (
<Box maxW="7xl" mx="auto" px="8"> <Box maxW="7xl" mx="auto" px="8">
<SimpleGrid spacing="10" columns={2}> <SimpleGrid spacing="10" columns={2}>
{links[0].children?.map((item, idx) => ( {links[0].children?.map((item, idx) => (
<NextChakraLink <Box
as={Link}
key={idx} key={idx}
className="group" className="group"
href={item.href} href={item.href}
@ -41,9 +42,11 @@ export const ResourcesMenu = ({ isOpen }: Props) => (
rounded="lg" rounded="lg"
_hover={{ bg: mode('gray.50', 'gray.600') }} _hover={{ bg: mode('gray.50', 'gray.600') }}
_focus={{ shadow: 'outline' }} _focus={{ shadow: 'outline' }}
isExternal={ target={
item.href.startsWith('https') && item.href.startsWith('https') &&
!item.href.includes('app.typebot.io') !item.href.includes('app.typebot.io')
? '_blank'
: undefined
} }
> >
<Center <Center
@ -80,7 +83,7 @@ export const ResourcesMenu = ({ isOpen }: Props) => (
{item.description} {item.description}
</Text> </Text>
</Box> </Box>
</NextChakraLink> </Box>
))} ))}
</SimpleGrid> </SimpleGrid>
</Box> </Box>

View File

@ -0,0 +1,37 @@
import Link, { LinkProps } from 'next/link'
import React from 'react'
import { Box, chakra, HStack, Stack, TextProps } from '@chakra-ui/react'
import { ExternalLinkIcon } from 'assets/icons/ExternalLinkIcon'
type TextLinkProps = LinkProps & TextProps & { isExternal?: boolean }
export const TextLink = ({
children,
href,
shallow,
replace,
scroll,
prefetch,
isExternal,
...textProps
}: TextLinkProps) => (
<Link
href={href}
shallow={shallow}
replace={replace}
scroll={scroll}
prefetch={prefetch}
target={isExternal ? '_blank' : undefined}
>
<chakra.span textDecor="underline" display="inline-block" {...textProps}>
{isExternal ? (
<HStack as="span" spacing={1}>
<chakra.span>{children}</chakra.span>
<ExternalLinkIcon />
</HStack>
) : (
children
)}
</chakra.span>
</Link>
)

View File

@ -1,50 +0,0 @@
import { PropsWithChildren } from 'react'
import NextLink from 'next/link'
import { LinkProps as NextLinkProps } from 'next/dist/client/link'
import {
Link as ChakraLink,
LinkProps as ChakraLinkProps,
} from '@chakra-ui/react'
import React from 'react'
export type NextChakraLinkProps = PropsWithChildren<
NextLinkProps & Omit<ChakraLinkProps, 'as'>
>
// Has to be a new component because both chakra and next share the `as` keyword
// eslint-disable-next-line react/display-name
export const NextChakraLink = React.forwardRef(
(
{
href,
as,
replace,
scroll,
shallow,
prefetch,
children,
locale,
...chakraProps
}: NextChakraLinkProps,
ref
) => {
return (
<NextLink
passHref={true}
href={href}
as={as}
replace={replace}
scroll={scroll}
shallow={shallow}
prefetch={prefetch}
locale={locale}
>
{/*eslint-disable-next-line @typescript-eslint/ban-ts-comment*/}
{/*@ts-ignore*/}
<ChakraLink ref={ref} {...chakraProps}>
{children}
</ChakraLink>
</NextLink>
)
}
)

View File

@ -5,7 +5,7 @@ import React from 'react'
import selfie from '../public/images/about/selfie.png' import selfie from '../public/images/about/selfie.png'
import Image from 'next/image' import Image from 'next/image'
import { Footer } from 'components/common/Footer' import { Footer } from 'components/common/Footer'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink' import { TextLink } from 'components/common/TextLink'
const AboutPage = () => { const AboutPage = () => {
return ( return (
@ -67,12 +67,9 @@ const AboutPage = () => {
</Text> </Text>
<Text> <Text>
If you have any questions, feel free to reach out to me at{' '} If you have any questions, feel free to reach out to me at{' '}
<NextChakraLink <TextLink href={'mailto:baptiste@typebot.io'}>
href={'mailto:baptiste@typebot.io'}
textDecor="underline"
>
baptiste@typebot.io baptiste@typebot.io
</NextChakraLink> </TextLink>
</Text> </Text>
</Stack> </Stack>
<Footer /> <Footer />

View File

@ -15,7 +15,6 @@ import {
} from '@chakra-ui/react' } from '@chakra-ui/react'
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 { 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'
@ -25,13 +24,13 @@ import { StripeClimateLogo } from 'assets/logos/StripeClimateLogo'
import { FreePlanCard } from 'components/PricingPage/FreePlanCard' import { FreePlanCard } from 'components/PricingPage/FreePlanCard'
import { StarterPlanCard } from 'components/PricingPage/StarterPlanCard' import { StarterPlanCard } from 'components/PricingPage/StarterPlanCard'
import { ProPlanCard } from 'components/PricingPage/ProPlanCard' import { ProPlanCard } from 'components/PricingPage/ProPlanCard'
import { TextLink } from 'components/common/TextLink'
const Pricing = () => { const Pricing = () => {
const [starterPrice, setStarterPrice] = useState('$39') const [starterPrice, setStarterPrice] = useState('$39')
const [proPrice, setProPrice] = useState('$89') const [proPrice, setProPrice] = useState('$89')
useEffect(() => { useEffect(() => {
if (typeof window === 'undefined') return
setStarterPrice(formatPrice(prices.STARTER)) setStarterPrice(formatPrice(prices.STARTER))
setProPrice(formatPrice(prices.PRO)) setProPrice(formatPrice(prices.PRO))
}, []) }, [])
@ -81,13 +80,9 @@ const Pricing = () => {
<Text fontSize="sm"> <Text fontSize="sm">
Typebot is contributing 1% of your subscription to remove CO₂ Typebot is contributing 1% of your subscription to remove CO₂
from the atmosphere.{' '} from the atmosphere.{' '}
<NextChakraLink <TextLink href="https://climate.stripe.com/5VCRAq" isExternal>
href="https://climate.stripe.com/5VCRAq" More info
isExternal </TextLink>
textDecor="underline"
>
More info.
</NextChakraLink>
</Text> </Text>
</HStack> </HStack>
<Stack <Stack
@ -104,13 +99,9 @@ const Pricing = () => {
</Stack> </Stack>
<Text fontSize="lg"> <Text fontSize="lg">
Need custom limits? Specific features?{' '} Need custom limits? Specific features?{' '}
<NextChakraLink <TextLink href={'https://typebot.io/enterprise-lead-form'}>
href={'https://typebot.io/enterprise-lead-form'}
isExternal
textDecor="underline"
>
Let's chat! Let's chat!
</NextChakraLink> </TextLink>
</Text> </Text>
</Stack> </Stack>
@ -195,12 +186,9 @@ const Faq = () => {
</Heading> </Heading>
<AccordionPanel pb={4}> <AccordionPanel pb={4}>
Sure! Just{' '} Sure! Just{' '}
<NextChakraLink <TextLink href="mailto:baptiste@typebot.io">
href="mailto:baptiste@typebot.io"
textDecor="underline"
>
shoot me an email shoot me an email
</NextChakraLink>{' '} </TextLink>{' '}
and we'll figure things out 😀 and we'll figure things out 😀
</AccordionPanel> </AccordionPanel>
</AccordionItem> </AccordionItem>