diff --git a/.changeset/mighty-worms-watch.md b/.changeset/mighty-worms-watch.md new file mode 100644 index 00000000000..b5118a50901 --- /dev/null +++ b/.changeset/mighty-worms-watch.md @@ -0,0 +1,5 @@ +--- +"@clerk/clerk-js": patch +--- + +Show a localized message for all errors returned from the backend if the user tries to perform an invalid plan change. diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json index 72395d72abe..47b4a4fdd85 100644 --- a/packages/clerk-js/bundlewatch.config.json +++ b/packages/clerk-js/bundlewatch.config.json @@ -21,7 +21,7 @@ { "path": "./dist/waitlist*.js", "maxSize": "1.3KB" }, { "path": "./dist/keylessPrompt*.js", "maxSize": "6.5KB" }, { "path": "./dist/pricingTable*.js", "maxSize": "4.02KB" }, - { "path": "./dist/checkout*.js", "maxSize": "5.2KB" }, + { "path": "./dist/checkout*.js", "maxSize": "5.3KB" }, { "path": "./dist/paymentSources*.js", "maxSize": "8.9KB" }, { "path": "./dist/up-billing-page*.js", "maxSize": "2.4KB" }, { "path": "./dist/op-billing-page*.js", "maxSize": "2.4KB" }, diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx index 3f888afc149..428b6faff75 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx @@ -1,7 +1,11 @@ -import type { __experimental_CheckoutProps, __experimental_CommerceCheckoutResource } from '@clerk/types'; +import type { + __experimental_CheckoutProps, + __experimental_CommerceCheckoutResource, + ClerkAPIError, +} from '@clerk/types'; import { useEffect } from 'react'; -import { Alert, Box, localizationKeys, Spinner } from '../../customizables'; +import { Alert, Box, Flex, localizationKeys, Spinner, useLocalizations } from '../../customizables'; import { Drawer, useDrawerContext } from '../../elements'; import { useCheckout } from '../../hooks'; import { EmailForm } from '../UserProfile/EmailForm'; @@ -9,15 +13,18 @@ import { CheckoutComplete } from './CheckoutComplete'; import { CheckoutForm } from './CheckoutForm'; export const CheckoutPage = (props: __experimental_CheckoutProps) => { + const { translateError } = useLocalizations(); const { planId, planPeriod, subscriberType, onSubscriptionComplete } = props; const { setIsOpen, isOpen } = useDrawerContext(); - const { checkout, isLoading, invalidate, revalidate, updateCheckout, isMissingPayerEmail } = useCheckout({ + const { checkout, isLoading, invalidate, revalidate, updateCheckout, errors } = useCheckout({ planId, planPeriod, subscriberType, }); + const isMissingPayerEmail = !!errors?.some((e: ClerkAPIError) => e.code === 'missing_payer_email'); + const onCheckoutComplete = (newCheckout: __experimental_CommerceCheckoutResource) => { invalidate(); // invalidate the initial checkout on complete updateCheckout(newCheckout); @@ -74,16 +81,20 @@ export const CheckoutPage = (props: __experimental_CheckoutProps) => { } return ( - <> - {/* TODO(@COMMERCE): needs localization */} - + ({ + height: '100%', + padding: t.space.$4, + fontSize: t.fontSizes.$md, + })} > - There was a problem, please try again later. - - + + {errors ? translateError(errors[0]) : 'There was a problem, please try again later.'} + + + ); }; diff --git a/packages/clerk-js/src/ui/hooks/useCheckout.ts b/packages/clerk-js/src/ui/hooks/useCheckout.ts index 68e05ef6d2f..5dac8c76cb9 100644 --- a/packages/clerk-js/src/ui/hooks/useCheckout.ts +++ b/packages/clerk-js/src/ui/hooks/useCheckout.ts @@ -1,9 +1,6 @@ +import type { ClerkAPIResponseError } from '@clerk/shared/error'; import { useClerk, useOrganization, useUser } from '@clerk/shared/react'; -import type { - __experimental_CheckoutProps, - __experimental_CommerceCheckoutResource, - ClerkAPIError, -} from '@clerk/types'; +import type { __experimental_CheckoutProps, __experimental_CommerceCheckoutResource } from '@clerk/types'; import { useCallback, useEffect, useState } from 'react'; import { useFetch } from './useFetch'; @@ -20,7 +17,7 @@ export const useCheckout = (props: __experimental_CheckoutProps) => { isLoading, invalidate, revalidate, - error, + error: _error, } = useFetch( __experimental_commerce?.__experimental_billing.startCheckout, { @@ -32,6 +29,8 @@ export const useCheckout = (props: __experimental_CheckoutProps) => { `commerce-checkout-${user?.id}`, ); + const error = _error as ClerkAPIResponseError | undefined; + const updateCheckout = useCallback((newCheckout: __experimental_CommerceCheckoutResource) => { setCurrentCheckout(newCheckout); }, []); @@ -48,6 +47,6 @@ export const useCheckout = (props: __experimental_CheckoutProps) => { isLoading, invalidate, revalidate, - isMissingPayerEmail: error?.errors.some((e: ClerkAPIError) => e.code === 'missing_payer_email'), + errors: error?.errors, }; };