Files
myeasycms-v2/apps/web/app/(dashboard)/home/[account]/billing/page.tsx
giancarlo 406739d96d Refactor Supabase server client and improve team management features
Refactored Supabase server component client to improve type safety. Improved team account management by adjusting role data providers to consider account IDs, and adjusted invite member functionality to use account IDs and slugs. Enhanced invitation update dialog by adding account parameter. Fixed database webhook URLs in seed.sql. Overall, these changes enhance the robustness and usability of the team management functionalities.
2024-04-03 22:34:12 +08:00

142 lines
3.8 KiB
TypeScript

import { ExclamationTriangleIcon } from '@radix-ui/react-icons';
import {
BillingPortalCard,
CurrentSubscriptionCard,
} 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');
const Checkout = () => {
if (!canManageBilling) {
return <CannotManageBillingAlert />;
}
return (
<TeamAccountCheckoutForm customerId={customerId} accountId={accountId} />
);
};
const BillingPortal = () => {
if (!canManageBilling || !customerId) {
return null;
}
return (
<form action={createBillingPortalSession}>
<input type="hidden" name={'accountId'} value={accountId} />
<input type="hidden" name={'slug'} value={params.account} />
<BillingPortalCard />
</form>
);
};
return (
<>
<PageHeader
title={<Trans i18nKey={'common:billingTabLabel'} />}
description={<Trans i18nKey={'common:billingTabDescription'} />}
/>
<PageBody>
<div className={'mx-auto w-full'}>
<div>
<div className={'flex flex-col space-y-6'}>
<If
condition={subscription}
fallback={
<>
<Checkout />
</>
}
>
{(subscription) => (
<CurrentSubscriptionCard
subscription={subscription}
config={billingConfig}
/>
)}
</If>
<BillingPortal />
</div>
</div>
</div>
</PageBody>
</>
);
}
export default withI18n(TeamAccountBillingPage);
function CannotManageBillingAlert() {
return (
<Alert variant={'warning'}>
<ExclamationTriangleIcon className={'h-4'} />
<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]);
}