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-06-09 18:21:18 +10:00
|
|
|
import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-session';
|
2023-09-18 22:33:07 +10:00
|
|
|
import { Stripe, 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-09-18 22:33:07 +10:00
|
|
|
import BillingPortalButton from './billing-portal-button';
|
|
|
|
|
|
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-09-18 22:33:07 +10:00
|
|
|
const subscription = await getSubscriptionByUserId({ userId: user.id });
|
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-09-18 22:33:07 +10:00
|
|
|
if (subscription?.planId) {
|
|
|
|
|
const foundSubscriptionProduct = (await stripe.products.list()).data.find(
|
|
|
|
|
(item) => item.default_price === subscription.planId,
|
|
|
|
|
);
|
2023-08-30 16:36:22 +10:00
|
|
|
|
2023-09-18 22:33:07 +10:00
|
|
|
subscriptionProduct = foundSubscriptionProduct ?? null;
|
2023-08-30 16:36:22 +10:00
|
|
|
}
|
|
|
|
|
|
2023-09-18 22:33:07 +10:00
|
|
|
const isMissingOrInactiveOrFreePlan =
|
|
|
|
|
!subscription ||
|
|
|
|
|
subscription.status === 'INACTIVE' ||
|
|
|
|
|
subscription?.planId === process.env.NEXT_PUBLIC_STRIPE_FREE_PLAN_ID;
|
|
|
|
|
|
2023-06-09 18:21:18 +10:00
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-lg font-medium">Billing</h3>
|
|
|
|
|
|
2023-09-18 22:33:07 +10:00
|
|
|
<div className="mt-2 text-sm text-slate-500">
|
|
|
|
|
{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>
|
|
|
|
|
)}
|
|
|
|
|
{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-09-18 22:33:07 +10:00
|
|
|
<BillingPortalButton />
|
2023-06-09 18:21:18 +10:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|