diff --git a/.changeset/orange-doors-notice.md b/.changeset/orange-doors-notice.md new file mode 100644 index 00000000000..729f4fc37a6 --- /dev/null +++ b/.changeset/orange-doors-notice.md @@ -0,0 +1,7 @@ +--- +'@clerk/localizations': minor +'@clerk/clerk-js': patch +'@clerk/types': minor +--- + +Improve invalid plan change callout for monthly-only plans diff --git a/integration/tests/pricing-table.test.ts b/integration/tests/pricing-table.test.ts index bf804a71ff6..00a6584e791 100644 --- a/integration/tests/pricing-table.test.ts +++ b/integration/tests/pricing-table.test.ts @@ -351,7 +351,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl page .locator('.cl-checkout-root') .getByText( - 'You cannot subscribe to this plan by paying monthly. To subscribe to this plan, you need to choose to pay annually', + 'You cannot subscribe to this plan by paying monthly. To subscribe to this plan, you need to choose to pay annually.', ), ).toBeVisible(); diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json index 8e2e4fa4c06..cc0a673db41 100644 --- a/packages/clerk-js/bundlewatch.config.json +++ b/packages/clerk-js/bundlewatch.config.json @@ -23,7 +23,7 @@ { "path": "./dist/waitlist*.js", "maxSize": "1.5KB" }, { "path": "./dist/keylessPrompt*.js", "maxSize": "6.5KB" }, { "path": "./dist/pricingTable*.js", "maxSize": "4.02KB" }, - { "path": "./dist/checkout*.js", "maxSize": "8.4KB" }, + { "path": "./dist/checkout*.js", "maxSize": "8.45KB" }, { "path": "./dist/up-billing-page*.js", "maxSize": "3.0KB" }, { "path": "./dist/op-billing-page*.js", "maxSize": "3.0KB" }, { "path": "./dist/up-plans-page*.js", "maxSize": "1.0KB" }, diff --git a/packages/clerk-js/src/ui/components/Checkout/parts.tsx b/packages/clerk-js/src/ui/components/Checkout/parts.tsx index cd46f31f895..69ed898f9c5 100644 --- a/packages/clerk-js/src/ui/components/Checkout/parts.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/parts.tsx @@ -48,6 +48,11 @@ export const InvalidPlanScreen = () => { return _error?.meta?.plan; }, [error]); + const isPlanUpgradePossible = useMemo(() => { + const _error = error?.errors.find(e => e.code === 'invalid_plan_change'); + return _error?.meta?.isPlanUpgradePossible || false; + }, [error]); + if (!planFromError) { return null; } @@ -85,7 +90,11 @@ export const InvalidPlanScreen = () => { diff --git a/packages/localizations/src/en-US.ts b/packages/localizations/src/en-US.ts index ff8a3e46624..a25466a14df 100644 --- a/packages/localizations/src/en-US.ts +++ b/packages/localizations/src/en-US.ts @@ -69,6 +69,8 @@ export const enUS: LocalizationResource = { cancelSubscriptionTitle: 'Cancel {{plan}} Subscription?', cannotSubscribeMonthly: 'You cannot subscribe to this plan by paying monthly. To subscribe to this plan, you need to choose to pay annually.', + cannotSubscribeUnrecoverable: + 'You cannot subscribe to this plan. Your existing subscription is more expensive than this plan.', checkout: { description__paymentSuccessful: 'Your payment was successful.', description__subscriptionSuccessful: 'Your new subscription is all set.', diff --git a/packages/shared/src/error.ts b/packages/shared/src/error.ts index dd6c4473103..90f8a4c4807 100644 --- a/packages/shared/src/error.ts +++ b/packages/shared/src/error.ts @@ -167,6 +167,7 @@ export function parseError(error: ClerkAPIErrorJSON): ClerkAPIError { identifiers: error?.meta?.identifiers, zxcvbn: error?.meta?.zxcvbn, plan: error?.meta?.plan, + isPlanUpgradePossible: error?.meta?.is_plan_upgrade_possible, }, }; } @@ -188,6 +189,7 @@ export function errorToJSON(error: ClerkAPIError | null): ClerkAPIErrorJSON { identifiers: error?.meta?.identifiers, zxcvbn: error?.meta?.zxcvbn, plan: error?.meta?.plan, + is_plan_upgrade_possible: error?.meta?.isPlanUpgradePossible, }, }; } diff --git a/packages/types/src/api.ts b/packages/types/src/api.ts index 5e6e0e840df..bd1c3cfc3c7 100644 --- a/packages/types/src/api.ts +++ b/packages/types/src/api.ts @@ -36,6 +36,7 @@ export interface ClerkAPIError { id: string; name: string; }; + isPlanUpgradePossible?: boolean; }; } diff --git a/packages/types/src/json.ts b/packages/types/src/json.ts index ec37cef7cf0..68ec4108096 100644 --- a/packages/types/src/json.ts +++ b/packages/types/src/json.ts @@ -358,6 +358,7 @@ export interface ClerkAPIErrorJSON { id: string; name: string; }; + is_plan_upgrade_possible?: boolean; }; } diff --git a/packages/types/src/localization.ts b/packages/types/src/localization.ts index 3d3cf7c701d..4ff866aa834 100644 --- a/packages/types/src/localization.ts +++ b/packages/types/src/localization.ts @@ -214,6 +214,7 @@ export type __internal_LocalizationResource = { monthly: LocalizationValue; annually: LocalizationValue; cannotSubscribeMonthly: LocalizationValue; + cannotSubscribeUnrecoverable: LocalizationValue; pricingTable: { billingCycle: LocalizationValue; included: LocalizationValue;