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

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.
@@ -1,4 +1,10 @@
1
- import React, { createContext, useContext, useEffect, useMemo } from 'react';
1
+ import React, {
2
+ createContext,
3
+ useContext,
4
+ useEffect,
5
+ useMemo,
6
+ useCallback
7
+ } from 'react';
2
8
  import { connect } from 'react-redux';
3
9
  import { useMutation } from '@apollo/client';
4
10
  import gql from 'graphql-tag';
@@ -7,6 +13,8 @@ import { useAwaitQuery } from '@magento/peregrine/lib/hooks/useAwaitQuery';
7
13
  import actions from '../store/actions/cart/actions';
8
14
  import * as asyncActions from '../store/actions/cart/asyncActions';
9
15
  import bindActionCreators from '../util/bindActionCreators';
16
+ import { useEventListener } from '../hooks/useEventListener';
17
+ import BrowserPersistence from '../util/simplePersistence';
10
18
 
11
19
  const CartContext = createContext();
12
20
 
@@ -57,6 +65,18 @@ const CartContextProvider = props => {
57
65
  const [fetchCartId] = useMutation(CREATE_CART_MUTATION);
58
66
  const fetchCartDetails = useAwaitQuery(CART_DETAILS_QUERY);
59
67
 
68
+ // Storage listener to force a state update if cartId changes from another browser tab.
69
+ const storageListener = useCallback(() => {
70
+ const storage = new BrowserPersistence();
71
+ const currentCartId = storage.getItem('cartId');
72
+ const { cartId } = cartState;
73
+ if (cartId && currentCartId && cartId !== currentCartId) {
74
+ globalThis.location && globalThis.location.reload();
75
+ }
76
+ }, [cartState]);
77
+
78
+ useEventListener(globalThis, 'storage', storageListener);
79
+
60
80
  useEffect(() => {
61
81
  // cartApi.getCartDetails initializes the cart if there isn't one.
62
82
  cartApi.getCartDetails({
@@ -276,7 +276,7 @@ export const removeItemFromCart = payload => {
276
276
  await removeItem({
277
277
  variables: {
278
278
  cartId,
279
- itemId: item.id
279
+ itemId: item.uid
280
280
  }
281
281
  });
282
282
 
@@ -82,6 +82,7 @@ export const configurableItemResponse = {
82
82
  export const cartItem = {
83
83
  configurable_options: [{ id: 123, value_id: 1 }, { id: 456, value_id: 1 }],
84
84
  id: 123,
85
+ uid: 'NDA=',
85
86
  product: {
86
87
  sku: 'SP01'
87
88
  },
@@ -7,6 +7,7 @@ const GET_CONFIGURABLE_OPTIONS = gql`
7
7
  products(filter: { sku: { eq: $sku } }) {
8
8
  items {
9
9
  id
10
+ uid
10
11
  ...ProductFormFragment
11
12
  }
12
13
  }
@@ -17,13 +18,15 @@ const GET_CONFIGURABLE_OPTIONS = gql`
17
18
  const UPDATE_QUANTITY_MUTATION = gql`
18
19
  mutation UpdateCartItemQuantity(
19
20
  $cartId: String!
20
- $cartItemId: Int!
21
+ $cartItemId: ID!
21
22
  $quantity: Float!
22
23
  ) {
23
24
  updateCartItems(
24
25
  input: {
25
26
  cart_id: $cartId
26
- cart_items: [{ cart_item_id: $cartItemId, quantity: $quantity }]
27
+ cart_items: [
28
+ { cart_item_uid: $cartItemId, quantity: $quantity }
29
+ ]
27
30
  }
28
31
  ) @connection(key: "updateCartItems") {
29
32
  cart {
@@ -38,7 +41,7 @@ const UPDATE_QUANTITY_MUTATION = gql`
38
41
  const UPDATE_CONFIGURABLE_OPTIONS_MUTATION = gql`
39
42
  mutation UpdateConfigurableOptions(
40
43
  $cartId: String!
41
- $cartItemId: Int!
44
+ $cartItemId: ID!
42
45
  $parentSku: String!
43
46
  $variantSku: String!
44
47
  $quantity: Float!
@@ -60,7 +63,7 @@ const UPDATE_CONFIGURABLE_OPTIONS_MUTATION = gql`
60
63
  }
61
64
 
62
65
  removeItemFromCart(
63
- input: { cart_id: $cartId, cart_item_id: $cartItemId }
66
+ input: { cart_id: $cartId, cart_item_uid: $cartItemId }
64
67
  ) @connection(key: "removeItemFromCart") {
65
68
  cart {
66
69
  id
@@ -3,6 +3,7 @@ import { gql } from '@apollo/client';
3
3
  export const ProductFormFragment = gql`
4
4
  fragment ProductFormFragment on ProductInterface {
5
5
  id
6
+ uid
6
7
  sku
7
8
  ... on ConfigurableProduct {
8
9
  configurable_options {
@@ -156,7 +156,7 @@ export const useProductForm = props => {
156
156
  await updateConfigurableOptions({
157
157
  variables: {
158
158
  cartId,
159
- cartItemId: cartItem.id,
159
+ cartItemId: cartItem.uid,
160
160
  parentSku: cartItem.product.sku,
161
161
  variantSku: selectedVariant.product.sku,
162
162
  quantity: formValues.quantity
@@ -168,7 +168,7 @@ export const useProductForm = props => {
168
168
  await updateItemQuantity({
169
169
  variables: {
170
170
  cartId,
171
- cartItemId: cartItem.id,
171
+ cartItemId: cartItem.uid,
172
172
  quantity: formValues.quantity
173
173
  }
174
174
  });
@@ -5,6 +5,7 @@ export const ProductListingFragment = gql`
5
5
  id
6
6
  items {
7
7
  id
8
+ uid
8
9
  product {
9
10
  id
10
11
  name
@@ -128,14 +128,14 @@ export const useProduct = props => {
128
128
  await removeItemFromCart({
129
129
  variables: {
130
130
  cartId,
131
- itemId: item.id
131
+ itemId: item.uid
132
132
  }
133
133
  });
134
134
  } catch (err) {
135
135
  // Make sure any errors from the mutation are displayed.
136
136
  setDisplayError(true);
137
137
  }
138
- }, [cartId, item.id, removeItemFromCart]);
138
+ }, [cartId, item.uid, removeItemFromCart]);
139
139
 
140
140
  const handleUpdateItemQuantity = useCallback(
141
141
  async quantity => {
@@ -143,7 +143,7 @@ export const useProduct = props => {
143
143
  await updateItemQuantity({
144
144
  variables: {
145
145
  cartId,
146
- itemId: item.id,
146
+ itemId: item.uid,
147
147
  quantity
148
148
  }
149
149
  });
@@ -152,7 +152,7 @@ export const useProduct = props => {
152
152
  setDisplayError(true);
153
153
  }
154
154
  },
155
- [cartId, item.id, updateItemQuantity]
155
+ [cartId, item.uid, updateItemQuantity]
156
156
  );
157
157
 
158
158
  useEffect(() => {
@@ -6,7 +6,7 @@ import { useCartContext } from '../../context/cart';
6
6
  import operations from './addToCart.gql';
7
7
 
8
8
  /**
9
- * @param {Number} props.item.id - id of item
9
+ * @param {String} props.item.uid - uid of item
10
10
  * @param {String} props.item.name - name of item
11
11
  * @param {String} props.item.stock_status - stock status of item
12
12
  * @param {String} props.item.type_id - product type
@@ -56,7 +56,12 @@ export const useAddToCartButton = props => {
56
56
  cartId,
57
57
  cartItem: {
58
58
  quantity: 1,
59
- selected_options: [],
59
+ entered_options: [
60
+ {
61
+ uid: item.uid,
62
+ value: item.name
63
+ }
64
+ ],
60
65
  sku: item.sku
61
66
  }
62
67
  }
@@ -71,7 +76,16 @@ export const useAddToCartButton = props => {
71
76
  } catch (error) {
72
77
  console.error(error);
73
78
  }
74
- }, [addToCart, cartId, history, item.sku, item.url_key, productType]);
79
+ }, [
80
+ addToCart,
81
+ cartId,
82
+ history,
83
+ item.sku,
84
+ item.url_key,
85
+ productType,
86
+ item.uid,
87
+ item.name
88
+ ]);
75
89
 
76
90
  return {
77
91
  handleAddToCart,
@@ -5,6 +5,7 @@ export const ProductListFragment = gql`
5
5
  id
6
6
  items {
7
7
  id
8
+ uid
8
9
  product {
9
10
  id
10
11
  name
@@ -1,14 +1,14 @@
1
1
  import { useState, useCallback } from 'react';
2
2
 
3
3
  export const useItem = props => {
4
- const { id, handleRemoveItem } = props;
4
+ const { uid, handleRemoveItem } = props;
5
5
 
6
6
  const [isDeleting, setIsDeleting] = useState(false);
7
7
 
8
8
  const removeItem = useCallback(() => {
9
9
  setIsDeleting(true);
10
- handleRemoveItem(id);
11
- }, [handleRemoveItem, id]);
10
+ handleRemoveItem(uid);
11
+ }, [handleRemoveItem, uid]);
12
12
 
13
13
  return {
14
14
  isDeleting,
@@ -0,0 +1,11 @@
1
+ import { gql } from '@apollo/client';
2
+ export const SUBSCRIBE_TO_NEWSLETTER = gql`
3
+ mutation SubscribeToNewsletter($email: String!) {
4
+ subscribeEmailToNewsletter(email: $email) {
5
+ status
6
+ }
7
+ }
8
+ `;
9
+ export default {
10
+ subscribeMutation: SUBSCRIBE_TO_NEWSLETTER
11
+ };
@@ -0,0 +1,51 @@
1
+ import { useCallback, useRef, useState, useMemo } from 'react';
2
+ import { useMutation } from '@apollo/client';
3
+ import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
4
+ import DEFAULT_OPERATIONS from './newsletter.gql';
5
+
6
+ export const useNewsletter = (props = {}) => {
7
+ const { subscribeMutation } = mergeOperations(
8
+ DEFAULT_OPERATIONS,
9
+ props.operations
10
+ );
11
+ const [subscribing, setSubscribing] = useState(false);
12
+ const [subscribeNewsLetter, { error: newsLetterError, data }] = useMutation(
13
+ subscribeMutation,
14
+ {
15
+ fetchPolicy: 'no-cache'
16
+ }
17
+ );
18
+ const formApiRef = useRef(null);
19
+ const setFormApi = useCallback(api => (formApiRef.current = api), []);
20
+ const handleSubmit = useCallback(
21
+ async ({ email }) => {
22
+ setSubscribing(true);
23
+ try {
24
+ await subscribeNewsLetter({
25
+ variables: { email }
26
+ });
27
+ if (formApiRef.current) {
28
+ formApiRef.current.reset();
29
+ }
30
+ } catch (error) {
31
+ if (process.env.NODE_ENV !== 'production') {
32
+ console.error(error);
33
+ }
34
+ }
35
+ setSubscribing(false);
36
+ },
37
+ [subscribeNewsLetter]
38
+ );
39
+ const errors = useMemo(
40
+ () => new Map([['subscribeMutation', newsLetterError]]),
41
+ [newsLetterError]
42
+ );
43
+
44
+ return {
45
+ errors,
46
+ handleSubmit,
47
+ isBusy: subscribing,
48
+ setFormApi,
49
+ newsLetterResponse: data && data.subscribeEmailToNewsletter
50
+ };
51
+ };
@@ -368,7 +368,13 @@ export const useProductFullDetail = props => {
368
368
  product: {
369
369
  sku: product.sku,
370
370
  quantity
371
- }
371
+ },
372
+ entered_options: [
373
+ {
374
+ uid: product.uid,
375
+ value: product.name
376
+ }
377
+ ]
372
378
  };
373
379
 
374
380
  if (selectedOptionsArray.length) {
@@ -13,6 +13,7 @@ export const ProductsFragment = gql`
13
13
  fragment ProductsFragment on Products {
14
14
  items {
15
15
  id
16
+ uid
16
17
  name
17
18
  price_range {
18
19
  maximum_price {
@@ -16,6 +16,7 @@ export const GET_PRODUCT_DETAIL_QUERY = gql`
16
16
  products(filter: { url_key: { eq: $urlKey } }) {
17
17
  items {
18
18
  id
19
+ uid
19
20
  ...ProductDetailsFragment
20
21
  }
21
22
  }
@@ -5,6 +5,7 @@ export const ProductDetailsFragment = gql`
5
5
  __typename
6
6
  categories {
7
7
  id
8
+ uid
8
9
  breadcrumbs {
9
10
  category_id
10
11
  }
@@ -13,6 +14,7 @@ export const ProductDetailsFragment = gql`
13
14
  html
14
15
  }
15
16
  id
17
+ uid
16
18
  media_gallery_entries {
17
19
  # id is deprecated and unused in our code, but lint rules require we
18
20
  # request it if available
@@ -67,6 +69,7 @@ export const ProductDetailsFragment = gql`
67
69
  }
68
70
  product {
69
71
  id
72
+ uid
70
73
  media_gallery_entries {
71
74
  # id is deprecated and unused in our code, but lint rules require we
72
75
  # request it if available
@@ -42,6 +42,7 @@ export const PRODUCT_SEARCH = gql`
42
42
  ) {
43
43
  items {
44
44
  id
45
+ uid
45
46
  name
46
47
  price_range {
47
48
  maximum_price {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magento/peregrine",
3
- "version": "12.0.0-alpha.3",
3
+ "version": "12.1.0-beta.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },