feat: abstract the pricing plans for setup and billing page

This commit is contained in:
Ahmed Bouhuolia
2024-07-30 17:47:03 +02:00
parent 07c57ed539
commit ba7f32c1bf
13 changed files with 253 additions and 120 deletions

View File

@@ -1,112 +0,0 @@
// @ts-nocheck
import { Intent } from '@blueprintjs/core';
import * as R from 'ramda';
import { AppToaster } from '@/components';
import { useGetLemonSqueezyCheckout } from '@/hooks/query';
import { PricingPlan } from '@/components/PricingPlan/PricingPlan';
import { SubscriptionPlansPeriod } from '@/store/plans/plans.reducer';
import {
WithPlansProps,
withPlans,
} from '@/containers/Subscriptions/withPlans';
interface SubscriptionPricingFeature {
text: string;
hint?: string;
hintLabel?: string;
style?: Record<string, string>;
}
interface SubscriptionPricingProps {
slug: string;
label: string;
description: string;
features?: Array<SubscriptionPricingFeature>;
featured?: boolean;
monthlyPrice: string;
monthlyPriceLabel: string;
annuallyPrice: string;
annuallyPriceLabel: string;
monthlyVariantId?: string;
annuallyVariantId?: string;
onSubscribe?: (variantId: number) => void;
}
interface SubscriptionPricingCombinedProps
extends SubscriptionPricingProps,
WithPlansProps {}
function SubscriptionPlanRoot({
label,
description,
featured,
features,
monthlyPrice,
monthlyPriceLabel,
annuallyPrice,
annuallyPriceLabel,
monthlyVariantId,
annuallyVariantId,
onSubscribe,
// #withPlans
plansPeriod,
}: SubscriptionPricingCombinedProps) {
const { mutateAsync: getLemonCheckout, isLoading } =
useGetLemonSqueezyCheckout();
const handleClick = () => {
const variantId =
SubscriptionPlansPeriod.Monthly === plansPeriod
? monthlyVariantId
: annuallyVariantId;
onSubscribe && onSubscribe(variantId);
// getLemonCheckout({ variantId })
// .then((res) => {
// const checkoutUrl = res.data.data.attributes.url;
// window.LemonSqueezy.Url.Open(checkoutUrl);
// })
// .catch(() => {
// AppToaster.show({
// message: 'Something went wrong!',
// intent: Intent.DANGER,
// });
// });
};
return (
<PricingPlan featured={featured}>
{featured && <PricingPlan.Featured>Most Popular</PricingPlan.Featured>}
<PricingPlan.Header label={label} description={description} />
{plansPeriod === SubscriptionPlansPeriod.Monthly ? (
<PricingPlan.Price price={monthlyPrice} subPrice={monthlyPriceLabel} />
) : (
<PricingPlan.Price
price={annuallyPrice}
subPrice={annuallyPriceLabel}
/>
)}
<PricingPlan.BuyButton loading={isLoading} onClick={handleClick}>
Subscribe
</PricingPlan.BuyButton>
<PricingPlan.Features>
{features?.map((feature) => (
<PricingPlan.FeatureLine
hintLabel={feature.hintLabel}
hintContent={feature.hint}
>
{feature.text}
</PricingPlan.FeatureLine>
))}
</PricingPlan.Features>
</PricingPlan>
);
}
export const SubscriptionPlan = R.compose(
withPlans(({ plansPeriod }) => ({ plansPeriod })),
)(SubscriptionPlanRoot);

View File

@@ -1,6 +1,13 @@
import { Group, GroupProps } from '@/components';
import { SubscriptionPlan } from './SubscriptionPlan';
// @ts-nocheck
import * as R from 'ramda';
import { Intent } from '@blueprintjs/core';
import { AppToaster, Group, GroupProps } from '@/components';
import { SubscriptionPlansPeriod } from '@/store/plans/plans.reducer';
import { SubscriptionPlan } from '@/containers/Subscriptions/component/SubscriptionPlan';
import { useGetLemonSqueezyCheckout } from '@/hooks/query';
import { useSubscriptionPlans } from './hooks';
import { withPlans } from '@/containers/Subscriptions/withPlans';
import { withSubscriptionPlanMapper } from '@/containers/Subscriptions/component/withSubscriptionPlanMapper';
interface SubscriptionPlansProps {
wrapProps?: GroupProps;
@@ -9,29 +16,51 @@ interface SubscriptionPlansProps {
export function SubscriptionPlans({
wrapProps,
onSubscribe
onSubscribe,
}: SubscriptionPlansProps) {
const subscriptionPlans = useSubscriptionPlans();
return (
<Group spacing={14} noWrap align="stretch" {...wrapProps}>
{subscriptionPlans.map((plan, index) => (
<SubscriptionPlan
key={index}
slug={plan.slug}
label={plan.name}
description={plan.description}
features={plan.features}
featured={plan.featured}
monthlyPrice={plan.monthlyPrice}
monthlyPriceLabel={plan.monthlyPriceLabel}
annuallyPrice={plan.annuallyPrice}
annuallyPriceLabel={plan.annuallyPriceLabel}
monthlyVariantId={plan.monthlyVariantId}
annuallyVariantId={plan.annuallyVariantId}
onSubscribe={onSubscribe}
/>
<SubscriptionPlanMapped key={index} plan={plan} />
))}
</Group>
);
}
const SubscriptionPlanMapped = R.compose(
withSubscriptionPlanMapper,
withPlans(({ plansPeriod }) => ({ plansPeriod })),
)(({ plansPeriod, monthlyVariantId, annuallyVariantId, ...props }) => {
const { mutateAsync: getLemonCheckout, isLoading } =
useGetLemonSqueezyCheckout();
const handleSubscribeBtnClick = () => {
const variantId =
SubscriptionPlansPeriod.Monthly === plansPeriod
? monthlyVariantId
: annuallyVariantId;
getLemonCheckout({ variantId })
.then((res) => {
const checkoutUrl = res.data.data.attributes.url;
window.LemonSqueezy.Url.Open(checkoutUrl);
})
.catch(() => {
AppToaster.show({
message: 'Something went wrong!',
intent: Intent.DANGER,
});
});
};
return (
<SubscriptionPlan
{...props}
onSubscribe={handleSubscribeBtnClick}
subscribeButtonProps={{
loading: isLoading,
}}
/>
);
});