Merge pull request #1715 from automatisch/AUT-698

refactor: rewrite usePaddleInfo and usePaymentPlans with RQ
This commit is contained in:
Ali BARIN
2024-03-13 09:20:39 +01:00
committed by GitHub
10 changed files with 59 additions and 78 deletions

View File

@@ -1,10 +0,0 @@
import appConfig from '../../config/app.js';
import Billing from '../../helpers/billing/index.ee.js';
const getPaddleInfo = async () => {
if (!appConfig.isCloud) return;
return Billing.paddleInfo;
};
export default getPaddleInfo;

View File

@@ -1,10 +0,0 @@
import appConfig from '../../config/app.js';
import Billing from '../../helpers/billing/index.ee.js';
const getPaymentPlans = async () => {
if (!appConfig.isCloud) return;
return Billing.paddlePlans;
};
export default getPaymentPlans;

View File

@@ -11,8 +11,6 @@ import getFlow from './queries/get-flow.js';
import getFlows from './queries/get-flows.js'; import getFlows from './queries/get-flows.js';
import getInvoices from './queries/get-invoices.ee.js'; import getInvoices from './queries/get-invoices.ee.js';
import getNotifications from './queries/get-notifications.js'; import getNotifications from './queries/get-notifications.js';
import getPaddleInfo from './queries/get-paddle-info.ee.js';
import getPaymentPlans from './queries/get-payment-plans.ee.js';
import getPermissionCatalog from './queries/get-permission-catalog.ee.js'; import getPermissionCatalog from './queries/get-permission-catalog.ee.js';
import getRole from './queries/get-role.ee.js'; import getRole from './queries/get-role.ee.js';
import getRoles from './queries/get-roles.ee.js'; import getRoles from './queries/get-roles.ee.js';
@@ -41,8 +39,6 @@ const queryResolvers = {
getFlows, getFlows,
getInvoices, getInvoices,
getNotifications, getNotifications,
getPaddleInfo,
getPaymentPlans,
getPermissionCatalog, getPermissionCatalog,
getRole, getRole,
getRoles, getRoles,

View File

@@ -27,8 +27,6 @@ type Query {
getCurrentUser: User getCurrentUser: User
getConfig(keys: [String]): JSONObject getConfig(keys: [String]): JSONObject
getInvoices: [Invoice] getInvoices: [Invoice]
getPaddleInfo: GetPaddleInfo
getPaymentPlans: [PaymentPlan]
getPermissionCatalog: PermissionCatalog getPermissionCatalog: PermissionCatalog
getRole(id: String!): Role getRole(id: String!): Role
getRoles: [Role] getRoles: [Role]
@@ -660,11 +658,6 @@ type Usage {
task: Int task: Int
} }
type GetPaddleInfo {
sandbox: Boolean
vendorId: Int
}
type Invoice { type Invoice {
id: Int id: Int
amount: Float amount: Float
@@ -673,13 +666,6 @@ type Invoice {
receipt_url: String receipt_url: String
} }
type PaymentPlan {
name: String
limit: String
price: String
productId: String
}
type ListSamlAuthProvider { type ListSamlAuthProvider {
id: String id: String
name: String name: String

View File

@@ -14,16 +14,19 @@ import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow'; import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper'; import Paper from '@mui/material/Paper';
import LockIcon from '@mui/icons-material/Lock'; import LockIcon from '@mui/icons-material/Lock';
import usePaymentPlans from 'hooks/usePaymentPlans.ee'; import usePaymentPlans from 'hooks/usePaymentPlans.ee';
import useCurrentUser from 'hooks/useCurrentUser'; import useCurrentUser from 'hooks/useCurrentUser';
import usePaddle from 'hooks/usePaddle.ee'; import usePaddle from 'hooks/usePaddle.ee';
export default function UpgradeFreeTrial() { export default function UpgradeFreeTrial() {
const { plans, loading } = usePaymentPlans(); const { data: plans, isLoading: isPaymentPlansLoading } = usePaymentPlans();
const currentUser = useCurrentUser(); const currentUser = useCurrentUser();
const { loaded: paddleLoaded } = usePaddle(); const { loaded: paddleLoaded } = usePaddle();
const [selectedIndex, setSelectedIndex] = React.useState(0); const [selectedIndex, setSelectedIndex] = React.useState(0);
const selectedPlan = plans?.[selectedIndex]; const selectedPlan = plans?.data?.[selectedIndex];
const updateSelection = (index) => setSelectedIndex(index); const updateSelection = (index) => setSelectedIndex(index);
const handleCheckout = React.useCallback(() => { const handleCheckout = React.useCallback(() => {
window.Paddle.Checkout?.open({ window.Paddle.Checkout?.open({
product: selectedPlan.productId, product: selectedPlan.productId,
@@ -34,7 +37,9 @@ export default function UpgradeFreeTrial() {
}), }),
}); });
}, [selectedPlan, currentUser]); }, [selectedPlan, currentUser]);
if (loading || !plans.length) return null;
if (isPaymentPlansLoading || !plans?.data?.length) return null;
return ( return (
<React.Fragment> <React.Fragment>
<Card sx={{ mb: 3, p: 2 }}> <Card sx={{ mb: 3, p: 2 }}>
@@ -82,7 +87,7 @@ export default function UpgradeFreeTrial() {
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
{plans.map((plan, index) => ( {plans?.data?.map((plan, index) => (
<TableRow <TableRow
key={plan.productId} key={plan.productId}
onClick={() => updateSelection(index)} onClick={() => updateSelection(index)}

View File

@@ -1,21 +1,29 @@
import * as React from 'react'; import * as React from 'react';
import { useNavigate } from 'react-router-dom'; 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 apolloClient from 'graphql/client';
export const PaddleContext = React.createContext({ export const PaddleContext = React.createContext({
loaded: false, loaded: false,
}); });
export const PaddleProvider = (props) => { export const PaddleProvider = (props) => {
const { children } = props; const { children } = props;
const isCloud = useCloud(); const isCloud = useCloud();
const navigate = useNavigate(); const navigate = useNavigate();
const { sandbox, vendorId } = usePaddleInfo(); const { data } = usePaddleInfo();
const sandbox = data?.data?.sandbox;
const vendorId = data?.data?.vendorId;
const [loaded, setLoaded] = React.useState(false); const [loaded, setLoaded] = React.useState(false);
const paddleEventHandler = React.useCallback( const paddleEventHandler = React.useCallback(
async (payload) => { async (payload) => {
const { event, eventData } = payload; const { event, eventData } = payload;
if (event === 'Checkout.Close') { if (event === 'Checkout.Close') {
const completed = eventData.checkout?.completed; const completed = eventData.checkout?.completed;
if (completed) { if (completed) {
@@ -24,6 +32,7 @@ export const PaddleProvider = (props) => {
await apolloClient.refetchQueries({ await apolloClient.refetchQueries({
include: ['GetTrialStatus', 'GetBillingAndUsage'], include: ['GetTrialStatus', 'GetBillingAndUsage'],
}); });
navigate(URLS.SETTINGS_BILLING_AND_USAGE, { navigate(URLS.SETTINGS_BILLING_AND_USAGE, {
state: { checkoutCompleted: true }, state: { checkoutCompleted: true },
}); });
@@ -32,15 +41,18 @@ export const PaddleProvider = (props) => {
}, },
[navigate], [navigate],
); );
const value = React.useMemo(() => { const value = React.useMemo(() => {
return { return {
loaded, loaded,
}; };
}, [loaded]); }, [loaded]);
React.useEffect( React.useEffect(
function loadPaddleScript() { function loadPaddleScript() {
if (!isCloud) return; if (!isCloud) return;
const isInjected = document.getElementById('paddle-js'); const isInjected = document.getElementById('paddle-js');
if (isInjected) { if (isInjected) {
setLoaded(true); setLoaded(true);
return; return;
@@ -51,21 +63,26 @@ export const PaddleProvider = (props) => {
g.defer = true; g.defer = true;
g.async = true; g.async = true;
g.id = 'paddle-js'; g.id = 'paddle-js';
if (s.parentNode) { if (s.parentNode) {
s.parentNode.insertBefore(g, s); s.parentNode.insertBefore(g, s);
} }
g.onload = function () { g.onload = function () {
setLoaded(true); setLoaded(true);
}; };
}, },
[isCloud], [isCloud],
); );
React.useEffect( React.useEffect(
function initPaddleScript() { function initPaddleScript() {
if (!loaded || !vendorId) return; if (!loaded || !vendorId) return;
if (sandbox) { if (sandbox) {
window.Paddle.Environment.set('sandbox'); window.Paddle.Environment.set('sandbox');
} }
window.Paddle.Setup({ window.Paddle.Setup({
vendor: vendorId, vendor: vendorId,
eventCallback: paddleEventHandler, eventCallback: paddleEventHandler,
@@ -73,6 +90,7 @@ export const PaddleProvider = (props) => {
}, },
[loaded, sandbox, vendorId, paddleEventHandler], [loaded, sandbox, vendorId, paddleEventHandler],
); );
return ( return (
<PaddleContext.Provider value={value}>{children}</PaddleContext.Provider> <PaddleContext.Provider value={value}>{children}</PaddleContext.Provider>
); );

View File

@@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const GET_PADDLE_INFO = gql`
query GetPaddleInfo {
getPaddleInfo {
sandbox
vendorId
}
}
`;

View File

@@ -1,11 +0,0 @@
import { gql } from '@apollo/client';
export const GET_PAYMENT_PLANS = gql`
query GetPaymentPlans {
getPaymentPlans {
name
limit
price
productId
}
}
`;

View File

@@ -1,10 +1,17 @@
import { useQuery } from '@apollo/client'; import { useQuery } from '@tanstack/react-query';
import { GET_PADDLE_INFO } from 'graphql/queries/get-paddle-info.ee'; import api from 'helpers/api';
export default function usePaddleInfo() { export default function usePaddleInfo() {
const { data, loading } = useQuery(GET_PADDLE_INFO); const query = useQuery({
return { queryKey: ['paddleInfo'],
sandbox: data?.getPaddleInfo?.sandbox, queryFn: async ({ signal }) => {
vendorId: data?.getPaddleInfo?.vendorId, const { data } = await api.get('/v1/payment/paddle-info', {
loading, signal,
}; });
return data;
},
});
return query;
} }

View File

@@ -1,9 +1,18 @@
import { useQuery } from '@apollo/client'; import { useQuery } from '@tanstack/react-query';
import { GET_PAYMENT_PLANS } from 'graphql/queries/get-payment-plans.ee';
import api from 'helpers/api';
export default function usePaymentPlans() { export default function usePaymentPlans() {
const { data, loading } = useQuery(GET_PAYMENT_PLANS); const query = useQuery({
return { queryKey: ['paymentPlans'],
plans: data?.getPaymentPlans || [], queryFn: async ({ signal }) => {
loading, const { data } = await api.get('/v1/payment/plans', {
}; signal,
});
return data;
},
});
return query;
} }