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 -->
92 lines
2.7 KiB
TypeScript
92 lines
2.7 KiB
TypeScript
import {
|
|
Modal,
|
|
ModalOverlay,
|
|
ModalContent,
|
|
ModalHeader,
|
|
ModalCloseButton,
|
|
ModalBody,
|
|
Stack,
|
|
ModalFooter,
|
|
Heading,
|
|
Table,
|
|
TableContainer,
|
|
Tbody,
|
|
Td,
|
|
Th,
|
|
Thead,
|
|
Tr,
|
|
} from '@chakra-ui/react'
|
|
import { proChatTiers } from '@typebot.io/lib/billing/constants'
|
|
import { formatPrice } from '@typebot.io/lib/billing/formatPrice'
|
|
|
|
type Props = {
|
|
isOpen: boolean
|
|
onClose: () => void
|
|
}
|
|
|
|
export const ChatsProTiersModal = ({ isOpen, onClose }: Props) => {
|
|
return (
|
|
<Modal isOpen={isOpen} onClose={onClose} size="xl">
|
|
<ModalOverlay />
|
|
<ModalContent>
|
|
<ModalHeader>
|
|
<Heading size="lg">Chats pricing table</Heading>
|
|
</ModalHeader>
|
|
<ModalCloseButton />
|
|
<ModalBody as={Stack} spacing="6">
|
|
<TableContainer>
|
|
<Table variant="simple">
|
|
<Thead>
|
|
<Tr>
|
|
<Th isNumeric>Max chats</Th>
|
|
<Th isNumeric>Price per month</Th>
|
|
<Th isNumeric>Price per 1k chats</Th>
|
|
</Tr>
|
|
</Thead>
|
|
<Tbody>
|
|
{proChatTiers.map((tier, index) => {
|
|
const pricePerMonth =
|
|
proChatTiers
|
|
.slice(0, index + 1)
|
|
.reduce(
|
|
(acc, slicedTier) =>
|
|
acc + (slicedTier.flat_amount ?? 0),
|
|
0
|
|
) / 100
|
|
return (
|
|
<Tr key={tier.up_to}>
|
|
<Td isNumeric>
|
|
{tier.up_to === 'inf'
|
|
? '2,000,000+'
|
|
: tier.up_to.toLocaleString()}
|
|
</Td>
|
|
<Td isNumeric>
|
|
{index === 0 ? 'included' : formatPrice(pricePerMonth)}
|
|
</Td>
|
|
<Td isNumeric>
|
|
{index === proChatTiers.length - 1
|
|
? formatPrice(4.42, { maxFractionDigits: 2 })
|
|
: index === 0
|
|
? 'included'
|
|
: formatPrice(
|
|
(((pricePerMonth * 100) /
|
|
((tier.up_to as number) -
|
|
(proChatTiers.at(0)?.up_to as number))) *
|
|
1000) /
|
|
100,
|
|
{ maxFractionDigits: 2 }
|
|
)}
|
|
</Td>
|
|
</Tr>
|
|
)
|
|
})}
|
|
</Tbody>
|
|
</Table>
|
|
</TableContainer>
|
|
</ModalBody>
|
|
<ModalFooter />
|
|
</ModalContent>
|
|
</Modal>
|
|
)
|
|
}
|