@@ -225,11 +225,17 @@ const ContactInfo = ({isSocialEnabled = false, idps = [], onRegisteredUserChoseG
225225 // Successful OTP verification - user is now logged in
226226 const hasBasketItem = basket . productItems ?. length > 0
227227 if ( hasBasketItem ) {
228- mergeBasket . mutate ( {
228+ // Mirror legacy checkout flow header and await completion
229+ await mergeBasket . mutateAsync ( {
230+ headers : {
231+ 'Content-Type' : 'application/json'
232+ } ,
229233 parameters : {
230234 createDestinationBasket : true
231235 }
232236 } )
237+ // Make sure UI reflects merged state before proceeding
238+ await currentBasketQuery . refetch ( )
233239 }
234240
235241 // Update basket with email after successful OTP verification
@@ -267,6 +273,38 @@ const ContactInfo = ({isSocialEnabled = false, idps = [], onRegisteredUserChoseG
267273 }
268274 }
269275
276+ // Post-auth recovery: if user is already registered (after redirect-based auth),
277+ // attempt a one-time merge to carry over any guest items.
278+ const hasAttemptedRecoveryRef = useRef ( false )
279+ useEffect ( ( ) => {
280+ const attemptRecovery = async ( ) => {
281+ if ( hasAttemptedRecoveryRef . current ) return
282+ if ( ! isRegistered ) return
283+ const hasBasketItem = basket ?. productItems ?. length > 0
284+ if ( ! hasBasketItem ) {
285+ hasAttemptedRecoveryRef . current = true
286+ return
287+ }
288+ try {
289+ await mergeBasket . mutateAsync ( {
290+ headers : {
291+ 'Content-Type' : 'application/json'
292+ } ,
293+ parameters : {
294+ createDestinationBasket : true
295+ }
296+ } )
297+ await currentBasketQuery . refetch ( )
298+ } catch ( _e ) {
299+ // no-op
300+ } finally {
301+ hasAttemptedRecoveryRef . current = true
302+ }
303+ }
304+ attemptRecovery ( )
305+ // eslint-disable-next-line react-hooks/exhaustive-deps
306+ } , [ isRegistered ] )
307+
270308 // Custom form submit handler to prevent default form submission for registered users
271309 const handleFormSubmit = async ( event ) => {
272310 event . preventDefault ( )
0 commit comments