diff --git a/packages/console/src/components/ApplicationCreation/CreateForm/index.tsx b/packages/console/src/components/ApplicationCreation/CreateForm/index.tsx
index bb6418b12..35ed12a7d 100644
--- a/packages/console/src/components/ApplicationCreation/CreateForm/index.tsx
+++ b/packages/console/src/components/ApplicationCreation/CreateForm/index.tsx
@@ -1,6 +1,6 @@
import { type AdminConsoleKey } from '@logto/phrases';
import type { Application } from '@logto/schemas';
-import { ApplicationType, ReservedPlanId } from '@logto/schemas';
+import { ApplicationType } from '@logto/schemas';
import { conditional } from '@silverhand/essentials';
import { type ReactElement, useContext, useMemo } from 'react';
import { useController, useForm } from 'react-hook-form';
@@ -11,6 +11,7 @@ import { useSWRConfig } from 'swr';
import { GtagConversionId, reportConversion } from '@/components/Conversion/utils';
import { isDevFeaturesEnabled } from '@/consts/env';
+import { latestProPlanId } from '@/consts/subscriptions';
import { SubscriptionDataContext } from '@/contexts/SubscriptionDataProvider';
import DynamicT from '@/ds-components/DynamicT';
import FormField from '@/ds-components/FormField';
@@ -142,10 +143,7 @@ function CreateForm({
title="applications.create"
subtitle={subtitleElement}
paywall={conditional(
- isPaidTenant &&
- watch('type') === ApplicationType.MachineToMachine &&
- planId !== ReservedPlanId.Pro &&
- ReservedPlanId.Pro
+ !isPaidTenant && watch('type') === ApplicationType.MachineToMachine && latestProPlanId
)}
hasAddOnTag={
isPaidTenant &&
diff --git a/packages/console/src/components/CreateTenantModal/SelectTenantPlanModal/SkuCardItem/index.tsx b/packages/console/src/components/CreateTenantModal/SelectTenantPlanModal/SkuCardItem/index.tsx
index c59e4a044..040e22790 100644
--- a/packages/console/src/components/CreateTenantModal/SelectTenantPlanModal/SkuCardItem/index.tsx
+++ b/packages/console/src/components/CreateTenantModal/SelectTenantPlanModal/SkuCardItem/index.tsx
@@ -14,6 +14,7 @@ import DangerousRaw from '@/ds-components/DangerousRaw';
import DynamicT from '@/ds-components/DynamicT';
import FlipOnRtl from '@/ds-components/FlipOnRtl';
import TextLink from '@/ds-components/TextLink';
+import { isProPlan } from '@/utils/subscription';
import FeaturedSkuContent from './FeaturedSkuContent';
import styles from './index.module.scss';
@@ -92,9 +93,7 @@ function SkuCardItem({ sku, onSelect, buttonProps }: Props) {
disabled={(isFreeSku && isFreeTenantExceeded) || buttonProps?.disabled}
/>
- {skuId === ReservedPlanId.Pro && (
-
{t('most_popular')}
- )}
+ {isProPlan(skuId) &&
{t('most_popular')}
}
);
}
diff --git a/packages/console/src/components/FeatureTag/index.tsx b/packages/console/src/components/FeatureTag/index.tsx
index 2a6947d48..f1f5f835c 100644
--- a/packages/console/src/components/FeatureTag/index.tsx
+++ b/packages/console/src/components/FeatureTag/index.tsx
@@ -5,11 +5,29 @@ import { useContext } from 'react';
import { isCloud } from '@/consts/env';
import { SubscriptionDataContext } from '@/contexts/SubscriptionDataProvider';
import { TenantsContext } from '@/contexts/TenantsProvider';
+import { isProPlan } from '@/utils/subscription';
import styles from './index.module.scss';
export { default as BetaTag } from './BetaTag';
+/**
+ * The display tag mapping for each ReservedPlanId.
+ */
+const planIdTagMap: Record = {
+ [ReservedPlanId.Free]: 'free',
+ [ReservedPlanId.Pro]: 'pro',
+ [ReservedPlanId.Pro202411]: 'pro',
+ [ReservedPlanId.Development]: 'dev',
+ [ReservedPlanId.Admin]: 'admin',
+};
+
+/**
+ * The minimum plan required to use the feature.
+ * Currently we only have pro plan paywall.
+ */
+export type PaywallPlanId = Extract;
+
export type Props = {
/**
* Whether the tag should be visible. It should be `true` if the tenant's subscription
@@ -17,8 +35,12 @@ export type Props = {
* tenants.
*/
readonly isVisible: boolean;
- /** The minimum plan required to use the feature. */
- readonly plan: Exclude;
+ /**
+ * The minimum plan required to use the feature.
+ * Currently we only have pro plan paywall.
+ * Set the default value to the latest pro plan id we are using.
+ */
+ readonly plan: PaywallPlanId;
readonly className?: string;
};
@@ -61,7 +83,7 @@ function FeatureTag(props: Props) {
return null;
}
- return
{plan}
;
+ return
{planIdTagMap[plan]}
;
}
export default FeatureTag;
@@ -89,7 +111,7 @@ export function CombinedAddOnAndFeatureTag(props: CombinedAddOnAndFeatureTagProp
}
// Show the "Add-on" tag for Pro plan.
- if (hasAddOnTag && isCloud && planId === ReservedPlanId.Pro) {
+ if (hasAddOnTag && isCloud && isProPlan(planId)) {
return (
Add-on
);
diff --git a/packages/console/src/components/Guide/GuideCard/index.tsx b/packages/console/src/components/Guide/GuideCard/index.tsx
index 22e491712..e4a8a0945 100644
--- a/packages/console/src/components/Guide/GuideCard/index.tsx
+++ b/packages/console/src/components/Guide/GuideCard/index.tsx
@@ -1,9 +1,10 @@
-import { ReservedPlanId, Theme } from '@logto/schemas';
+import { Theme } from '@logto/schemas';
import classNames from 'classnames';
import { Suspense, useCallback } from 'react';
import { type Guide, type GuideMetadata } from '@/assets/docs/guides/types';
import FeatureTag, { BetaTag } from '@/components/FeatureTag';
+import { latestProPlanId } from '@/consts/subscriptions';
import Button from '@/ds-components/Button';
import useTheme from '@/hooks/use-theme';
import { onKeyDownHandler } from '@/utils/a11y';
@@ -61,7 +62,7 @@ function GuideCard({ data, onClick, hasBorder, hasButton, hasPaywall, isBeta }: