Files
myeasycms-v2/packages/billing-gateway/src/components/embedded-checkout.tsx
giancarlo 99db8f4ca4 Implement custom roles and improve permissions logic
The commit refactors the handling of account roles and enhances permissions checks. The account role has been shifted to use a string type, providing the ability to define custom roles. It also introduces the RolesDataProvider component, which stipulates role-related data for different forms and tables. The modification goes further to consider user role hierarchy in permissions checks, offering a more granular access control.
2024-03-29 14:48:45 +08:00

93 lines
2.1 KiB
TypeScript

import { Suspense, forwardRef, lazy, memo, useMemo } from 'react';
import { Database } from '@kit/supabase/database';
import { LoadingOverlay } from '@kit/ui/loading-overlay';
type BillingProvider = Database['public']['Enums']['billing_provider'];
const Fallback = <LoadingOverlay fullPage={false} />;
export function EmbeddedCheckout(
props: React.PropsWithChildren<{
checkoutToken: string;
provider: BillingProvider;
onClose?: () => void;
}>,
) {
const CheckoutComponent = useMemo(
() => loadCheckoutComponent(props.provider),
[props.provider],
);
return (
<CheckoutComponent
onClose={props.onClose}
checkoutToken={props.checkoutToken}
/>
);
}
function loadCheckoutComponent(provider: BillingProvider) {
switch (provider) {
case 'stripe': {
return buildLazyComponent(() => {
return import('@kit/stripe/components').then(({ StripeCheckout }) => {
return {
default: StripeCheckout,
};
});
});
}
case 'lemon-squeezy': {
throw new Error('Lemon Squeezy is not yet supported');
}
case 'paddle': {
throw new Error('Paddle is not yet supported');
}
default:
throw new Error(`Unsupported provider: ${provider as string}`);
}
}
function buildLazyComponent<
Component extends React.ComponentType<{
onClose: (() => unknown) | undefined;
checkoutToken: string;
}>,
>(
load: () => Promise<{
default: Component;
}>,
fallback = Fallback,
) {
let LoadedComponent: ReturnType<typeof lazy<Component>> | null = null;
const LazyComponent = forwardRef<
React.ElementRef<'div'>,
{
onClose: (() => unknown) | undefined;
checkoutToken: string;
}
>(function LazyDynamicComponent(props, ref) {
if (!LoadedComponent) {
LoadedComponent = lazy(load);
}
return (
<Suspense fallback={fallback}>
{/* @ts-expect-error: weird TS */}
<LoadedComponent
onClose={props.onClose}
checkoutToken={props.checkoutToken}
ref={ref}
/>
</Suspense>
);
});
return memo(LazyComponent);
}