2023-06-09 18:21:18 +10:00
|
|
|
import { redirect } from 'next/navigation';
|
|
|
|
|
|
2023-09-18 22:33:07 +10:00
|
|
|
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-09-18 22:33:07 +10:00
|
|
|
|
2023-06-09 18:21:18 +10:00
|
|
|
export default async function BillingSettingsPage() {
|
2023-09-28 17:32:31 +10:00
|
|
|
const { user } = await getRequiredServerComponentSession();
|
2023-06-09 18:21:18 +10:00
|
|
|
|
2023-08-21 11:44:56 +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
|
|
|
|
2023-09-18 22:33:07 +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-09-18 22:33:07 +10:00
|
|
|
);
|
2023-08-30 16:36:22 +10:00
|
|
|
}
|
|
|
|
|
|
2023-10-13 23:33:40 +11:00
|
|
|
const isMissingOrInactiveOrFreePlan = !subscription || subscription.status === 'INACTIVE';
|
2023-09-18 22:33:07 +10:00
|
|
|
|
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">
|
2023-09-18 22:33:07 +10:00
|
|
|
{isMissingOrInactiveOrFreePlan && (
|
|
|
|
|
<p>
|
|
|
|
|
You are currently on the <span className="font-semibold">Free Plan</span>.
|
|
|
|
|
</p>
|
2023-08-30 16:36:22 +10:00
|
|
|
)}
|
2023-09-18 22:33:07 +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
|
|
|
|
2023-09-18 22:33:07 +10: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>
|
|
|
|
|
);
|
|
|
|
|
}
|