✏️ (lp) Fix incorrect additional limits price
This commit is contained in:
@ -18,8 +18,8 @@ export const StripeClimateLogo = (props: IconProps) => (
|
||||
y2="7.8394"
|
||||
gradientTransform="matrix(1 0 0 -1 0 34)"
|
||||
>
|
||||
<stop offset="0" stop-color="#00d924" />
|
||||
<stop offset="1" stop-color="#00cb1b" />
|
||||
<stop offset="0" stopColor="#00d924" />
|
||||
<stop offset="1" stopColor="#00cb1b" />
|
||||
</linearGradient>
|
||||
<path
|
||||
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"
|
||||
gradientTransform="matrix(1 0 0 -1 0 34)"
|
||||
>
|
||||
<stop offset=".1562" stop-color="#009c00" />
|
||||
<stop offset="1" stop-color="#00be20" />
|
||||
<stop offset=".1562" stopColor="#009c00" />
|
||||
<stop offset="1" stopColor="#00be20" />
|
||||
</linearGradient>
|
||||
<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"
|
||||
@ -50,8 +50,8 @@ export const StripeClimateLogo = (props: IconProps) => (
|
||||
y2="29.1239"
|
||||
gradientTransform="matrix(1 0 0 -1 0 34)"
|
||||
>
|
||||
<stop offset="0" stop-color="#ffe37d" />
|
||||
<stop offset="1" stop-color="#ffc900" />
|
||||
<stop offset="0" stopColor="#ffe37d" />
|
||||
<stop offset="1" stopColor="#ffc900" />
|
||||
</linearGradient>
|
||||
<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"
|
||||
|
@ -16,7 +16,7 @@ export const BillingContent = () => {
|
||||
return (
|
||||
<Stack spacing="10" w="full">
|
||||
<UsageContent workspace={workspace} />
|
||||
<Stack gap="2">
|
||||
<Stack spacing="2">
|
||||
<CurrentSubscriptionContent
|
||||
plan={workspace.plan}
|
||||
stripeId={workspace.stripeId}
|
||||
|
@ -44,7 +44,7 @@ export const CurrentSubscriptionContent = ({
|
||||
const isSubscribed = (plan === Plan.STARTER || plan === Plan.PRO) && stripeId
|
||||
|
||||
return (
|
||||
<Stack gap="2">
|
||||
<Stack spacing="2">
|
||||
<Heading fontSize="3xl">Subscription</Heading>
|
||||
<HStack data-testid="current-subscription">
|
||||
<Text>Current workspace subscription: </Text>
|
||||
@ -70,7 +70,7 @@ export const CurrentSubscriptionContent = ({
|
||||
|
||||
{isSubscribed && !isCancelling && (
|
||||
<>
|
||||
<Stack gap="1">
|
||||
<Stack spacing="1">
|
||||
<Text fontSize="sm">
|
||||
Need to change payment method or billing information? Head over to
|
||||
your billing portal:
|
||||
|
@ -127,13 +127,6 @@ export const UsageContent = ({ workspace }: Props) => {
|
||||
</Tooltip>
|
||||
)}
|
||||
</HStack>
|
||||
<Heading
|
||||
fontSize="xl"
|
||||
as="h3"
|
||||
display="inline-flex"
|
||||
alignItems="center"
|
||||
gap="2"
|
||||
></Heading>
|
||||
<HStack>
|
||||
<Skeleton
|
||||
fontWeight="bold"
|
||||
|
@ -93,7 +93,7 @@ export const MembersList = () => {
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack w="full" gap="3">
|
||||
<Stack w="full" spacing={3}>
|
||||
{!canInviteNewMember && (
|
||||
<UnlockPlanInfo
|
||||
contentLabel={`
|
||||
|
10
apps/landing-page/assets/icons/ExternalLinkIcon.tsx
Normal file
10
apps/landing-page/assets/icons/ExternalLinkIcon.tsx
Normal 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>
|
||||
)
|
@ -18,8 +18,8 @@ export const StripeClimateLogo = (props: IconProps) => (
|
||||
y2="7.8394"
|
||||
gradientTransform="matrix(1 0 0 -1 0 34)"
|
||||
>
|
||||
<stop offset="0" stop-color="#00d924" />
|
||||
<stop offset="1" stop-color="#00cb1b" />
|
||||
<stop offset="0" stopColor="#00d924" />
|
||||
<stop offset="1" stopColor="#00cb1b" />
|
||||
</linearGradient>
|
||||
<path
|
||||
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"
|
||||
gradientTransform="matrix(1 0 0 -1 0 34)"
|
||||
>
|
||||
<stop offset=".1562" stop-color="#009c00" />
|
||||
<stop offset="1" stop-color="#00be20" />
|
||||
<stop offset=".1562" stopColor="#009c00" />
|
||||
<stop offset="1" stopColor="#00be20" />
|
||||
</linearGradient>
|
||||
<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"
|
||||
@ -50,8 +50,8 @@ export const StripeClimateLogo = (props: IconProps) => (
|
||||
y2="29.1239"
|
||||
gradientTransform="matrix(1 0 0 -1 0 34)"
|
||||
>
|
||||
<stop offset="0" stop-color="#ffe37d" />
|
||||
<stop offset="1" stop-color="#ffc900" />
|
||||
<stop offset="0" stopColor="#ffe37d" />
|
||||
<stop offset="1" stopColor="#ffc900" />
|
||||
</linearGradient>
|
||||
<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"
|
||||
|
@ -2,9 +2,9 @@ import { Flex, Stack, Heading, Box, Text, Button } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
import Image from 'next/image'
|
||||
import builderDndSrc from 'public/images/homepage/builder-dnd.png'
|
||||
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||
import { ArrowRight } from 'assets/icons/ArrowRight'
|
||||
import { Flare } from 'assets/illustrations/Flare'
|
||||
import Link from 'next/link'
|
||||
|
||||
export const EasyBuildingExperience = () => {
|
||||
return (
|
||||
@ -41,7 +41,7 @@ export const EasyBuildingExperience = () => {
|
||||
</Text>
|
||||
<Flex>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
rightIcon={<ArrowRight />}
|
||||
href={`https://app.typebot.io/register`}
|
||||
variant="ghost"
|
||||
|
@ -2,9 +2,9 @@ import { Flex, Stack, Heading, Box, Text, Button } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
import Image from 'next/image'
|
||||
import nativeFeelingSrc from 'public/images/homepage/native-feeling.png'
|
||||
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||
import { ArrowRight } from 'assets/icons/ArrowRight'
|
||||
import { Flare } from 'assets/illustrations/Flare'
|
||||
import Link from 'next/link'
|
||||
|
||||
export const EasyEmbed = () => {
|
||||
return (
|
||||
@ -42,7 +42,7 @@ export const EasyEmbed = () => {
|
||||
</Text>
|
||||
<Flex data-aos="fade">
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
rightIcon={<ArrowRight />}
|
||||
href={`https://app.typebot.io/register`}
|
||||
variant="ghost"
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { BackgroundPolygons } from './Hero/BackgroundPolygons'
|
||||
|
||||
@ -31,7 +31,7 @@ export const EndCta = () => {
|
||||
</Heading>
|
||||
<Flex>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href="https://app.typebot.io/register"
|
||||
size="lg"
|
||||
colorScheme="orange"
|
||||
|
@ -8,13 +8,13 @@ import {
|
||||
Text,
|
||||
VStack,
|
||||
} from '@chakra-ui/react'
|
||||
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||
import * as React from 'react'
|
||||
import { Header } from '../../common/Header/Header'
|
||||
import { BackgroundPolygons } from './BackgroundPolygons'
|
||||
import * as Logos from './Brands'
|
||||
import Image from 'next/image'
|
||||
import builderScreenshotSrc from 'public/images/homepage/builder.png'
|
||||
import Link from 'next/link'
|
||||
|
||||
export const Hero = () => {
|
||||
return (
|
||||
@ -52,7 +52,7 @@ export const Hero = () => {
|
||||
data-aos-delay="200"
|
||||
>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href="https://app.typebot.io/register"
|
||||
colorScheme="orange"
|
||||
size="lg"
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Flex, Stack, Heading, Text, Button, VStack } from '@chakra-ui/react'
|
||||
import { ArrowRight } from 'assets/icons/ArrowRight'
|
||||
import { TypebotViewer } from 'bot-engine'
|
||||
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||
import { PublicTypebot, Typebot } from 'models'
|
||||
import Link from 'next/link'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { sendRequest } from 'utils'
|
||||
|
||||
@ -72,7 +72,7 @@ export const RealTimeResults = () => {
|
||||
</Text>
|
||||
<Flex>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
rightIcon={<ArrowRight />}
|
||||
href={`https://app.typebot.io/register`}
|
||||
variant="ghost"
|
||||
|
@ -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 { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import { PricingCard } from './PricingCard'
|
||||
import { ActionButton } from './PricingCard/ActionButton'
|
||||
|
||||
export const FreePlanCard = () => (
|
||||
<PricingCard
|
||||
@ -34,12 +33,18 @@ export const FreePlanCard = () => (
|
||||
],
|
||||
}}
|
||||
button={
|
||||
<NextChakraLink
|
||||
<Button
|
||||
as={Link}
|
||||
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>
|
||||
</NextChakraLink>
|
||||
Get started
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
)
|
||||
|
@ -17,9 +17,10 @@ import {
|
||||
} from '@chakra-ui/react'
|
||||
import { CheckIcon } from 'assets/icons/CheckIcon'
|
||||
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
|
||||
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||
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 = {
|
||||
starterPrice: string
|
||||
@ -31,6 +32,20 @@ export const PlanComparisonTables = ({
|
||||
proPrice,
|
||||
...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 (
|
||||
<Stack spacing="12" {...props}>
|
||||
<TableContainer>
|
||||
@ -61,8 +76,8 @@ export const PlanComparisonTables = ({
|
||||
<Tr>
|
||||
<Td>Additional Chats</Td>
|
||||
<Td />
|
||||
<Td>$10 per 500</Td>
|
||||
<Td>$10 per 1,000</Td>
|
||||
<Td>{additionalChatsPrice} per 500</Td>
|
||||
<Td>{additionalChatsPrice} per 1,000</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>Storage</Td>
|
||||
@ -73,8 +88,8 @@ export const PlanComparisonTables = ({
|
||||
<Tr>
|
||||
<Td>Additional Storage</Td>
|
||||
<Td />
|
||||
<Td>$5 per 1 GB</Td>
|
||||
<Td>$5 per 1 GB</Td>
|
||||
<Td>{additionalStoragePrice} per 1 GB</Td>
|
||||
<Td>{additionalStoragePrice} per 1 GB</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>Members</Td>
|
||||
@ -331,12 +346,9 @@ export const PlanComparisonTables = ({
|
||||
Personal
|
||||
</Heading>
|
||||
<Heading as="h3">Free</Heading>
|
||||
<NextChakraLink
|
||||
href="https://app.typebot.io/register"
|
||||
_hover={{ textDecor: 'none' }}
|
||||
>
|
||||
<Link href="https://app.typebot.io/register">
|
||||
<Button variant="outline">Get started</Button>
|
||||
</NextChakraLink>
|
||||
</Link>
|
||||
</Stack>
|
||||
<Stack spacing={4}>
|
||||
<Heading as="h3" size="md" color="orange.200">
|
||||
@ -345,12 +357,11 @@ export const PlanComparisonTables = ({
|
||||
<Heading as="h3">
|
||||
{starterPrice} <chakra.span fontSize="lg">/ month</chakra.span>
|
||||
</Heading>
|
||||
<NextChakraLink
|
||||
<Link
|
||||
href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}`}
|
||||
_hover={{ textDecor: 'none' }}
|
||||
>
|
||||
<Button>Subscribe</Button>
|
||||
</NextChakraLink>
|
||||
</Link>
|
||||
</Stack>
|
||||
<Stack spacing={4}>
|
||||
<Heading as="h3" size="md" color="blue.200">
|
||||
@ -359,12 +370,11 @@ export const PlanComparisonTables = ({
|
||||
<Heading as="h3">
|
||||
{proPrice} <chakra.span fontSize="lg">/ month</chakra.span>
|
||||
</Heading>
|
||||
<NextChakraLink
|
||||
<Link
|
||||
href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}`}
|
||||
_hover={{ textDecor: 'none' }}
|
||||
>
|
||||
<Button>Subscribe</Button>
|
||||
</NextChakraLink>
|
||||
</Link>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
@ -378,12 +388,12 @@ const TdWithTooltip = ({
|
||||
text: string
|
||||
tooltip: string
|
||||
}) => (
|
||||
<Td as={HStack}>
|
||||
<HStack as={Td}>
|
||||
<Text>{text}</Text>
|
||||
<Tooltip hasArrow placement="top" label={tooltip}>
|
||||
<chakra.span cursor="pointer">
|
||||
<HelpCircleIcon />
|
||||
</chakra.span>
|
||||
</Tooltip>
|
||||
</Td>
|
||||
</HStack>
|
||||
)
|
||||
|
@ -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}
|
||||
/>
|
||||
)
|
@ -9,13 +9,15 @@ import {
|
||||
VStack,
|
||||
} from '@chakra-ui/react'
|
||||
import * as React from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { formatPrice } from 'utils'
|
||||
import { CheckCircleIcon } from '../../../assets/icons/CheckCircleIcon'
|
||||
import { Card, CardProps } from './Card'
|
||||
|
||||
export interface PricingCardData {
|
||||
features: React.ReactNode[]
|
||||
name: string
|
||||
price: string
|
||||
price: number | string
|
||||
featureLabel?: string
|
||||
}
|
||||
|
||||
@ -32,8 +34,13 @@ export const PricingCard = ({
|
||||
...rest
|
||||
}: PricingCardProps) => {
|
||||
const { features, price, name } = data
|
||||
const [formattedPrice, setFormattedPrice] = useState(price)
|
||||
const accentColor = useColorModeValue('blue.500', 'white')
|
||||
|
||||
useEffect(() => {
|
||||
setFormattedPrice(typeof price === 'number' ? formatPrice(price) : price)
|
||||
}, [price])
|
||||
|
||||
return (
|
||||
<Card rounded="xl" bgColor="gray.800" {...rest}>
|
||||
<Flex justifyContent="space-between" flexDir="column" h="full">
|
||||
@ -52,9 +59,9 @@ export const PricingCard = ({
|
||||
my="8"
|
||||
>
|
||||
<Heading size="2xl" fontWeight="inherit" lineHeight="0.9em">
|
||||
{price}
|
||||
{formattedPrice}
|
||||
</Heading>
|
||||
{(price.includes('$') || price.includes('€')) && (
|
||||
{typeof price === 'number' && (
|
||||
<Text fontWeight="inherit" fontSize="xl">
|
||||
/ month
|
||||
</Text>
|
||||
|
@ -11,21 +11,19 @@ import {
|
||||
} 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 Link from 'next/link'
|
||||
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 [price, setPrice] = useState(89)
|
||||
|
||||
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
|
||||
useState<number>(0)
|
||||
@ -34,13 +32,11 @@ export const ProPlanCard = () => {
|
||||
|
||||
useEffect(() => {
|
||||
setPrice(
|
||||
formatPrice(
|
||||
computePrice(
|
||||
Plan.PRO,
|
||||
selectedChatsLimitIndex ?? 0,
|
||||
selectedStorageLimitIndex ?? 0
|
||||
) ?? NaN
|
||||
)
|
||||
computePrice(
|
||||
Plan.PRO,
|
||||
selectedChatsLimitIndex ?? 0,
|
||||
selectedStorageLimitIndex ?? 0
|
||||
) ?? NaN
|
||||
)
|
||||
}, [selectedChatsLimitIndex, selectedStorageLimitIndex])
|
||||
|
||||
@ -54,66 +50,64 @@ export const ProPlanCard = () => {
|
||||
<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>
|
||||
<HStack key="chats" spacing={1.5}>
|
||||
<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>{' '}
|
||||
<Text>chats/mo</Text>
|
||||
<Tooltip
|
||||
hasArrow
|
||||
placement="top"
|
||||
@ -125,66 +119,64 @@ export const ProPlanCard = () => {
|
||||
</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>
|
||||
<HStack key="storage" spacing={1.5}>
|
||||
<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>{' '}
|
||||
<Text>GB of storage</Text>
|
||||
<Tooltip
|
||||
hasArrow
|
||||
placement="top"
|
||||
@ -204,12 +196,17 @@ export const ProPlanCard = () => {
|
||||
borderWidth="3px"
|
||||
borderColor="blue.200"
|
||||
button={
|
||||
<NextChakraLink
|
||||
<Button
|
||||
as={Link}
|
||||
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>
|
||||
</NextChakraLink>
|
||||
Subscribe now
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
)
|
||||
|
@ -11,8 +11,8 @@ import {
|
||||
} 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 Link from 'next/link'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import {
|
||||
chatsLimit,
|
||||
@ -22,10 +22,9 @@ import {
|
||||
storageLimit,
|
||||
} from 'utils'
|
||||
import { PricingCard } from './PricingCard'
|
||||
import { ActionButton } from './PricingCard/ActionButton'
|
||||
|
||||
export const StarterPlanCard = () => {
|
||||
const [price, setPrice] = useState('39$')
|
||||
const [price, setPrice] = useState(39)
|
||||
|
||||
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
|
||||
useState<number>(0)
|
||||
@ -34,13 +33,11 @@ export const StarterPlanCard = () => {
|
||||
|
||||
useEffect(() => {
|
||||
setPrice(
|
||||
formatPrice(
|
||||
computePrice(
|
||||
Plan.STARTER,
|
||||
selectedChatsLimitIndex ?? 0,
|
||||
selectedStorageLimitIndex ?? 0
|
||||
) ?? NaN
|
||||
)
|
||||
computePrice(
|
||||
Plan.STARTER,
|
||||
selectedChatsLimitIndex ?? 0,
|
||||
selectedStorageLimitIndex ?? 0
|
||||
) ?? NaN
|
||||
)
|
||||
}, [selectedChatsLimitIndex, selectedStorageLimitIndex])
|
||||
|
||||
@ -54,67 +51,62 @@ export const StarterPlanCard = () => {
|
||||
<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>
|
||||
<HStack key="chats" spacing={1.5}>
|
||||
<Menu>
|
||||
<MenuButton
|
||||
as={Button}
|
||||
rightIcon={<ChevronDownIcon />}
|
||||
size="sm"
|
||||
variant="outline"
|
||||
colorScheme="orange"
|
||||
>
|
||||
{parseNumberWithCommas(
|
||||
chatsLimit.STARTER.totalIncluded +
|
||||
chatsLimit.STARTER.increaseStep.amount *
|
||||
selectedChatsLimitIndex
|
||||
)}
|
||||
</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>{' '}
|
||||
<Text>chats/mo</Text>
|
||||
<Tooltip
|
||||
hasArrow
|
||||
placement="top"
|
||||
@ -126,69 +118,65 @@ export const StarterPlanCard = () => {
|
||||
</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>
|
||||
<HStack key="storage" spacing={1.5}>
|
||||
<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>{' '}
|
||||
<Text>GB of storage</Text>
|
||||
<Tooltip
|
||||
hasArrow
|
||||
placement="top"
|
||||
@ -209,12 +197,17 @@ export const StarterPlanCard = () => {
|
||||
borderWidth="1px"
|
||||
borderColor="orange.200"
|
||||
button={
|
||||
<NextChakraLink
|
||||
<Button
|
||||
as={Link}
|
||||
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>
|
||||
</NextChakraLink>
|
||||
Subscribe now
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
)
|
||||
|
@ -9,8 +9,8 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
} from '@chakra-ui/react'
|
||||
import { NextChakraLink } from './nextChakraAdapters/NextChakraLink'
|
||||
import { Logo } from 'assets/icons/Logo'
|
||||
import { TextLink } from './TextLink'
|
||||
|
||||
const facebookGroupUrl = 'https://www.facebook.com/groups/typebot'
|
||||
const typebotLinkedInUrl = 'https://www.linkedin.com/company/typebot'
|
||||
@ -35,64 +35,40 @@ export const Footer = () => {
|
||||
</HStack>
|
||||
<Text>
|
||||
Made with ❤️ by{' '}
|
||||
<NextChakraLink href={baptisteTwitterUrl} color="gray.400">
|
||||
@baptisteArno
|
||||
</NextChakraLink>
|
||||
<TextLink href={baptisteTwitterUrl}>@baptisteArno</TextLink>
|
||||
</Text>
|
||||
</Stack>
|
||||
<Stack align={'flex-start'}>
|
||||
<ListHeader>Product</ListHeader>
|
||||
<NextChakraLink
|
||||
href={documentationLink}
|
||||
isExternal
|
||||
color="gray.400"
|
||||
>
|
||||
<TextLink href={documentationLink} isExternal>
|
||||
Documentation
|
||||
</NextChakraLink>
|
||||
<NextChakraLink href={roadmapLink} isExternal color="gray.400">
|
||||
</TextLink>
|
||||
<TextLink href={roadmapLink} isExternal>
|
||||
Roadmap
|
||||
</NextChakraLink>
|
||||
<NextChakraLink href={'/pricing'} color="gray.400">
|
||||
Pricing
|
||||
</NextChakraLink>
|
||||
</TextLink>
|
||||
<TextLink href={'/pricing'}>Pricing</TextLink>
|
||||
</Stack>
|
||||
<Stack align={'flex-start'}>
|
||||
<ListHeader>Community</ListHeader>
|
||||
<NextChakraLink href={githubRepoLink} isExternal color="gray.400">
|
||||
<TextLink href={githubRepoLink} isExternal>
|
||||
GitHub repository
|
||||
</NextChakraLink>
|
||||
<NextChakraLink href={facebookGroupUrl} isExternal color="gray.400">
|
||||
</TextLink>
|
||||
<TextLink href={facebookGroupUrl} isExternal>
|
||||
Facebook Group
|
||||
</NextChakraLink>
|
||||
<NextChakraLink
|
||||
href={typebotTwitterUrl}
|
||||
isExternal
|
||||
color="gray.400"
|
||||
>
|
||||
</TextLink>
|
||||
<TextLink href={typebotTwitterUrl} isExternal>
|
||||
Twitter
|
||||
</NextChakraLink>
|
||||
<NextChakraLink
|
||||
href={typebotLinkedInUrl}
|
||||
isExternal
|
||||
color="gray.400"
|
||||
>
|
||||
</TextLink>
|
||||
<TextLink href={typebotLinkedInUrl} isExternal>
|
||||
LinkedIn
|
||||
</NextChakraLink>
|
||||
</TextLink>
|
||||
</Stack>
|
||||
<Stack align={'flex-start'}>
|
||||
<ListHeader>Company</ListHeader>
|
||||
<NextChakraLink href="/about" color="gray.400">
|
||||
About
|
||||
</NextChakraLink>
|
||||
<NextChakraLink href="mailto:baptiste@typebot.io" color="gray.400">
|
||||
Contact
|
||||
</NextChakraLink>
|
||||
<NextChakraLink href={'/terms-of-service'} color="gray.400">
|
||||
Terms of Service
|
||||
</NextChakraLink>
|
||||
<NextChakraLink href={'/privacy-policies'} color="gray.400">
|
||||
Privacy Policy
|
||||
</NextChakraLink>
|
||||
<TextLink href="/about">About</TextLink>
|
||||
<TextLink href="mailto:baptiste@typebot.io">Contact</TextLink>
|
||||
<TextLink href={'/terms-of-service'}>Terms of Service</TextLink>
|
||||
<TextLink href={'/privacy-policies'}>Privacy Policy</TextLink>
|
||||
</Stack>
|
||||
</SimpleGrid>
|
||||
</Container>
|
||||
|
@ -7,13 +7,13 @@ import {
|
||||
useColorModeValue as mode,
|
||||
useDisclosure,
|
||||
Box,
|
||||
Link,
|
||||
} from '@chakra-ui/react'
|
||||
import { HamburgerIcon } from 'assets/icons'
|
||||
import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon'
|
||||
import { CloseIcon } from 'assets/icons/CloseIcon'
|
||||
import { Logo } from 'assets/icons/Logo'
|
||||
import * as React from 'react'
|
||||
import { NextChakraLink } from '../nextChakraAdapters/NextChakraLink'
|
||||
import { MobileMenu } from './MobileMenu'
|
||||
import { ResourcesMenu } from './ResourcesMenu'
|
||||
|
||||
@ -40,7 +40,7 @@ export const Header = () => {
|
||||
className="nav-content__mobile"
|
||||
color={mode('white', 'white')}
|
||||
>
|
||||
<HStack as={NextChakraLink} href="/" rel="home" ml="2">
|
||||
<HStack as={Link} href="/" rel="home" ml="2">
|
||||
<Logo boxSize="35px" />
|
||||
<Heading as="p" fontSize="lg">
|
||||
Typebot
|
||||
@ -77,7 +77,7 @@ export const Header = () => {
|
||||
<ResourcesMenu isOpen={isOpen} />
|
||||
</Flex>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href="/pricing"
|
||||
variant="ghost"
|
||||
colorScheme="gray"
|
||||
@ -86,7 +86,7 @@ export const Header = () => {
|
||||
Pricing
|
||||
</Button>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href="https://app.typebot.io/signin"
|
||||
colorScheme="blue"
|
||||
variant="outline"
|
||||
@ -95,7 +95,7 @@ export const Header = () => {
|
||||
Sign in
|
||||
</Button>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href="https://app.typebot.io/register"
|
||||
colorScheme="orange"
|
||||
fontWeight={700}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Collapse, Stack, Button, Text } from '@chakra-ui/react'
|
||||
import { NextChakraLink } from '../nextChakraAdapters/NextChakraLink'
|
||||
import Link from 'next/link'
|
||||
import { links } from './_data'
|
||||
|
||||
type Props = { isOpen: boolean }
|
||||
@ -15,7 +15,7 @@ export const MobileMenu = ({ isOpen }: Props) => (
|
||||
spacing={4}
|
||||
>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href="https://app.typebot.io/signin"
|
||||
colorScheme="blue"
|
||||
variant="outline"
|
||||
@ -24,7 +24,7 @@ export const MobileMenu = ({ isOpen }: Props) => (
|
||||
Sign in
|
||||
</Button>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href="https://app.typebot.io/register"
|
||||
colorScheme="orange"
|
||||
fontWeight={700}
|
||||
@ -32,7 +32,7 @@ export const MobileMenu = ({ isOpen }: Props) => (
|
||||
Create a typebot
|
||||
</Button>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href="/pricing"
|
||||
variant="outline"
|
||||
colorScheme="gray"
|
||||
@ -43,7 +43,7 @@ export const MobileMenu = ({ isOpen }: Props) => (
|
||||
<Text fontWeight="700">Resources:</Text>
|
||||
{links[0].children?.map((link, idx) => (
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href={link.href}
|
||||
key={idx}
|
||||
variant="outline"
|
||||
|
@ -8,8 +8,8 @@ import {
|
||||
useColorModeValue as mode,
|
||||
} from '@chakra-ui/react'
|
||||
import { ChevronRightIcon } from 'assets/icons/ChevronRightIcon'
|
||||
import Link from 'next/link'
|
||||
import * as React from 'react'
|
||||
import { NextChakraLink } from '../nextChakraAdapters/NextChakraLink'
|
||||
import { links } from './_data'
|
||||
|
||||
type Props = { isOpen: boolean }
|
||||
@ -29,7 +29,8 @@ export const ResourcesMenu = ({ isOpen }: Props) => (
|
||||
<Box maxW="7xl" mx="auto" px="8">
|
||||
<SimpleGrid spacing="10" columns={2}>
|
||||
{links[0].children?.map((item, idx) => (
|
||||
<NextChakraLink
|
||||
<Box
|
||||
as={Link}
|
||||
key={idx}
|
||||
className="group"
|
||||
href={item.href}
|
||||
@ -41,9 +42,11 @@ export const ResourcesMenu = ({ isOpen }: Props) => (
|
||||
rounded="lg"
|
||||
_hover={{ bg: mode('gray.50', 'gray.600') }}
|
||||
_focus={{ shadow: 'outline' }}
|
||||
isExternal={
|
||||
target={
|
||||
item.href.startsWith('https') &&
|
||||
!item.href.includes('app.typebot.io')
|
||||
? '_blank'
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Center
|
||||
@ -80,7 +83,7 @@ export const ResourcesMenu = ({ isOpen }: Props) => (
|
||||
{item.description}
|
||||
</Text>
|
||||
</Box>
|
||||
</NextChakraLink>
|
||||
</Box>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
|
37
apps/landing-page/components/common/TextLink.tsx
Normal file
37
apps/landing-page/components/common/TextLink.tsx
Normal 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>
|
||||
)
|
@ -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>
|
||||
)
|
||||
}
|
||||
)
|
@ -5,7 +5,7 @@ import React from 'react'
|
||||
import selfie from '../public/images/about/selfie.png'
|
||||
import Image from 'next/image'
|
||||
import { Footer } from 'components/common/Footer'
|
||||
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||
import { TextLink } from 'components/common/TextLink'
|
||||
|
||||
const AboutPage = () => {
|
||||
return (
|
||||
@ -67,12 +67,9 @@ const AboutPage = () => {
|
||||
</Text>
|
||||
<Text>
|
||||
If you have any questions, feel free to reach out to me at{' '}
|
||||
<NextChakraLink
|
||||
href={'mailto:baptiste@typebot.io'}
|
||||
textDecor="underline"
|
||||
>
|
||||
<TextLink href={'mailto:baptiste@typebot.io'}>
|
||||
baptiste@typebot.io
|
||||
</NextChakraLink>
|
||||
</TextLink>
|
||||
</Text>
|
||||
</Stack>
|
||||
<Footer />
|
||||
|
@ -15,7 +15,6 @@ import {
|
||||
} from '@chakra-ui/react'
|
||||
import { Footer } from 'components/common/Footer'
|
||||
import { Header } from 'components/common/Header/Header'
|
||||
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
|
||||
import { SocialMetaTags } from 'components/common/SocialMetaTags'
|
||||
import { BackgroundPolygons } from 'components/Homepage/Hero/BackgroundPolygons'
|
||||
import { PlanComparisonTables } from 'components/PricingPage/PlanComparisonTables'
|
||||
@ -25,13 +24,13 @@ import { StripeClimateLogo } from 'assets/logos/StripeClimateLogo'
|
||||
import { FreePlanCard } from 'components/PricingPage/FreePlanCard'
|
||||
import { StarterPlanCard } from 'components/PricingPage/StarterPlanCard'
|
||||
import { ProPlanCard } from 'components/PricingPage/ProPlanCard'
|
||||
import { TextLink } from 'components/common/TextLink'
|
||||
|
||||
const Pricing = () => {
|
||||
const [starterPrice, setStarterPrice] = useState('$39')
|
||||
const [proPrice, setProPrice] = useState('$89')
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined') return
|
||||
setStarterPrice(formatPrice(prices.STARTER))
|
||||
setProPrice(formatPrice(prices.PRO))
|
||||
}, [])
|
||||
@ -81,13 +80,9 @@ const Pricing = () => {
|
||||
<Text fontSize="sm">
|
||||
Typebot is contributing 1% of your subscription to remove CO₂
|
||||
from the atmosphere.{' '}
|
||||
<NextChakraLink
|
||||
href="https://climate.stripe.com/5VCRAq"
|
||||
isExternal
|
||||
textDecor="underline"
|
||||
>
|
||||
More info.
|
||||
</NextChakraLink>
|
||||
<TextLink href="https://climate.stripe.com/5VCRAq" isExternal>
|
||||
More info
|
||||
</TextLink>
|
||||
</Text>
|
||||
</HStack>
|
||||
<Stack
|
||||
@ -104,13 +99,9 @@ const Pricing = () => {
|
||||
</Stack>
|
||||
<Text fontSize="lg">
|
||||
Need custom limits? Specific features?{' '}
|
||||
<NextChakraLink
|
||||
href={'https://typebot.io/enterprise-lead-form'}
|
||||
isExternal
|
||||
textDecor="underline"
|
||||
>
|
||||
<TextLink href={'https://typebot.io/enterprise-lead-form'}>
|
||||
Let's chat!
|
||||
</NextChakraLink>
|
||||
</TextLink>
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
@ -195,12 +186,9 @@ const Faq = () => {
|
||||
</Heading>
|
||||
<AccordionPanel pb={4}>
|
||||
Sure! Just{' '}
|
||||
<NextChakraLink
|
||||
href="mailto:baptiste@typebot.io"
|
||||
textDecor="underline"
|
||||
>
|
||||
<TextLink href="mailto:baptiste@typebot.io">
|
||||
shoot me an email
|
||||
</NextChakraLink>{' '}
|
||||
</TextLink>{' '}
|
||||
and we'll figure things out 😀
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
|
Reference in New Issue
Block a user