@magento/peregrine 12.4.0 → 12.5.0

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 (64) hide show
  1. package/lib/Apollo/links/authLink.js +19 -0
  2. package/lib/Apollo/links/errorLink.js +64 -0
  3. package/lib/Apollo/links/gqlCacheLink.js +63 -0
  4. package/lib/Apollo/links/index.js +66 -0
  5. package/lib/Apollo/links/mutationQueueLink.js +5 -0
  6. package/lib/Apollo/links/retryLink.js +17 -0
  7. package/lib/Apollo/links/storeLink.js +22 -0
  8. package/lib/Apollo/magentoGqlCacheLink.js +3 -59
  9. package/lib/PeregrineContextProvider/peregrineContextProvider.js +2 -0
  10. package/lib/context/eventing.js +57 -0
  11. package/lib/hooks/useDelayedTransition.js +1 -1
  12. package/lib/talons/AccountInformationPage/useAccountInformationPage.js +15 -1
  13. package/lib/talons/Adapter/useAdapter.js +23 -200
  14. package/lib/talons/AddToCartDialog/addToCartDialog.gql.js +8 -0
  15. package/lib/talons/AddToCartDialog/useAddToCartDialog.js +46 -2
  16. package/lib/talons/AddressBookPage/useAddressBookPage.js +52 -17
  17. package/lib/talons/AuthModal/useAuthModal.js +12 -2
  18. package/lib/talons/Breadcrumbs/useBreadcrumbs.js +7 -2
  19. package/lib/talons/CartPage/ProductListing/EditModal/__fixtures__/configurableProduct.js +39 -4
  20. package/lib/talons/CartPage/ProductListing/EditModal/useProductForm.js +47 -3
  21. package/lib/talons/CartPage/ProductListing/productListingFragments.gql.js +6 -0
  22. package/lib/talons/CartPage/ProductListing/useProduct.js +49 -3
  23. package/lib/talons/CartPage/useCartPage.js +15 -0
  24. package/lib/talons/CheckoutPage/ItemsReview/itemsReviewFragments.gql.js +12 -14
  25. package/lib/talons/CheckoutPage/OrderConfirmationPage/orderConfirmationPageFragments.gql.js +21 -1
  26. package/lib/talons/CheckoutPage/OrderConfirmationPage/useCreateAccount.js +15 -1
  27. package/lib/talons/CheckoutPage/PaymentInformation/useEditModal.js +10 -1
  28. package/lib/talons/CheckoutPage/PaymentInformation/usePaymentInformation.js +14 -0
  29. package/lib/talons/CheckoutPage/ShippingInformation/AddressForm/useCustomerForm.js +38 -1
  30. package/lib/talons/CheckoutPage/ShippingInformation/AddressForm/useGuestForm.js +15 -1
  31. package/lib/talons/CheckoutPage/ShippingInformation/useShippingInformation.js +13 -0
  32. package/lib/talons/CheckoutPage/ShippingMethod/useShippingMethod.js +28 -6
  33. package/lib/talons/CheckoutPage/checkoutPage.gql.js +3 -0
  34. package/lib/talons/CheckoutPage/useCheckoutPage.js +79 -3
  35. package/lib/talons/Cms/useCmsPage.js +14 -0
  36. package/lib/talons/CreateAccount/useCreateAccount.js +15 -1
  37. package/lib/talons/FilterModal/helpers.js +8 -2
  38. package/lib/talons/FilterModal/useFilterModal.js +1 -0
  39. package/lib/talons/FilterSidebar/useFilterSidebar.js +1 -0
  40. package/lib/talons/Gallery/useAddToCartButton.js +24 -12
  41. package/lib/talons/Gallery/useGalleryItem.js +85 -1
  42. package/lib/talons/Header/storeSwitcher.gql.js +1 -16
  43. package/lib/talons/Header/useAccountMenu.js +21 -2
  44. package/lib/talons/Header/useStoreSwitcher.js +40 -93
  45. package/lib/talons/MagentoRoute/useMagentoRoute.js +7 -7
  46. package/lib/talons/MiniCart/ProductList/productListFragments.gql.js +4 -0
  47. package/lib/talons/MiniCart/useMiniCart.js +46 -3
  48. package/lib/talons/ProductFullDetail/useProductFullDetail.js +37 -9
  49. package/lib/talons/RootComponents/Category/categoryContent.gql.js +2 -0
  50. package/lib/talons/RootComponents/Category/categoryFragments.gql.js +3 -0
  51. package/lib/talons/RootComponents/Category/useCategory.js +4 -1
  52. package/lib/talons/RootComponents/Category/useCategoryContent.js +35 -13
  53. package/lib/talons/RootComponents/Product/productDetailFragment.gql.js +6 -0
  54. package/lib/talons/RootComponents/Product/useProduct.js +27 -0
  55. package/lib/talons/SearchBar/index.js +1 -0
  56. package/lib/talons/SearchBar/useAutocomplete.js +18 -1
  57. package/lib/talons/SearchBar/useSuggestedProduct.js +99 -0
  58. package/lib/talons/SearchPage/searchPage.gql.js +3 -0
  59. package/lib/talons/SearchPage/useSearchPage.js +56 -28
  60. package/lib/talons/SignIn/useSignIn.js +19 -2
  61. package/lib/talons/WishlistPage/useWishlistItem.js +36 -1
  62. package/lib/talons/WishlistPage/wishlistItemFragments.gql.js +3 -0
  63. package/lib/util/makeUrl.js +1 -1
  64. package/package.json +5 -4
@@ -5,6 +5,7 @@ import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
5
5
  import { useCartContext } from '../../../../context/cart';
6
6
  import { findMatchingVariant } from '../../../../util/findMatchingProductVariant';
7
7
  import DEFAULT_OPERATIONS from './productForm.gql';
8
+ import { useEventingContext } from '../../../../context/eventing';
8
9
 
9
10
  /**
10
11
  * This talon contains logic for a product edit form.
@@ -48,6 +49,8 @@ export const useProductForm = props => {
48
49
  setActiveEditItem
49
50
  } = props;
50
51
 
52
+ const [, { dispatch }] = useEventingContext();
53
+
51
54
  const [{ cartId }] = useCartContext();
52
55
  const [optionSelections, setOptionSelections] = useState(new Map());
53
56
 
@@ -116,6 +119,7 @@ export const useProductForm = props => {
116
119
 
117
120
  const configItem =
118
121
  !loading && !error && data ? data.products.items[0] : null;
122
+
119
123
  const configurableOptionCodes = useMemo(() => {
120
124
  const optionCodeMap = new Map();
121
125
 
@@ -158,6 +162,8 @@ export const useProductForm = props => {
158
162
  const handleSubmit = useCallback(
159
163
  async formValues => {
160
164
  try {
165
+ const quantity = formValues.quantity;
166
+
161
167
  if (selectedVariant && optionSelections.size) {
162
168
  await updateConfigurableOptions({
163
169
  variables: {
@@ -165,20 +171,56 @@ export const useProductForm = props => {
165
171
  cartItemId: cartItem.uid,
166
172
  parentSku: cartItem.product.sku,
167
173
  variantSku: selectedVariant.product.sku,
168
- quantity: formValues.quantity
174
+ quantity: quantity
169
175
  }
170
176
  });
171
177
 
172
178
  setOptionSelections(new Map());
173
- } else if (formValues.quantity !== cartItem.quantity) {
179
+ } else if (quantity !== cartItem.quantity) {
174
180
  await updateItemQuantity({
175
181
  variables: {
176
182
  cartId,
177
183
  cartItemId: cartItem.uid,
178
- quantity: formValues.quantity
184
+ quantity: quantity
179
185
  }
180
186
  });
181
187
  }
188
+
189
+ const selectedOptionsLabels =
190
+ // with updated variant
191
+ selectedVariant?.attributes?.map(({ value_index }, i) => {
192
+ const current = configItem.configurable_options[i];
193
+ const attribute = current.label;
194
+ const value = current.values.find(
195
+ x => x.value_index === value_index
196
+ )?.label;
197
+
198
+ return { attribute, value };
199
+ }) ||
200
+ // with current variant (updating only quantity)
201
+ cartItem.configurable_options.map(
202
+ ({ option_label, value_label }) => ({
203
+ attribute: option_label,
204
+ value: value_label
205
+ })
206
+ ) ||
207
+ // not applicable
208
+ null;
209
+
210
+ dispatch({
211
+ type: 'CART_UPDATE_ITEM',
212
+ payload: {
213
+ cartId,
214
+ sku: cartItem.product.sku,
215
+ name: cartItem.product.name,
216
+ priceTotal: cartItem.prices.price.value,
217
+ currencyCode: cartItem.prices.price.currency,
218
+ discountAmount:
219
+ cartItem.prices.total_item_discount.value,
220
+ selectedOptions: selectedOptionsLabels,
221
+ quantity
222
+ }
223
+ });
182
224
  } catch {
183
225
  return;
184
226
  }
@@ -188,6 +230,8 @@ export const useProductForm = props => {
188
230
  [
189
231
  cartId,
190
232
  cartItem,
233
+ configItem,
234
+ dispatch,
191
235
  handleClose,
192
236
  optionSelections.size,
193
237
  selectedVariant,
@@ -40,6 +40,12 @@ export const ProductListingFragment = gql`
40
40
  currency
41
41
  value
42
42
  }
43
+ row_total {
44
+ value
45
+ }
46
+ total_item_discount {
47
+ value
48
+ }
43
49
  }
44
50
  quantity
45
51
  errors {
@@ -3,9 +3,9 @@ import { useIntl } from 'react-intl';
3
3
  import { useMutation, useQuery } from '@apollo/client';
4
4
  import { useCartContext } from '@magento/peregrine/lib/context/cart';
5
5
  import configuredVariant from '@magento/peregrine/lib/util/configuredVariant';
6
-
7
6
  import { deriveErrorMessage } from '../../../util/deriveErrorMessage';
8
7
  import DEFAULT_OPERATIONS from './product.gql';
8
+ import { useEventingContext } from '../../../context/eventing';
9
9
  import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
10
10
 
11
11
  /**
@@ -38,6 +38,8 @@ export const useProduct = props => {
38
38
  wishlistConfig
39
39
  } = props;
40
40
 
41
+ const [, { dispatch }] = useEventingContext();
42
+
41
43
  const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
42
44
  const {
43
45
  removeItemMutation,
@@ -138,11 +140,33 @@ export const useProduct = props => {
138
140
  itemId: item.uid
139
141
  }
140
142
  });
143
+
144
+ const selectedOptionsLabels =
145
+ item.configurable_options?.map(
146
+ ({ option_label, value_label }) => ({
147
+ attribute: option_label,
148
+ value: value_label
149
+ })
150
+ ) || null;
151
+
152
+ dispatch({
153
+ type: 'CART_REMOVE_ITEM',
154
+ payload: {
155
+ cartId,
156
+ sku: item.product.sku,
157
+ name: item.product.name,
158
+ priceTotal: item.prices.price.value,
159
+ currencyCode: item.prices.price.currency,
160
+ discountAmount: item.prices.total_item_discount.value,
161
+ selectedOptions: selectedOptionsLabels,
162
+ quantity: item.quantity
163
+ }
164
+ });
141
165
  } catch (err) {
142
166
  // Make sure any errors from the mutation are displayed.
143
167
  setDisplayError(true);
144
168
  }
145
- }, [cartId, item.uid, removeItemFromCart]);
169
+ }, [cartId, dispatch, item, removeItemFromCart]);
146
170
 
147
171
  const handleUpdateItemQuantity = useCallback(
148
172
  async quantity => {
@@ -154,12 +178,34 @@ export const useProduct = props => {
154
178
  quantity
155
179
  }
156
180
  });
181
+
182
+ const selectedOptions =
183
+ item.configurable_options?.map(
184
+ ({ option_label, value_label }) => ({
185
+ attribute: option_label,
186
+ value: value_label
187
+ })
188
+ ) || null;
189
+
190
+ dispatch({
191
+ type: quantity ? 'CART_UPDATE_ITEM' : 'CART_REMOVE_ITEM',
192
+ payload: {
193
+ cartId,
194
+ sku: item.product.sku,
195
+ name: item.product.name,
196
+ priceTotal: item.prices.price.value,
197
+ currencyCode: item.prices.price.currency,
198
+ discountAmount: item.prices.total_item_discount.value,
199
+ selectedOptions,
200
+ quantity: quantity || item.quantity
201
+ }
202
+ });
157
203
  } catch (err) {
158
204
  // Make sure any errors from the mutation are displayed.
159
205
  setDisplayError(true);
160
206
  }
161
207
  },
162
- [cartId, item.uid, updateItemQuantity]
208
+ [cartId, dispatch, item, updateItemQuantity]
163
209
  );
164
210
 
165
211
  useEffect(() => {
@@ -4,6 +4,7 @@ import { useLazyQuery } from '@apollo/client';
4
4
  import { useCartContext } from '@magento/peregrine/lib/context/cart';
5
5
  import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
6
6
  import DEFAULT_OPERATIONS from './cartPage.gql';
7
+ import { useEventingContext } from '../../context/eventing';
7
8
 
8
9
  /**
9
10
  * This talon contains logic for a cart page component.
@@ -52,6 +53,8 @@ export const useCartPage = (props = {}) => {
52
53
  setWishlistSuccessProps(successToastProps);
53
54
  }, []);
54
55
 
56
+ const [, { dispatch }] = useEventingContext();
57
+
55
58
  useEffect(() => {
56
59
  if (!called && cartId) {
57
60
  fetchCartDetails({ variables: { cartId } });
@@ -61,6 +64,18 @@ export const useCartPage = (props = {}) => {
61
64
  setIsCartUpdating(loading);
62
65
  }, [fetchCartDetails, called, cartId, loading]);
63
66
 
67
+ useEffect(() => {
68
+ if (called && cartId && !loading) {
69
+ dispatch({
70
+ type: 'CART_PAGE_VIEW',
71
+ payload: {
72
+ cart_id: cartId,
73
+ products: cartItems
74
+ }
75
+ });
76
+ }
77
+ }, [called, cartItems, cartId, loading, dispatch]);
78
+
64
79
  return {
65
80
  cartItems,
66
81
  hasItems,
@@ -10,24 +10,22 @@ export const ItemsReviewFragment = gql`
10
10
  # eslint-disable-next-line @graphql-eslint/require-id-when-available
11
11
  product {
12
12
  uid
13
+ sku
13
14
  name
14
15
  thumbnail {
15
16
  url
16
17
  }
17
- # eslint-disable-next-line @graphql-eslint/require-id-when-available
18
- ... on ConfigurableProduct {
19
- variants {
20
- attributes {
21
- uid
22
- }
23
- # eslint-disable-next-line @graphql-eslint/require-id-when-available
24
- product {
25
- uid
26
- thumbnail {
27
- url
28
- }
29
- }
30
- }
18
+ }
19
+ prices {
20
+ price {
21
+ currency
22
+ value
23
+ }
24
+ row_total {
25
+ value
26
+ }
27
+ total_item_discount {
28
+ value
31
29
  }
32
30
  }
33
31
  quantity
@@ -18,12 +18,32 @@ export const OrderConfirmationPageFragment = gql`
18
18
  country {
19
19
  label
20
20
  }
21
-
22
21
  selected_shipping_method {
22
+ amount {
23
+ value
24
+ currency
25
+ }
23
26
  carrier_title
24
27
  method_title
25
28
  }
26
29
  }
30
+ selected_payment_method {
31
+ purchase_order_number
32
+ title
33
+ }
34
+ prices {
35
+ grand_total {
36
+ value
37
+ currency
38
+ }
39
+ discounts {
40
+ amount {
41
+ currency
42
+ value
43
+ }
44
+ label
45
+ }
46
+ }
27
47
  ...ItemsReviewFragment
28
48
  }
29
49
  ${ItemsReviewFragment}
@@ -8,6 +8,7 @@ import { useAwaitQuery } from '../../../hooks/useAwaitQuery';
8
8
  import { useGoogleReCaptcha } from '../../../hooks/useGoogleReCaptcha';
9
9
 
10
10
  import DEFAULT_OPERATIONS from './createAccount.gql';
11
+ import { useEventingContext } from '../../../context/eventing';
11
12
 
12
13
  /**
13
14
  * Returns props necessary to render CreateAccount component. In particular this
@@ -46,6 +47,8 @@ export const useCreateAccount = props => {
46
47
  { getUserDetails, setToken }
47
48
  ] = useUserContext();
48
49
 
50
+ const [, { dispatch }] = useEventingContext();
51
+
49
52
  const [fetchCartId] = useMutation(createCartMutation);
50
53
 
51
54
  // For create account and sign in mutations, we don't want to cache any
@@ -92,6 +95,16 @@ export const useCreateAccount = props => {
92
95
  ...recaptchaDataForCreateAccount
93
96
  });
94
97
 
98
+ dispatch({
99
+ type: 'USER_CREATE_ACCOUNT',
100
+ payload: {
101
+ email: formValues.customer.email,
102
+ firstName: formValues.customer.firstname,
103
+ lastName: formValues.customer.lastname,
104
+ isSubscribed: !!formValues.subscribe
105
+ }
106
+ });
107
+
95
108
  // Get reCaptchaV3 Data for signIn mutation
96
109
  const recaptchaDataForSignIn = await generateReCaptchaData();
97
110
 
@@ -143,7 +156,8 @@ export const useCreateAccount = props => {
143
156
  onSubmit,
144
157
  removeCart,
145
158
  setToken,
146
- signIn
159
+ signIn,
160
+ dispatch
147
161
  ]
148
162
  );
149
163
 
@@ -2,6 +2,7 @@ import { useState, useCallback } from 'react';
2
2
  import { useQuery } from '@apollo/client';
3
3
  import DEFAULT_OPERATIONS from './editModal.gql';
4
4
  import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
5
+ import { useEventingContext } from '../../../context/eventing';
5
6
 
6
7
  import { useCartContext } from '../../../context/cart';
7
8
 
@@ -35,6 +36,7 @@ export const useEditModal = props => {
35
36
  const [isLoading, setIsLoading] = useState(true);
36
37
  const [updateButtonClicked, setUpdateButtonClicked] = useState(false);
37
38
  const [{ cartId }] = useCartContext();
39
+ const [, { dispatch }] = useEventingContext();
38
40
 
39
41
  /**
40
42
  * Queries
@@ -67,7 +69,14 @@ export const useEditModal = props => {
67
69
 
68
70
  const handlePaymentSuccess = useCallback(() => {
69
71
  onClose();
70
- }, [onClose]);
72
+ dispatch({
73
+ type: 'CHECKOUT_BILLING_INFORMATION_UPDATED',
74
+ payload: {
75
+ cart_id: cartId,
76
+ selected_payment_method: selectedPaymentMethod
77
+ }
78
+ });
79
+ }, [onClose, dispatch, cartId, selectedPaymentMethod]);
71
80
 
72
81
  const handlePaymentError = useCallback(() => {
73
82
  setUpdateButtonClicked(false);
@@ -5,6 +5,7 @@ import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
5
5
 
6
6
  import { useCartContext } from '../../../context/cart';
7
7
  import CheckoutError from '../CheckoutError';
8
+ import { useEventingContext } from '../../../context/eventing';
8
9
  import { CHECKOUT_STEP } from '../useCheckoutPage';
9
10
 
10
11
  /**
@@ -44,6 +45,7 @@ export const usePaymentInformation = props => {
44
45
  const [isEditModalActive, setIsEditModalActive] = useState(false);
45
46
  const [{ cartId }] = useCartContext();
46
47
  const client = useApolloClient();
48
+ const [, { dispatch }] = useEventingContext();
47
49
 
48
50
  /**
49
51
  * Helper Functions
@@ -244,6 +246,18 @@ export const usePaymentInformation = props => {
244
246
  }
245
247
  }, [checkoutError, handleExpiredPaymentError]);
246
248
 
249
+ useEffect(() => {
250
+ if (doneEditing) {
251
+ dispatch({
252
+ type: 'CHECKOUT_BILLING_INFORMATION_ADDED',
253
+ payload: {
254
+ cart_id: cartId,
255
+ selected_payment_method: selectedPaymentMethod
256
+ }
257
+ });
258
+ }
259
+ }, [cartId, selectedPaymentMethod, doneEditing, dispatch]);
260
+
247
261
  return {
248
262
  doneEditing,
249
263
  handlePaymentError,
@@ -2,6 +2,7 @@ import { useCallback, useMemo } from 'react';
2
2
  import { useMutation, useQuery } from '@apollo/client';
3
3
  import DEFAULT_OPERATIONS from './customerForm.gql';
4
4
  import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
5
+ import { useEventingContext } from '../../../../context/eventing';
5
6
 
6
7
  export const useCustomerForm = props => {
7
8
  const { afterSubmit, onCancel, onSuccess, shippingData } = props;
@@ -71,6 +72,39 @@ export const useCustomerForm = props => {
71
72
  };
72
73
  }
73
74
 
75
+ const [, { dispatch }] = useEventingContext();
76
+ const dispatchEvent = useCallback(
77
+ (action, address) => {
78
+ if (action === 'ADD') {
79
+ dispatch({
80
+ type: 'USER_ADDRESS_CREATE',
81
+ payload: {
82
+ address: address,
83
+ user: customerData
84
+ }
85
+ });
86
+ }
87
+ if (action === 'EDIT') {
88
+ dispatch({
89
+ type: 'USER_ADDRESS_EDIT',
90
+ payload: {
91
+ address: address,
92
+ user: customerData
93
+ }
94
+ });
95
+ }
96
+ if (!hasDefaultShipping) {
97
+ dispatch({
98
+ type: 'CHECKOUT_SHIPPING_INFORMATION_ADDED',
99
+ payload: {
100
+ cart_id: customerData.cart_id
101
+ }
102
+ });
103
+ }
104
+ },
105
+ [customerData, dispatch, hasDefaultShipping]
106
+ );
107
+
74
108
  const handleSubmit = useCallback(
75
109
  async formValues => {
76
110
  // eslint-disable-next-line no-unused-vars
@@ -92,6 +126,7 @@ export const useCustomerForm = props => {
92
126
  },
93
127
  refetchQueries: [{ query: getCustomerAddressesQuery }]
94
128
  });
129
+ dispatchEvent('EDIT', customerAddress);
95
130
  } else {
96
131
  await createCustomerAddress({
97
132
  variables: {
@@ -102,6 +137,7 @@ export const useCustomerForm = props => {
102
137
  { query: getDefaultShippingQuery }
103
138
  ]
104
139
  });
140
+ dispatchEvent('ADD', customerAddress);
105
141
  }
106
142
  } catch {
107
143
  return;
@@ -118,7 +154,8 @@ export const useCustomerForm = props => {
118
154
  getDefaultShippingQuery,
119
155
  isUpdate,
120
156
  shippingData,
121
- updateCustomerAddress
157
+ updateCustomerAddress,
158
+ dispatchEvent
122
159
  ]
123
160
  );
124
161
 
@@ -4,6 +4,7 @@ import DEFAULT_OPERATIONS from './guestForm.gql';
4
4
  import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
5
5
 
6
6
  import { useCartContext } from '../../../../context/cart';
7
+ import { useEventingContext } from '../../../../context/eventing';
7
8
 
8
9
  export const useGuestForm = props => {
9
10
  const {
@@ -45,6 +46,18 @@ export const useGuestForm = props => {
45
46
  // Simple heuristic to indicate form was submitted prior to this render
46
47
  const isUpdate = !!shippingData.city;
47
48
 
49
+ const [, { dispatch }] = useEventingContext();
50
+ const dispatchEvent = useCallback(() => {
51
+ if (!isUpdate) {
52
+ dispatch({
53
+ type: 'CHECKOUT_SHIPPING_INFORMATION_ADDED',
54
+ payload: {
55
+ cart_id: cartId
56
+ }
57
+ });
58
+ }
59
+ }, [isUpdate, cartId, dispatch]);
60
+
48
61
  const handleSubmit = useCallback(
49
62
  async formValues => {
50
63
  const { country, email, region, ...address } = formValues;
@@ -63,6 +76,7 @@ export const useGuestForm = props => {
63
76
  }
64
77
  }
65
78
  });
79
+ dispatchEvent();
66
80
  } catch {
67
81
  return;
68
82
  }
@@ -71,7 +85,7 @@ export const useGuestForm = props => {
71
85
  afterSubmit();
72
86
  }
73
87
  },
74
- [afterSubmit, cartId, setGuestShipping]
88
+ [afterSubmit, cartId, setGuestShipping, dispatchEvent]
75
89
  );
76
90
 
77
91
  const handleCancel = useCallback(() => {
@@ -7,6 +7,7 @@ import { useAppContext } from '../../../context/app';
7
7
  import { useCartContext } from '../../../context/cart';
8
8
  import { useUserContext } from '../../../context/user';
9
9
  import { MOCKED_ADDRESS } from '../../CartPage/PriceAdjustments/ShippingMethods/useShippingForm';
10
+ import { useEventingContext } from '../../../context/eventing';
10
11
 
11
12
  export const useShippingInformation = props => {
12
13
  const { onSave, toggleActiveContent } = props;
@@ -97,6 +98,7 @@ export const useShippingInformation = props => {
97
98
  // On first submission, when we have data, we should tell the checkout page
98
99
  // so that we set the next step correctly.
99
100
  const doneEditing = !!shippingData && !!shippingData.city;
101
+ const [, { dispatch }] = useEventingContext();
100
102
 
101
103
  useEffect(() => {
102
104
  if (doneEditing) {
@@ -158,6 +160,17 @@ export const useShippingInformation = props => {
158
160
  }
159
161
  }, [isSignedIn, toggleActiveContent, toggleDrawer]);
160
162
 
163
+ useEffect(() => {
164
+ if (doneEditing && hasUpdate) {
165
+ dispatch({
166
+ type: 'CHECKOUT_SHIPPING_INFORMATION_UPDATED',
167
+ payload: {
168
+ cart_id: cartId
169
+ }
170
+ });
171
+ }
172
+ }, [cartId, doneEditing, dispatch, hasUpdate]);
173
+
161
174
  return {
162
175
  doneEditing,
163
176
  handleEditShipping,
@@ -5,6 +5,7 @@ import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
5
5
 
6
6
  import { useCartContext } from '@magento/peregrine/lib/context/cart';
7
7
  import { useUserContext } from '@magento/peregrine/lib/context/user';
8
+ import { useEventingContext } from '../../../context/eventing';
8
9
 
9
10
  export const displayStates = {
10
11
  DONE: 'done',
@@ -53,6 +54,7 @@ export const useShippingMethod = props => {
53
54
 
54
55
  const [{ cartId }] = useCartContext();
55
56
  const [{ isSignedIn }] = useUserContext();
57
+ const [, { dispatch }] = useEventingContext();
56
58
 
57
59
  /*
58
60
  * Apollo Hooks.
@@ -93,11 +95,13 @@ export const useShippingMethod = props => {
93
95
  ? data.cart.shipping_addresses[0]
94
96
  : null;
95
97
 
96
- const derivedSelectedShippingMethod = derivedPrimaryShippingAddress
97
- ? addSerializedProperty(
98
- derivedPrimaryShippingAddress.selected_shipping_method
99
- )
100
- : DEFAULT_SELECTED_SHIPPING_METHOD;
98
+ const derivedSelectedShippingMethod = useMemo(() => {
99
+ return derivedPrimaryShippingAddress
100
+ ? addSerializedProperty(
101
+ derivedPrimaryShippingAddress.selected_shipping_method
102
+ )
103
+ : DEFAULT_SELECTED_SHIPPING_METHOD;
104
+ }, [derivedPrimaryShippingAddress]);
101
105
 
102
106
  const derivedShippingMethods = useMemo(() => {
103
107
  if (!derivedPrimaryShippingAddress)
@@ -128,6 +132,23 @@ export const useShippingMethod = props => {
128
132
  /*
129
133
  * Callbacks.
130
134
  */
135
+ const dispatchEvent = useCallback(
136
+ shippingMethod => {
137
+ dispatch({
138
+ type: !isUpdateMode
139
+ ? 'CHECKOUT_SHIPPING_METHOD_ADDED'
140
+ : 'CHECKOUT_SHIPPING_METHOD_UPDATED',
141
+ payload: {
142
+ cart_id: cartId,
143
+ selected_shipping_method: {
144
+ serializedValue: shippingMethod
145
+ }
146
+ }
147
+ });
148
+ },
149
+ [dispatch, cartId, isUpdateMode]
150
+ );
151
+
131
152
  const handleSubmit = useCallback(
132
153
  async value => {
133
154
  const [carrierCode, methodCode] = deserializeShippingMethod(
@@ -144,13 +165,14 @@ export const useShippingMethod = props => {
144
165
  }
145
166
  }
146
167
  });
168
+ dispatchEvent(value.shipping_method);
147
169
  } catch {
148
170
  return;
149
171
  }
150
172
 
151
173
  setIsUpdateMode(false);
152
174
  },
153
- [cartId, setIsUpdateMode, setShippingMethodCall]
175
+ [cartId, setIsUpdateMode, setShippingMethodCall, dispatchEvent]
154
176
  );
155
177
 
156
178
  const handleCancelUpdate = useCallback(() => {
@@ -1,5 +1,6 @@
1
1
  import { gql } from '@apollo/client';
2
2
  import { CheckoutPageFragment } from './checkoutPageFragments.gql';
3
+ import { ItemsReviewFragment } from './ItemsReview/itemsReviewFragments.gql';
3
4
  import { OrderConfirmationPageFragment } from './OrderConfirmationPage/orderConfirmationPageFragments.gql';
4
5
 
5
6
  export const CREATE_CART = gql`
@@ -37,9 +38,11 @@ export const GET_CHECKOUT_DETAILS = gql`
37
38
  cart(cart_id: $cartId) {
38
39
  id
39
40
  ...CheckoutPageFragment
41
+ ...ItemsReviewFragment
40
42
  }
41
43
  }
42
44
  ${CheckoutPageFragment}
45
+ ${ItemsReviewFragment}
43
46
  `;
44
47
 
45
48
  export const GET_CUSTOMER = gql`