diff --git a/packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-contact-info.jsx b/packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-contact-info.jsx index 4620c4ea71..3a76cb4b97 100644 --- a/packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-contact-info.jsx +++ b/packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-contact-info.jsx @@ -225,11 +225,17 @@ const ContactInfo = ({isSocialEnabled = false, idps = [], onRegisteredUserChoseG // Successful OTP verification - user is now logged in const hasBasketItem = basket.productItems?.length > 0 if (hasBasketItem) { - mergeBasket.mutate({ + // Mirror legacy checkout flow header and await completion + await mergeBasket.mutateAsync({ + headers: { + 'Content-Type': 'application/json' + }, parameters: { createDestinationBasket: true } }) + // Make sure UI reflects merged state before proceeding + await currentBasketQuery.refetch() } // Update basket with email after successful OTP verification @@ -267,6 +273,38 @@ const ContactInfo = ({isSocialEnabled = false, idps = [], onRegisteredUserChoseG } } + // Post-auth recovery: if user is already registered (after redirect-based auth), + // attempt a one-time merge to carry over any guest items. + const hasAttemptedRecoveryRef = useRef(false) + useEffect(() => { + const attemptRecovery = async () => { + if (hasAttemptedRecoveryRef.current) return + if (!isRegistered) return + const hasBasketItem = basket?.productItems?.length > 0 + if (!hasBasketItem) { + hasAttemptedRecoveryRef.current = true + return + } + try { + await mergeBasket.mutateAsync({ + headers: { + 'Content-Type': 'application/json' + }, + parameters: { + createDestinationBasket: true + } + }) + await currentBasketQuery.refetch() + } catch (_e) { + // no-op + } finally { + hasAttemptedRecoveryRef.current = true + } + } + attemptRecovery() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isRegistered]) + // Custom form submit handler to prevent default form submission for registered users const handleFormSubmit = async (event) => { event.preventDefault() diff --git a/packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-contact-info.test.js b/packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-contact-info.test.js index 74fed37902..0470e54408 100644 --- a/packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-contact-info.test.js +++ b/packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-contact-info.test.js @@ -22,7 +22,7 @@ const mockAuthHelperFunctions = { } const mockUpdateCustomerForBasket = {mutateAsync: jest.fn()} -const mockMergeBasket = {mutate: jest.fn()} +const mockMergeBasket = {mutate: jest.fn(), mutateAsync: jest.fn()} jest.mock('@salesforce/commerce-sdk-react', () => { const originalModule = jest.requireActual('@salesforce/commerce-sdk-react') @@ -50,7 +50,8 @@ jest.mock('@salesforce/retail-react-app/app/hooks/use-current-basket', () => ({ derivedData: { hasBasket: true, totalItems: 1 - } + }, + refetch: jest.fn() }) }))