Files
sign/apps/web/src/app/(dashboard)/settings/billing/page.tsx

97 lines
3.4 KiB
TypeScript
Raw Normal View History

2023-06-09 18:21:18 +10:00
import { redirect } from 'next/navigation';
import { match } from 'ts-pattern';
2023-10-13 23:33:40 +11:00
import { getPricesByInterval } from '@documenso/ee/server-only/stripe/get-prices-by-interval';
2023-10-15 20:26:32 +11:00
import { getProductByPriceId } from '@documenso/ee/server-only/stripe/get-product-by-price-id';
2023-11-16 07:35:45 +05:30
import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session';
2023-10-13 23:33:40 +11:00
import { getServerComponentFlag } from '@documenso/lib/server-only/feature-flags/get-server-component-feature-flag';
2023-11-16 07:35:45 +05:30
import type { Stripe } from '@documenso/lib/server-only/stripe';
2023-08-30 16:36:22 +10:00
import { getSubscriptionByUserId } from '@documenso/lib/server-only/subscription/get-subscription-by-user-id';
2023-06-09 18:21:18 +10:00
2023-08-30 16:36:22 +10:00
import { LocaleDate } from '~/components/formatter/locale-date';
2023-06-09 18:21:18 +10:00
2023-10-13 23:33:40 +11:00
import { BillingPlans } from './billing-plans';
2023-10-13 23:56:11 +11:00
import { BillingPortalButton } from './billing-portal-button';
2023-06-09 18:21:18 +10:00
export default async function BillingSettingsPage() {
const { user } = await getRequiredServerComponentSession();
2023-06-09 18:21:18 +10:00
const isBillingEnabled = await getServerComponentFlag('app_billing');
2023-08-18 20:05:14 +10:00
2023-06-09 18:21:18 +10:00
// Redirect if subscriptions are not enabled.
2023-08-18 20:05:14 +10:00
if (!isBillingEnabled) {
2023-06-09 18:21:18 +10:00
redirect('/settings/profile');
}
2023-10-13 23:33:40 +11:00
const [subscription, prices] = await Promise.all([
getSubscriptionByUserId({ userId: user.id }),
getPricesByInterval(),
]);
2023-08-30 16:36:22 +10:00
let subscriptionProduct: Stripe.Product | null = null;
2023-08-30 16:36:22 +10:00
2023-10-15 20:26:32 +11:00
if (subscription?.priceId) {
subscriptionProduct = await getProductByPriceId({ priceId: subscription.priceId }).catch(
() => null,
);
2023-08-30 16:36:22 +10:00
}
2023-10-13 23:33:40 +11:00
const isMissingOrInactiveOrFreePlan = !subscription || subscription.status === 'INACTIVE';
2023-06-09 18:21:18 +10:00
return (
<div>
<h3 className="text-lg font-medium">Billing</h3>
2023-10-13 23:33:40 +11:00
<div className="text-muted-foreground mt-2 text-sm">
{isMissingOrInactiveOrFreePlan && (
<p>
You are currently on the <span className="font-semibold">Free Plan</span>.
</p>
2023-08-30 16:36:22 +10:00
)}
{!isMissingOrInactiveOrFreePlan &&
match(subscription.status)
.with('ACTIVE', () => (
<p>
{subscriptionProduct ? (
<span>
You are currently subscribed to{' '}
<span className="font-semibold">{subscriptionProduct.name}</span>
</span>
) : (
<span>You currently have an active plan</span>
)}
2023-10-13 23:33:40 +11:00
{subscription.periodEnd && (
<span>
{' '}
which is set to{' '}
{subscription.cancelAtPeriodEnd ? (
<span>
end on{' '}
<LocaleDate className="font-semibold" date={subscription.periodEnd} />.
</span>
) : (
<span>
automatically renew on{' '}
<LocaleDate className="font-semibold" date={subscription.periodEnd} />.
</span>
)}
</span>
)}
</p>
))
.with('PAST_DUE', () => (
<p>Your current plan is past due. Please update your payment information.</p>
))
.otherwise(() => null)}
</div>
2023-06-09 18:21:18 +10:00
<hr className="my-4" />
2023-10-13 23:33:40 +11:00
{isMissingOrInactiveOrFreePlan ? <BillingPlans prices={prices} /> : <BillingPortalButton />}
2023-06-09 18:21:18 +10:00
</div>
);
}