refactor: remove useBillingAndUsageData hook
This commit is contained in:
@@ -1,101 +0,0 @@
|
|||||||
import { DateTime } from 'luxon';
|
|
||||||
import Billing from '../../helpers/billing/index.ee.js';
|
|
||||||
import ExecutionStep from '../../models/execution-step.js';
|
|
||||||
|
|
||||||
const getBillingAndUsage = async (_parent, _params, context) => {
|
|
||||||
const persistedSubscription = await context.currentUser.$relatedQuery(
|
|
||||||
'currentSubscription'
|
|
||||||
);
|
|
||||||
|
|
||||||
const subscription = persistedSubscription
|
|
||||||
? paidSubscription(persistedSubscription)
|
|
||||||
: freeTrialSubscription();
|
|
||||||
|
|
||||||
return {
|
|
||||||
subscription,
|
|
||||||
usage: {
|
|
||||||
task: executionStepCount(context),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const paidSubscription = (subscription) => {
|
|
||||||
const currentPlan = Billing.paddlePlans.find(
|
|
||||||
(plan) => plan.productId === subscription.paddlePlanId
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
status: subscription.status,
|
|
||||||
monthlyQuota: {
|
|
||||||
title: currentPlan.limit,
|
|
||||||
action: {
|
|
||||||
type: 'link',
|
|
||||||
text: 'Cancel plan',
|
|
||||||
src: subscription.cancelUrl,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
nextBillAmount: {
|
|
||||||
title: subscription.nextBillAmount
|
|
||||||
? '€' + subscription.nextBillAmount
|
|
||||||
: '---',
|
|
||||||
action: {
|
|
||||||
type: 'link',
|
|
||||||
text: 'Update payment method',
|
|
||||||
src: subscription.updateUrl,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
nextBillDate: {
|
|
||||||
title: subscription.nextBillDate ? subscription.nextBillDate : '---',
|
|
||||||
action: {
|
|
||||||
type: 'text',
|
|
||||||
text: '(monthly payment)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const freeTrialSubscription = () => {
|
|
||||||
return {
|
|
||||||
status: null,
|
|
||||||
monthlyQuota: {
|
|
||||||
title: 'Free Trial',
|
|
||||||
action: {
|
|
||||||
type: 'link',
|
|
||||||
text: 'Upgrade plan',
|
|
||||||
src: '/settings/billing/upgrade',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
nextBillAmount: {
|
|
||||||
title: '---',
|
|
||||||
action: null,
|
|
||||||
},
|
|
||||||
nextBillDate: {
|
|
||||||
title: '---',
|
|
||||||
action: null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const executionIds = async (context) => {
|
|
||||||
return (
|
|
||||||
await context.currentUser
|
|
||||||
.$relatedQuery('executions')
|
|
||||||
.select('executions.id')
|
|
||||||
).map((execution) => execution.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const executionStepCount = async (context) => {
|
|
||||||
const executionStepCount = await ExecutionStep.query()
|
|
||||||
.whereIn('execution_id', await executionIds(context))
|
|
||||||
.andWhere(
|
|
||||||
'created_at',
|
|
||||||
'>=',
|
|
||||||
DateTime.now().minus({ days: 30 }).toISODate()
|
|
||||||
)
|
|
||||||
.count()
|
|
||||||
.first();
|
|
||||||
|
|
||||||
return executionStepCount.count;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getBillingAndUsage;
|
|
@@ -1,6 +1,5 @@
|
|||||||
import getApp from './queries/get-app.js';
|
import getApp from './queries/get-app.js';
|
||||||
import getAppAuthClient from './queries/get-app-auth-client.ee.js';
|
import getAppAuthClient from './queries/get-app-auth-client.ee.js';
|
||||||
import getBillingAndUsage from './queries/get-billing-and-usage.ee.js';
|
|
||||||
import getConnectedApps from './queries/get-connected-apps.js';
|
import getConnectedApps from './queries/get-connected-apps.js';
|
||||||
import getDynamicData from './queries/get-dynamic-data.js';
|
import getDynamicData from './queries/get-dynamic-data.js';
|
||||||
import getStepWithTestExecutions from './queries/get-step-with-test-executions.js';
|
import getStepWithTestExecutions from './queries/get-step-with-test-executions.js';
|
||||||
@@ -9,7 +8,6 @@ import testConnection from './queries/test-connection.js';
|
|||||||
const queryResolvers = {
|
const queryResolvers = {
|
||||||
getApp,
|
getApp,
|
||||||
getAppAuthClient,
|
getAppAuthClient,
|
||||||
getBillingAndUsage,
|
|
||||||
getConnectedApps,
|
getConnectedApps,
|
||||||
getDynamicData,
|
getDynamicData,
|
||||||
getStepWithTestExecutions,
|
getStepWithTestExecutions,
|
||||||
|
@@ -9,7 +9,6 @@ type Query {
|
|||||||
key: String!
|
key: String!
|
||||||
parameters: JSONObject
|
parameters: JSONObject
|
||||||
): JSONObject
|
): JSONObject
|
||||||
getBillingAndUsage: GetBillingAndUsage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
@@ -561,43 +560,6 @@ type License {
|
|||||||
verified: Boolean
|
verified: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetBillingAndUsage {
|
|
||||||
subscription: Subscription
|
|
||||||
usage: Usage
|
|
||||||
}
|
|
||||||
|
|
||||||
type MonthlyQuota {
|
|
||||||
title: String
|
|
||||||
action: BillingCardAction
|
|
||||||
}
|
|
||||||
|
|
||||||
type NextBillAmount {
|
|
||||||
title: String
|
|
||||||
action: BillingCardAction
|
|
||||||
}
|
|
||||||
|
|
||||||
type NextBillDate {
|
|
||||||
title: String
|
|
||||||
action: BillingCardAction
|
|
||||||
}
|
|
||||||
|
|
||||||
type BillingCardAction {
|
|
||||||
type: String
|
|
||||||
text: String
|
|
||||||
src: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type Subscription {
|
|
||||||
status: String
|
|
||||||
monthlyQuota: MonthlyQuota
|
|
||||||
nextBillAmount: NextBillAmount
|
|
||||||
nextBillDate: NextBillDate
|
|
||||||
}
|
|
||||||
|
|
||||||
type Usage {
|
|
||||||
task: Int
|
|
||||||
}
|
|
||||||
|
|
||||||
type Permission {
|
type Permission {
|
||||||
id: String
|
id: String
|
||||||
action: String
|
action: String
|
||||||
|
@@ -1,14 +1,17 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
import useSubscription from 'hooks/useSubscription.ee';
|
|
||||||
|
|
||||||
export default function CheckoutCompletedAlert() {
|
export default function CheckoutCompletedAlert() {
|
||||||
const formatMessage = useFormatMessage();
|
const formatMessage = useFormatMessage();
|
||||||
const subscription = useSubscription();
|
const location = useLocation();
|
||||||
|
const state = location.state;
|
||||||
|
const checkoutCompleted = state?.checkoutCompleted;
|
||||||
|
|
||||||
if (subscription?.data?.status !== 'active') return <React.Fragment />;
|
if (!checkoutCompleted) return <React.Fragment />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Alert
|
<Alert
|
||||||
|
@@ -102,7 +102,7 @@ export default function UsageDataInformation() {
|
|||||||
billingInfo = {
|
billingInfo = {
|
||||||
monthlyQuota: {
|
monthlyQuota: {
|
||||||
title: formatMessage('usageDataInformation.freeTrial'),
|
title: formatMessage('usageDataInformation.freeTrial'),
|
||||||
action: '/settings/billing/upgrade',
|
action: URLS.SETTINGS_PLAN_UPGRADE,
|
||||||
text: 'Upgrade plan',
|
text: 'Upgrade plan',
|
||||||
},
|
},
|
||||||
nextBillAmount: {
|
nextBillAmount: {
|
||||||
|
@@ -4,7 +4,7 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
import * as URLS from 'config/urls';
|
import * as URLS from 'config/urls';
|
||||||
import useCloud from 'hooks/useCloud';
|
import useCloud from 'hooks/useCloud';
|
||||||
import usePaddleInfo from 'hooks/usePaddleInfo.ee';
|
import usePaddleInfo from 'hooks/usePaddleInfo.ee';
|
||||||
import apolloClient from 'graphql/client';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
export const PaddleContext = React.createContext({
|
export const PaddleContext = React.createContext({
|
||||||
loaded: false,
|
loaded: false,
|
||||||
@@ -17,6 +17,7 @@ export const PaddleProvider = (props) => {
|
|||||||
const { data } = usePaddleInfo();
|
const { data } = usePaddleInfo();
|
||||||
const sandbox = data?.data?.sandbox;
|
const sandbox = data?.data?.sandbox;
|
||||||
const vendorId = data?.data?.vendorId;
|
const vendorId = data?.data?.vendorId;
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const [loaded, setLoaded] = React.useState(false);
|
const [loaded, setLoaded] = React.useState(false);
|
||||||
|
|
||||||
@@ -29,8 +30,12 @@ export const PaddleProvider = (props) => {
|
|||||||
if (completed) {
|
if (completed) {
|
||||||
// Paddle has side effects in the background,
|
// Paddle has side effects in the background,
|
||||||
// so we need to refetch the relevant queries
|
// so we need to refetch the relevant queries
|
||||||
await apolloClient.refetchQueries({
|
await queryClient.refetchQueries({
|
||||||
include: ['GetTrialStatus', 'GetBillingAndUsage'],
|
queryKey: ['userTrial'],
|
||||||
|
});
|
||||||
|
|
||||||
|
await queryClient.refetchQueries({
|
||||||
|
queryKey: ['subscription'],
|
||||||
});
|
});
|
||||||
|
|
||||||
navigate(URLS.SETTINGS_BILLING_AND_USAGE, {
|
navigate(URLS.SETTINGS_BILLING_AND_USAGE, {
|
||||||
@@ -39,7 +44,7 @@ export const PaddleProvider = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[navigate],
|
[navigate, queryClient],
|
||||||
);
|
);
|
||||||
|
|
||||||
const value = React.useMemo(() => {
|
const value = React.useMemo(() => {
|
||||||
|
@@ -1,37 +0,0 @@
|
|||||||
import { gql } from '@apollo/client';
|
|
||||||
export const GET_BILLING_AND_USAGE = gql`
|
|
||||||
query GetBillingAndUsage {
|
|
||||||
getBillingAndUsage {
|
|
||||||
subscription {
|
|
||||||
status
|
|
||||||
monthlyQuota {
|
|
||||||
title
|
|
||||||
action {
|
|
||||||
type
|
|
||||||
text
|
|
||||||
src
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextBillDate {
|
|
||||||
title
|
|
||||||
action {
|
|
||||||
type
|
|
||||||
text
|
|
||||||
src
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextBillAmount {
|
|
||||||
title
|
|
||||||
action {
|
|
||||||
type
|
|
||||||
text
|
|
||||||
src
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
usage {
|
|
||||||
task
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
@@ -1,52 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import { useQuery } from '@apollo/client';
|
|
||||||
import { useLocation } from 'react-router-dom';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { GET_BILLING_AND_USAGE } from 'graphql/queries/get-billing-and-usage.ee';
|
|
||||||
function transform(billingAndUsageData) {
|
|
||||||
const nextBillDate = billingAndUsageData.subscription.nextBillDate;
|
|
||||||
const nextBillDateTitle = nextBillDate.title;
|
|
||||||
const nextBillDateTitleDateObject = DateTime.fromMillis(
|
|
||||||
Number(nextBillDateTitle),
|
|
||||||
);
|
|
||||||
const formattedNextBillDateTitle = nextBillDateTitleDateObject.isValid
|
|
||||||
? nextBillDateTitleDateObject.toFormat('LLL dd, yyyy')
|
|
||||||
: nextBillDateTitle;
|
|
||||||
return {
|
|
||||||
...billingAndUsageData,
|
|
||||||
subscription: {
|
|
||||||
...billingAndUsageData.subscription,
|
|
||||||
nextBillDate: {
|
|
||||||
...billingAndUsageData.subscription.nextBillDate,
|
|
||||||
title: formattedNextBillDateTitle,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export default function useBillingAndUsageData() {
|
|
||||||
const location = useLocation();
|
|
||||||
const state = location.state;
|
|
||||||
const { data, loading, startPolling, stopPolling } = useQuery(
|
|
||||||
GET_BILLING_AND_USAGE,
|
|
||||||
);
|
|
||||||
const checkoutCompleted = state?.checkoutCompleted;
|
|
||||||
const hasSubscription = !!data?.getBillingAndUsage?.subscription?.status;
|
|
||||||
React.useEffect(
|
|
||||||
function pollDataUntilSubscriptionIsCreated() {
|
|
||||||
if (checkoutCompleted && !hasSubscription) {
|
|
||||||
startPolling(1000);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[checkoutCompleted, hasSubscription, startPolling],
|
|
||||||
);
|
|
||||||
React.useEffect(
|
|
||||||
function stopPollingWhenSubscriptionIsCreated() {
|
|
||||||
if (checkoutCompleted && hasSubscription) {
|
|
||||||
stopPolling();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[checkoutCompleted, hasSubscription, stopPolling],
|
|
||||||
);
|
|
||||||
if (loading) return null;
|
|
||||||
return transform(data.getBillingAndUsage);
|
|
||||||
}
|
|
@@ -24,7 +24,7 @@ export default function useSubscription() {
|
|||||||
const checkoutCompleted = state?.checkoutCompleted;
|
const checkoutCompleted = state?.checkoutCompleted;
|
||||||
const [isPolling, setIsPolling] = React.useState(false);
|
const [isPolling, setIsPolling] = React.useState(false);
|
||||||
|
|
||||||
const { data, isLoading: isSubscriptionLoading } = useQuery({
|
const { data } = useQuery({
|
||||||
queryKey: ['subscription'],
|
queryKey: ['subscription'],
|
||||||
queryFn: async ({ signal }) => {
|
queryFn: async ({ signal }) => {
|
||||||
const { data } = await api.get(`/v1/users/me/subscription`, {
|
const { data } = await api.get(`/v1/users/me/subscription`, {
|
||||||
@@ -38,32 +38,17 @@ export default function useSubscription() {
|
|||||||
|
|
||||||
const subscription = data?.data;
|
const subscription = data?.data;
|
||||||
|
|
||||||
const hasSubscription = !!subscription?.status;
|
const hasSubscription = subscription?.status === 'active';
|
||||||
|
|
||||||
React.useEffect(
|
React.useEffect(
|
||||||
function pollDataUntilSubscriptionIsCreated() {
|
function pollDataUntilSubscriptionIsCreated() {
|
||||||
if (checkoutCompleted && !hasSubscription) {
|
if (checkoutCompleted) {
|
||||||
setIsPolling(true);
|
setIsPolling(!hasSubscription);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[checkoutCompleted, hasSubscription],
|
[checkoutCompleted, hasSubscription],
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(
|
|
||||||
function stopPollingWhenSubscriptionIsCreated() {
|
|
||||||
if (checkoutCompleted && hasSubscription) {
|
|
||||||
setIsPolling(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[checkoutCompleted, hasSubscription],
|
|
||||||
);
|
|
||||||
|
|
||||||
const cancellationEffectiveDate = subscription?.cancellationEffectiveDate;
|
|
||||||
|
|
||||||
const hasCancelled = !!cancellationEffectiveDate;
|
|
||||||
|
|
||||||
if (isSubscriptionLoading || !hasCancelled) return null;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: transform(subscription),
|
data: transform(subscription),
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user