diff --git a/packages/extension-chakra-storefront/jest.config.js b/packages/extension-chakra-storefront/jest.config.js index 5df625174b..2aa45b16a7 100644 --- a/packages/extension-chakra-storefront/jest.config.js +++ b/packages/extension-chakra-storefront/jest.config.js @@ -60,6 +60,7 @@ module.exports = { '/src/pages/checkout/partials/contact-info.test.js', '/src/pages/checkout/partials/login-state.test.js', '/src/utils/responsive-image.test.js', + '/src/hooks/use-errors.test.js', '/src/hooks/use-toast.test.js', '/src/pages/product-detail/metadata.test.js', '/src/pages/product-list/metadata.test.js', diff --git a/packages/extension-chakra-storefront/src/components/product-view/index.jsx b/packages/extension-chakra-storefront/src/components/product-view/index.jsx index d2cd2afc16..512078238b 100644 --- a/packages/extension-chakra-storefront/src/components/product-view/index.jsx +++ b/packages/extension-chakra-storefront/src/components/product-view/index.jsx @@ -23,8 +23,7 @@ import withRegistration from '../../components/with-registration' import {Skeleton as ImageGallerySkeleton} from '../../components/image-gallery' import {HideOnDesktop, HideOnMobile} from '../../components/responsive' import QuantityPicker from '../../components/quantity-picker' -import useToast from '../../hooks/use-toast' -import {API_ERROR_MESSAGE} from '../../constants' +import {useErrorHandler} from '../../hooks/use-errors' import DisplayPrice from '../../components/display-price' import Swatch from '../../components/swatch-group/swatch' import SwatchGroup from '../../components/swatch-group' @@ -114,7 +113,7 @@ const ProductView = forwardRef( ref ) => { const {currency: activeCurrency} = useCurrency() - const toast = useToast() + const showError = useErrorHandler() const intl = useIntl() const location = useLocation() const { @@ -194,10 +193,10 @@ const ProductView = forwardRef( const {scrollErrorIntoView = true} = opts // Validate that all attributes are selected before proceeding. const hasValidSelection = validateOrderability(variant, quantity, stockLevel) - const showError = !isProductASet && !isProductABundle && !hasValidSelection - const scrollToError = showError && scrollErrorIntoView + const hasError = !isProductASet && !isProductABundle && !hasValidSelection + const scrollToError = hasError && scrollErrorIntoView - toggleShowOptionsMessage(showError) + toggleShowOptionsMessage(hasError) if (scrollToError) { errorContainerRef.current.scrollIntoView({ @@ -242,13 +241,6 @@ const ProductView = forwardRef( }) } - const showError = () => { - toast({ - title: intl.formatMessage(API_ERROR_MESSAGE), - type: 'error' - }) - } - const handleCartItem = async () => { const hasValidSelection = validateAndShowError() diff --git a/packages/extension-chakra-storefront/src/pages/cart/utils/cart-utils.js b/packages/extension-chakra-storefront/src/hooks/use-errors.js similarity index 74% rename from packages/extension-chakra-storefront/src/pages/cart/utils/cart-utils.js rename to packages/extension-chakra-storefront/src/hooks/use-errors.js index 259322b484..8cbac31dbc 100644 --- a/packages/extension-chakra-storefront/src/pages/cart/utils/cart-utils.js +++ b/packages/extension-chakra-storefront/src/hooks/use-errors.js @@ -5,14 +5,14 @@ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ import {useIntl} from 'react-intl' -import useToast from '../../../hooks/use-toast' -import {API_ERROR_MESSAGE} from '../../../constants' +import useToast from './use-toast' +import {API_ERROR_MESSAGE} from '../constants' /** - * Custom hook for cart error handling + * Custom hook for error handling * @returns {Function} showError function */ -export const useCartErrorHandler = () => { +export const useErrorHandler = () => { const {formatMessage} = useIntl() const toast = useToast() diff --git a/packages/extension-chakra-storefront/src/pages/cart/utils/cart-utils.test.js b/packages/extension-chakra-storefront/src/hooks/use-errors.test.js similarity index 84% rename from packages/extension-chakra-storefront/src/pages/cart/utils/cart-utils.test.js rename to packages/extension-chakra-storefront/src/hooks/use-errors.test.js index 217022e61c..5cc8853f41 100644 --- a/packages/extension-chakra-storefront/src/pages/cart/utils/cart-utils.test.js +++ b/packages/extension-chakra-storefront/src/hooks/use-errors.test.js @@ -7,18 +7,18 @@ import React from 'react' import {renderHook} from '@testing-library/react' import {IntlProvider} from 'react-intl' -import {useCartErrorHandler} from './cart-utils' +import {useErrorHandler} from './use-errors' import PropTypes from 'prop-types' // Mock the toast hook const mockToast = jest.fn() -jest.mock('../../../hooks/use-toast', () => ({ +jest.mock('./use-toast', () => ({ __esModule: true, default: () => mockToast })) // Mock the constants -jest.mock('../../../constants', () => ({ +jest.mock('../constants', () => ({ API_ERROR_MESSAGE: { id: 'api.error.message', defaultMessage: 'Something went wrong. Please try again.' @@ -37,13 +37,13 @@ const TestWrapper = ({children}) => { ) } -describe('useCartErrorHandler', () => { +describe('useErrorHandler', () => { beforeEach(() => { mockToast.mockClear() }) it('returns a showError function', () => { - const {result} = renderHook(() => useCartErrorHandler(), { + const {result} = renderHook(() => useErrorHandler(), { wrapper: TestWrapper }) @@ -51,7 +51,7 @@ describe('useCartErrorHandler', () => { }) it('calls toast with correct parameters when showError is invoked', () => { - const {result} = renderHook(() => useCartErrorHandler(), { + const {result} = renderHook(() => useErrorHandler(), { wrapper: TestWrapper }) diff --git a/packages/extension-chakra-storefront/src/pages/account/addresses.jsx b/packages/extension-chakra-storefront/src/pages/account/addresses.jsx index c1ea813e95..6c157421e4 100644 --- a/packages/extension-chakra-storefront/src/pages/account/addresses.jsx +++ b/packages/extension-chakra-storefront/src/pages/account/addresses.jsx @@ -34,7 +34,7 @@ import PageActionPlaceHolder from '../../components/page-action-placeholder' import {useCurrentCustomer} from '../../hooks/use-current-customer' import {useShopperCustomersMutation} from '@salesforce/commerce-sdk-react' import {nanoid} from 'nanoid' -import {API_ERROR_MESSAGE} from '../../constants' +import {useErrorHandler} from '../../hooks/use-errors' const DEFAULT_SKELETON_COUNT = 3 @@ -147,6 +147,7 @@ const AccountAddresses = () => { const [selectedAddressId, setSelectedAddressId] = useState(false) const toast = useToast() const form = useForm() + const showError = useErrorHandler() const headingRef = useRef() useEffect(() => { @@ -165,12 +166,6 @@ const AccountAddresses = () => { }, [addresses]) const hasAddresses = addresses?.length > 0 - const showError = () => { - toast({ - title: formatMessage(API_ERROR_MESSAGE), - type: 'error' - }) - } const submitForm = async (address) => { try { let data diff --git a/packages/extension-chakra-storefront/src/pages/cart/index.jsx b/packages/extension-chakra-storefront/src/pages/cart/index.jsx index edccda3e7e..5698266c78 100644 --- a/packages/extension-chakra-storefront/src/pages/cart/index.jsx +++ b/packages/extension-chakra-storefront/src/pages/cart/index.jsx @@ -14,7 +14,7 @@ import {useCartOperations} from '../../hooks/cart/use-cart-operations' import {useCartWishlist} from '../../hooks/cart/use-cart-wishlist' import {useCartGiftItems} from '../../hooks/cart/use-cart-gift-items' import {useCartDefaultShipping} from '../../hooks/cart/use-cart-default-shipping' -import {useCartErrorHandler} from './utils/cart-utils' +import {useErrorHandler} from '../../hooks/use-errors' // Cart Components import CartTitle from './partials/cart-title' @@ -31,7 +31,7 @@ const Cart = () => { const {isRegistered} = customer || {} // Error handling - const showError = useCartErrorHandler() + const showError = useErrorHandler() // Product data and processing const {isProductsPending, productsByItemId} = useCartProducts(basket) diff --git a/packages/extension-chakra-storefront/src/pages/checkout/partials/payment.jsx b/packages/extension-chakra-storefront/src/pages/checkout/partials/payment.jsx index efb0c9d011..f9859653af 100644 --- a/packages/extension-chakra-storefront/src/pages/checkout/partials/payment.jsx +++ b/packages/extension-chakra-storefront/src/pages/checkout/partials/payment.jsx @@ -9,7 +9,6 @@ import PropTypes from 'prop-types' import {defineMessage, FormattedMessage, useIntl} from 'react-intl' import {Box, Button, Checkbox, Container, Heading, Stack, Text, Separator} from '@chakra-ui/react' import {useForm} from 'react-hook-form' -import useToast from '../../../hooks/use-toast' import {useShopperBasketsMutation} from '@salesforce/commerce-sdk-react' import {useCurrentBasket} from '../../../hooks/use-current-basket' import {useCheckout} from '../../../pages/checkout/util/checkout-context' @@ -23,7 +22,7 @@ import PaymentForm from '../../../pages/checkout/partials/payment-form' import ShippingAddressSelection from '../../../pages/checkout/partials/shipping-address-selection' import AddressDisplay from '../../../components/address-display' import {PromoCode, usePromoCode} from '../../../components/promo-code' -import {API_ERROR_MESSAGE} from '../../../constants' +import {useErrorHandler} from '../../../hooks/use-errors' const Payment = () => { const {formatMessage} = useIntl() @@ -42,13 +41,7 @@ const Payment = () => { const {mutateAsync: removePaymentInstrumentFromBasket} = useShopperBasketsMutation( 'removePaymentInstrumentFromBasket' ) - const toast = useToast() - const showError = () => { - toast({ - title: formatMessage(API_ERROR_MESSAGE), - type: 'error' - }) - } + const showError = useErrorHandler() const {step, STEPS, goToStep, goToNextStep} = useCheckout() diff --git a/packages/extension-chakra-storefront/src/pages/product-detail/use-product-detail-data.js b/packages/extension-chakra-storefront/src/pages/product-detail/use-product-detail-data.js index b540bcf20b..d35c809b59 100644 --- a/packages/extension-chakra-storefront/src/pages/product-detail/use-product-detail-data.js +++ b/packages/extension-chakra-storefront/src/pages/product-detail/use-product-detail-data.js @@ -6,7 +6,6 @@ */ import React, {useCallback, useEffect, useState} from 'react' -import {useIntl} from 'react-intl' import {keepPreviousData} from '@tanstack/react-query' import {HTTPNotFound, HTTPError} from '@salesforce/pwa-kit-react-sdk/ssr/universal/errors' @@ -21,20 +20,18 @@ import {useHistory, useLocation, useParams} from 'react-router-dom' import {useCurrentBasket, useVariant} from '../../hooks' import useEinstein from '../../hooks/use-einstein' -import useToast from '../../hooks/use-toast' import {useProductDetailWishlist} from './use-product-detail-wishlist' import {normalizeSetBundleProduct, getUpdateBundleChildArray} from '../../utils/product-utils' +import {useErrorHandler} from '../../hooks/use-errors' -import {API_ERROR_MESSAGE} from '../../constants' import {rebuildPathWithParams} from '../../utils/url' export const useProductDetailData = () => { - const {formatMessage} = useIntl() const history = useHistory() const location = useLocation() const einstein = useEinstein() - const toast = useToast() + const showError = useErrorHandler() const {handleAddToWishlist, isWishlistLoading} = useProductDetailWishlist() /****************************** Basket *********************************/ @@ -183,12 +180,6 @@ export const useProductDetailData = () => { }, [variant]) /**************** Add To Cart ****************/ - const showError = () => { - toast({ - title: formatMessage(API_ERROR_MESSAGE), - type: 'error' - }) - } const handleAddToCart = async (productSelectionValues) => { try { diff --git a/packages/extension-chakra-storefront/src/pages/product-detail/use-product-detail-wishlist.js b/packages/extension-chakra-storefront/src/pages/product-detail/use-product-detail-wishlist.js index 7008f348f1..e12b041310 100644 --- a/packages/extension-chakra-storefront/src/pages/product-detail/use-product-detail-wishlist.js +++ b/packages/extension-chakra-storefront/src/pages/product-detail/use-product-detail-wishlist.js @@ -12,8 +12,8 @@ import {useShopperCustomersMutation, useCustomerId} from '@salesforce/commerce-s import useNavigation from '../../hooks/use-navigation' import useToast from '../../hooks/use-toast' import {useWishList} from '../../hooks/use-wish-list' +import {useErrorHandler} from '../../hooks/use-errors' import { - API_ERROR_MESSAGE, TOAST_ACTION_VIEW_WISHLIST, TOAST_MESSAGE_ADDED_TO_WISHLIST, TOAST_MESSAGE_ALREADY_IN_WISHLIST @@ -28,19 +28,13 @@ export const useProductDetailWishlist = () => { const navigate = useNavigation() const customerId = useCustomerId() const toast = useToast() + const showError = useErrorHandler() const {data: wishlist, isLoading: isWishlistLoading} = useWishList() const createCustomerProductListItem = useShopperCustomersMutation( 'createCustomerProductListItem' ) - const showError = () => { - toast({ - title: formatMessage(API_ERROR_MESSAGE), - type: 'error' - }) - } - const handleAddToWishlist = (product, variant, quantity) => { const isItemInWishlist = wishlist?.customerProductListItems?.find( (i) => i.productId === variant?.productId || i.productId === product?.id