@magento/peregrine 11.0.0-beta.1 → 12.0.0-alpha.3

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 (133) hide show
  1. package/lib/Apollo/magentoGqlCacheLink.js +59 -0
  2. package/lib/List/item.js +12 -9
  3. package/lib/List/list.js +10 -7
  4. package/lib/Price/price.js +0 -1
  5. package/lib/context/cart.js +9 -10
  6. package/lib/hooks/hook-wrappers/useInformedFieldStateWrapper.js +27 -0
  7. package/lib/hooks/useDelayedTransition.js +127 -0
  8. package/lib/hooks/useDetectScrollWidth.js +77 -0
  9. package/lib/hooks/useInternalLink.js +21 -0
  10. package/lib/hooks/useIntersectionObserver.js +7 -0
  11. package/lib/hooks/useIsInViewport.js +44 -0
  12. package/lib/store/actions/app/actions.js +2 -1
  13. package/lib/store/reducers/app.js +8 -1
  14. package/lib/talons/AccountInformationPage/useAccountInformationPage.js +0 -1
  15. package/lib/talons/Adapter/useAdapter.js +23 -3
  16. package/lib/talons/AddressBookPage/useAddressBookPage.js +0 -10
  17. package/lib/talons/Breadcrumbs/breadcrumbs.gql.js +11 -2
  18. package/lib/talons/Breadcrumbs/useBreadcrumbs.js +19 -5
  19. package/lib/talons/CartPage/GiftCards/giftCardFragments.gql.ee.js +14 -0
  20. package/lib/talons/CartPage/GiftCards/giftCardFragments.gql.js +8 -0
  21. package/lib/talons/CartPage/GiftCards/giftCardQueries.gql.ee.js +73 -0
  22. package/lib/talons/CartPage/GiftCards/useGiftCards.js +25 -16
  23. package/lib/talons/CartPage/PriceAdjustments/CouponCode/couponCode.gql.js +56 -0
  24. package/lib/talons/CartPage/PriceAdjustments/CouponCode/couponCodeFragments.gql.js +10 -0
  25. package/lib/talons/CartPage/PriceAdjustments/{useCouponCode.js → CouponCode/useCouponCode.js} +10 -6
  26. package/lib/talons/CartPage/{GiftOptions → PriceAdjustments/GiftOptions}/client-schema.graphql +0 -0
  27. package/lib/talons/CartPage/PriceAdjustments/GiftOptions/giftOptions.gql.js +21 -0
  28. package/lib/talons/CartPage/{GiftOptions → PriceAdjustments/GiftOptions}/useGiftOptions.js +5 -3
  29. package/lib/talons/CartPage/PriceAdjustments/ShippingMethods/shippingMethods.gql.js +43 -0
  30. package/lib/talons/CartPage/PriceAdjustments/ShippingMethods/shippingMethodsFragments.gql.js +60 -0
  31. package/lib/talons/CartPage/PriceAdjustments/ShippingMethods/useShippingForm.js +8 -9
  32. package/lib/talons/CartPage/PriceAdjustments/ShippingMethods/useShippingMethods.js +7 -5
  33. package/lib/talons/CartPage/PriceAdjustments/ShippingMethods/useShippingRadios.js +1 -1
  34. package/lib/talons/CartPage/PriceSummary/priceSummary.gql.js +16 -0
  35. package/lib/talons/CartPage/PriceSummary/usePriceSummary.js +6 -5
  36. package/lib/talons/CartPage/ProductListing/EditModal/productForm.gql.js +78 -0
  37. package/lib/talons/CartPage/ProductListing/EditModal/productFormFragment.gql.js +47 -0
  38. package/lib/talons/CartPage/ProductListing/EditModal/useProductForm.js +18 -8
  39. package/lib/talons/CartPage/ProductListing/product.gql.js +4 -3
  40. package/lib/talons/CartPage/ProductListing/productListing.gql.ce.js +13 -1
  41. package/lib/talons/CartPage/ProductListing/productListing.gql.ee.js +13 -1
  42. package/lib/talons/CartPage/ProductListing/productListingFragments.gql.js +52 -0
  43. package/lib/talons/CartPage/ProductListing/useProduct.js +22 -18
  44. package/lib/talons/CartPage/ProductListing/useProductListing.js +8 -13
  45. package/lib/talons/CartPage/ProductListing/useQuantity.js +2 -1
  46. package/lib/talons/CartPage/cartPage.gql.js +16 -0
  47. package/lib/talons/CartPage/cartPageFragments.gql.js +21 -0
  48. package/lib/talons/CartPage/useCartPage.js +7 -6
  49. package/lib/talons/CategoryList/categoryList.gql.js +11 -2
  50. package/lib/talons/CategoryList/useCategoryList.js +8 -1
  51. package/lib/talons/CategoryList/useCategoryTile.js +10 -4
  52. package/lib/talons/CategoryTree/categoryTree.gql.js +11 -2
  53. package/lib/talons/CategoryTree/useCategoryTree.js +12 -3
  54. package/lib/talons/CheckoutPage/AddressBook/addressBook.gql.js +34 -0
  55. package/lib/talons/CheckoutPage/AddressBook/addressBookFragments.gql.js +31 -0
  56. package/lib/talons/CheckoutPage/AddressBook/useAddressBook.js +16 -8
  57. package/lib/talons/CheckoutPage/PaymentInformation/braintreeSummary.gql.js +1 -1
  58. package/lib/talons/CheckoutPage/PaymentInformation/editModal.gql.js +16 -0
  59. package/lib/talons/CheckoutPage/PaymentInformation/paymentInformation.gql.js +4 -8
  60. package/lib/talons/CheckoutPage/PaymentInformation/paymentMethods.gql.js +17 -0
  61. package/lib/talons/CheckoutPage/PaymentInformation/useBraintreeSummary.js +1 -1
  62. package/lib/talons/CheckoutPage/PaymentInformation/useEditModal.js +6 -5
  63. package/lib/talons/CheckoutPage/PaymentInformation/usePaymentInformation.js +22 -16
  64. package/lib/talons/CheckoutPage/PaymentInformation/usePaymentMethods.js +6 -3
  65. package/lib/talons/CheckoutPage/ShippingInformation/AddressForm/customerForm.gql.js +55 -0
  66. package/lib/talons/CheckoutPage/ShippingInformation/AddressForm/guestForm.gql.js +44 -0
  67. package/lib/talons/CheckoutPage/ShippingInformation/AddressForm/useCustomerForm.js +11 -14
  68. package/lib/talons/CheckoutPage/ShippingInformation/AddressForm/useGuestForm.js +6 -7
  69. package/lib/talons/CheckoutPage/ShippingInformation/shippingInformation.gql.js +54 -0
  70. package/lib/talons/CheckoutPage/ShippingInformation/shippingInformationFragments.gql.js +25 -0
  71. package/lib/talons/CheckoutPage/ShippingInformation/useShippingInformation.js +11 -6
  72. package/lib/talons/CheckoutPage/ShippingMethod/shippingMethod.gql.js +64 -0
  73. package/lib/talons/CheckoutPage/ShippingMethod/shippingMethodFragments.gql.js +64 -0
  74. package/lib/talons/CheckoutPage/{useShippingMethod.js → ShippingMethod/useShippingMethod.js} +11 -8
  75. package/lib/talons/Cms/cmsPage.gql.js +2 -2
  76. package/lib/talons/Cms/useCmsPage.js +2 -2
  77. package/lib/talons/CommunicationsPage/useCommunicationsPage.js +1 -2
  78. package/lib/talons/CreateAccount/createAccount.gql.js +3 -0
  79. package/lib/talons/CreateAccount/useCreateAccount.js +2 -4
  80. package/lib/talons/CreateAccountPage/useCreateAccountPage.js +38 -9
  81. package/lib/talons/FilterModal/useFilterList.js +17 -3
  82. package/lib/talons/FilterModal/useFilterModal.js +4 -5
  83. package/lib/talons/FilterSidebar/useFilterSidebar.js +4 -5
  84. package/lib/talons/ForgotPasswordPage/useForgotPasswordPage.js +46 -0
  85. package/lib/talons/FormError/useFormError.js +10 -3
  86. package/lib/talons/Gallery/__fixtures__/apolloMocks.js +8 -6
  87. package/lib/talons/Gallery/addToCart.gql.js +17 -0
  88. package/lib/talons/Gallery/gallery.gql.ce.js +4 -3
  89. package/lib/talons/Gallery/gallery.gql.ee.js +4 -3
  90. package/lib/talons/Gallery/useAddToCartButton.js +81 -0
  91. package/lib/talons/Gallery/useGallery.js +4 -7
  92. package/lib/talons/Gallery/useGalleryItem.js +7 -1
  93. package/lib/talons/Header/useCartTrigger.js +14 -7
  94. package/lib/talons/Link/useLink.js +68 -0
  95. package/lib/talons/MagentoRoute/magentoRoute.gql.js +12 -3
  96. package/lib/talons/MagentoRoute/useMagentoRoute.js +115 -30
  97. package/lib/talons/MegaMenu/megaMenu.gql.js +10 -4
  98. package/lib/talons/MegaMenu/useMegaMenu.js +61 -11
  99. package/lib/talons/MegaMenu/useMegaMenuItem.js +61 -0
  100. package/lib/talons/MegaMenu/useSubMenu.js +20 -0
  101. package/lib/talons/MiniCart/ProductList/productListFragments.gql.js +0 -1
  102. package/lib/talons/MiniCart/miniCart.gql.js +4 -3
  103. package/lib/talons/MiniCart/useMiniCart.js +15 -12
  104. package/lib/talons/Navigation/useNavigation.js +6 -1
  105. package/lib/talons/OrderHistoryPage/orderRow.gql.js +0 -1
  106. package/lib/talons/OrderHistoryPage/useOrderHistoryPage.js +2 -14
  107. package/lib/talons/PageLoadingIndicator/usePageLoadingIndicator.js +52 -0
  108. package/lib/talons/Postcode/usePostcode.js +2 -1
  109. package/lib/talons/ProductFullDetail/useProductFullDetail.js +30 -5
  110. package/lib/talons/Region/useRegion.js +12 -10
  111. package/lib/talons/RootComponents/Category/categoryFragments.gql.js +5 -4
  112. package/lib/talons/RootComponents/Product/productDetailFragment.gql.js +7 -0
  113. package/lib/talons/SavedPaymentsPage/useSavedPaymentsPage.js +1 -11
  114. package/lib/talons/SearchBar/useAutocomplete.js +1 -1
  115. package/lib/talons/SearchBar/useSearchField.js +2 -1
  116. package/lib/talons/SearchBar/useSuggestedCategory.js +4 -6
  117. package/lib/talons/SearchPage/searchPage.gql.js +10 -9
  118. package/lib/talons/SignIn/signIn.gql.js +3 -0
  119. package/lib/talons/SignInPage/useSignInPage.js +63 -0
  120. package/lib/talons/Wishlist/AddToListButton/helpers/useSingleWishlist.js +2 -2
  121. package/lib/talons/Wishlist/AddToListButton/useAddToListButton.ee.js +2 -1
  122. package/lib/talons/WishlistPage/useActionMenu.js +39 -5
  123. package/lib/talons/WishlistPage/useWishlist.js +4 -4
  124. package/lib/talons/WishlistPage/useWishlistPage.js +3 -11
  125. package/lib/talons/WishlistPage/wishlist.gql.js +1 -1
  126. package/lib/talons/WishlistPage/wishlistConfig.gql.ce.js +14 -0
  127. package/lib/talons/WishlistPage/wishlistConfig.gql.ee.js +15 -0
  128. package/lib/targets/peregrine-declare.js +0 -4
  129. package/lib/util/deriveErrorMessage.js +12 -6
  130. package/lib/util/images.js +3 -2
  131. package/lib/util/isSupportedProductType.js +5 -0
  132. package/lib/util/magentoRouteData.js +9 -0
  133. package/package.json +8 -8
@@ -0,0 +1,64 @@
1
+ import { gql } from '@apollo/client';
2
+
3
+ import { PriceSummaryFragment } from '../../CartPage/PriceSummary/priceSummaryFragments.gql';
4
+ import { ShippingInformationFragment } from '../ShippingInformation/shippingInformationFragments.gql';
5
+
6
+ import {
7
+ AvailableShippingMethodsCheckoutFragment,
8
+ SelectedShippingMethodCheckoutFragment
9
+ } from './shippingMethodFragments.gql';
10
+
11
+ export const GET_SELECTED_AND_AVAILABLE_SHIPPING_METHODS = gql`
12
+ query getSelectedAndAvailableShippingMethods($cartId: String!) {
13
+ cart(cart_id: $cartId) {
14
+ id
15
+ ...AvailableShippingMethodsCheckoutFragment
16
+ ...SelectedShippingMethodCheckoutFragment
17
+ # We include the following fragments to avoid extra requeries
18
+ # after this mutation completes. This all comes down to not
19
+ # having ids for shipping address objects. With ids we could
20
+ # merge results.
21
+ ...ShippingInformationFragment
22
+ }
23
+ }
24
+ ${AvailableShippingMethodsCheckoutFragment}
25
+ ${SelectedShippingMethodCheckoutFragment}
26
+ ${ShippingInformationFragment}
27
+ `;
28
+
29
+ export const SET_SHIPPING_METHOD = gql`
30
+ mutation SetShippingMethod(
31
+ $cartId: String!
32
+ $shippingMethod: ShippingMethodInput!
33
+ ) {
34
+ setShippingMethodsOnCart(
35
+ input: { cart_id: $cartId, shipping_methods: [$shippingMethod] }
36
+ ) @connection(key: "setShippingMethodsOnCart") {
37
+ cart {
38
+ id
39
+ # If this mutation causes "free" to become available we need to know.
40
+ available_payment_methods {
41
+ code
42
+ title
43
+ }
44
+ ...SelectedShippingMethodCheckoutFragment
45
+ ...PriceSummaryFragment
46
+ # We include the following fragments to avoid extra requeries
47
+ # after this mutation completes. This all comes down to not
48
+ # having ids for shipping address objects. With ids we could
49
+ # merge results.
50
+ ...ShippingInformationFragment
51
+ ...AvailableShippingMethodsCheckoutFragment
52
+ }
53
+ }
54
+ }
55
+ ${AvailableShippingMethodsCheckoutFragment}
56
+ ${SelectedShippingMethodCheckoutFragment}
57
+ ${PriceSummaryFragment}
58
+ ${ShippingInformationFragment}
59
+ `;
60
+
61
+ export default {
62
+ setShippingMethodMutation: SET_SHIPPING_METHOD,
63
+ getSelectedAndAvailableShippingMethodsQuery: GET_SELECTED_AND_AVAILABLE_SHIPPING_METHODS
64
+ };
@@ -0,0 +1,64 @@
1
+ import { gql } from '@apollo/client';
2
+
3
+ /**
4
+ * WARNING: This fragment can cause slowdowns on the network request because it
5
+ * causes the backend to make remote queries to carriers for real-time data.
6
+ * Make sure you are conscious about the side effects when including it in queries and mutations.
7
+ */
8
+ export const AvailableShippingMethodsCheckoutFragment = gql`
9
+ fragment AvailableShippingMethodsCheckoutFragment on Cart {
10
+ id
11
+ shipping_addresses {
12
+ available_shipping_methods {
13
+ amount {
14
+ currency
15
+ value
16
+ }
17
+ available
18
+ carrier_code
19
+ carrier_title
20
+ method_code
21
+ method_title
22
+ }
23
+ street
24
+ }
25
+ }
26
+ `;
27
+
28
+ export const SelectedShippingMethodCheckoutFragment = gql`
29
+ fragment SelectedShippingMethodCheckoutFragment on Cart {
30
+ id
31
+ shipping_addresses {
32
+ selected_shipping_method {
33
+ amount {
34
+ currency
35
+ value
36
+ }
37
+ carrier_code
38
+ method_code
39
+ method_title
40
+ }
41
+ street
42
+ }
43
+ }
44
+ `;
45
+
46
+ export const ShippingMethodsCheckoutFragment = gql`
47
+ fragment ShippingMethodsCheckoutFragment on Cart {
48
+ id
49
+ ...AvailableShippingMethodsCheckoutFragment
50
+ ...SelectedShippingMethodCheckoutFragment
51
+ shipping_addresses {
52
+ country {
53
+ code
54
+ }
55
+ postcode
56
+ region {
57
+ code
58
+ }
59
+ street
60
+ }
61
+ }
62
+ ${AvailableShippingMethodsCheckoutFragment}
63
+ ${SelectedShippingMethodCheckoutFragment}
64
+ `;
@@ -1,5 +1,7 @@
1
1
  import { useCallback, useEffect, useMemo, useState } from 'react';
2
2
  import { useMutation, useQuery } from '@apollo/client';
3
+ import DEFAULT_OPERATIONS from './shippingMethod.gql';
4
+ import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
3
5
 
4
6
  import { useCartContext } from '@magento/peregrine/lib/context/cart';
5
7
  import { useUserContext } from '@magento/peregrine/lib/context/user';
@@ -40,13 +42,14 @@ const DEFAULT_SELECTED_SHIPPING_METHOD = null;
40
42
  const DEFAULT_AVAILABLE_SHIPPING_METHODS = [];
41
43
 
42
44
  export const useShippingMethod = props => {
45
+ const { onSave, onSuccess, setPageIsUpdating } = props;
46
+
47
+ const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
48
+
43
49
  const {
44
- onSave,
45
- onSuccess,
46
- mutations: { setShippingMethod },
47
- queries: { getSelectedAndAvailableShippingMethods },
48
- setPageIsUpdating
49
- } = props;
50
+ getSelectedAndAvailableShippingMethodsQuery,
51
+ setShippingMethodMutation
52
+ } = operations;
50
53
 
51
54
  const [{ cartId }] = useCartContext();
52
55
  const [{ isSignedIn }] = useUserContext();
@@ -57,14 +60,14 @@ export const useShippingMethod = props => {
57
60
  const [
58
61
  setShippingMethodCall,
59
62
  { error: setShippingMethodError, loading: isSettingShippingMethod }
60
- ] = useMutation(setShippingMethod, {
63
+ ] = useMutation(setShippingMethodMutation, {
61
64
  onCompleted: () => {
62
65
  onSuccess();
63
66
  }
64
67
  });
65
68
 
66
69
  const { data, loading: isLoadingShippingMethods } = useQuery(
67
- getSelectedAndAvailableShippingMethods,
70
+ getSelectedAndAvailableShippingMethodsQuery,
68
71
  {
69
72
  fetchPolicy: 'cache-and-network',
70
73
  nextFetchPolicy: 'cache-first',
@@ -1,8 +1,8 @@
1
1
  import { gql } from '@apollo/client';
2
2
 
3
3
  export const GET_CMS_PAGE = gql`
4
- query GetCmsPage($id: Int!) {
5
- cmsPage(id: $id) {
4
+ query GetCmsPage($identifier: String!) {
5
+ cmsPage(identifier: $identifier) {
6
6
  url_key
7
7
  content
8
8
  content_heading
@@ -16,14 +16,14 @@ import DEFAULT_OPERATIONS from './cmsPage.gql';
16
16
  * @returns {{shouldShowLoadingIndicator: *, hasContent: *, cmsPage: *, error: *}}
17
17
  */
18
18
  export const useCmsPage = props => {
19
- const { id } = props;
19
+ const { identifier } = props;
20
20
 
21
21
  const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
22
22
  const { getCMSPageQuery } = operations;
23
23
 
24
24
  const { loading, error, data } = useQuery(getCMSPageQuery, {
25
25
  variables: {
26
- id: Number(id)
26
+ identifier: identifier
27
27
  },
28
28
  fetchPolicy: 'cache-and-network',
29
29
  nextFetchPolicy: 'cache-first'
@@ -55,7 +55,6 @@ export const useCommunicationsPage = props => {
55
55
  formErrors: [setNewsletterSubscriptionError, subscriptionDataError],
56
56
  initialValues,
57
57
  handleSubmit,
58
- isDisabled: isSubmitting,
59
- isSignedIn
58
+ isDisabled: isSubmitting
60
59
  };
61
60
  };
@@ -1,4 +1,5 @@
1
1
  import { gql } from '@apollo/client';
2
+ import { CheckoutPageFragment } from '../CheckoutPage/checkoutPageFragments.gql';
2
3
 
3
4
  export const CREATE_ACCOUNT = gql`
4
5
  mutation CreateAccount(
@@ -112,8 +113,10 @@ export const MERGE_CARTS = gql`
112
113
  items {
113
114
  id
114
115
  }
116
+ ...CheckoutPageFragment
115
117
  }
116
118
  }
119
+ ${CheckoutPageFragment}
117
120
  `;
118
121
 
119
122
  export default {
@@ -46,7 +46,7 @@ export const useCreateAccount = props => {
46
46
  { createCart, removeCart, getCartDetails }
47
47
  ] = useCartContext();
48
48
  const [
49
- { isGettingDetails, isSignedIn },
49
+ { isGettingDetails },
50
50
  { getUserDetails, setToken }
51
51
  ] = useUserContext();
52
52
 
@@ -178,8 +178,7 @@ export const useCreateAccount = props => {
178
178
  handleCancel,
179
179
  handleSubmit,
180
180
  initialValues: sanitizedInitialValues,
181
- isDisabled: isSubmitting || isGettingDetails,
182
- isSignedIn
181
+ isDisabled: isSubmitting || isGettingDetails
183
182
  };
184
183
  };
185
184
 
@@ -240,5 +239,4 @@ export const useCreateAccount = props => {
240
239
  * @property {Function} handleSubmit callback function to handle form submission
241
240
  * @property {SanitizedInitialValues} initialValues initial values for the create account form
242
241
  * @property {Boolean} isDisabled true if either details are being fetched or form is being submitted. False otherwise.
243
- * @property {Boolean} isSignedIn true if user is signed in. False otherwise.
244
242
  */
@@ -1,6 +1,8 @@
1
- import { useCallback, useMemo } from 'react';
1
+ import { useCallback, useEffect, useMemo } from 'react';
2
2
  import { useHistory, useLocation } from 'react-router-dom';
3
3
 
4
+ import { useUserContext } from '@magento/peregrine/lib/context/user';
5
+
4
6
  const validCreateAccountParams = ['email', 'firstName', 'lastName'];
5
7
 
6
8
  const getCreateAccountInitialValues = search => {
@@ -13,27 +15,54 @@ const getCreateAccountInitialValues = search => {
13
15
  };
14
16
 
15
17
  /**
16
- * Returns props necessary to render CreateAccountPage component.
18
+ * @typedef {function} useCreateAccountPage
19
+ *
20
+ * @param {String} props.signedInRedirectUrl - Url to push when user is signed in
21
+ * @param {String} props.signInPageUrl - Sign In Page url
17
22
  *
18
23
  * @returns {{
19
- * handleCreateAccount: function,
20
- * initialValues: object
24
+ * createAccountProps: object
21
25
  * }}
22
26
  */
23
- export const useCreateAccountPage = () => {
27
+ export const useCreateAccountPage = props => {
28
+ const { signedInRedirectUrl, signInPageUrl } = props;
24
29
  const history = useHistory();
30
+ const [{ isSignedIn }] = useUserContext();
25
31
  const { search } = useLocation();
26
32
 
27
- const handleCreateAccount = useCallback(() => {
28
- history.push('/');
33
+ // Keep location state in memory when pushing history and redirect to
34
+ // the `from` url instead when creating an account
35
+ const historyState = useMemo(() => {
36
+ return history && history.location.state ? history.location.state : {};
29
37
  }, [history]);
38
+ const fromRedirectUrl = historyState.from || null;
39
+
40
+ // Redirect if user is signed in
41
+ useEffect(() => {
42
+ if (isSignedIn) {
43
+ if (fromRedirectUrl || signedInRedirectUrl) {
44
+ history.push(fromRedirectUrl || signedInRedirectUrl);
45
+ }
46
+ }
47
+ }, [fromRedirectUrl, history, isSignedIn, signedInRedirectUrl]);
48
+
49
+ const handleOnCancel = useCallback(() => {
50
+ if (signInPageUrl) {
51
+ history.push(signInPageUrl, historyState);
52
+ }
53
+ }, [history, historyState, signInPageUrl]);
30
54
 
31
55
  const initialValues = useMemo(() => getCreateAccountInitialValues(search), [
32
56
  search
33
57
  ]);
34
58
 
59
+ const createAccountProps = {
60
+ initialValues,
61
+ isCancelButtonHidden: false,
62
+ onCancel: handleOnCancel
63
+ };
64
+
35
65
  return {
36
- handleCreateAccount,
37
- initialValues
66
+ createAccountProps
38
67
  };
39
68
  };
@@ -1,7 +1,21 @@
1
- import { useCallback, useState } from 'react';
1
+ import { useCallback, useMemo, useState } from 'react';
2
2
 
3
- export const useFilterList = () => {
4
- const [isListExpanded, setExpanded] = useState(false);
3
+ export const useFilterList = props => {
4
+ const { filterState, items, itemCountToShow } = props;
5
+
6
+ const hasSelected = useMemo(
7
+ () =>
8
+ items.some((item, index) => {
9
+ return (
10
+ filterState &&
11
+ filterState.has(item) &&
12
+ index >= itemCountToShow
13
+ );
14
+ }),
15
+ [filterState, itemCountToShow, items]
16
+ );
17
+
18
+ const [isListExpanded, setExpanded] = useState(hasSelected);
5
19
 
6
20
  const handleListToggle = useCallback(() => {
7
21
  setExpanded(value => !value);
@@ -39,10 +39,6 @@ export const useFilterModal = props => {
39
39
 
40
40
  const { data: introspectionData } = useQuery(getFilterInputsQuery);
41
41
 
42
- const inputFields = introspectionData
43
- ? introspectionData.__type.inputFields
44
- : [];
45
-
46
42
  const attributeCodes = useMemo(
47
43
  () => filters.map(({ attribute_code }) => attribute_code),
48
44
  [filters]
@@ -64,6 +60,9 @@ export const useFilterModal = props => {
64
60
  // that the api will understand.
65
61
  const possibleFilters = useMemo(() => {
66
62
  const nextFilters = new Set();
63
+ const inputFields = introspectionData
64
+ ? introspectionData.__type.inputFields
65
+ : [];
67
66
 
68
67
  // perform mapping and filtering in the same cycle
69
68
  for (const { name } of inputFields) {
@@ -76,7 +75,7 @@ export const useFilterModal = props => {
76
75
  }
77
76
 
78
77
  return nextFilters;
79
- }, [DISABLED_FILTERS, attributeCodes, inputFields]);
78
+ }, [DISABLED_FILTERS, attributeCodes, introspectionData]);
80
79
 
81
80
  // iterate over filters once to set up all the collections we need
82
81
  const [filterNames, filterKeys, filterItems] = useMemo(() => {
@@ -33,10 +33,6 @@ export const useFilterSidebar = props => {
33
33
 
34
34
  const { data: introspectionData } = useQuery(getFilterInputsQuery);
35
35
 
36
- const inputFields = introspectionData
37
- ? introspectionData.__type.inputFields
38
- : [];
39
-
40
36
  const attributeCodes = useMemo(
41
37
  () => filters.map(({ attribute_code }) => attribute_code),
42
38
  [filters]
@@ -58,6 +54,9 @@ export const useFilterSidebar = props => {
58
54
  // that the api will understand.
59
55
  const possibleFilters = useMemo(() => {
60
56
  const nextFilters = new Set();
57
+ const inputFields = introspectionData
58
+ ? introspectionData.__type.inputFields
59
+ : [];
61
60
 
62
61
  // perform mapping and filtering in the same cycle
63
62
  for (const { name } of inputFields) {
@@ -70,7 +69,7 @@ export const useFilterSidebar = props => {
70
69
  }
71
70
 
72
71
  return nextFilters;
73
- }, [DISABLED_FILTERS, attributeCodes, inputFields]);
72
+ }, [DISABLED_FILTERS, attributeCodes, introspectionData]);
74
73
 
75
74
  // iterate over filters once to set up all the collections we need
76
75
  const [filterNames, filterKeys, filterItems] = useMemo(() => {
@@ -0,0 +1,46 @@
1
+ import { useCallback, useEffect, useMemo } from 'react';
2
+ import { useHistory } from 'react-router-dom';
3
+
4
+ import { useUserContext } from '@magento/peregrine/lib/context/user';
5
+
6
+ /**
7
+ * @typedef {function} useForgotPasswordPage
8
+ *
9
+ * @param {String} props.signedInRedirectUrl - Url to push when user is signed in
10
+ * @param {String} props.signInPageUrl - Sign In Page url
11
+ *
12
+ * @returns {{
13
+ * forgotPasswordProps: object
14
+ * }}
15
+ */
16
+ export const useForgotPasswordPage = props => {
17
+ const { signedInRedirectUrl, signInPageUrl } = props;
18
+ const history = useHistory();
19
+ const [{ isSignedIn }] = useUserContext();
20
+
21
+ // Keep location state in memory when pushing history
22
+ const historyState = useMemo(() => {
23
+ return history && history.location.state ? history.location.state : {};
24
+ }, [history]);
25
+
26
+ // Redirect if user is signed in
27
+ useEffect(() => {
28
+ if (isSignedIn && signedInRedirectUrl) {
29
+ history.push(signedInRedirectUrl);
30
+ }
31
+ }, [history, isSignedIn, signedInRedirectUrl]);
32
+
33
+ const handleOnCancel = useCallback(() => {
34
+ if (signInPageUrl) {
35
+ history.push(signInPageUrl, historyState);
36
+ }
37
+ }, [history, historyState, signInPageUrl]);
38
+
39
+ const forgotPasswordProps = {
40
+ onCancel: handleOnCancel
41
+ };
42
+
43
+ return {
44
+ forgotPasswordProps
45
+ };
46
+ };
@@ -1,12 +1,19 @@
1
1
  import { useMemo } from 'react';
2
2
  import { deriveErrorMessage } from '../../util/deriveErrorMessage';
3
+ import { useIntl } from 'react-intl';
3
4
 
4
5
  export const useFormError = props => {
5
6
  const { errors } = props;
7
+ const { formatMessage } = useIntl();
6
8
 
7
- const derivedErrorMessage = useMemo(() => deriveErrorMessage(errors), [
8
- errors
9
- ]);
9
+ const derivedErrorMessage = useMemo(() => {
10
+ const defaultErrorMessage = formatMessage({
11
+ id: 'formError.errorMessage',
12
+ defaultMessage:
13
+ 'An error has occurred. Please check the input and try again.'
14
+ });
15
+ return deriveErrorMessage(errors, defaultErrorMessage);
16
+ }, [errors, formatMessage]);
10
17
 
11
18
  return {
12
19
  errorMessage: derivedErrorMessage
@@ -1,30 +1,32 @@
1
1
  import eeOperations from '../gallery.gql.ee';
2
2
  import ceOperations from '../gallery.gql.ce';
3
3
 
4
- export const mockGetWishlistConfigEE = {
4
+ export const mockGetStoreConfigEE = {
5
5
  request: {
6
- query: eeOperations.getWishlistConfigQuery
6
+ query: eeOperations.getStoreConfigQuery
7
7
  },
8
8
  result: {
9
9
  data: {
10
10
  storeConfig: {
11
11
  id: 1,
12
12
  magento_wishlist_general_is_enabled: '1',
13
- enable_multiple_wishlists: '1'
13
+ enable_multiple_wishlists: '1',
14
+ product_url_suffix: '.html'
14
15
  }
15
16
  }
16
17
  }
17
18
  };
18
19
 
19
- export const mockGetWishlistConfigCE = {
20
+ export const mockGetStoreConfigCE = {
20
21
  request: {
21
- query: ceOperations.getWishlistConfigQuery
22
+ query: ceOperations.getStoreConfigQuery
22
23
  },
23
24
  result: {
24
25
  data: {
25
26
  storeConfig: {
26
27
  id: 1,
27
- magento_wishlist_general_is_enabled: '1'
28
+ magento_wishlist_general_is_enabled: '1',
29
+ product_url_suffix: '.html'
28
30
  }
29
31
  }
30
32
  }
@@ -0,0 +1,17 @@
1
+ import { gql } from '@apollo/client';
2
+ import { MiniCartFragment } from '../MiniCart/miniCartFragments.gql';
3
+
4
+ const ADD_ITEM = gql`
5
+ mutation AddItemToCart($cartId: String!, $cartItem: CartItemInput!) {
6
+ addProductsToCart(cartId: $cartId, cartItems: [$cartItem]) {
7
+ cart {
8
+ id
9
+ ...MiniCartFragment
10
+ }
11
+ }
12
+ }
13
+ ${MiniCartFragment}
14
+ `;
15
+ export default {
16
+ ADD_ITEM
17
+ };
@@ -1,14 +1,15 @@
1
1
  import { gql } from '@apollo/client';
2
2
 
3
- export const GET_WISHLIST_CONFIG = gql`
4
- query GetWishlistConfigForGalleryCE {
3
+ export const GET_STORE_CONFIG_DATA = gql`
4
+ query GetStoreConfigDataForGalleryCE {
5
5
  storeConfig {
6
6
  id
7
+ product_url_suffix
7
8
  magento_wishlist_general_is_enabled
8
9
  }
9
10
  }
10
11
  `;
11
12
 
12
13
  export default {
13
- getWishlistConfigQuery: GET_WISHLIST_CONFIG
14
+ getStoreConfigQuery: GET_STORE_CONFIG_DATA
14
15
  };
@@ -1,9 +1,10 @@
1
1
  import { gql } from '@apollo/client';
2
2
 
3
- export const GET_WISHLIST_CONFIG = gql`
4
- query GetWishlistConfigForGalleryEE {
3
+ export const GET_STORE_CONFIG_DATA = gql`
4
+ query GetStoreConfigDataForGalleryEE {
5
5
  storeConfig {
6
6
  id
7
+ product_url_suffix
7
8
  magento_wishlist_general_is_enabled
8
9
  enable_multiple_wishlists
9
10
  }
@@ -11,5 +12,5 @@ export const GET_WISHLIST_CONFIG = gql`
11
12
  `;
12
13
 
13
14
  export default {
14
- getWishlistConfigQuery: GET_WISHLIST_CONFIG
15
+ getStoreConfigQuery: GET_STORE_CONFIG_DATA
15
16
  };
@@ -0,0 +1,81 @@
1
+ import { useCallback, useState } from 'react';
2
+ import { useMutation } from '@apollo/client';
3
+ import { useHistory } from 'react-router-dom';
4
+
5
+ import { useCartContext } from '../../context/cart';
6
+ import operations from './addToCart.gql';
7
+
8
+ /**
9
+ * @param {Number} props.item.id - id of item
10
+ * @param {String} props.item.name - name of item
11
+ * @param {String} props.item.stock_status - stock status of item
12
+ * @param {String} props.item.type_id - product type
13
+ * @param {String} props.item.url_key - item url key
14
+ * @param {String} props.item.sku - item sku
15
+ *
16
+ * @returns {
17
+ * handleAddToCart: Function,
18
+ * isDisabled: Boolean,
19
+ * isInStock: Boolean
20
+ * }
21
+ *
22
+ */
23
+ const UNSUPPORTED_PRODUCT_TYPES = [
24
+ 'virtual',
25
+ 'bundle',
26
+ 'grouped',
27
+ 'downloadable'
28
+ ];
29
+
30
+ export const useAddToCartButton = props => {
31
+ const { item } = props;
32
+
33
+ const [isLoading, setIsLoading] = useState(false);
34
+
35
+ const isInStock = item.stock_status === 'IN_STOCK';
36
+
37
+ const productType = item.type_id;
38
+ const isUnsupportedProductType = UNSUPPORTED_PRODUCT_TYPES.includes(
39
+ productType
40
+ );
41
+ const isDisabled = isLoading || !isInStock || isUnsupportedProductType;
42
+
43
+ const history = useHistory();
44
+
45
+ const [{ cartId }] = useCartContext();
46
+
47
+ const [addToCart] = useMutation(operations.ADD_ITEM);
48
+
49
+ const handleAddToCart = useCallback(async () => {
50
+ try {
51
+ if (productType === 'simple') {
52
+ setIsLoading(true);
53
+
54
+ await addToCart({
55
+ variables: {
56
+ cartId,
57
+ cartItem: {
58
+ quantity: 1,
59
+ selected_options: [],
60
+ sku: item.sku
61
+ }
62
+ }
63
+ });
64
+
65
+ setIsLoading(false);
66
+ } else if (productType === 'configurable') {
67
+ history.push(`${item.url_key}.html`);
68
+ } else {
69
+ console.warn('Unsupported product type unable to handle.');
70
+ }
71
+ } catch (error) {
72
+ console.error(error);
73
+ }
74
+ }, [addToCart, cartId, history, item.sku, item.url_key, productType]);
75
+
76
+ return {
77
+ handleAddToCart,
78
+ isDisabled,
79
+ isInStock
80
+ };
81
+ };