2
0
Files
bot/apps/landing-page/components/PricingPage/PricingCard/index.tsx
Baptiste Arnaud 797751b418 (billing) Automatic usage-based billing (#924)
BREAKING CHANGE: Stripe environment variables simplified. Check out the
new configs to adapt your existing system.

Closes #906





<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
### Summary by CodeRabbit

**New Features:**
- Introduced a usage-based billing system, providing more flexibility
and options for users.
- Integrated with Stripe for a smoother and more secure payment process.
- Enhanced the user interface with improvements to the billing,
workspace, and pricing pages for a more intuitive experience.

**Improvements:**
- Simplified the billing logic, removing additional chats and yearly
billing for a more streamlined user experience.
- Updated email notifications to keep users informed about their usage
and limits.
- Improved pricing and currency formatting for better clarity and
understanding.

**Testing:**
- Updated tests and specifications to ensure the reliability of new
features and improvements.

**Note:** These changes aim to provide a more flexible and user-friendly
billing system, with clearer pricing and improved notifications. Users
should find the new system more intuitive and easier to navigate.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2023-10-17 08:03:30 +02:00

95 lines
2.4 KiB
TypeScript

import {
Flex,
Heading,
List,
ListIcon,
ListItem,
Text,
useColorModeValue,
VStack,
} from '@chakra-ui/react'
import * as React from 'react'
import { CheckCircleIcon } from '../../../assets/icons/CheckCircleIcon'
import { Card, CardProps } from './Card'
import { formatPrice } from '@typebot.io/lib/billing/formatPrice'
export interface PricingCardData {
features: React.ReactNode[]
name: string
price: number | string
featureLabel?: string
}
interface PricingCardProps extends CardProps {
data: PricingCardData
icon?: JSX.Element
button: React.ReactElement
}
export const PricingCard = ({
data,
icon,
button,
...rest
}: PricingCardProps) => {
const { features, price, name } = data
const accentColor = useColorModeValue('blue.500', 'white')
const formattedPrice = typeof price === 'number' ? formatPrice(price) : price
return (
<Card rounded="xl" bgColor="gray.800" {...rest}>
<Flex justifyContent="space-between" flexDir="column" h="full">
<Flex flexDir="column">
<VStack spacing={6}>
{icon}
<Heading size="md" fontWeight="extrabold" color={rest.borderColor}>
{name}
</Heading>
</VStack>
<Flex
align="flex-end"
justify="center"
fontWeight="extrabold"
color={accentColor}
my="8"
>
<Heading size="2xl" fontWeight="inherit" lineHeight="0.9em">
{formattedPrice}
</Heading>
{typeof price === 'number' && (
<Text fontWeight="inherit" fontSize="xl">
/ month
</Text>
)}
</Flex>
<List spacing="4" mb="8" maxW="30ch" mx="auto">
{data.featureLabel && (
<Text fontWeight="bold">{data.featureLabel}</Text>
)}
{features.map((feature, index) => (
<ListItem
fontWeight="medium"
key={index}
display="flex"
alignItems="center"
>
<ListIcon
fontSize="xl"
as={CheckCircleIcon}
marginEnd={2}
color={accentColor}
fill={rest.borderColor}
/>
{feature}
</ListItem>
))}
</List>
</Flex>
{button}
</Flex>
</Card>
)
}