Files
myeasycms-v2/apps/web/app/(dashboard)/home/[account]/billing/page.tsx
giancarlo d6004f2f7e Refactor billing gateway and enhance localization
Refactored the 'plan-picker' component in the billing gateway to remove unwanted line items and improve checkout session and subscription handling. Enhanced the localization support by adding translations in the plan picker and introduced a new function to check trial eligibility so that existing customers can't start a new trial period. These changes enhance the usability of the application across different regions and provide accurate trial period conditions.
2024-04-01 11:52:35 +08:00

124 lines
3.6 KiB
TypeScript

import {
BillingPortalCard,
CurrentPlanCard,
} from '@kit/billing-gateway/components';
import { getSupabaseServerComponentClient } from '@kit/supabase/server-component-client';
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
import { If } from '@kit/ui/if';
import { PageBody, PageHeader } from '@kit/ui/page';
import { Trans } from '@kit/ui/trans';
import { loadTeamWorkspace } from '~/(dashboard)/home/[account]/_lib/load-team-account-workspace';
import { createBillingPortalSession } from '~/(dashboard)/home/[account]/billing/server-actions';
import billingConfig from '~/config/billing.config';
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
import { withI18n } from '~/lib/i18n/with-i18n';
import { TeamAccountCheckoutForm } from './_components/team-account-checkout-form';
interface Params {
params: {
account: string;
};
}
export const generateMetadata = async () => {
const i18n = await createI18nServerInstance();
const title = i18n.t('teams:billing.pageTitle');
return {
title,
};
};
async function TeamAccountBillingPage({ params }: Params) {
const workspace = await loadTeamWorkspace(params.account);
const accountId = workspace.account.id;
const [subscription, customerId] = await loadAccountData(accountId);
const canManageBilling =
workspace.account.permissions.includes('billing.manage');
return (
<>
<PageHeader
title={<Trans i18nKey={'common:billingTabLabel'} />}
description={<Trans i18nKey={'common:billingTabDescription'} />}
/>
<PageBody>
<div className={'mx-auto w-full'}>
<If condition={!canManageBilling}>
<CannotManageBillingAlert />
</If>
<div>
<div className={'flex flex-col space-y-2'}>
<If
condition={subscription}
fallback={
<If condition={canManageBilling}>
<TeamAccountCheckoutForm
customerId={customerId}
accountId={accountId}
/>
</If>
}
>
{(data) => (
<CurrentPlanCard subscription={data} config={billingConfig} />
)}
</If>
<If condition={customerId && canManageBilling}>
<form action={createBillingPortalSession}>
<input type="hidden" name={'accountId'} value={accountId} />
<input type="hidden" name={'slug'} value={params.account} />
<BillingPortalCard />
</form>
</If>
</div>
</div>
</div>
</PageBody>
</>
);
}
export default withI18n(TeamAccountBillingPage);
function CannotManageBillingAlert() {
return (
<Alert>
<AlertTitle>
<Trans i18nKey={'billing:cannotManageBillingAlertTitle'} />
</AlertTitle>
<AlertDescription>
<Trans i18nKey={'billing:cannotManageBillingAlertDescription'} />
</AlertDescription>
</Alert>
);
}
async function loadAccountData(accountId: string) {
const client = getSupabaseServerComponentClient();
const subscription = client
.from('subscriptions')
.select('*, items: subscription_items !inner (*)')
.eq('account_id', accountId)
.maybeSingle()
.then(({ data }) => data);
const customerId = client
.from('billing_customers')
.select('customer_id')
.eq('account_id', accountId)
.maybeSingle()
.then(({ data }) => data?.customer_id);
return Promise.all([subscription, customerId]);
}