From 57c814ceca777379b7a4b2a3657fac944435e9e2 Mon Sep 17 00:00:00 2001 From: Baptiste Arnaud Date: Wed, 19 Oct 2022 08:29:33 +0200 Subject: [PATCH] :sparkles: (lp) Add custom chats and storage in pricing cards --- apps/builder/pages/typebots.tsx | 10 +- .../components/PricingPage/FreePlanCard.tsx | 45 ++++ .../PricingPage/PlanComparisonTables.tsx | 4 +- .../components/PricingPage/ProPlanCard.tsx | 216 +++++++++++++++++ .../PricingPage/StarterPlanCard.tsx | 221 ++++++++++++++++++ apps/landing-page/pages/pricing.tsx | 172 +------------- 6 files changed, 497 insertions(+), 171 deletions(-) create mode 100644 apps/landing-page/components/PricingPage/FreePlanCard.tsx create mode 100644 apps/landing-page/components/PricingPage/ProPlanCard.tsx create mode 100644 apps/landing-page/components/PricingPage/StarterPlanCard.tsx diff --git a/apps/builder/pages/typebots.tsx b/apps/builder/pages/typebots.tsx index 6b380f08d..e3c476670 100644 --- a/apps/builder/pages/typebots.tsx +++ b/apps/builder/pages/typebots.tsx @@ -18,15 +18,19 @@ const DashboardPage = () => { const { workspace } = useWorkspace() useEffect(() => { - const subscribePlan = query.subscribePlan as Plan | undefined + const { subscribePlan, chats, storage } = query as { + subscribePlan: Plan | undefined + chats: string | undefined + storage: string | undefined + } if (workspace && subscribePlan && user && workspace.plan === 'FREE') { setIsLoading(true) pay({ user, plan: subscribePlan, workspaceId: workspace.id, - additionalChats: 0, - additionalStorage: 0, + additionalChats: chats ? parseInt(chats) : 0, + additionalStorage: storage ? parseInt(storage) : 0, }) } }, [query, user, workspace]) diff --git a/apps/landing-page/components/PricingPage/FreePlanCard.tsx b/apps/landing-page/components/PricingPage/FreePlanCard.tsx new file mode 100644 index 000000000..fef84f5a3 --- /dev/null +++ b/apps/landing-page/components/PricingPage/FreePlanCard.tsx @@ -0,0 +1,45 @@ +import { chakra, Tooltip, Text } from '@chakra-ui/react' +import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon' +import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink' +import React from 'react' +import { PricingCard } from './PricingCard' +import { ActionButton } from './PricingCard/ActionButton' + +export const FreePlanCard = () => ( + + + 300 chats included + +   + + + + + + , + 'Native integrations', + 'Webhooks', + 'Custom Javascript & CSS', + ], + }} + button={ + + Get started + + } + /> +) diff --git a/apps/landing-page/components/PricingPage/PlanComparisonTables.tsx b/apps/landing-page/components/PricingPage/PlanComparisonTables.tsx index 382bb01c4..8d54361be 100644 --- a/apps/landing-page/components/PricingPage/PlanComparisonTables.tsx +++ b/apps/landing-page/components/PricingPage/PlanComparisonTables.tsx @@ -42,7 +42,7 @@ export const PlanComparisonTables = ({ Free Starter - Pro + Pro @@ -100,7 +100,7 @@ export const PlanComparisonTables = ({ Free Starter - Pro + Pro diff --git a/apps/landing-page/components/PricingPage/ProPlanCard.tsx b/apps/landing-page/components/PricingPage/ProPlanCard.tsx new file mode 100644 index 000000000..505cca4c2 --- /dev/null +++ b/apps/landing-page/components/PricingPage/ProPlanCard.tsx @@ -0,0 +1,216 @@ +import { + chakra, + Tooltip, + Text, + Button, + HStack, + Menu, + MenuButton, + MenuItem, + MenuList, +} from '@chakra-ui/react' +import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon' +import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon' +import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink' +import { Plan } from 'db' +import React, { useEffect, useState } from 'react' +import { + chatsLimit, + computePrice, + formatPrice, + parseNumberWithCommas, + storageLimit, +} from 'utils' +import { PricingCard } from './PricingCard' +import { ActionButton } from './PricingCard/ActionButton' + +export const ProPlanCard = () => { + const [price, setPrice] = useState('89$') + + const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] = + useState(0) + const [selectedStorageLimitIndex, setSelectedStorageLimitIndex] = + useState(0) + + useEffect(() => { + setPrice( + formatPrice( + computePrice( + Plan.PRO, + selectedChatsLimitIndex ?? 0, + selectedStorageLimitIndex ?? 0 + ) ?? NaN + ) + ) + }, [selectedChatsLimitIndex, selectedStorageLimitIndex]) + + return ( + + 5 seats included + , + + + + } + size="sm" + variant="outline" + isLoading={selectedChatsLimitIndex === undefined} + > + {selectedChatsLimitIndex !== undefined + ? parseNumberWithCommas( + chatsLimit.PRO.totalIncluded + + chatsLimit.PRO.increaseStep.amount * + selectedChatsLimitIndex + ) + : undefined} + + + {selectedChatsLimitIndex !== 0 && ( + setSelectedChatsLimitIndex(0)}> + {parseNumberWithCommas(chatsLimit.PRO.totalIncluded)} + + )} + {selectedChatsLimitIndex !== 1 && ( + setSelectedChatsLimitIndex(1)}> + {parseNumberWithCommas( + chatsLimit.PRO.totalIncluded + + chatsLimit.PRO.increaseStep.amount + )} + + )} + {selectedChatsLimitIndex !== 2 && ( + setSelectedChatsLimitIndex(2)}> + {parseNumberWithCommas( + chatsLimit.PRO.totalIncluded + + chatsLimit.PRO.increaseStep.amount * 2 + )} + + )} + {selectedChatsLimitIndex !== 3 && ( + setSelectedChatsLimitIndex(3)}> + {parseNumberWithCommas( + chatsLimit.PRO.totalIncluded + + chatsLimit.PRO.increaseStep.amount * 3 + )} + + )} + {selectedChatsLimitIndex !== 4 && ( + setSelectedChatsLimitIndex(4)}> + {parseNumberWithCommas( + chatsLimit.PRO.totalIncluded + + chatsLimit.PRO.increaseStep.amount * 4 + )} + + )} + + {' '} + chats/mo + + + + + + + , + + + + } + size="sm" + variant="outline" + isLoading={selectedStorageLimitIndex === undefined} + > + {selectedStorageLimitIndex !== undefined + ? parseNumberWithCommas( + storageLimit.PRO.totalIncluded + + storageLimit.PRO.increaseStep.amount * + selectedStorageLimitIndex + ) + : undefined} + + + {selectedStorageLimitIndex !== 0 && ( + setSelectedStorageLimitIndex(0)}> + {parseNumberWithCommas(storageLimit.PRO.totalIncluded)} + + )} + {selectedStorageLimitIndex !== 1 && ( + setSelectedStorageLimitIndex(1)}> + {parseNumberWithCommas( + storageLimit.PRO.totalIncluded + + storageLimit.PRO.increaseStep.amount + )} + + )} + {selectedStorageLimitIndex !== 2 && ( + setSelectedStorageLimitIndex(2)}> + {parseNumberWithCommas( + storageLimit.PRO.totalIncluded + + storageLimit.PRO.increaseStep.amount * 2 + )} + + )} + {selectedStorageLimitIndex !== 3 && ( + setSelectedStorageLimitIndex(3)}> + {parseNumberWithCommas( + storageLimit.PRO.totalIncluded + + storageLimit.PRO.increaseStep.amount * 3 + )} + + )} + {selectedStorageLimitIndex !== 4 && ( + setSelectedStorageLimitIndex(4)}> + {parseNumberWithCommas( + storageLimit.PRO.totalIncluded + + storageLimit.PRO.increaseStep.amount * 4 + )} + + )} + + {' '} + GB of storage + + + + + + + , + 'Custom domains', + 'In-depth analytics', + ], + }} + borderWidth="3px" + borderColor="blue.200" + button={ + + Subscribe now + + } + /> + ) +} diff --git a/apps/landing-page/components/PricingPage/StarterPlanCard.tsx b/apps/landing-page/components/PricingPage/StarterPlanCard.tsx new file mode 100644 index 000000000..166b936bf --- /dev/null +++ b/apps/landing-page/components/PricingPage/StarterPlanCard.tsx @@ -0,0 +1,221 @@ +import { + chakra, + Tooltip, + Text, + HStack, + Menu, + MenuButton, + Button, + MenuItem, + MenuList, +} from '@chakra-ui/react' +import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon' +import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon' +import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink' +import { Plan } from 'db' +import React, { useEffect, useState } from 'react' +import { + chatsLimit, + computePrice, + formatPrice, + parseNumberWithCommas, + storageLimit, +} from 'utils' +import { PricingCard } from './PricingCard' +import { ActionButton } from './PricingCard/ActionButton' + +export const StarterPlanCard = () => { + const [price, setPrice] = useState('39$') + + const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] = + useState(0) + const [selectedStorageLimitIndex, setSelectedStorageLimitIndex] = + useState(0) + + useEffect(() => { + setPrice( + formatPrice( + computePrice( + Plan.STARTER, + selectedChatsLimitIndex ?? 0, + selectedStorageLimitIndex ?? 0 + ) ?? NaN + ) + ) + }, [selectedChatsLimitIndex, selectedStorageLimitIndex]) + + return ( + + 2 seats included + , + + + + } + size="sm" + variant="outline" + isLoading={selectedChatsLimitIndex === undefined} + colorScheme="orange" + > + {selectedChatsLimitIndex !== undefined + ? parseNumberWithCommas( + chatsLimit.STARTER.totalIncluded + + chatsLimit.STARTER.increaseStep.amount * + selectedChatsLimitIndex + ) + : undefined} + + + {selectedChatsLimitIndex !== 0 && ( + setSelectedChatsLimitIndex(0)}> + {parseNumberWithCommas(chatsLimit.STARTER.totalIncluded)} + + )} + {selectedChatsLimitIndex !== 1 && ( + setSelectedChatsLimitIndex(1)}> + {parseNumberWithCommas( + chatsLimit.STARTER.totalIncluded + + chatsLimit.STARTER.increaseStep.amount + )} + + )} + {selectedChatsLimitIndex !== 2 && ( + setSelectedChatsLimitIndex(2)}> + {parseNumberWithCommas( + chatsLimit.STARTER.totalIncluded + + chatsLimit.STARTER.increaseStep.amount * 2 + )} + + )} + {selectedChatsLimitIndex !== 3 && ( + setSelectedChatsLimitIndex(3)}> + {parseNumberWithCommas( + chatsLimit.STARTER.totalIncluded + + chatsLimit.STARTER.increaseStep.amount * 3 + )} + + )} + {selectedChatsLimitIndex !== 4 && ( + setSelectedChatsLimitIndex(4)}> + {parseNumberWithCommas( + chatsLimit.STARTER.totalIncluded + + chatsLimit.STARTER.increaseStep.amount * 4 + )} + + )} + + {' '} + chats/mo + + + + + + + , + + + + } + size="sm" + variant="outline" + isLoading={selectedStorageLimitIndex === undefined} + colorScheme="orange" + > + {selectedStorageLimitIndex !== undefined + ? parseNumberWithCommas( + storageLimit.STARTER.totalIncluded + + storageLimit.STARTER.increaseStep.amount * + selectedStorageLimitIndex + ) + : undefined} + + + {selectedStorageLimitIndex !== 0 && ( + setSelectedStorageLimitIndex(0)}> + {parseNumberWithCommas( + storageLimit.STARTER.totalIncluded + )} + + )} + {selectedStorageLimitIndex !== 1 && ( + setSelectedStorageLimitIndex(1)}> + {parseNumberWithCommas( + storageLimit.STARTER.totalIncluded + + storageLimit.STARTER.increaseStep.amount + )} + + )} + {selectedStorageLimitIndex !== 2 && ( + setSelectedStorageLimitIndex(2)}> + {parseNumberWithCommas( + storageLimit.STARTER.totalIncluded + + storageLimit.STARTER.increaseStep.amount * 2 + )} + + )} + {selectedStorageLimitIndex !== 3 && ( + setSelectedStorageLimitIndex(3)}> + {parseNumberWithCommas( + storageLimit.STARTER.totalIncluded + + storageLimit.STARTER.increaseStep.amount * 3 + )} + + )} + {selectedStorageLimitIndex !== 4 && ( + setSelectedStorageLimitIndex(4)}> + {parseNumberWithCommas( + storageLimit.STARTER.totalIncluded + + storageLimit.STARTER.increaseStep.amount * 4 + )} + + )} + + {' '} + GB of storage + + + + + + + , + 'Branding removed', + 'Collect files from users', + 'Create folders', + ], + }} + borderWidth="1px" + borderColor="orange.200" + button={ + + Subscribe now + + } + /> + ) +} diff --git a/apps/landing-page/pages/pricing.tsx b/apps/landing-page/pages/pricing.tsx index 6d93b9e2a..6fba252a2 100644 --- a/apps/landing-page/pages/pricing.tsx +++ b/apps/landing-page/pages/pricing.tsx @@ -11,23 +11,20 @@ import { Heading, VStack, Text, - chakra, - Tooltip, HStack, } from '@chakra-ui/react' -import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon' 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' -import { PricingCard } from 'components/PricingPage/PricingCard' -import { ActionButton } from 'components/PricingPage/PricingCard/ActionButton' import { useEffect, useState } from 'react' import { formatPrice, prices } from 'utils' -import { Plan } from 'db' import { StripeClimateLogo } from 'assets/logos/StripeClimateLogo' +import { FreePlanCard } from 'components/PricingPage/FreePlanCard' +import { StarterPlanCard } from 'components/PricingPage/StarterPlanCard' +import { ProPlanCard } from 'components/PricingPage/ProPlanCard' const Pricing = () => { const [starterPrice, setStarterPrice] = useState('$39') @@ -101,166 +98,9 @@ const Pricing = () => { w="full" maxW="1200px" > - - - 300 chats{' '} - included - -   - - - - - - , - 'Native integrations', - 'Webhooks', - 'Custom Javascript & CSS', - ], - }} - button={ - - Get started - - } - /> - - 2 seats{' '} - included - , - <> - - 2,000 chats{' '} - included - -   - - - - - - , - <> - - 2 GB{' '} - included - -   - - - - - - , - 'Branding removed', - 'Collect files from users', - 'Create folders', - ], - }} - borderWidth="1px" - borderColor="orange.200" - button={ - - Subscribe now - - } - /> - - 5 seats{' '} - included - , - <> - - - 10,000 chats - {' '} - included - -   - - - - - - , - <> - - 10 GB{' '} - included - -   - - - - - - , - 'Custom domains', - 'In-depth analytics', - ], - }} - borderWidth="3px" - borderColor="blue.200" - button={ - - Subscribe now - - } - /> + + + Need custom limits? Specific features?{' '}