mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
refactor(console): sort quota list items (#4246)
This commit is contained in:
parent
0aa00307cb
commit
5a1c9d3a7b
5 changed files with 51 additions and 29 deletions
|
@ -1,7 +1,9 @@
|
|||
import classNames from 'classnames';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { planQuotaItemOrder } from '@/consts/plan-quotas';
|
||||
import { type SubscriptionPlanQuota } from '@/types/subscriptions';
|
||||
import { sortBy } from '@/utils/sort';
|
||||
|
||||
import QuotaItem from './QuotaItem';
|
||||
import * as styles from './index.module.scss';
|
||||
|
@ -16,7 +18,6 @@ type Props = {
|
|||
|
||||
function PlanQuotaList({ quota, featuredQuotaKeys, isDiff, hasIcon, className }: Props) {
|
||||
const items = useMemo(() => {
|
||||
// Todo: @xiaoyijun LOG-6540 order keys
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const entries = Object.entries(quota) as Array<
|
||||
[keyof SubscriptionPlanQuota, SubscriptionPlanQuota[keyof SubscriptionPlanQuota]]
|
||||
|
@ -26,7 +27,11 @@ function PlanQuotaList({ quota, featuredQuotaKeys, isDiff, hasIcon, className }:
|
|||
? entries.filter(([key]) => featuredQuotaKeys.includes(key))
|
||||
: entries;
|
||||
|
||||
return featuredEntries;
|
||||
return featuredEntries
|
||||
.slice()
|
||||
.sort(([preQuotaKey], [nextQuotaKey]) =>
|
||||
sortBy(planQuotaItemOrder)(preQuotaKey, nextQuotaKey)
|
||||
);
|
||||
}, [quota, featuredQuotaKeys]);
|
||||
|
||||
return (
|
||||
|
|
|
@ -149,3 +149,5 @@ export const planTableGroupKeyMap: SubscriptionPlanTableGroupKeyMap = Object.fre
|
|||
[SubscriptionPlanTableGroupKey.hooks]: ['hooksLimit'],
|
||||
[SubscriptionPlanTableGroupKey.support]: ['communitySupportEnabled', 'ticketSupportResponseTime'],
|
||||
}) satisfies SubscriptionPlanTableGroupKeyMap;
|
||||
|
||||
export const planQuotaItemOrder = Object.values(planTableGroupKeyMap).flat();
|
||||
|
|
|
@ -7,6 +7,7 @@ import { type SubscriptionPlanResponse } from '@/cloud/types/router';
|
|||
import { isCloud } from '@/consts/env';
|
||||
import { reservedPlanIdOrder } from '@/consts/subscriptions';
|
||||
import { type SubscriptionPlan } from '@/types/subscriptions';
|
||||
import { sortBy } from '@/utils/sort';
|
||||
import { addSupportQuotaToPlan } from '@/utils/subscription';
|
||||
|
||||
const useSubscriptionPlans = () => {
|
||||
|
@ -26,28 +27,9 @@ const useSubscriptionPlans = () => {
|
|||
return subscriptionPlansResponse
|
||||
.map((plan) => addSupportQuotaToPlan(plan))
|
||||
.slice()
|
||||
.sort(({ id: previousId }, { id: nextId }) => {
|
||||
const previousIndex = reservedPlanIdOrder.indexOf(previousId);
|
||||
const nextIndex = reservedPlanIdOrder.indexOf(nextId);
|
||||
|
||||
if (previousIndex === -1 && nextIndex === -1) {
|
||||
// Note: If both plan ids not present in `reservedPlanIdOrder`, sort them in default order
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (previousIndex === -1) {
|
||||
// Note: If only the previous plan has an id not present in `reservedPlanIdOrder`, move it to the end
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nextIndex === -1) {
|
||||
// Note: If only the next plan has an id not present in `reservedPlanIdOrder`, move it to the end
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Note: Compare them based on the index in the `reservedPlanIdOrder` array
|
||||
return previousIndex - nextIndex;
|
||||
});
|
||||
.sort(({ id: previousId }, { id: nextId }) =>
|
||||
sortBy(reservedPlanIdOrder)(previousId, nextId)
|
||||
);
|
||||
}, [subscriptionPlansResponse]);
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import { conditional } from '@silverhand/essentials';
|
||||
import { useMemo } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
import ContactUsPhraseLink from '@/components/ContactUsPhraseLink';
|
||||
import PlanName from '@/components/PlanName';
|
||||
import { planQuotaItemOrder } from '@/consts/plan-quotas';
|
||||
import {
|
||||
quotaItemLimitedPhrasesMap,
|
||||
quotaItemNotEligiblePhrasesMap,
|
||||
} from '@/consts/quota-item-phrases';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
import { type SubscriptionPlan, type SubscriptionPlanQuota } from '@/types/subscriptions';
|
||||
import { sortBy } from '@/utils/sort';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
|
@ -30,10 +33,17 @@ function NotEligibleSwitchPlanModalContent({ targetPlan, isDowngrade = false }:
|
|||
|
||||
const { name, quota } = targetPlan;
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const entries = Object.entries(quota) as Array<
|
||||
[keyof SubscriptionPlanQuota, SubscriptionPlanQuota[keyof SubscriptionPlanQuota]]
|
||||
>;
|
||||
const orderedEntries = useMemo(() => {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const entries = Object.entries(quota) as Array<
|
||||
[keyof SubscriptionPlanQuota, SubscriptionPlanQuota[keyof SubscriptionPlanQuota]]
|
||||
>;
|
||||
return entries
|
||||
.slice()
|
||||
.sort(([preQuotaKey], [nextQuotaKey]) =>
|
||||
sortBy(planQuotaItemOrder)(preQuotaKey, nextQuotaKey)
|
||||
);
|
||||
}, [quota]);
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
|
@ -47,7 +57,7 @@ function NotEligibleSwitchPlanModalContent({ targetPlan, isDowngrade = false }:
|
|||
</Trans>
|
||||
</div>
|
||||
<ul className={styles.list}>
|
||||
{entries.map(([quotaKey, quotaValue]) => {
|
||||
{orderedEntries.map(([quotaKey, quotaValue]) => {
|
||||
if (
|
||||
excludedQuotaKeys.has(quotaKey) ||
|
||||
quotaValue === null || // Unlimited items
|
||||
|
|
23
packages/console/src/utils/sort.ts
Normal file
23
packages/console/src/utils/sort.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
export const sortBy = (order: string[]) => {
|
||||
return (previous: string, next: string) => {
|
||||
const preIndex = order.indexOf(previous);
|
||||
const nextIndex = order.indexOf(next);
|
||||
// Note: If both plan ids not present in the order array, sort them in default order
|
||||
if (preIndex === -1 && nextIndex === -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Note: If only the previous item is not present in the order array, move it to the end
|
||||
if (preIndex === -1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Note: If only the next item is not present in the order array, keep it in the end
|
||||
if (nextIndex === -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Note: Compare them based on the index in the order array
|
||||
return preIndex - nextIndex;
|
||||
};
|
||||
};
|
Loading…
Reference in a new issue