0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

refactor(console): use useSWRImmutable to avoid redundant subscrtipion data fetching (#4272)

This commit is contained in:
Xiao Yijun 2023-08-03 14:04:25 +08:00 committed by GitHub
parent 8cba35d116
commit 56b0a2cd18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 55 deletions

View file

@ -1,7 +1,9 @@
import { useContext, useEffect, useState } from 'react';
import { useContext, useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import ReactModal from 'react-modal';
import useSWRImmutable from 'swr/immutable';
import { useCloudApi } from '@/cloud/hooks/use-cloud-api';
import PlanUsage from '@/components/PlanUsage';
import { contactEmailLink } from '@/consts';
import { subscriptionPage } from '@/consts/pages';
@ -10,9 +12,7 @@ import Button from '@/ds-components/Button';
import FormField from '@/ds-components/FormField';
import InlineNotification from '@/ds-components/InlineNotification';
import ModalLayout from '@/ds-components/ModalLayout';
import useSubscription from '@/hooks/use-subscription';
import useSubscriptionPlan from '@/hooks/use-subscription-plan';
import useSubscriptionUsage from '@/hooks/use-subscription-usage';
import useSubscriptionPlans from '@/hooks/use-subscription-plans';
import useTenantPathname from '@/hooks/use-tenant-pathname';
import * as modalStyles from '@/scss/modal.module.scss';
@ -22,55 +22,52 @@ import * as styles from './index.module.scss';
function MauExceededModal() {
const { currentTenantId } = useContext(TenantsContext);
const cloudApi = useCloudApi();
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const { navigate } = useTenantPathname();
const [hasClosed, setHasClosed] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const handleCloseModal = () => {
setHasClosed(true);
setIsOpen(false);
};
const { data: currentUsage, error: fetchUsageError } = useSubscriptionUsage(currentTenantId);
const { data: currentSubscription, error: fetchSubscriptionError } =
useSubscription(currentTenantId);
const { data: currentPlan, error: fetchCurrentPlanError } = useSubscriptionPlan(currentTenantId);
const { data: subscriptionPlans } = useSubscriptionPlans();
const isLoadingUsage = !currentUsage && !fetchUsageError;
const isLoadingSubscription = !currentSubscription && !fetchSubscriptionError;
const isLoadingCurrentPlan = !currentPlan && !fetchCurrentPlanError;
const { data: currentSubscription } = useSWRImmutable(
`/api/tenants/${currentTenantId}/subscription`,
async () =>
cloudApi.get('/api/tenants/:tenantId/subscription', { params: { tenantId: currentTenantId } })
);
useEffect(() => {
if (!currentUsage || !currentPlan || hasClosed) {
return;
}
const { data: currentUsage } = useSWRImmutable(
`/api/tenants/${currentTenantId}/usage`,
async () =>
cloudApi.get('/api/tenants/:tenantId/usage', { params: { tenantId: currentTenantId } })
);
const {
quota: { mauLimit },
} = currentPlan;
const currentPlan =
currentSubscription &&
subscriptionPlans?.find((plan) => plan.id === currentSubscription.planId);
if (mauLimit === null) {
return;
}
if (currentUsage.activeUsers >= mauLimit) {
setIsOpen(true);
}
}, [currentPlan, currentUsage, hasClosed]);
if (isLoadingUsage || isLoadingSubscription || isLoadingCurrentPlan) {
if (!currentPlan || !currentUsage || hasClosed) {
return null;
}
if (!currentUsage || !currentSubscription || !currentPlan) {
const {
quota: { mauLimit },
name: planName,
} = currentPlan;
const isMauExceeded = mauLimit !== null && currentUsage.activeUsers >= mauLimit;
if (!isMauExceeded) {
return null;
}
return (
<ReactModal
isOpen
shouldCloseOnEsc
isOpen={isOpen}
className={modalStyles.content}
overlayClassName={modalStyles.overlay}
onRequestClose={handleCloseModal}
@ -97,7 +94,7 @@ function MauExceededModal() {
<InlineNotification severity="error">
<Trans
components={{
planName: <PlanName name={currentPlan.name} />,
planName: <PlanName name={planName} />,
}}
>
{t('upsell.mau_exceeded_modal.notification')}

View file

@ -1,15 +1,16 @@
import { conditional } from '@silverhand/essentials';
import { useContext, useEffect, useMemo, useState } from 'react';
import { useContext, useMemo, useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import ReactModal from 'react-modal';
import useSWRImmutable from 'swr/immutable';
import { useCloudApi } from '@/cloud/hooks/use-cloud-api';
import { contactEmailLink } from '@/consts';
import { TenantsContext } from '@/contexts/TenantsProvider';
import Button from '@/ds-components/Button';
import FormField from '@/ds-components/FormField';
import InlineNotification from '@/ds-components/InlineNotification';
import ModalLayout from '@/ds-components/ModalLayout';
import useInvoices from '@/hooks/use-invoices';
import useSubscribe from '@/hooks/use-subscribe';
import * as modalStyles from '@/scss/modal.module.scss';
import { getLatestUnpaidInvoice } from '@/utils/subscription';
@ -21,41 +22,33 @@ import * as styles from './index.module.scss';
function PaymentOverdueModal() {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const { currentTenant, currentTenantId } = useContext(TenantsContext);
const { data: invoices, error } = useInvoices(currentTenantId);
const cloudApi = useCloudApi();
const { data: invoicesResponse } = useSWRImmutable(
`/api/tenants/${currentTenantId}/invoices`,
async () =>
cloudApi.get('/api/tenants/:tenantId/invoices', { params: { tenantId: currentTenantId } })
);
const { visitManagePaymentPage } = useSubscribe();
const [isActionLoading, setIsActionLoading] = useState(false);
const isLoadingInvoices = !invoices && !error;
const latestUnpaidInvoice = useMemo(() => {
return conditional(invoices && getLatestUnpaidInvoice(invoices));
}, [invoices]);
const latestUnpaidInvoice = useMemo(
() => conditional(invoicesResponse && getLatestUnpaidInvoice(invoicesResponse.invoices)),
[invoicesResponse]
);
const [hasClosed, setHasClosed] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const handleCloseModal = () => {
setHasClosed(true);
setIsOpen(false);
};
useEffect(() => {
if (isLoadingInvoices || hasClosed) {
return;
}
if (latestUnpaidInvoice) {
setIsOpen(true);
}
}, [hasClosed, isLoadingInvoices, latestUnpaidInvoice]);
if (isLoadingInvoices || !latestUnpaidInvoice || hasClosed) {
if (!invoicesResponse || !latestUnpaidInvoice || hasClosed) {
return null;
}
return (
<ReactModal
isOpen
shouldCloseOnEsc
isOpen={isOpen}
className={modalStyles.content}
overlayClassName={modalStyles.overlay}
onRequestClose={handleCloseModal}