Skip to content
Merged
Show file tree
Hide file tree
Changes from 88 commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
43aee28
Support standard product on PDP @W-12360908 (#2518)
sf-emmyzhang Jun 13, 2025
cdc9151
Handle SDK Client not initialized
shethj Jun 9, 2025
23a8b38
Added tests for useResolvedClient
shethj Jun 9, 2025
447807f
Handle missing SDK Client ShopperContext
shethj Jun 9, 2025
93eae95
ShopperCustomers - Handle SDK Client no init
shethj Jun 9, 2025
b70b3a3
ShopperExperience - Handle missing SDK Client
shethj Jun 9, 2025
4f5b333
ShopperGiftCertificates - Handle missing SDK Client
shethj Jun 9, 2025
a971777
ShopperLogin: Handle missing SDK client
shethj Jun 9, 2025
19ca020
ShopperOrders - Handle Missing SDK Client
shethj Jun 9, 2025
e82bd99
ShopperProducts: Handle missing SDK Client
shethj Jun 9, 2025
f1a23ea
ShopperPromotions: Handle missing SDK client
shethj Jun 9, 2025
140bcd3
ShopperSearch - Handle missing SDK Client
shethj Jun 9, 2025
24fd839
ShopperSEO: Handle missing SDK Client
shethj Jun 9, 2025
f3a4445
ShopperStores: Handle missing SDK Client
shethj Jun 9, 2025
68a6fb8
Fix linting errors
shethj Jun 9, 2025
d281148
Update useResolvedClient tests
shethj Jun 9, 2025
70593af
Update changelog
shethj Jun 9, 2025
e850378
Update changelog
shethj Jun 9, 2025
4b2940e
Extract CLIENT_KEY literal to constnt
shethj Jun 9, 2025
4c317c4
Remove additional hook for client validation
shethj Jun 10, 2025
4e4b412
Fix linting
shethj Jun 10, 2025
965fe8b
Add comments
shethj Jun 10, 2025
8a25816
rename apiClients variable to add clarity
shethj Jun 11, 2025
26bb0e6
update variable name for apiClients
shethj Jun 11, 2025
83988fe
Update sample query implementation in query.ts
shethj Jun 18, 2025
058a7c0
Initial Commit
bendvc Jun 12, 2025
782cfb9
Update CHANGELOG.md
bendvc Jun 12, 2025
9210d0e
Add some additional tests
bendvc Jun 12, 2025
1a2f75a
PR Feedback
bendvc Jun 16, 2025
06703ad
Fix bar reference to master.variantId
bendvc Jun 16, 2025
7d1aa03
feat: cursor rules for unit tests
szirpesf Jun 17, 2025
4386fdb
Update change log
bendvc Jun 17, 2025
c474063
Support standard product on PDP @W-12360908 (#2518)
sf-emmyzhang Jun 13, 2025
ba29cb0
Resolve merge conflict
sf-emmyzhang Jun 23, 2025
0bc9de4
Update files with conflicts
sf-emmyzhang Jun 23, 2025
22bbb48
omg so we're not adding these
sf-emmyzhang Jun 23, 2025
b5e7dc8
merge develop into standard product feature branch (#2626)
sf-emmyzhang Jun 23, 2025
75da2b7
@W-12360935 Modify the Product Card to support standard products (#2581)
sf-shikhar-prasoon Jun 24, 2025
581313c
udpate changelog to resolve conflict
sf-emmyzhang Jun 24, 2025
adcc08b
udpate changelog to resolve conflict 2
sf-emmyzhang Jun 24, 2025
1e2afd4
udpate changelog to resolve conflict 3
sf-emmyzhang Jun 24, 2025
95819a0
oops
sf-emmyzhang Jun 24, 2025
6896d4f
Merge develop into standard-product-support (#2633)
sf-emmyzhang Jun 24, 2025
f3ced62
Support standard product as a child item in bundles @W-18790730 (#2574)
sf-emmyzhang Jun 24, 2025
2a73e91
Merge branch 'develop' into merge-develop-into-standard-product-suppo…
jeremy-jung1 Jun 25, 2025
1e4f31b
Handle standard product shape in sendAddToCart
jeremy-jung1 Jun 25, 2025
6b94099
Update CHANGELOG.md
jeremy-jung1 Jun 25, 2025
4ed540f
Support standard product as a child item in sets @W-18790730 (#2636)
sf-emmyzhang Jun 25, 2025
d81d171
Add test
jeremy-jung1 Jun 26, 2025
2046cfe
Lint tests
jeremy-jung1 Jun 26, 2025
f0f10d6
@W-18767088 refactor add to cart
sf-kyle-wright Jun 26, 2025
f241f49
@W-18767088 refactor add to cart
sf-kyle-wright Jun 26, 2025
f545efe
@W-18767088 fix lint errors
sf-kyle-wright Jun 26, 2025
fef01e8
Merge branch 'standard-product-support' into W-17118204-verify-einste…
jeremy-jung1 Jun 26, 2025
b322006
Merge branch 'develop' into W-17118204-verify-einstein-activity
jeremy-jung1 Jun 26, 2025
891af1f
Merge pull request #2650 from SalesforceCommerceCloud/W-17118204-veri…
jeremy-jung1 Jun 26, 2025
dd72f4f
@W-18767088 do not move handleChildProductValidation
sf-kyle-wright Jun 26, 2025
a637f3b
Merge branch 'standard-product-support' into t/cc-shark/W-18767088/re…
sf-kyle-wright Jun 26, 2025
e9f5769
@W-12360935 2nd PR- fixing Edit button appearing briefly for standard…
sf-shikhar-prasoon Jun 27, 2025
f73f650
@W-18767088 utils rename
sf-kyle-wright Jun 27, 2025
eea4a61
Merge pull request #2664 from SalesforceCommerceCloud/t/cc-shark/W-18…
sf-kyle-wright Jun 27, 2025
6d4b28b
Merge branch 'develop' into standard-product-support
sf-emmyzhang Jun 30, 2025
608b3eb
Merge branch 'develop' into standard-product-support
sf-emmyzhang Jul 1, 2025
3cfff41
Revert CHANGELOG.md
sf-emmyzhang Jul 1, 2025
dcd48c0
increase bundle size for ci error
sf-emmyzhang Jul 1, 2025
0b46f33
Merge branch 'develop' into standard-product-support
sf-emmyzhang Jul 1, 2025
9d90f80
update use add to cart modal unit test
sf-emmyzhang Jul 2, 2025
63bcfb1
revert auto merge change
sf-emmyzhang Jul 3, 2025
fd18a0b
add image placeholder todo
sf-emmyzhang Jul 3, 2025
73768d3
rename bundleChildVariant
sf-emmyzhang Jul 3, 2025
8639953
revert refactor work
sf-emmyzhang Jul 3, 2025
9b2fae0
add bundle test
sf-emmyzhang Jul 3, 2025
0bcda60
lint
sf-emmyzhang Jul 3, 2025
ca387c8
update test
sf-emmyzhang Jul 3, 2025
55ee64a
Merge branch 'develop' into standard-product-support
sf-emmyzhang Jul 3, 2025
4bac244
lint
sf-emmyzhang Jul 3, 2025
0a45ee8
Handle out of stock for standard product
jeremy-jung1 Jul 6, 2025
5707bb5
tests and linting
jeremy-jung1 Jul 6, 2025
c915f7c
handle lack of type
jeremy-jung1 Jul 6, 2025
29d3f06
Merge branch 'develop' into standard-product-support
sf-emmyzhang Jul 7, 2025
9f93d7f
Fix child standard product item in set 400 on addToCart
jeremy-jung1 Jul 8, 2025
353b0ee
Merge branch 'develop' into standard-product-support
sf-emmyzhang Jul 8, 2025
6c9a253
Merge branch 'develop' into standard-product-support
sf-emmyzhang Jul 8, 2025
7622258
pr suggestions
sf-emmyzhang Jul 8, 2025
e9b8c14
Merge branch 'develop' into standard-product-support
sf-emmyzhang Jul 8, 2025
2ed7ed8
lint and test failure
sf-emmyzhang Jul 8, 2025
fd8b3bd
Fix standard product bundle add to cart for pick up in store?. And li…
jeremy-jung1 Jul 9, 2025
260d46f
Merge branch 'develop' into standard-product-support
sf-emmyzhang Jul 9, 2025
8ae2dcb
Ensure toast has a string to show
jeremy-jung1 Jul 9, 2025
c591eaa
linting
jeremy-jung1 Jul 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/template-retail-react-app/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
- Password Reset and Passwordless Integration Test [#2669](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2669)
- Update latest translations for all languages [#2616](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2616)
- Added support for Buy Online Pick up In Store (BOPIS) [#2646](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2646)
- Support standard product on PDP [#2518](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2518)
- Removed the "Edit" button from product cards of Standard Products [#2581](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2581)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small knit, but maybe just put the last PR (this one) in the changelog, i dont think we ended up adding all the statements for the other features.

- Support standard product as a child item in bundles [#2574](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2574)
- Verify einstein activity with standard product [#2650](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2650)
- Support standard product as a child item in sets [#2636](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2636)
- Load active data scripts on demand only [#2623](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2623)
- Refactor Add to Cart in PDP [#2664](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2664)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR did not make it in to develop, so this needs to be pulled

- Provide base image for convenient perf optimizations [#2642](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2642)
- Support saving billing phone number on user registration from order confirmation [#2653](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2653)
- Support saving default shipping address on user registration from order confirmation [#2706](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2706)
Expand Down Expand Up @@ -452,4 +458,4 @@ The versions published below were not published on npm, and the versioning match

### v1.0.0 (Sep 08, 2021)

- PWA Kit General Availability and open source. 🎉
- PWA Kit General Availability and open source. 🎉
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ const BundleProductViewModal = ({product: bundle, isOpen, onClose, updateCart, .
let childProductIds = productViewModalData.product?.bundledProductItems
?.map(({productId}) => productId)
.join(',')
const productIds = selectedChildProducts.map(({variant}) => variant.productId).join(',')
const productIds = selectedChildProducts
.map(({variant, product}) => variant?.productId || product?.id)
.join(',')
if (productIds?.length > 0 && productIds !== childProductIds) {
childProductIds = productIds
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
mockProductBundle
} from '@salesforce/retail-react-app/app/mocks/product-bundle'
import {rest} from 'msw'
import {mockStandardProductOrderable} from '@salesforce/retail-react-app/app/mocks/standard-product'

const MockComponent = ({updateCart}) => {
const {isOpen, onOpen, onClose} = useDisclosure()
Expand Down Expand Up @@ -166,6 +167,20 @@ test('bundle product view modal disables update button when quantity exceeds chi
expect(swingTankProductView).toBeInTheDocument()
expect(sizeSelectBtn).toBeInTheDocument()
expect(quantityInput).toBeInTheDocument()
})

// Wait for all child products to be rendered
await waitFor(() => {
expect(screen.getAllByText('Sleeveless Pleated Floral Front Blouse')).toHaveLength(2)
expect(screen.getAllByText('Swing Tank')).toHaveLength(2)
expect(screen.getAllByText('Pull On Neutral Pant')).toHaveLength(2)
})

// Select a valid variant
fireEvent.click(sizeSelectBtn)

// Wait for the initial state to be fully loaded and the button to be enabled
await waitFor(() => {
expect(updateBtn).toBeInTheDocument()
})

Expand All @@ -187,3 +202,58 @@ test('bundle product view modal disables update button when quantity exceeds chi
expect(screen.getByText('Only 1 left!')).toBeInTheDocument()
})
})

test('modal displays standard product child name when bundle contains a standard product', async () => {
// Create a bundle with a standard product as the first child
const bundleWithStandardChild = {
...mockBundledProductItemsVariant,
bundledProductItems: [
{
...mockBundledProductItemsVariant.bundledProductItems[0],
productId: mockStandardProductOrderable.id,
productName: mockStandardProductOrderable.name,
itemText: mockStandardProductOrderable.name
},
...mockBundledProductItemsVariant.bundledProductItems.slice(1)
]
}

// Custom MSW handler for this test
global.server.use(
rest.get('*/products', (req, res, ctx) => {
const ids = req.url.searchParams.get('ids')
if (ids && ids.includes(mockStandardProductOrderable.id)) {
return res(ctx.json({data: [mockStandardProductOrderable], total: 1}))
}
return res(ctx.json(mockProductBundleWithVariants))
})
)

const MockComponent = ({updateCart}) => {
const {isOpen, onOpen, onClose} = useDisclosure()
return (
<div>
<button onClick={onOpen}>Open Modal</button>
<BundleProductViewModal
updateCart={updateCart}
onOpen={onOpen}
onClose={onClose}
isOpen={isOpen}
product={bundleWithStandardChild}
/>
</div>
)
}
MockComponent.propTypes = {updateCart: PropTypes.func}

renderWithProviders(<MockComponent />)
await waitFor(() => {
const trigger = screen.getByText(/open modal/i)
fireEvent.click(trigger)
})

// Assert the standard product child name is rendered
await waitFor(() => {
expect(screen.getAllByText(mockStandardProductOrderable.name)[0]).toBeInTheDocument()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,21 @@ const ProductView = forwardRef(
setChildProductOrderability,
isBasketLoading = false,
onVariantSelected = () => {},
validateOrderability = (variant, quantity, stockLevel) =>
!isProductLoading && variant?.orderable && quantity > 0 && quantity <= stockLevel,
validateOrderability = (variant, product, quantity, stockLevel) => {
if (isProductLoading) return false

// If product has variations, a variant must be selected
if (product?.variationAttributes?.length > 0 && !variant) {
return false
}

// Check if product (either variant or standard) is orderable and if quantity is valid
return (
(variant?.orderable || product?.inventory?.orderable) &&
quantity > 0 &&
quantity <= stockLevel
)
},
showImageGallery = true,
setSelectedBundleQuantity = () => {},
selectedBundleParentQuantity = 1,
Expand Down Expand Up @@ -169,8 +182,8 @@ const ProductView = forwardRef(
return getPriceData(product, {quantity})
}, [product, quantity])
const canAddToWishlist = !isProductLoading
const isProductASet = product?.type.set
const isProductABundle = product?.type.bundle
const isProductASet = product?.type?.set
const isProductABundle = product?.type?.bundle
const errorContainerRef = useRef(null)
const [pickupEnabled, setPickupEnabled] = useState(false)
const storeName = selectedStore?.name
Expand Down Expand Up @@ -223,7 +236,7 @@ const ProductView = forwardRef(
const validateAndShowError = (opts = {}) => {
const {scrollErrorIntoView = true} = opts
// Validate that all attributes are selected before proceeding.
const hasValidSelection = validateOrderability(variant, quantity, stockLevel)
const hasValidSelection = validateOrderability(variant, product, quantity, stockLevel)
const showError = !isProductASet && !isProductABundle && !hasValidSelection
const scrollToError = showError && scrollErrorIntoView

Expand Down Expand Up @@ -292,7 +305,7 @@ const ProductView = forwardRef(
return
}
try {
const itemsAdded = await addToCart(variant, quantity)
const itemsAdded = await addToCart([{product, variant, quantity}])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi, @sf-emmyzhang we just removed this change in #2729. Is there a benefit to adding it back?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Product is part of standard product changes and is needed for standard products to work

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... before BOPIS or standard-product the product was added as a lambda in the parent container addToCart handler in pages/product-detail. And a childProduct was added in the parent for product sets and bundles. My worry is with this change back that bundles and sets will not work properly.

Copy link
Collaborator

@jeremy-jung1 jeremy-jung1 Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the code to account for both features (commit)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for the record I still don't think this change is needed nor advisable. We're changing the data contract between product-view and product-detail, which implies more merge work for custom implementations. There should be a good reason.

// Open modal only when `addToCart` returns some data
// It's possible that the item has been added to cart, but we don't want to open the modal.
// See wishlist_primary_action for example.
Expand Down Expand Up @@ -390,7 +403,7 @@ const ProductView = forwardRef(
if (
!isProductASet &&
!isProductABundle &&
validateOrderability(variant, quantity, stockLevel)
validateOrderability(variant, product, quantity, stockLevel)
) {
toggleShowOptionsMessage(false)
}
Expand All @@ -402,6 +415,12 @@ const ProductView = forwardRef(
}
}, [variant?.productId, quantity])

useEffect(() => {
if ((isProductPartOfBundle || isProductPartOfSet) && product && product.type?.item) {
onVariantSelected(product, null, childOfBundleQuantity || quantity)
}
}, [product, childOfBundleQuantity, quantity, isProductPartOfBundle, isProductPartOfSet])

useEffect(() => {
if (isProductPartOfBundle || isProductPartOfSet) {
const key = product.itemId ?? product.id
Expand Down
Loading
Loading