mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 13:20:31 +00:00
feat: wip billing page
This commit is contained in:
@@ -15,12 +15,17 @@ interface BillingPageBootProps {
|
||||
}
|
||||
|
||||
export function BillingPageBoot({ children }: BillingPageBootProps) {
|
||||
const { isLoading: isSubscriptionsLoading, data: subscriptions } =
|
||||
const { isLoading: isSubscriptionsLoading, data: subscriptionsRes } =
|
||||
useGetSubscriptions();
|
||||
|
||||
const mainSubscription = subscriptionsRes?.subscriptions?.find(
|
||||
(s) => s.slug === 'main',
|
||||
);
|
||||
|
||||
const value = {
|
||||
isSubscriptionsLoading,
|
||||
subscriptions,
|
||||
subscriptions: subscriptionsRes?.subscriptions,
|
||||
mainSubscription,
|
||||
};
|
||||
return <BillingBoot.Provider value={value}>{children}</BillingBoot.Provider>;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
// @ts-nocheck
|
||||
import { Box, Group } from '@/components';
|
||||
import { Text } from '@blueprintjs/core';
|
||||
import { Spinner, Text } from '@blueprintjs/core';
|
||||
import { Subscription } from './BillingSubscription';
|
||||
import { useBillingPageBoot } from './BillingPageBoot';
|
||||
import styles from './BillingPageContent.module.scss';
|
||||
|
||||
export function BillingPageContent() {
|
||||
const { isSubscriptionsLoading, subscriptions } = useBillingPageBoot();
|
||||
|
||||
if (isSubscriptionsLoading || !subscriptions) {
|
||||
return <Spinner size={30} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box className={styles.root}>
|
||||
<Text>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
.title{
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #3D4C58;
|
||||
}
|
||||
@@ -56,8 +56,4 @@
|
||||
}
|
||||
.actions{
|
||||
margin-top: 16px;
|
||||
|
||||
button{
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
@@ -4,25 +4,42 @@ import { Box, Group, Stack } from '@/components';
|
||||
import { Button, Card, Intent, Text } from '@blueprintjs/core';
|
||||
import withAlertActions from '../Alert/withAlertActions';
|
||||
import styles from './BillingSubscription.module.scss';
|
||||
import withDrawerActions from '../Drawer/withDrawerActions';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
import { useBillingPageBoot } from './BillingPageBoot';
|
||||
|
||||
function SubscriptionRoot({ openAlert }) {
|
||||
function SubscriptionRoot({ openAlert, openDrawer }) {
|
||||
const { mainSubscription } = useBillingPageBoot();
|
||||
|
||||
// Can't continue if the main subscription is not loaded.
|
||||
if (!mainSubscription) {
|
||||
return null;
|
||||
}
|
||||
const handleCancelSubBtnClick = () => {
|
||||
openAlert('cancel-main-subscription');
|
||||
};
|
||||
const handleResumeSubBtnClick = () => {
|
||||
openAlert('resume-main-subscription');
|
||||
};
|
||||
const handleUpdatePaymentMethod = () => {};
|
||||
|
||||
const handleUpgradeBtnClick = () => {};
|
||||
const handleUpdatePaymentMethod = () => {
|
||||
window.LemonSqueezy.Url.Open(
|
||||
mainSubscription.lemonUrls?.updatePaymentMethod,
|
||||
);
|
||||
};
|
||||
// Handle upgrade button click.
|
||||
const handleUpgradeBtnClick = () => {
|
||||
openDrawer(DRAWERS.CHANGE_SUBSCARIPTION_PLAN);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className={styles.root}>
|
||||
<Stack spacing={8}>
|
||||
<h1 className={styles.title}>Capital Essential</h1>
|
||||
<Stack spacing={6}>
|
||||
<h1 className={styles.title}>{mainSubscription.planName}</h1>
|
||||
|
||||
<Group spacing={0} className={styles.period}>
|
||||
<Text className={styles.periodStatus}>Trial</Text>
|
||||
<Text className={styles.periodStatus}>
|
||||
{mainSubscription.statusFormatted}
|
||||
</Text>
|
||||
<Text className={styles.periodText}>Trial ends in 10 days.</Text>
|
||||
</Group>
|
||||
</Stack>
|
||||
@@ -43,15 +60,29 @@ function SubscriptionRoot({ openAlert }) {
|
||||
>
|
||||
Upgrade the Plan
|
||||
</Button>
|
||||
<Button
|
||||
minimal
|
||||
small
|
||||
inline
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleCancelSubBtnClick}
|
||||
>
|
||||
Cancel Subscription
|
||||
</Button>
|
||||
|
||||
{mainSubscription.canceled && (
|
||||
<Button
|
||||
minimal
|
||||
small
|
||||
inline
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleResumeSubBtnClick}
|
||||
>
|
||||
Resume Subscription
|
||||
</Button>
|
||||
)}
|
||||
{!mainSubscription.canceled && (
|
||||
<Button
|
||||
minimal
|
||||
small
|
||||
inline
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleCancelSubBtnClick}
|
||||
>
|
||||
Cancel Subscription
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
minimal
|
||||
small
|
||||
@@ -65,22 +96,38 @@ function SubscriptionRoot({ openAlert }) {
|
||||
|
||||
<Group position={'apart'} style={{ marginTop: 'auto' }}>
|
||||
<Group spacing={4}>
|
||||
<Text className={styles.priceAmount}>$10</Text>
|
||||
<Text className={styles.pricePeriod}>/ mo</Text>
|
||||
<Text className={styles.priceAmount}>
|
||||
{mainSubscription.planPriceFormatted}
|
||||
</Text>
|
||||
|
||||
{mainSubscription.planPeriod && (
|
||||
<Text className={styles.pricePeriod}>
|
||||
{mainSubscription.planPeriod === 'month'
|
||||
? 'mo'
|
||||
: mainSubscription.planPeriod === 'year'
|
||||
? 'yearly'
|
||||
: ''}
|
||||
</Text>
|
||||
)}
|
||||
</Group>
|
||||
|
||||
<Box>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleResumeSubBtnClick}
|
||||
className={styles.subscribeButton}
|
||||
>
|
||||
Resume Subscription
|
||||
</Button>
|
||||
{mainSubscription.canceled && (
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleResumeSubBtnClick}
|
||||
className={styles.subscribeButton}
|
||||
>
|
||||
Resume Subscription
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
</Group>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export const Subscription = R.compose(withAlertActions)(SubscriptionRoot);
|
||||
export const Subscription = R.compose(
|
||||
withAlertActions,
|
||||
withDrawerActions,
|
||||
)(SubscriptionRoot);
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// @ts-nocheck
|
||||
import * as R from 'ramda';
|
||||
import { Callout, Classes, Intent } from '@blueprintjs/core';
|
||||
import { AppToaster, Box } from '@/components';
|
||||
import { SubscriptionPlans } from '@/containers/Setup/SetupSubscription/SubscriptionPlans';
|
||||
import { SubscriptionPlansPeriodSwitcher } from '@/containers/Setup/SetupSubscription/SubscriptionPlansPeriodSwitcher';
|
||||
import { useChangeSubscriptionPlan } from '@/hooks/query/subscription';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
|
||||
function ChangeSubscriptionPlanContent({ closeDrawer }) {
|
||||
const { mutateAsync: changeSubscriptionPlan } = useChangeSubscriptionPlan();
|
||||
|
||||
// Handle the subscribe button click.
|
||||
const handleSubscribe = (variantId: number) => {
|
||||
changeSubscriptionPlan({ variant_id: variantId })
|
||||
.then(() => {
|
||||
closeDrawer(DRAWERS.CHANGE_SUBSCARIPTION_PLAN);
|
||||
AppToaster.show({
|
||||
intent: Intent.SUCCESS,
|
||||
message: 'The subscription plan has been changed successfully.',
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
AppToaster.show({
|
||||
intent: Intent.DANGER,
|
||||
message: 'Something went wrong.',
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Box className={Classes.DRAWER_BODY}>
|
||||
<Box
|
||||
style={{
|
||||
maxWidth: 1024,
|
||||
margin: '0 auto',
|
||||
padding: '50px 20px 80px',
|
||||
}}
|
||||
>
|
||||
<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>
|
||||
|
||||
<SubscriptionPlansPeriodSwitcher />
|
||||
<SubscriptionPlans onSubscribe={handleSubscribe} />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default R.compose(withDrawerActions)(ChangeSubscriptionPlanContent);
|
||||
Reference in New Issue
Block a user