refactor: rewrite useSubscription with RQ and use it in UsageDataInformation

This commit is contained in:
Rıdvan Akca
2024-03-28 15:53:10 +03:00
parent 1827f5413f
commit f0ef12f904
4 changed files with 136 additions and 61 deletions

View File

@@ -18,11 +18,15 @@ import * as URLS from 'config/urls';
import useBillingAndUsageData from 'hooks/useBillingAndUsageData.ee'; import useBillingAndUsageData from 'hooks/useBillingAndUsageData.ee';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import usePlanAndUsage from 'hooks/usePlanAndUsage'; import usePlanAndUsage from 'hooks/usePlanAndUsage';
import useSubscription from 'hooks/useSubscription.ee';
import useUserTrial from 'hooks/useUserTrial.ee';
import { useQueryClient } from '@tanstack/react-query';
import useCurrentUser from 'hooks/useCurrentUser';
const capitalize = (str) => str[0].toUpperCase() + str.slice(1, str.length); const capitalize = (str) => str[0].toUpperCase() + str.slice(1, str.length);
function BillingCard(props) { function BillingCard(props) {
const { name, title = '', action } = props; const { name, title = '', action, text } = props;
return ( return (
<Card <Card
@@ -45,36 +49,31 @@ function BillingCard(props) {
</CardContent> </CardContent>
<CardActions> <CardActions>
<Action action={action} /> <Action action={action} text={text} />
</CardActions> </CardActions>
</Card> </Card>
); );
} }
function Action(props) { function Action(props) {
const { action } = props; const { action, text } = props;
if (!action) return <React.Fragment />; if (!action) return <React.Fragment />;
const { text, type } = action; if (action.startsWith('http')) {
if (type === 'link') {
if (action.src.startsWith('http')) {
return ( return (
<Button size="small" href={action.src} target="_blank"> <Button size="small" href={action.src} target="_blank">
{text} {text}
</Button> </Button>
); );
} else { } else if (action.startsWith('/')) {
return ( return (
<Button size="small" component={Link} to={action.src}> <Button size="small" component={Link} to={action.src}>
{text} {text}
</Button> </Button>
); );
} }
}
if (type === 'text') {
return ( return (
<Typography variant="subtitle2" pb={1}> <Typography variant="subtitle2" pb={1}>
{text} {text}
@@ -82,13 +81,62 @@ function Action(props) {
); );
} }
return <React.Fragment />;
}
export default function UsageDataInformation() { export default function UsageDataInformation() {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const billingAndUsageData = useBillingAndUsageData(); const billingAndUsageData = useBillingAndUsageData();
const queryClient = useQueryClient();
const { data } = usePlanAndUsage(); const { data } = usePlanAndUsage();
const planAndUsage = data?.data; const planAndUsage = data?.data;
const { data: currentUser } = useCurrentUser();
const currentUserId = currentUser?.data?.id;
const trial = useUserTrial();
const subscriptionData = useSubscription();
const subscription = subscriptionData?.data;
let billingInfo;
React.useEffect(() => {
queryClient.invalidateQueries({
queryKey: ['planAndUsage', currentUserId],
});
}, [subscription, queryClient, currentUserId]);
if (trial.hasTrial) {
billingInfo = {
monthlyQuota: {
title: formatMessage('usageDataInformation.freeTrial'),
action: '/settings/billing/upgrade',
text: 'Upgrade plan',
},
nextBillAmount: {
title: '---',
action: null,
text: null,
},
nextBillDate: {
title: '---',
action: null,
text: null,
},
};
} else {
billingInfo = {
monthlyQuota: {
title: planAndUsage?.plan?.limit,
action: subscription?.cancelUrl,
text: formatMessage('usageDataInformation.cancelPlan'),
},
nextBillAmount: {
title: `${subscription?.nextBillAmount}`,
action: subscription?.updateUrl,
text: formatMessage('usageDataInformation.updatePaymentMethod'),
},
nextBillDate: {
title: subscription?.nextBillDate,
action: formatMessage('usageDataInformation.monthlyPayment'),
text: formatMessage('usageDataInformation.monthlyPayment'),
},
};
}
return ( return (
<React.Fragment> <React.Fragment>
@@ -106,11 +154,8 @@ export default function UsageDataInformation() {
{formatMessage('usageDataInformation.subscriptionPlan')} {formatMessage('usageDataInformation.subscriptionPlan')}
</Typography> </Typography>
{billingAndUsageData?.subscription?.status && ( {subscription?.status && (
<Chip <Chip label={capitalize(subscription?.status)} color="success" />
label={capitalize(billingAndUsageData?.subscription?.status)}
color="success"
/>
)} )}
</Box> </Box>
@@ -127,26 +172,27 @@ export default function UsageDataInformation() {
<Grid item xs={12} md={4}> <Grid item xs={12} md={4}>
<BillingCard <BillingCard
name={formatMessage('usageDataInformation.monthlyQuota')} name={formatMessage('usageDataInformation.monthlyQuota')}
title={billingAndUsageData?.subscription?.monthlyQuota.title} title={billingInfo.monthlyQuota.title}
action={billingAndUsageData?.subscription?.monthlyQuota.action} action={billingInfo.monthlyQuota.action}
text={billingInfo.monthlyQuota.text}
/> />
</Grid> </Grid>
<Grid item xs={12} md={4}> <Grid item xs={12} md={4}>
<BillingCard <BillingCard
name={formatMessage('usageDataInformation.nextBillAmount')} name={formatMessage('usageDataInformation.nextBillAmount')}
title={billingAndUsageData?.subscription?.nextBillAmount.title} title={billingInfo.nextBillAmount.title}
action={ action={billingInfo.nextBillAmount.action}
billingAndUsageData?.subscription?.nextBillAmount.action text={billingInfo.nextBillAmount.text}
}
/> />
</Grid> </Grid>
<Grid item xs={12} md={4}> <Grid item xs={12} md={4}>
<BillingCard <BillingCard
name={formatMessage('usageDataInformation.nextBillDate')} name={formatMessage('usageDataInformation.nextBillDate')}
title={billingAndUsageData?.subscription?.nextBillDate.title} title={billingInfo.nextBillDate.title}
action={billingAndUsageData?.subscription?.nextBillDate.action} action={billingInfo.nextBillDate.action}
text={billingInfo.nextBillDate.text}
/> />
</Grid> </Grid>
</Grid> </Grid>
@@ -193,7 +239,7 @@ export default function UsageDataInformation() {
</Box> </Box>
{/* free plan has `null` status so that we can show the upgrade button */} {/* free plan has `null` status so that we can show the upgrade button */}
{billingAndUsageData?.subscription?.status === null && ( {subscription?.status === null && (
<Button <Button
component={Link} component={Link}
to={URLS.SETTINGS_PLAN_UPGRADE} to={URLS.SETTINGS_PLAN_UPGRADE}

View File

@@ -1,21 +1,14 @@
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import api from 'helpers/api'; import api from 'helpers/api';
import useCurrentUser from './useCurrentUser';
export default function usePlanAndUsage() {
const { data } = useCurrentUser();
const currentUserId = data?.data?.id;
export default function usePlanAndUsage(userId) {
const query = useQuery({ const query = useQuery({
queryKey: ['planAndUsage', currentUserId], queryKey: ['planAndUsage', userId],
queryFn: async ({ signal }) => { queryFn: async ({ signal }) => {
const { data } = await api.get( const { data } = await api.get(`/v1/users/${userId}/plan-and-usage`, {
`/v1/users/${currentUserId}/plan-and-usage`,
{
signal, signal,
}, });
);
return data; return data;
}, },

View File

@@ -1,11 +1,28 @@
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { useLocation } from 'react-router-dom';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import * as React from 'react';
import useFormatMessage from './useFormatMessage';
import api from 'helpers/api'; import api from 'helpers/api';
function transform(subscription) {
const nextBillDate = subscription?.nextBillDate;
const nextBillDateTitleDateObject = DateTime.fromISO(nextBillDate);
const formattedNextBillDateTitle = nextBillDateTitleDateObject.isValid
? nextBillDateTitleDateObject.toFormat('LLL dd, yyyy')
: nextBillDate;
return {
...subscription,
nextBillDate: formattedNextBillDateTitle,
};
}
export default function useSubscription() { export default function useSubscription() {
const formatMessage = useFormatMessage(); const location = useLocation();
const state = location.state;
const checkoutCompleted = state?.checkoutCompleted;
const [isPolling, setIsPolling] = React.useState(false);
const { data, isLoading: isSubscriptionLoading } = useQuery({ const { data, isLoading: isSubscriptionLoading } = useQuery({
queryKey: ['subscription'], queryKey: ['subscription'],
@@ -16,23 +33,38 @@ export default function useSubscription() {
return data; return data;
}, },
refetchInterval: isPolling ? 1000 : false,
}); });
const subscription = data?.data; const subscription = data?.data;
const hasSubscription = !!subscription?.status;
React.useEffect(
function pollDataUntilSubscriptionIsCreated() {
if (checkoutCompleted && !hasSubscription) {
setIsPolling(true);
}
},
[checkoutCompleted, hasSubscription],
);
React.useEffect(
function stopPollingWhenSubscriptionIsCreated() {
if (checkoutCompleted && hasSubscription) {
setIsPolling(false);
}
},
[checkoutCompleted, hasSubscription],
);
const cancellationEffectiveDate = subscription?.cancellationEffectiveDate; const cancellationEffectiveDate = subscription?.cancellationEffectiveDate;
const hasCancelled = !!cancellationEffectiveDate; const hasCancelled = !!cancellationEffectiveDate;
if (isSubscriptionLoading || !hasCancelled) return null; if (isSubscriptionLoading || !hasCancelled) return null;
const cancellationEffectiveDateObject = DateTime.fromISO(
cancellationEffectiveDate,
);
return { return {
message: formatMessage('subscriptionCancelledAlert.text', { data: transform(subscription),
date: cancellationEffectiveDateObject.toFormat('DDD'),
}),
cancellationEffectiveDate: cancellationEffectiveDateObject,
}; };
} }

View File

@@ -165,6 +165,10 @@
"usageDataInformation.yourUsageDescription": "Last 30 days total usage", "usageDataInformation.yourUsageDescription": "Last 30 days total usage",
"usageDataInformation.yourUsageTasks": "Tasks", "usageDataInformation.yourUsageTasks": "Tasks",
"usageDataInformation.upgrade": "Upgrade", "usageDataInformation.upgrade": "Upgrade",
"usageDataInformation.cancelPlan": "Cancel plan",
"usageDataInformation.updatePaymentMethod": "Update payment method",
"usageDataInformation.monthlyPayment": "(monthly payment)",
"usageDataInformation.upgradePlan": "Upgrade plan",
"invoices.invoices": "Invoices", "invoices.invoices": "Invoices",
"invoices.date": "Date", "invoices.date": "Date",
"invoices.amount": "Amount", "invoices.amount": "Amount",