diff --git a/packages/template-retail-react-app/app/components/_app/index.jsx b/packages/template-retail-react-app/app/components/_app/index.jsx index 6dfb4178ea..6c44baad91 100644 --- a/packages/template-retail-react-app/app/components/_app/index.jsx +++ b/packages/template-retail-react-app/app/components/_app/index.jsx @@ -74,7 +74,8 @@ import { THEME_COLOR, CAT_MENU_DEFAULT_NAV_SSR_DEPTH, CAT_MENU_DEFAULT_ROOT_CATEGORY, - DEFAULT_LOCALE + DEFAULT_LOCALE, + STORE_LOCATOR_IS_ENABLED } from '@salesforce/retail-react-app/app/constants' import Seo from '@salesforce/retail-react-app/app/components/seo' @@ -354,10 +355,12 @@ const App = (props) => { Skip to Content - + {STORE_LOCATOR_IS_ENABLED && ( + + )} {!isCheckout ? ( <> diff --git a/packages/template-retail-react-app/app/components/product-view/index.jsx b/packages/template-retail-react-app/app/components/product-view/index.jsx index 8d220c0ea4..cf289e0ec7 100644 --- a/packages/template-retail-react-app/app/components/product-view/index.jsx +++ b/packages/template-retail-react-app/app/components/product-view/index.jsx @@ -26,6 +26,7 @@ import { } from '@salesforce/retail-react-app/app/components/shared/ui' import {useCurrency, useDerivedProduct} from '@salesforce/retail-react-app/app/hooks' import {useAddToCartModalContext} from '@salesforce/retail-react-app/app/hooks/use-add-to-cart-modal' +import {STORE_LOCATOR_IS_ENABLED} from '@salesforce/retail-react-app/app/constants' // project components import ImageGallery from '@salesforce/retail-react-app/app/components/image-gallery' @@ -672,13 +673,8 @@ const ProductView = forwardRef( {showDeliveryOptions && ( <> - - + + - - - + {STORE_LOCATOR_IS_ENABLED && ( + + + + )} - {storeName && inventoryId && ( - - {!isSelectedStoreOutOfStock - ? intl.formatMessage( - { - id: 'product_view.status.in_stock_at_store', - defaultMessage: - 'In Stock at {storeName}' - }, - { - storeName: ( - - {storeName} - - ) - } - ) - : intl.formatMessage( - { - id: 'product_view.status.out_of_stock_at_store', - defaultMessage: - 'Out of Stock at {storeName}' - }, - { - storeName: ( - - {storeName} - + + {STORE_LOCATOR_IS_ENABLED && ( + <> + {storeName && inventoryId && ( + + {!isSelectedStoreOutOfStock + ? intl.formatMessage( + { + id: 'product_view.status.in_stock_at_store', + defaultMessage: + 'In Stock at {storeName}' + }, + { + storeName: ( + + {storeName} + + ) + } ) - } - )} - - )} - {/* Show label if pickup is disabled due to no store/inventoryId */} - {!pickupEnabled && !storeName && !inventoryId && ( - - {' '} - - - - + : intl.formatMessage( + { + id: 'product_view.status.out_of_stock_at_store', + defaultMessage: + 'Out of Stock at {storeName}' + }, + { + storeName: ( + + {storeName} + + ) + } + )} + + )} + + {/* Show label if pickup is disabled due to no store/inventoryId */} + {!pickupEnabled && !storeName && !inventoryId && ( + + {' '} + + + + + )} + )} )} diff --git a/packages/template-retail-react-app/app/hooks/use-pickup-shipment.js b/packages/template-retail-react-app/app/hooks/use-pickup-shipment.js index 333b0b93a4..f5d941331f 100644 --- a/packages/template-retail-react-app/app/hooks/use-pickup-shipment.js +++ b/packages/template-retail-react-app/app/hooks/use-pickup-shipment.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Salesforce, Inc. + * Copyright (c) 2025, Salesforce, Inc. * All rights reserved. * 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 diff --git a/packages/template-retail-react-app/app/pages/cart/index.jsx b/packages/template-retail-react-app/app/pages/cart/index.jsx index f207b30150..bff5324b69 100644 --- a/packages/template-retail-react-app/app/pages/cart/index.jsx +++ b/packages/template-retail-react-app/app/pages/cart/index.jsx @@ -44,7 +44,8 @@ import { TOAST_ACTION_VIEW_WISHLIST, TOAST_MESSAGE_ADDED_TO_WISHLIST, TOAST_MESSAGE_REMOVED_ITEM_FROM_CART, - TOAST_MESSAGE_ALREADY_IN_WISHLIST + TOAST_MESSAGE_ALREADY_IN_WISHLIST, + STORE_LOCATOR_IS_ENABLED } from '@salesforce/retail-react-app/app/constants' import {REMOVE_CART_ITEM_CONFIRMATION_DIALOG_CONFIG} from '@salesforce/retail-react-app/app/pages/cart/partials/cart-secondary-button-group' @@ -68,8 +69,10 @@ const DEBOUNCE_WAIT = 750 const Cart = () => { const {data: basket, isLoading} = useCurrentBasket() - // Pickup in Store - const isPickupOrder = basket?.shipments[0]?.shippingMethod?.c_storePickupEnabled === true + // Pickup in Store - only enabled if feature toggle is on + const isPickupOrder = STORE_LOCATOR_IS_ENABLED + ? basket?.shipments[0]?.shippingMethod?.c_storePickupEnabled === true + : false const storeId = basket?.shipments?.[0]?.c_fromStoreId const {data: storeData} = useStores( { @@ -78,7 +81,7 @@ const Cart = () => { } }, { - enabled: !!storeId + enabled: !!storeId && STORE_LOCATOR_IS_ENABLED } ) const storeName = storeData?.data?.[0]?.name @@ -606,26 +609,29 @@ const Cart = () => { > - - {isPickupOrder ? ( - - - - ) : ( - - - - )} - + {/* Order Type Display */} + {STORE_LOCATOR_IS_ENABLED && ( + + {isPickupOrder ? ( + + + + ) : ( + + + + )} + + )} {basket.productItems?.map((productItem, idx) => { return ( { const form = useForm() // Check if this is a pickup order and get store details - const isPickupOrder = order?.shipments?.[0]?.shippingMethod?.c_storePickupEnabled === true + const isPickupOrder = STORE_LOCATOR_IS_ENABLED + ? order?.shipments?.[0]?.shippingMethod?.c_storePickupEnabled === true + : false const storeId = order?.shipments?.[0]?.c_fromStoreId const {data: storeData} = useStores( { @@ -252,8 +257,8 @@ const CheckoutConfirmation = () => { /> - - + + { const isSocialEnabled = !!social?.enabled const isPasswordlessEnabled = !!passwordless?.enabled - const isPickupOrder = basket?.shipments[0]?.shippingMethod?.c_storePickupEnabled === true + // Only enable BOPIS functionality if the feature toggle is on + const isPickupOrder = STORE_LOCATOR_IS_ENABLED + ? basket?.shipments[0]?.shippingMethod?.c_storePickupEnabled === true + : false useEffect(() => { if (error || step === 4) { diff --git a/packages/template-retail-react-app/app/pages/checkout/partials/payment.jsx b/packages/template-retail-react-app/app/pages/checkout/partials/payment.jsx index c2103b4fd5..7f020ad930 100644 --- a/packages/template-retail-react-app/app/pages/checkout/partials/payment.jsx +++ b/packages/template-retail-react-app/app/pages/checkout/partials/payment.jsx @@ -46,7 +46,7 @@ const Payment = () => { const appliedPayment = basket?.paymentInstruments && basket?.paymentInstruments[0] const isPickupOrder = basket?.shipments[0]?.shippingMethod?.c_storePickupEnabled === true - const [billingSameAsShipping, setBillingSameAsShipping] = useState(!isPickupOrder) // By default, have billing addr to be the same as shipping + const [billingSameAsShipping, setBillingSameAsShipping] = useState(!isPickupOrder) const {mutateAsync: addPaymentInstrumentToBasket} = useShopperBasketsMutation( 'addPaymentInstrumentToBasket' ) diff --git a/packages/template-retail-react-app/app/pages/checkout/util/checkout-context.js b/packages/template-retail-react-app/app/pages/checkout/util/checkout-context.js index f47e58eb90..1983288a06 100644 --- a/packages/template-retail-react-app/app/pages/checkout/util/checkout-context.js +++ b/packages/template-retail-react-app/app/pages/checkout/util/checkout-context.js @@ -9,6 +9,7 @@ import PropTypes from 'prop-types' import useEinstein from '@salesforce/retail-react-app/app/hooks/use-einstein' import {useCurrentCustomer} from '@salesforce/retail-react-app/app/hooks/use-current-customer' import {useCurrentBasket} from '@salesforce/retail-react-app/app/hooks/use-current-basket' +import {STORE_LOCATOR_IS_ENABLED} from '@salesforce/retail-react-app/app/constants' const CheckoutContext = React.createContext() @@ -40,8 +41,9 @@ export const CheckoutProvider = ({children}) => { if (customer.isGuest && !basket.customerInfo?.email) { step = STEPS.CONTACT_INFO } else if (!basket.shipments[0]?.shippingAddress?.address1) { - // Check if it's a pickup order + // Check if it's a pickup order - only if BOPIS is enabled const isPickupOrder = + STORE_LOCATOR_IS_ENABLED && basket?.shipments[0]?.shippingMethod?.c_storePickupEnabled === true step = isPickupOrder ? STEPS.PICKUP_ADDRESS : STEPS.SHIPPING_ADDRESS } else if (!basket.shipments[0]?.shippingMethod) { @@ -75,22 +77,27 @@ export const CheckoutProvider = ({children}) => { } }, [step]) + const goToNextStep = () => { + // Check if current step is CONTACT_INFO + if (step === STEPS.CONTACT_INFO) { + // Determine if it's a pickup order - only if BOPIS is enabled + const isPickupOrder = + STORE_LOCATOR_IS_ENABLED && + basket?.shipments[0]?.shippingMethod?.c_storePickupEnabled === true + // Skip to appropriate next step + setStep(isPickupOrder ? STEPS.PICKUP_ADDRESS : STEPS.SHIPPING_ADDRESS) + } else { + setStep(step + 1) + } + } + + const goToStep = (step) => setStep(step) + const value = { step, STEPS, - goToNextStep: () => { - // Check if current step is CONTACT_INFO - if (step === STEPS.CONTACT_INFO) { - // Determine if it's a pickup order - const isPickupOrder = - basket?.shipments[0]?.shippingMethod?.c_storePickupEnabled === true - // Skip to appropriate next step - setStep(isPickupOrder ? STEPS.PICKUP_ADDRESS : STEPS.SHIPPING_ADDRESS) - } else { - setStep(step + 1) - } - }, - goToStep: (step) => setStep(step) + goToNextStep, + goToStep } return {children} diff --git a/packages/template-retail-react-app/app/pages/product-detail/index.jsx b/packages/template-retail-react-app/app/pages/product-detail/index.jsx index c6fb309b47..304ad0a6dc 100644 --- a/packages/template-retail-react-app/app/pages/product-detail/index.jsx +++ b/packages/template-retail-react-app/app/pages/product-detail/index.jsx @@ -36,6 +36,7 @@ import useActiveData from '@salesforce/retail-react-app/app/hooks/use-active-dat import {useServerContext} from '@salesforce/pwa-kit-react-sdk/ssr/universal/hooks' import usePickupShipment from '@salesforce/retail-react-app/app/hooks/use-pickup-shipment' import {useSelectedStore} from '@salesforce/retail-react-app/app/hooks/use-selected-store' +import {STORE_LOCATOR_IS_ENABLED} from '@salesforce/retail-react-app/app/constants' // Project Components import RecommendedProducts from '@salesforce/retail-react-app/app/components/recommended-products' import ProductView from '@salesforce/retail-react-app/app/components/product-view' @@ -675,6 +676,7 @@ const ProductDetail = () => { product && handlePickupInStoreChange(product.id, checked) } onOpenStoreLocator={onOpenStoreLocator} + showDeliveryOptions={STORE_LOCATOR_IS_ENABLED} />
@@ -745,6 +747,7 @@ const ProductDetail = () => { handlePickupInStoreChange(childProduct.id, checked) } onOpenStoreLocator={onOpenStoreLocator} + showDeliveryOptions={STORE_LOCATOR_IS_ENABLED} /> @@ -775,6 +778,7 @@ const ProductDetail = () => { product && handlePickupInStoreChange(product.id, checked) } onOpenStoreLocator={onOpenStoreLocator} + showDeliveryOptions={STORE_LOCATOR_IS_ENABLED} /> @@ -824,7 +828,9 @@ const ProductDetail = () => { />
- + {STORE_LOCATOR_IS_ENABLED && ( + + )}
) } diff --git a/packages/template-retail-react-app/app/pages/product-list/index.jsx b/packages/template-retail-react-app/app/pages/product-list/index.jsx index 0586d6824a..d8c791c50c 100644 --- a/packages/template-retail-react-app/app/pages/product-list/index.jsx +++ b/packages/template-retail-react-app/app/pages/product-list/index.jsx @@ -90,7 +90,8 @@ import { TOAST_MESSAGE_REMOVED_FROM_WISHLIST, STALE_WHILE_REVALIDATE, PRODUCT_LIST_IMAGE_VIEW_TYPE, - PRODUCT_LIST_SELECTABLE_ATTRIBUTE_ID + PRODUCT_LIST_SELECTABLE_ATTRIBUTE_ID, + STORE_LOCATOR_IS_ENABLED } from '@salesforce/retail-react-app/app/constants' import useNavigation from '@salesforce/retail-react-app/app/hooks/use-navigation' import LoadingSpinner from '@salesforce/retail-react-app/app/components/loading-spinner' @@ -396,6 +397,15 @@ const ProductList = (props) => { navigate(newPath) } + // Create reusable StoreInventoryFilter component to avoid repetition + const storeInventoryFilterComponent = ( + + ) + /**************** Einstein ****************/ useEffect(() => { if (productSearchResult) { @@ -555,24 +565,16 @@ const ProductList = (props) => { itemsBefore={ category?.categories ? [ - , - - ] + , + STORE_LOCATOR_IS_ENABLED && storeInventoryFilterComponent + ].filter(Boolean) : [ - - ] + STORE_LOCATOR_IS_ENABLED && storeInventoryFilterComponent + ].filter(Boolean) } isLoading={filtersLoading} toggleFilter={toggleFilter} @@ -712,23 +714,11 @@ const ProductList = (props) => { category={category} onSelect={onClose} />, - - ] + STORE_LOCATOR_IS_ENABLED && storeInventoryFilterComponent + ].filter(Boolean) : [ - - ] + STORE_LOCATOR_IS_ENABLED && storeInventoryFilterComponent + ].filter(Boolean) } excludedFilters={['cgid']} /> diff --git a/packages/template-retail-react-app/app/pages/product-list/partials/selected-refinements.jsx b/packages/template-retail-react-app/app/pages/product-list/partials/selected-refinements.jsx index 06768c8c54..436325b19b 100644 --- a/packages/template-retail-react-app/app/pages/product-list/partials/selected-refinements.jsx +++ b/packages/template-retail-react-app/app/pages/product-list/partials/selected-refinements.jsx @@ -12,6 +12,7 @@ import {Box, Button, Wrap, WrapItem} from '@salesforce/retail-react-app/app/comp import {CloseIcon} from '@salesforce/retail-react-app/app/components/icons' import {REMOVE_FILTER} from '@salesforce/retail-react-app/app/pages/product-list/partials/refinements-utils' import {useSelectedStore} from '@salesforce/retail-react-app/app/hooks/use-selected-store' +import {STORE_LOCATOR_IS_ENABLED} from '@salesforce/retail-react-app/app/constants' const SelectedRefinements = ({toggleFilter, selectedFilterValues, filters, handleReset}) => { const {formatMessage} = useIntl() @@ -27,7 +28,7 @@ const SelectedRefinements = ({toggleFilter, selectedFilterValues, filters, handl uiLabel = priceFilterValues?.values?.find((priceFilter) => priceFilter.value === filter) ?.label || filter - } else if (key === 'ilids') { + } else if (key === 'ilids' && STORE_LOCATOR_IS_ENABLED) { // Fallback text for in stock selected filter uiLabel = formatMessage({ id: 'selected_refinements.filter.in_stock',