@salesforce/retail-react-app 7.1.0-preview.1 → 8.0.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.
Files changed (113) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/app/components/_app/index.jsx +9 -7
  3. package/app/components/_app/index.test.js +2 -2
  4. package/app/components/_app-config/index.jsx +9 -3
  5. package/app/components/drawer-menu/drawer-menu.jsx +3 -1
  6. package/app/components/footer/index.jsx +3 -1
  7. package/app/components/header/index.jsx +3 -1
  8. package/app/components/header/index.test.js +2 -2
  9. package/app/components/island/README.md +1 -1
  10. package/app/components/island/index.jsx +3 -1
  11. package/app/components/island/index.test.js +94 -5
  12. package/app/components/item-variant/item-attributes.jsx +12 -3
  13. package/app/components/multiship/multiship-order-summary.jsx +137 -0
  14. package/app/components/multiship/multiship-order-summary.test.js +121 -0
  15. package/app/components/order-summary/index.jsx +2 -4
  16. package/app/components/pickup-or-delivery/index.jsx +80 -0
  17. package/app/components/pickup-or-delivery/index.test.jsx +182 -0
  18. package/app/components/product-item/index.jsx +26 -16
  19. package/app/components/product-item/index.test.js +29 -2
  20. package/app/components/product-item-list/index.jsx +10 -0
  21. package/app/components/product-item-list/index.test.jsx +14 -0
  22. package/app/components/product-view/index.jsx +9 -6
  23. package/app/components/product-view/index.test.js +25 -21
  24. package/app/components/quantity-picker/index.test.jsx +12 -12
  25. package/app/components/reset-password/index.test.js +1 -1
  26. package/app/components/shared/ui/AlertDescription/index.jsx +8 -0
  27. package/app/components/shared/ui/index.jsx +1 -0
  28. package/app/components/store-display/index.jsx +28 -4
  29. package/app/components/store-display/index.test.js +71 -0
  30. package/app/components/store-locator/form.test.jsx +16 -4
  31. package/app/components/store-locator/list.jsx +9 -4
  32. package/app/components/toggle-card/index.jsx +14 -0
  33. package/app/components/unavailable-product-confirmation-modal/index.jsx +19 -5
  34. package/app/components/unavailable-product-confirmation-modal/index.test.js +122 -1
  35. package/app/constants.js +20 -6
  36. package/app/contexts/store-locator-provider.jsx +7 -1
  37. package/app/contexts/store-locator-provider.test.jsx +36 -1
  38. package/app/hooks/use-address-form.js +155 -0
  39. package/app/hooks/use-address-form.test.js +501 -0
  40. package/app/hooks/use-auth-modal.js +2 -6
  41. package/app/hooks/use-current-basket.js +71 -2
  42. package/app/hooks/use-current-basket.test.js +37 -1
  43. package/app/hooks/use-dnt-notification.js +4 -4
  44. package/app/hooks/use-dnt-notification.test.js +5 -5
  45. package/app/hooks/use-item-shipment-management.js +233 -0
  46. package/app/hooks/use-item-shipment-management.test.js +696 -0
  47. package/app/hooks/use-multiship.js +589 -0
  48. package/app/hooks/use-multiship.test.js +776 -0
  49. package/app/hooks/use-pickup-shipment.js +70 -106
  50. package/app/hooks/use-pickup-shipment.test.js +345 -209
  51. package/app/hooks/use-product-address-assignment.js +280 -0
  52. package/app/hooks/use-product-address-assignment.test.js +414 -0
  53. package/app/hooks/use-product-inventory.js +100 -0
  54. package/app/hooks/use-product-inventory.test.js +254 -0
  55. package/app/hooks/use-shipment-operations.js +168 -0
  56. package/app/hooks/use-shipment-operations.test.js +385 -0
  57. package/app/hooks/use-store-locator.js +24 -2
  58. package/app/hooks/use-store-locator.test.jsx +109 -1
  59. package/app/pages/account/index.test.js +1 -1
  60. package/app/pages/account/profile.test.js +0 -2
  61. package/app/pages/cart/index.jsx +397 -157
  62. package/app/pages/cart/index.test.js +353 -2
  63. package/app/pages/cart/partials/bonus-products-title.jsx +10 -8
  64. package/app/pages/cart/partials/cart-secondary-button-group.test.js +1 -1
  65. package/app/pages/cart/partials/order-type-display.jsx +68 -0
  66. package/app/pages/cart/partials/order-type-display.test.js +241 -0
  67. package/app/pages/checkout/confirmation.jsx +79 -158
  68. package/app/pages/checkout/index.jsx +34 -9
  69. package/app/pages/checkout/index.test.js +245 -118
  70. package/app/pages/checkout/partials/contact-info.jsx +2 -6
  71. package/app/pages/checkout/partials/contact-info.test.js +93 -7
  72. package/app/pages/checkout/partials/payment.jsx +19 -5
  73. package/app/pages/checkout/partials/pickup-address.jsx +340 -70
  74. package/app/pages/checkout/partials/pickup-address.test.js +1075 -82
  75. package/app/pages/checkout/partials/product-shipping-address-card.jsx +382 -0
  76. package/app/pages/checkout/partials/shipment-details.jsx +209 -0
  77. package/app/pages/checkout/partials/shipment-details.test.js +246 -0
  78. package/app/pages/checkout/partials/shipping-address.jsx +156 -68
  79. package/app/pages/checkout/partials/shipping-address.test.js +673 -0
  80. package/app/pages/checkout/partials/shipping-method-options.jsx +180 -0
  81. package/app/pages/checkout/partials/shipping-methods.jsx +403 -0
  82. package/app/pages/checkout/partials/shipping-methods.test.js +472 -0
  83. package/app/pages/checkout/partials/shipping-multi-address.jsx +259 -0
  84. package/app/pages/checkout/partials/shipping-multi-address.test.js +2088 -0
  85. package/app/pages/checkout/partials/shipping-product-cards.jsx +101 -0
  86. package/app/pages/checkout/util/checkout-context.js +25 -18
  87. package/app/pages/login/index.jsx +2 -6
  88. package/app/pages/product-detail/index.jsx +96 -81
  89. package/app/pages/product-detail/index.test.js +103 -19
  90. package/app/pages/product-list/index.jsx +3 -1
  91. package/app/pages/product-list/partials/inventory-filter.jsx +18 -21
  92. package/app/pages/product-list/partials/inventory-filter.test.js +15 -17
  93. package/app/pages/product-list/partials/selected-refinements.jsx +3 -1
  94. package/app/ssr.js +1 -1
  95. package/app/static/translations/compiled/en-GB.json +316 -30
  96. package/app/static/translations/compiled/en-US.json +316 -30
  97. package/app/static/translations/compiled/en-XA.json +673 -75
  98. package/app/utils/address-utils.js +112 -0
  99. package/app/utils/address-utils.test.js +484 -0
  100. package/app/utils/product-utils.js +17 -5
  101. package/app/utils/product-utils.test.js +17 -8
  102. package/app/utils/sfdc-user-agent-utils.js +32 -0
  103. package/app/utils/sfdc-user-agent-utils.test.js +82 -0
  104. package/app/utils/shipment-utils.js +196 -0
  105. package/app/utils/shipment-utils.test.js +458 -0
  106. package/app/utils/test-utils.js +4 -4
  107. package/app/utils/utils.js +6 -1
  108. package/config/default.js +4 -1
  109. package/config/mocks/default.js +3 -1
  110. package/package.json +9 -9
  111. package/translations/en-GB.json +127 -10
  112. package/translations/en-US.json +127 -10
  113. package/app/pages/checkout/partials/shipping-options.jsx +0 -269
@@ -1,269 +0,0 @@
1
- /*
2
- * Copyright (c) 2021, salesforce.com, inc.
3
- * All rights reserved.
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
- */
7
- import React, {useEffect} from 'react'
8
- import {FormattedMessage, FormattedNumber, useIntl} from 'react-intl'
9
- import {
10
- Box,
11
- Button,
12
- Container,
13
- Flex,
14
- Radio,
15
- RadioGroup,
16
- Stack,
17
- Text
18
- } from '@salesforce/retail-react-app/app/components/shared/ui'
19
- import {useForm, Controller} from 'react-hook-form'
20
- import {useCheckout} from '@salesforce/retail-react-app/app/pages/checkout/util/checkout-context'
21
- import {ChevronDownIcon} from '@salesforce/retail-react-app/app/components/icons'
22
- import {
23
- ToggleCard,
24
- ToggleCardEdit,
25
- ToggleCardSummary
26
- } from '@salesforce/retail-react-app/app/components/toggle-card'
27
- import {
28
- useShippingMethodsForShipment,
29
- useShopperBasketsMutation
30
- } from '@salesforce/commerce-sdk-react'
31
- import {useCurrentBasket} from '@salesforce/retail-react-app/app/hooks/use-current-basket'
32
- import {useCurrency} from '@salesforce/retail-react-app/app/hooks'
33
-
34
- export default function ShippingOptions() {
35
- const {formatMessage} = useIntl()
36
- const {step, STEPS, goToStep, goToNextStep} = useCheckout()
37
- const {data: basket} = useCurrentBasket()
38
- const {currency} = useCurrency()
39
- const updateShippingMethod = useShopperBasketsMutation('updateShippingMethodForShipment')
40
- const {data: shippingMethods} = useShippingMethodsForShipment(
41
- {
42
- parameters: {
43
- basketId: basket?.basketId,
44
- shipmentId: 'me'
45
- }
46
- },
47
- {
48
- enabled: Boolean(basket?.basketId) && step === STEPS.SHIPPING_OPTIONS
49
- }
50
- )
51
-
52
- const selectedShippingMethod = basket?.shipments?.[0]?.shippingMethod
53
- const selectedShippingAddress = basket?.shipments?.[0]?.shippingAddress
54
-
55
- const form = useForm({
56
- shouldUnregister: false,
57
- defaultValues: {
58
- shippingMethodId: selectedShippingMethod?.id || shippingMethods?.defaultShippingMethodId
59
- }
60
- })
61
-
62
- useEffect(() => {
63
- const defaultMethodId = shippingMethods?.defaultShippingMethodId
64
- const methodId = form.getValues().shippingMethodId
65
- if (!selectedShippingMethod && !methodId && defaultMethodId) {
66
- form.reset({shippingMethodId: defaultMethodId})
67
- }
68
- if (selectedShippingMethod && methodId !== selectedShippingMethod.id) {
69
- form.reset({shippingMethodId: selectedShippingMethod.id})
70
- }
71
- }, [selectedShippingMethod, shippingMethods])
72
-
73
- const submitForm = async ({shippingMethodId}) => {
74
- await updateShippingMethod.mutateAsync({
75
- parameters: {
76
- basketId: basket.basketId,
77
- shipmentId: 'me'
78
- },
79
- body: {
80
- id: shippingMethodId
81
- }
82
- })
83
- goToNextStep()
84
- }
85
-
86
- const shippingItem = basket?.shippingItems?.[0]
87
-
88
- const selectedMethodDisplayPrice = Math.min(
89
- shippingItem?.price || 0,
90
- shippingItem?.priceAfterItemDiscount || 0
91
- )
92
-
93
- const freeLabel = formatMessage({
94
- defaultMessage: 'Free',
95
- id: 'checkout_confirmation.label.free'
96
- })
97
-
98
- let shippingPriceLabel = selectedMethodDisplayPrice
99
- if (selectedMethodDisplayPrice !== shippingItem.price) {
100
- const currentPrice =
101
- selectedMethodDisplayPrice === 0 ? freeLabel : selectedMethodDisplayPrice
102
-
103
- shippingPriceLabel = formatMessage(
104
- {
105
- defaultMessage: 'Originally {originalPrice}, now {newPrice}',
106
- id: 'checkout_confirmation.label.shipping.strikethrough.price'
107
- },
108
- {
109
- originalPrice: shippingItem.price,
110
- newPrice: currentPrice
111
- }
112
- )
113
- }
114
-
115
- // Note that this card is disabled when there is no shipping address as well as no shipping method.
116
- // We do this because we apply the default shipping method to the basket before checkout - so when
117
- // landing on checkout the first time will put you at the first step (contact info), but the shipping
118
- // method step would appear filled out already. This fix attempts to avoid any confusion in the UI.
119
- return (
120
- <ToggleCard
121
- id="step-2"
122
- title={formatMessage({
123
- defaultMessage: 'Shipping & Gift Options',
124
- id: 'shipping_options.title.shipping_gift_options'
125
- })}
126
- editing={step === STEPS.SHIPPING_OPTIONS}
127
- isLoading={form.formState.isSubmitting}
128
- disabled={selectedShippingMethod == null || !selectedShippingAddress}
129
- onEdit={() => goToStep(STEPS.SHIPPING_OPTIONS)}
130
- editLabel={formatMessage({
131
- defaultMessage: 'Edit Shipping Options',
132
- id: 'toggle_card.action.editShippingOptions'
133
- })}
134
- >
135
- <ToggleCardEdit>
136
- <form
137
- onSubmit={form.handleSubmit(submitForm)}
138
- data-testid="sf-checkout-shipping-options-form"
139
- >
140
- <Stack spacing={6}>
141
- {shippingMethods?.applicableShippingMethods && (
142
- <Controller
143
- name="shippingMethodId"
144
- control={form.control}
145
- defaultValue=""
146
- render={({field: {value, onChange}}) => (
147
- <RadioGroup
148
- name="shipping-options-radiogroup"
149
- value={value}
150
- onChange={onChange}
151
- >
152
- <Stack spacing={5}>
153
- {shippingMethods.applicableShippingMethods.map(
154
- (opt) => (
155
- <Radio value={opt.id} key={opt.id}>
156
- <Flex justify="space-between" w="full">
157
- <Box>
158
- <Text>{opt.name}</Text>
159
- <Text
160
- fontSize="sm"
161
- color="gray.600"
162
- >
163
- {opt.description}
164
- </Text>
165
- </Box>
166
- <Text fontWeight="bold">
167
- <FormattedNumber
168
- value={opt.price}
169
- style="currency"
170
- currency={currency}
171
- />
172
- </Text>
173
- </Flex>
174
-
175
- {opt.shippingPromotions?.map((promo) => {
176
- return (
177
- <Text
178
- key={promo.promotionId}
179
- fontSize="sm"
180
- color="green.600"
181
- >
182
- {promo.calloutMsg}
183
- </Text>
184
- )
185
- })}
186
- </Radio>
187
- )
188
- )}
189
- </Stack>
190
- </RadioGroup>
191
- )}
192
- />
193
- )}
194
-
195
- <Box>
196
- <Button variant="link" size="sm" rightIcon={<ChevronDownIcon />}>
197
- <FormattedMessage
198
- defaultMessage="Do you want to send this as a gift?"
199
- id="shipping_options.action.send_as_a_gift"
200
- />
201
- </Button>
202
- </Box>
203
- <Box>
204
- <Container variant="form">
205
- <Button w="full" type="submit">
206
- <FormattedMessage
207
- defaultMessage="Continue to Payment"
208
- id="shipping_options.button.continue_to_payment"
209
- />
210
- </Button>
211
- </Container>
212
- </Box>
213
- </Stack>
214
- </form>
215
- </ToggleCardEdit>
216
-
217
- {selectedShippingMethod && selectedShippingAddress && (
218
- <ToggleCardSummary>
219
- <Flex justify="space-between" w="full">
220
- <Text>{selectedShippingMethod.name}</Text>
221
- <Flex alignItems="center" aria-label={shippingPriceLabel} role="group">
222
- <Text fontWeight="bold" aria-hidden="true" role="presentation">
223
- {selectedMethodDisplayPrice === 0 ? (
224
- freeLabel
225
- ) : (
226
- <FormattedNumber
227
- value={selectedMethodDisplayPrice}
228
- style="currency"
229
- currency={currency}
230
- />
231
- )}
232
- </Text>
233
- {selectedMethodDisplayPrice !== shippingItem.price && (
234
- <Text
235
- fontWeight="normal"
236
- textDecoration="line-through"
237
- color="gray.600"
238
- marginLeft={1}
239
- aria-hidden="true"
240
- role="presentation"
241
- >
242
- <FormattedNumber
243
- style="currency"
244
- currency={currency}
245
- value={shippingItem.price}
246
- />
247
- </Text>
248
- )}
249
- </Flex>
250
- </Flex>
251
- <Text fontSize="sm" color="gray.700">
252
- {selectedShippingMethod.description}
253
- </Text>
254
- {shippingItem?.priceAdjustments?.map((adjustment) => {
255
- return (
256
- <Text
257
- key={adjustment.priceAdjustmentId}
258
- fontSize="sm"
259
- color="green.600"
260
- >
261
- {adjustment.itemText}
262
- </Text>
263
- )
264
- })}
265
- </ToggleCardSummary>
266
- )}
267
- </ToggleCard>
268
- )
269
- }