diff --git a/packages/template-retail-react-app/CHANGELOG.md b/packages/template-retail-react-app/CHANGELOG.md index a03918a245..c2e439ed81 100644 --- a/packages/template-retail-react-app/CHANGELOG.md +++ b/packages/template-retail-react-app/CHANGELOG.md @@ -9,6 +9,8 @@ - Enhanced the shopping assistant that integrates Salesforce Embedded Messaging Service with PWA Kit applications, adding comprehensive context support, localization capabilities, and improved user experience features. [#3259](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3259) - Removed domainUrl, locale, basetId properties as part off the ShopperAgent during initialization. [#3259](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3259) - Only show option to deliver to multiple addresses if there are multiple items in the basket. [#3336](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3336) +- When registering a guest user on the confirmation page only save the delivery addresses to the new account +[#3412](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3412) - Added support for Choice of Bonus Products feature. Users can now select from available bonus products when they qualify for the associated promotion. The bonus product selection flow can be entered from either the "Item Added to Cart" modal (when adding the qualifying product to the cart) or from the cart page. [#3292] (https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3292) - Add @h4ad/serverless-adapter to jest config [#3325](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3325) - Fix bug where pick up items were displaying delivery stock levels instead of in store stock levels [#3401](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3401) diff --git a/packages/template-retail-react-app/app/pages/checkout/confirmation.jsx b/packages/template-retail-react-app/app/pages/checkout/confirmation.jsx index 6230aeebfb..ff4b2c35d0 100644 --- a/packages/template-retail-react-app/app/pages/checkout/confirmation.jsx +++ b/packages/template-retail-react-app/app/pages/checkout/confirmation.jsx @@ -31,6 +31,9 @@ import { useShopperCustomersMutation } from '@salesforce/commerce-sdk-react' import {getCreditCardIcon} from '@salesforce/retail-react-app/app/utils/cc-utils' +import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config' +import {isPickupShipment} from '@salesforce/retail-react-app/app/utils/shipment-utils' +import {areAddressesEqual} from '@salesforce/retail-react-app/app/utils/address-utils' // Components import Link from '@salesforce/retail-react-app/app/components/link' @@ -51,7 +54,10 @@ import {useCurrentCustomer} from '@salesforce/retail-react-app/app/hooks/use-cur import {useCurrency} from '@salesforce/retail-react-app/app/hooks' // Constants -import {API_ERROR_MESSAGE} from '@salesforce/retail-react-app/app/constants' +import { + API_ERROR_MESSAGE, + STORE_LOCATOR_IS_ENABLED +} from '@salesforce/retail-react-app/app/constants' const onClient = typeof window !== 'undefined' @@ -96,19 +102,42 @@ const CheckoutConfirmation = () => { const CardIcon = getCreditCardIcon(order.paymentInstruments[0].paymentCard?.cardType) const submitForm = async (data) => { + // Save the unique delivery addresses, excluding pickup shipments const saveShippingAddress = async (customerId) => { try { - const shippingAddress = order.shipments[0].shippingAddress - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const {id, ...shippingAddressWithoutId} = shippingAddress - const bodyShippingAddress = { - addressId: nanoid(), - ...shippingAddressWithoutId - } - await createCustomerAddress.mutateAsync({ - body: bodyShippingAddress, - parameters: {customerId: customerId} + const storeLocatorEnabled = + getConfig()?.app?.storeLocatorEnabled ?? STORE_LOCATOR_IS_ENABLED + + const deliveryShipments = (order.shipments || []).filter((shipment) => { + if (!shipment.shippingAddress) return false + if (storeLocatorEnabled && isPickupShipment(shipment)) return false + return true }) + + const uniqueAddresses = [] + deliveryShipments.forEach((shipment) => { + const address = shipment.shippingAddress + const isDuplicate = uniqueAddresses.some((existingAddr) => + areAddressesEqual(existingAddr, address) + ) + if (!isDuplicate) { + uniqueAddresses.push(address) + } + }) + + for (let i = 0; i < uniqueAddresses.length; i++) { + const shippingAddress = uniqueAddresses[i] + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const {id, _type, ...shippingAddressWithoutId} = shippingAddress + const bodyShippingAddress = { + addressId: nanoid(), + ...shippingAddressWithoutId + } + await createCustomerAddress.mutateAsync({ + body: bodyShippingAddress, + parameters: {customerId: customerId} + }) + } } catch (error) { // Fail silently } diff --git a/packages/template-retail-react-app/app/pages/checkout/confirmation.test.js b/packages/template-retail-react-app/app/pages/checkout/confirmation.test.js index 1181af13a3..a1e5579f36 100644 --- a/packages/template-retail-react-app/app/pages/checkout/confirmation.test.js +++ b/packages/template-retail-react-app/app/pages/checkout/confirmation.test.js @@ -290,4 +290,87 @@ describe('Account form', () => { expect(window.location.pathname).toBe('/uk/en-GB/account') }) }) + + test('save delivery addresses but does not save pickup addresses when store locator is enabled', async () => { + const savedAddresses = [] + const mockOrderWithPickup = { + ...mockOrder, + shipments: [ + { + ...mockOrder.shipments[0], + shipmentId: 'delivery-shipment', + shippingAddress: { + address1: '456 Delivery St', + city: 'Vancouver', + countryCode: 'CA', + firstName: 'John', + lastName: 'Doe', + phone: '(604) 555-1234', + postalCode: 'V6B 1A1', + stateCode: 'BC' + }, + shippingMethod: { + id: 'standard-delivery', + name: 'Standard Delivery' + } + }, + { + shipmentId: 'pickup-shipment', + shippingAddress: { + address1: '789 Store Location Ave', + city: 'Burnaby', + countryCode: 'CA', + firstName: 'Store', + lastName: 'Pickup', + phone: '(604) 555-5678', + postalCode: 'V5H 2E2', + stateCode: 'BC' + }, + shippingMethod: { + id: '005', + name: 'Store Pickup', + c_storePickupEnabled: true + }, + c_fromStoreId: 'store-123' + } + ] + } + + global.server.use( + rest.get('*/orders/:orderId', (req, res, ctx) => { + return res(ctx.delay(0), ctx.json(mockOrderWithPickup)) + }), + rest.post('*/customers', (_, res, ctx) => { + return res(ctx.status(200), ctx.json(mockCustomer)) + }), + rest.post('*/customers/:customerId/addresses', (req, res, ctx) => { + savedAddresses.push(req.body) + return res(ctx.status(200)) + }) + ) + + const {user} = renderWithProviders(, { + wrapperProps: {isGuest: true} + }) + + const createAccountButton = await screen.findByRole('button', {name: /create account/i}) + const password = screen.getByLabelText('Password') + await user.type(password, 'P4ssword!') + await user.click(createAccountButton) + + await waitFor(() => { + expect(window.location.pathname).toBe('/uk/en-GB/account') + }) + + // Verify that only one address was saved (the delivery address, not the pickup address) + expect(savedAddresses).toHaveLength(1) + expect(savedAddresses[0].address1).toBe('456 Delivery St') + expect(savedAddresses[0].city).toBe('Vancouver') + + // Verify the pickup address was NOT saved + const hasPickupAddress = savedAddresses.some( + (addr) => addr.address1 === '789 Store Location Ave' + ) + expect(hasPickupAddress).toBe(false) + }) })