diff --git a/packages/template-retail-react-app/CHANGELOG.md b/packages/template-retail-react-app/CHANGELOG.md index b0c6e67541..afcbab3e98 100644 --- a/packages/template-retail-react-app/CHANGELOG.md +++ b/packages/template-retail-react-app/CHANGELOG.md @@ -1,3 +1,6 @@ +## v2.8.0-dev (Mar 03, 2023) +- Make `mergeBasket` conditional more robust [#1048](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1048) + ## v2.7.0 (Mar 03, 2023) - Add Page Designer ImageTile component [#967](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/967) - Add Page Designer ImageWithText component [#991](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/991) diff --git a/packages/template-retail-react-app/app/commerce-api/hooks/useCustomer.js b/packages/template-retail-react-app/app/commerce-api/hooks/useCustomer.js index fe0cfe54fd..ffd95fef97 100644 --- a/packages/template-retail-react-app/app/commerce-api/hooks/useCustomer.js +++ b/packages/template-retail-react-app/app/commerce-api/hooks/useCustomer.js @@ -10,6 +10,12 @@ import {useCommerceAPI, CustomerContext} from '../contexts' const AuthTypes = Object.freeze({GUEST: 'guest', REGISTERED: 'registered'}) +// This value represents the max age in milliseconds a customer can be before they are +// no longer considered a "new" customer. +// E.g. If a customers creation date is older than 2 seconds it will no longer be considered +// a new customer. +const NEW_CUSTOMER_MAX_AGE = 2 * 1000 // 2 seconds in milliseconds + export default function useCustomer() { const api = useCommerceAPI() const {customer, setCustomer} = useContext(CustomerContext) @@ -39,6 +45,16 @@ export default function useCustomer() { return customer?.authType === AuthTypes.GUEST }, + /** + * Returns if this customer is newly registered. + */ + get isNew() { + if (!customer || customer.authType !== 'registered') return false + const lastLoginTimeStamp = Date.parse(customer.lastLoginTime) + const creationTimeStamp = Date.parse(customer.creationDate) + return lastLoginTimeStamp - creationTimeStamp < NEW_CUSTOMER_MAX_AGE + }, + /** Returns the customer's saved addresses with the 'preferred' address in the first index */ get addresses() { // TODO: This performs array manipulation every time it is accessed; should it be diff --git a/packages/template-retail-react-app/app/commerce-api/hooks/useShopper.js b/packages/template-retail-react-app/app/commerce-api/hooks/useShopper.js index 2bee91a771..7cafb76857 100644 --- a/packages/template-retail-react-app/app/commerce-api/hooks/useShopper.js +++ b/packages/template-retail-react-app/app/commerce-api/hooks/useShopper.js @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import {useEffect} from 'react' +import {useEffect, useRef} from 'react' import useBasket from './useBasket' import useCustomer from './useCustomer' @@ -17,6 +17,7 @@ const useShopper = (opts = {}) => { const {currency} = opts const customer = useCustomer() const basket = useBasket({currency}) + const prevAuthType = useRef() // Create or restore the user session upon mounting useEffect(() => { @@ -58,11 +59,22 @@ const useShopper = (opts = {}) => { } }, [customer.authType, basket.loaded]) - // Call merge basket whenever user type changes from guest to registered + // Call merge basket. useEffect(() => { - if (customer.authType === 'registered') { + // Only call merge when there are items in the guest basket and you are + // a returning customer. + const shouldMerge = + customer.authType === 'registered' && + prevAuthType.current === 'guest' && + !customer.isNew && + basket.itemCount > 0 + + if (shouldMerge) { basket.mergeBasket() } + + // Update the current `authType` value. + prevAuthType.current = customer.authType }, [customer.authType]) useEffect(() => {