@salesforce/retail-react-app 2.3.1-preview.0 → 2.4.0-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,4 +1,15 @@
1
- ## v2.3.1-preview.0 (Jan 23, 2024)
1
+ ## v2.4.0-dev (Jan 22, 2024)
2
+
3
+ ### Bug Fixes
4
+
5
+ - Fix promo codes not being properly applied in cart [#1692](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1692)
6
+ - Fix checkout shipping method fetching [#1693](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1693)
7
+ - Fix invalid query params warnings [#1655](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1655)
8
+ - Fix internal server error on account pages [#1675](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1675)
9
+ - Fix `product-item` component imports to ensure that it is overridable. [#1672](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1672)
10
+ - Fix locale selector navigating back to default locale [#1670](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1670)
11
+
12
+ ## v2.3.1 (Jan 23, 2024)
2
13
 
3
14
  ### Bug Fixes
4
15
 
@@ -5,7 +5,7 @@
5
5
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
7
  import React from 'react'
8
- import ProductItem from '@salesforce/retail-react-app/app/components/product-item/index'
8
+ import ProductItem from '@salesforce/retail-react-app/app/components/product-item'
9
9
  import {mockedCustomerProductListsDetails} from '@salesforce/retail-react-app/app/mocks/mock-data'
10
10
  import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
11
11
  import {screen} from '@testing-library/react'
@@ -33,38 +33,35 @@ export const usePromoCode = () => {
33
33
  const removePromoCodeMutation = useShopperBasketsMutation('removeCouponFromBasket')
34
34
 
35
35
  const submitPromoCode = async ({code}) => {
36
- applyPromoCodeMutation.mutate(
37
- {
36
+ try {
37
+ await applyPromoCodeMutation.mutateAsync({
38
38
  parameters: {basketId: basket?.basketId},
39
39
  body: {
40
40
  code
41
41
  }
42
- },
43
- {
44
- onSuccess: () => {
45
- form.reset({code: ''})
46
- toast({
47
- title: formatMessage({
48
- defaultMessage: 'Promotion applied',
49
- id: 'use_promocode.info.promo_applied'
50
- }),
51
- status: 'success',
52
- position: 'top-right',
53
- isClosable: true
54
- })
55
- },
56
- onError: () => {
57
- form.setError('code', {
58
- type: 'manual',
59
- message: formatMessage({
60
- defaultMessage:
61
- 'Check the code and try again, it may already be applied or the promo has expired.',
62
- id: 'use_promocode.error.check_the_code'
63
- })
64
- })
65
- }
66
- }
67
- )
42
+ })
43
+
44
+ form.reset({code: ''})
45
+
46
+ toast({
47
+ title: formatMessage({
48
+ defaultMessage: 'Promotion applied',
49
+ id: 'use_promocode.info.promo_applied'
50
+ }),
51
+ status: 'success',
52
+ position: 'top-right',
53
+ isClosable: true
54
+ })
55
+ } catch (e) {
56
+ form.setError('code', {
57
+ type: 'manual',
58
+ message: formatMessage({
59
+ defaultMessage:
60
+ 'Check the code and try again, it may already be applied or the promo has expired.',
61
+ id: 'use_promocode.error.check_the_code'
62
+ })
63
+ })
64
+ }
68
65
  }
69
66
 
70
67
  const removePromoCode = async (couponItemId) => {
@@ -110,11 +110,11 @@ const Account = () => {
110
110
  // If we have customer data and they are not registered, push to login page
111
111
  // Using Redirect allows us to store the directed page to location
112
112
  // so we can direct users back after they are successfully log in
113
- // we don't want redirect on server side
114
113
  if (customerType !== null && !isRegistered && onClient) {
115
114
  const path = buildUrl('/login')
116
115
  return <Redirect to={{pathname: path, state: {directedFrom: '/account'}}} />
117
116
  }
117
+
118
118
  return (
119
119
  <Box
120
120
  data-testid={isRegistered && isHydrated() ? 'account-page' : 'account-page-skeleton'}
@@ -5,7 +5,7 @@
5
5
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
7
 
8
- import React, {useEffect, useRef, useState} from 'react'
8
+ import React, {forwardRef, useEffect, useRef, useState} from 'react'
9
9
  import {FormattedMessage, useIntl} from 'react-intl'
10
10
  import {
11
11
  Alert,
@@ -42,7 +42,7 @@ import {useCurrentCustomer} from '@salesforce/retail-react-app/app/hooks/use-cur
42
42
  * the bounding element will affect the contents size.
43
43
  */
44
44
  // eslint-disable-next-line react/prop-types
45
- const Skeleton = ({children, height, width, ...rest}) => {
45
+ const Skeleton = forwardRef(({children, height, width, ...rest}, ref) => {
46
46
  const {data: customer} = useCurrentCustomer()
47
47
  const {isRegistered} = customer
48
48
  const size = !isRegistered
@@ -52,15 +52,17 @@ const Skeleton = ({children, height, width, ...rest}) => {
52
52
  }
53
53
  : {}
54
54
  return (
55
- <ChakraSkeleton isLoaded={!customer.isLoading} {...rest} {...size}>
55
+ <ChakraSkeleton ref={ref} isLoaded={!customer.isLoading} {...rest} {...size}>
56
56
  {children}
57
57
  </ChakraSkeleton>
58
58
  )
59
- }
59
+ })
60
+
61
+ Skeleton.displayName = 'Skeleton'
60
62
 
61
63
  const ProfileCard = () => {
62
64
  const {formatMessage} = useIntl()
63
-
65
+ const headingRef = useRef(null)
64
66
  const {data: customer} = useCurrentCustomer()
65
67
  const {isRegistered, customerId} = customer
66
68
 
@@ -87,14 +89,6 @@ const ProfileCard = () => {
87
89
  })
88
90
  }, [customer?.firstName, customer?.lastName, customer?.email, customer?.phoneHome])
89
91
 
90
- const profileHeadingText = formatMessage({
91
- defaultMessage: 'My Profile',
92
- id: 'profile_card.title.my_profile'
93
- })
94
- const profileHeading = Array.from(document.querySelectorAll('h2')).find(
95
- (element) => element.textContent === profileHeadingText
96
- )
97
-
98
92
  const submit = async (values) => {
99
93
  try {
100
94
  form.clearErrors()
@@ -126,7 +120,7 @@ const ProfileCard = () => {
126
120
  status: 'success',
127
121
  isClosable: true
128
122
  })
129
- profileHeading?.focus()
123
+ headingRef?.current?.focus()
130
124
  }
131
125
  }
132
126
  )
@@ -139,8 +133,11 @@ const ProfileCard = () => {
139
133
  <ToggleCard
140
134
  id="my-profile"
141
135
  title={
142
- <Skeleton height="30px" width="120px">
143
- {profileHeadingText}
136
+ <Skeleton ref={headingRef} tabIndex="-1" height="30px" width="120px">
137
+ <FormattedMessage
138
+ defaultMessage="My Profile"
139
+ id="profile_card.title.my_profile"
140
+ />
144
141
  </Skeleton>
145
142
  }
146
143
  editing={isEditing}
@@ -164,7 +161,8 @@ const ProfileCard = () => {
164
161
  <FormActionButtons
165
162
  onCancel={() => {
166
163
  setIsEditing(false)
167
- profileHeading?.focus()
164
+ headingRef?.current?.focus()
165
+ form.reset()
168
166
  }}
169
167
  />
170
168
  </Stack>
@@ -232,7 +230,7 @@ const ProfileCard = () => {
232
230
 
233
231
  const PasswordCard = () => {
234
232
  const {formatMessage} = useIntl()
235
-
233
+ const headingRef = useRef(null)
236
234
  const {data: customer} = useCurrentCustomer()
237
235
  const {isRegistered, customerId, email} = customer
238
236
 
@@ -244,14 +242,6 @@ const PasswordCard = () => {
244
242
 
245
243
  const form = useForm()
246
244
 
247
- const passwordHeadingText = formatMessage({
248
- defaultMessage: 'Password',
249
- id: 'password_card.title.password'
250
- })
251
- const passwordHeading = Array.from(document.querySelectorAll('h2')).find(
252
- (element) => element.textContent === passwordHeadingText
253
- )
254
-
255
245
  const submit = async (values) => {
256
246
  try {
257
247
  form.clearErrors()
@@ -278,7 +268,7 @@ const PasswordCard = () => {
278
268
  username: email,
279
269
  password: values.password
280
270
  })
281
- passwordHeading?.focus()
271
+ headingRef?.current?.focus()
282
272
  form.reset()
283
273
  },
284
274
  onError: async (err) => {
@@ -296,8 +286,8 @@ const PasswordCard = () => {
296
286
  <ToggleCard
297
287
  id="password"
298
288
  title={
299
- <Skeleton height="30px" width="120px">
300
- {passwordHeadingText}
289
+ <Skeleton ref={headingRef} tabIndex="-1" height="30px" width="120px">
290
+ <FormattedMessage defaultMessage="Password" id="password_card.title.password" />
301
291
  </Skeleton>
302
292
  }
303
293
  editing={isEditing}
@@ -321,7 +311,8 @@ const PasswordCard = () => {
321
311
  <FormActionButtons
322
312
  onCancel={() => {
323
313
  setIsEditing(false)
324
- passwordHeading?.focus()
314
+ headingRef?.current?.focus()
315
+ form.reset()
325
316
  }}
326
317
  />
327
318
  </Stack>
@@ -16,7 +16,7 @@ import {useWishList} from '@salesforce/retail-react-app/app/hooks/use-wish-list'
16
16
 
17
17
  import PageActionPlaceHolder from '@salesforce/retail-react-app/app/components/page-action-placeholder'
18
18
  import {HeartIcon} from '@salesforce/retail-react-app/app/components/icons'
19
- import ProductItem from '@salesforce/retail-react-app/app/components/product-item/index'
19
+ import ProductItem from '@salesforce/retail-react-app/app/components/product-item'
20
20
  import WishlistPrimaryAction from '@salesforce/retail-react-app/app/pages/account/wishlist/partials/wishlist-primary-action'
21
21
  import WishlistSecondaryButtonGroup from '@salesforce/retail-react-app/app/pages/account/wishlist/partials/wishlist-secondary-button-group'
22
22
 
@@ -26,7 +26,7 @@ import CartTitle from '@salesforce/retail-react-app/app/pages/cart/partials/cart
26
26
  import ConfirmationModal from '@salesforce/retail-react-app/app/components/confirmation-modal'
27
27
  import EmptyCart from '@salesforce/retail-react-app/app/pages/cart/partials/empty-cart'
28
28
  import OrderSummary from '@salesforce/retail-react-app/app/components/order-summary'
29
- import ProductItem from '@salesforce/retail-react-app/app/components/product-item/index'
29
+ import ProductItem from '@salesforce/retail-react-app/app/components/product-item'
30
30
  import ProductViewModal from '@salesforce/retail-react-app/app/components/product-view-modal'
31
31
  import RecommendedProducts from '@salesforce/retail-react-app/app/components/recommended-products'
32
32
 
@@ -109,9 +109,9 @@ const Payment = () => {
109
109
  // Using destructuring to remove properties from the object...
110
110
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
111
111
  const {addressId, creationDate, lastModified, preferred, ...address} = billingAddress
112
- return updateBillingAddressForBasket({
112
+ return await updateBillingAddressForBasket({
113
113
  body: address,
114
- parameters: {basketId: basket.basketId, shipmentId: 'me'}
114
+ parameters: {basketId: basket.basketId}
115
115
  })
116
116
  }
117
117
  const onPaymentRemoval = async () => {
@@ -45,7 +45,7 @@ export default function ShippingOptions() {
45
45
  }
46
46
  },
47
47
  {
48
- enabled: Boolean(basket?.basketId) && step === STEPS.ShippingOptions
48
+ enabled: Boolean(basket?.basketId) && step === STEPS.SHIPPING_OPTIONS
49
49
  }
50
50
  )
51
51
 
@@ -99,7 +99,7 @@ const ProductDetail = () => {
99
99
  } = useCategory({
100
100
  parameters: {
101
101
  id: product?.primaryCategoryId,
102
- level: 1
102
+ levels: 1
103
103
  }
104
104
  })
105
105
 
@@ -137,6 +137,9 @@ const ProductList = (props) => {
137
137
  )
138
138
 
139
139
  /**************** Query Actions ****************/
140
+ // _refine is an invalid param for useProductSearch, we don't want to pass it to API call
141
+ const {_refine, ...restOfParams} = searchParams
142
+
140
143
  const {
141
144
  isLoading,
142
145
  isRefetching,
@@ -144,7 +147,7 @@ const ProductList = (props) => {
144
147
  } = useProductSearch(
145
148
  {
146
149
  parameters: {
147
- ...searchParams,
150
+ ...restOfParams,
148
151
  refine: searchParams._refine
149
152
  }
150
153
  },
package/app/utils/url.js CHANGED
@@ -147,8 +147,6 @@ export const getPathWithLocale = (shortCode, buildUrl, opts = {}) => {
147
147
  // remove ending any &
148
148
  search = search.replace(/&$/, '')
149
149
 
150
- const defaultSite = getDefaultSite()
151
-
152
150
  // Remove query parameters
153
151
  const {disallowParams = []} = opts
154
152
 
@@ -161,7 +159,6 @@ export const getPathWithLocale = (shortCode, buildUrl, opts = {}) => {
161
159
  }
162
160
 
163
161
  const site = getSiteByReference(siteRef)
164
-
165
162
  const locale = getLocaleByReference(site, shortCode)
166
163
 
167
164
  // rebuild the url with new locale,
@@ -169,7 +166,7 @@ export const getPathWithLocale = (shortCode, buildUrl, opts = {}) => {
169
166
  `${pathname}${Array.from(queryString).length !== 0 ? `?${queryString}` : ''}`,
170
167
  // By default, as for home page, when the values of site and locale belongs to the default site,
171
168
  // they will be not shown in the url just
172
- defaultSite.alias || defaultSite.id,
169
+ site.alias || site.id,
173
170
  locale?.alias || locale?.id
174
171
  )
175
172
  return newUrl
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/retail-react-app",
3
- "version": "2.3.1-preview.0",
3
+ "version": "2.4.0-dev",
4
4
  "license": "See license in LICENSE",
5
5
  "author": "cc-pwa-kit@salesforce.com",
6
6
  "ccExtensibility": {
@@ -45,10 +45,10 @@
45
45
  "@lhci/cli": "^0.11.0",
46
46
  "@loadable/component": "^5.15.3",
47
47
  "@peculiar/webcrypto": "^1.4.2",
48
- "@salesforce/commerce-sdk-react": "1.3.0",
49
- "@salesforce/pwa-kit-dev": "3.4.0",
50
- "@salesforce/pwa-kit-react-sdk": "3.4.0",
51
- "@salesforce/pwa-kit-runtime": "3.4.0",
48
+ "@salesforce/commerce-sdk-react": "1.4.0-gpt-nightly-20240315030539",
49
+ "@salesforce/pwa-kit-dev": "3.5.0-dev",
50
+ "@salesforce/pwa-kit-react-sdk": "3.5.0-dev",
51
+ "@salesforce/pwa-kit-runtime": "3.5.0-dev",
52
52
  "@tanstack/react-query": "^4.28.0",
53
53
  "@tanstack/react-query-devtools": "^4.29.1",
54
54
  "@testing-library/dom": "^9.0.1",
@@ -97,8 +97,8 @@
97
97
  },
98
98
  {
99
99
  "path": "build/vendor.js",
100
- "maxSize": "320 kB"
100
+ "maxSize": "370 kB"
101
101
  }
102
102
  ],
103
- "gitHead": "9de5d6472f02d6c69c37668be1fe6ef81883341e"
103
+ "gitHead": "61dd7239a60def4e983fbab25194ffb1e25279fe"
104
104
  }