2
0

(lp) Add new pricing page

This commit is contained in:
Baptiste Arnaud
2022-09-18 19:01:37 +02:00
committed by Baptiste Arnaud
parent d8b1d8ad59
commit c94a6581be
18 changed files with 346 additions and 255 deletions

View File

@ -13,21 +13,23 @@ export const BillingContent = () => {
if (!workspace) return null
return (
<Stack spacing="10" w="full">
<CurrentSubscriptionContent
plan={workspace.plan}
stripeId={workspace.stripeId}
onCancelSuccess={() =>
refreshWorkspace({
plan: Plan.FREE,
additionalChatsIndex: 0,
additionalStorageIndex: 0,
})
}
/>
<UsageContent workspace={workspace} />
{workspace.plan !== Plan.LIFETIME && workspace.plan !== Plan.OFFERED && (
<ChangePlanForm />
)}
<Stack gap="2">
<CurrentSubscriptionContent
plan={workspace.plan}
stripeId={workspace.stripeId}
onCancelSuccess={() =>
refreshWorkspace({
plan: Plan.FREE,
additionalChatsIndex: 0,
additionalStorageIndex: 0,
})
}
/>
{workspace.plan !== Plan.LIFETIME &&
workspace.plan !== Plan.OFFERED && <ChangePlanForm />}
</Stack>
{workspace.stripeId && <InvoicesList workspace={workspace} />}
</Stack>
)

View File

@ -4,8 +4,8 @@ import {
Link,
Spinner,
Stack,
Flex,
Button,
Heading,
} from '@chakra-ui/react'
import { PlanTag } from 'components/shared/PlanTag'
import { Plan } from 'db'
@ -35,15 +35,29 @@ export const CurrentSubscriptionContent = ({
setIsCancelling(false)
}
const isSubscribed = (plan === Plan.STARTER || plan === Plan.PRO) && stripeId
if (isCancelling) return <Spinner colorScheme="gray" />
return (
<Stack gap="2">
<Heading fontSize="3xl">Subscription</Heading>
<HStack>
<Text>Current workspace subscription: </Text>
<PlanTag plan={plan} />
{isSubscribed && (
<Link
as="button"
color="gray.500"
textDecor="underline"
fontSize="sm"
onClick={cancelSubscription}
>
Cancel my subscription
</Link>
)}
</HStack>
{(plan === Plan.STARTER || plan === Plan.PRO) && stripeId && (
{isSubscribed && (
<>
<Stack gap="1">
<Text fontSize="sm">
@ -59,17 +73,6 @@ export const CurrentSubscriptionContent = ({
Billing Portal
</Button>
</Stack>
<Flex>
<Link
as="button"
color="gray.500"
textDecor="underline"
fontSize="sm"
onClick={cancelSubscription}
>
Cancel my subscription
</Link>
</Flex>
</>
)}
</Stack>

View File

@ -60,16 +60,7 @@ export const ChangePlanForm = () => {
return (
<Stack spacing={4}>
<HStack
alignItems="stretch"
spacing="4"
w="full"
pt={
workspace?.plan === Plan.STARTER || workspace?.plan === Plan.PRO
? '10'
: '0'
}
>
<HStack alignItems="stretch" spacing="4" w="full">
<StarterPlanContent
initialChatsLimitIndex={
workspace?.plan === Plan.STARTER ? data?.additionalChatsIndex : 0

View File

@ -23,10 +23,11 @@ import {
getStorageLimit,
storageLimit,
parseNumberWithCommas,
formatPrice,
computePrice,
} from 'utils'
import { MoreInfoTooltip } from '../MoreInfoTooltip'
import { FeaturesList } from './components/FeaturesList'
import { computePrice, formatPrice } from './helpers'
type ProPlanContentProps = {
initialChatsLimitIndex?: number
@ -72,8 +73,6 @@ export const ProPlanContent = ({
? getStorageLimit(workspace)
: undefined
console.log('workspaceChatsLimit', workspaceChatsLimit)
console.log('workspaceStorageLimit', workspace)
const isCurrentPlan =
chatsLimit[Plan.PRO].totalIncluded +
chatsLimit[Plan.PRO].increaseStep.amount *

View File

@ -20,10 +20,11 @@ import {
getStorageLimit,
storageLimit,
parseNumberWithCommas,
computePrice,
formatPrice,
} from 'utils'
import { MoreInfoTooltip } from '../MoreInfoTooltip'
import { FeaturesList } from './components/FeaturesList'
import { computePrice, formatPrice } from './helpers'
type StarterPlanContentProps = {
initialChatsLimitIndex?: number

View File

@ -1,86 +0,0 @@
import { Plan } from 'db'
import { chatsLimit, prices, storageLimit } from 'utils'
export const computePrice = (
plan: Plan,
selectedTotalChatsIndex: number,
selectedTotalStorageIndex: number
) => {
if (plan !== Plan.STARTER && plan !== Plan.PRO) return
const {
increaseStep: { price: chatsPrice },
} = chatsLimit[plan]
const {
increaseStep: { price: storagePrice },
} = storageLimit[plan]
return (
prices[plan] +
selectedTotalChatsIndex * chatsPrice +
selectedTotalStorageIndex * storagePrice
)
}
const europeanUnionCountryCodes = [
'AT',
'BE',
'BG',
'CY',
'CZ',
'DE',
'DK',
'EE',
'ES',
'FI',
'FR',
'GR',
'HR',
'HU',
'IE',
'IT',
'LT',
'LU',
'LV',
'MT',
'NL',
'PL',
'PT',
'RO',
'SE',
'SI',
'SK',
]
const europeanUnionExclusiveLanguageCodes = [
'fr',
'de',
'it',
'el',
'pl',
'fi',
'nl',
'hr',
'cs',
'hu',
'ro',
'sl',
'sv',
'bg',
]
export const guessIfUserIsEuropean = () =>
navigator.languages.some((language) => {
const [languageCode, countryCode] = language.split('-')
return countryCode
? europeanUnionCountryCodes.includes(countryCode)
: europeanUnionExclusiveLanguageCodes.includes(languageCode)
})
export const formatPrice = (price: number) => {
const isEuropean = guessIfUserIsEuropean()
const formatter = new Intl.NumberFormat(isEuropean ? 'fr-FR' : 'en-US', {
style: 'currency',
currency: isEuropean ? 'EUR' : 'USD',
maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
})
return formatter.format(price)
}

View File

@ -1,7 +1,12 @@
import { loadStripe } from '@stripe/stripe-js/pure'
import { Plan, User } from 'db'
import { env, isDefined, isEmpty, sendRequest } from 'utils'
import { guessIfUserIsEuropean } from '../helpers'
import {
env,
guessIfUserIsEuropean,
isDefined,
isEmpty,
sendRequest,
} from 'utils'
type UpgradeProps = {
user: User

View File

@ -155,7 +155,6 @@ const updateSubscription = async (req: NextApiRequest) => {
}
: undefined,
].filter(isDefined)
console.log(items)
await stripe.subscriptions.update(subscription.id, {
items,
})
@ -171,7 +170,6 @@ const updateSubscription = async (req: NextApiRequest) => {
const cancelSubscription =
(req: NextApiRequest, res: NextApiResponse) => async (userId: string) => {
console.log(req.query.stripeId, userId)
const stripeId = req.query.stripeId as string | undefined
if (!stripeId) return badRequest(res)
if (!process.env.STRIPE_SECRET_KEY)
@ -189,9 +187,7 @@ const cancelSubscription =
const existingSubscription = await stripe.subscriptions.list({
customer: workspace.stripeId,
})
console.log('yes')
await stripe.subscriptions.del(existingSubscription.data[0].id)
console.log('deleted')
await prisma.workspace.update({
where: { id: workspace.id },
data: {

View File

@ -18,12 +18,12 @@ const DashboardPage = () => {
const { workspace } = useWorkspace()
useEffect(() => {
const subscribePlan = query.subscribePlan as 'pro' | 'starter' | undefined
const subscribePlan = query.subscribePlan as Plan | undefined
if (workspace && subscribePlan && user && workspace.plan === 'FREE') {
setIsLoading(true)
pay({
user,
plan: subscribePlan === 'pro' ? Plan.PRO : Plan.STARTER,
plan: subscribePlan,
workspaceId: workspace.id,
additionalChats: 0,
additionalStorage: 0,

View File

@ -34,8 +34,6 @@ const ResultsPage = () => {
})
const { data: usageData } = useUsage(workspace?.id)
console.log(workspace?.id, usageData)
const chatsLimitPercentage = useMemo(() => {
if (!usageData?.totalChatsUsed || !workspace?.plan) return 0
return Math.round(
@ -53,7 +51,6 @@ const ResultsPage = () => {
])
const storageLimitPercentage = useMemo(() => {
console.log(usageData?.totalStorageUsed)
if (!usageData?.totalStorageUsed || !workspace?.plan) return 0
return Math.round(
(usageData.totalStorageUsed /