mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
feat: upgrade the subscription plans
This commit is contained in:
@@ -3,3 +3,7 @@
|
||||
margin: 0 auto;
|
||||
padding: 0 40px;
|
||||
}
|
||||
|
||||
.periodSwitch {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -1,27 +1,51 @@
|
||||
// @ts-nocheck
|
||||
import { AppToaster, Group, T } from '@/components';
|
||||
import { useGetLemonSqueezyCheckout } from '@/hooks/query';
|
||||
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<String>;
|
||||
features?: Array<SubscriptionPricingFeature>;
|
||||
featured?: boolean;
|
||||
price: string;
|
||||
pricePeriod: string;
|
||||
monthlyPrice: string;
|
||||
monthlyPriceLabel: string;
|
||||
annuallyPrice: string;
|
||||
annuallyPriceLabel: string;
|
||||
}
|
||||
|
||||
function SubscriptionPricing({
|
||||
featured,
|
||||
interface SubscriptionPricingCombinedProps
|
||||
extends SubscriptionPricingProps,
|
||||
WithPlansProps {}
|
||||
|
||||
function SubscriptionPlanRoot({
|
||||
label,
|
||||
description,
|
||||
featured,
|
||||
features,
|
||||
price,
|
||||
pricePeriod,
|
||||
}: SubscriptionPricingProps) {
|
||||
monthlyPrice,
|
||||
monthlyPriceLabel,
|
||||
annuallyPrice,
|
||||
annuallyPriceLabel,
|
||||
|
||||
// #withPlans
|
||||
plansPeriod,
|
||||
}: SubscriptionPricingCombinedProps) {
|
||||
const { mutateAsync: getLemonCheckout, isLoading } =
|
||||
useGetLemonSqueezyCheckout();
|
||||
|
||||
@@ -42,37 +66,34 @@ function SubscriptionPricing({
|
||||
return (
|
||||
<PricingPlan featured={featured}>
|
||||
{featured && <PricingPlan.Featured>Most Popular</PricingPlan.Featured>}
|
||||
|
||||
<PricingPlan.Header label={label} description={description} />
|
||||
<PricingPlan.Price price={price} subPrice={pricePeriod} />
|
||||
|
||||
{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>{feature}</PricingPlan.FeatureLine>
|
||||
<PricingPlan.FeatureLine
|
||||
hintLabel={feature.hintLabel}
|
||||
hintContent={feature.hint}
|
||||
>
|
||||
{feature.text}
|
||||
</PricingPlan.FeatureLine>
|
||||
))}
|
||||
</PricingPlan.Features>
|
||||
</PricingPlan>
|
||||
);
|
||||
}
|
||||
|
||||
export function SubscriptionPlans({ plans }) {
|
||||
return (
|
||||
<Group spacing={18} noWrap align='stretch'>
|
||||
{plans.map((plan, index) => (
|
||||
<SubscriptionPricing
|
||||
key={index}
|
||||
slug={plan.slug}
|
||||
label={plan.name}
|
||||
description={plan.description}
|
||||
features={plan.features}
|
||||
featured={plan.featured}
|
||||
price={plan.price}
|
||||
pricePeriod={plan.pricePeriod}
|
||||
/>
|
||||
))}
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
export const SubscriptionPlan = R.compose(
|
||||
withPlans(({ plansPeriod }) => ({ plansPeriod })),
|
||||
)(SubscriptionPlanRoot);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Group } from '@/components';
|
||||
import { SubscriptionPlan } from './SubscriptionPlan';
|
||||
import { useSubscriptionPlans } from './hooks';
|
||||
|
||||
export function SubscriptionPlans() {
|
||||
const subscriptionPlans = useSubscriptionPlans();
|
||||
|
||||
return (
|
||||
<Group spacing={14} noWrap align="stretch">
|
||||
{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}
|
||||
/>
|
||||
))}
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { Intent, Switch, Tag, Text } from '@blueprintjs/core';
|
||||
import { Group } from '@/components';
|
||||
import withSubscriptionPlansActions, {
|
||||
WithSubscriptionPlansActionsProps,
|
||||
} from '@/containers/Subscriptions/withSubscriptionPlansActions';
|
||||
import { SubscriptionPlansPeriod } from '@/store/plans/plans.reducer';
|
||||
import styles from './SetupSubscription.module.scss';
|
||||
|
||||
interface SubscriptionPlansPeriodsSwitchCombinedProps
|
||||
extends WithSubscriptionPlansActionsProps {}
|
||||
|
||||
function SubscriptionPlansPeriodSwitcherRoot({
|
||||
// #withSubscriptionPlansActions
|
||||
changeSubscriptionPlansPeriod,
|
||||
}: SubscriptionPlansPeriodsSwitchCombinedProps) {
|
||||
// Handles the period switch change.
|
||||
const handleSwitchChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
changeSubscriptionPlansPeriod(
|
||||
event.currentTarget.checked
|
||||
? SubscriptionPlansPeriod.Annually
|
||||
: SubscriptionPlansPeriod.Monthly,
|
||||
);
|
||||
};
|
||||
return (
|
||||
<Group position={'center'} spacing={10} style={{ marginBottom: '1.2rem' }}>
|
||||
<Text>Pay Monthly</Text>
|
||||
<Switch
|
||||
large
|
||||
onChange={handleSwitchChange}
|
||||
className={styles.periodSwitch}
|
||||
/>
|
||||
<Text>
|
||||
Pay Yearly{' '}
|
||||
<Tag minimal intent={Intent.NONE}>
|
||||
25% Off All Year
|
||||
</Tag>
|
||||
</Text>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
export const SubscriptionPlansPeriodSwitcher = R.compose(
|
||||
withSubscriptionPlansActions,
|
||||
)(SubscriptionPlansPeriodSwitcherRoot);
|
||||
@@ -1,29 +1,21 @@
|
||||
// @ts-nocheck
|
||||
import { Callout } from '@blueprintjs/core';
|
||||
import { SubscriptionPlans } from './SubscriptionPlan';
|
||||
import withPlans from '../../Subscriptions/withPlans';
|
||||
import { compose } from '@/utils';
|
||||
import { SubscriptionPlans } from './SubscriptionPlans';
|
||||
import { SubscriptionPlansPeriodSwitcher } from './SubscriptionPlansPeriodSwitcher';
|
||||
|
||||
/**
|
||||
* Billing plans.
|
||||
*/
|
||||
function SubscriptionPlansSectionRoot({ plans }) {
|
||||
export function SubscriptionPlansSection() {
|
||||
return (
|
||||
<section>
|
||||
<Callout
|
||||
style={{ marginBottom: '1.5rem' }}
|
||||
icon={null}
|
||||
title={'Early Adopter Plan'}
|
||||
>
|
||||
We're looking for 200 early adopters, when you subscribe you'll get the
|
||||
full features and unlimited users for a year regardless of the
|
||||
subscribed plan.
|
||||
<Callout style={{ marginBottom: '2rem' }} icon={null}>
|
||||
Simple plans. Simple prices. Only pay for what you really need. All
|
||||
plans come with award-winning 24/7 customer support. Prices do not
|
||||
include applicable taxes.
|
||||
</Callout>
|
||||
<SubscriptionPlans plans={plans} />
|
||||
|
||||
<SubscriptionPlansPeriodSwitcher />
|
||||
<SubscriptionPlans />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export const SubscriptionPlansSection = compose(
|
||||
withPlans(({ plans }) => ({ plans })),
|
||||
)(SubscriptionPlansSectionRoot);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { SubscriptionPlans } from '@/constants/subscriptionModels';
|
||||
|
||||
export const useSubscriptionPlans = () => {
|
||||
return SubscriptionPlans;
|
||||
};
|
||||
Reference in New Issue
Block a user