@magento/peregrine 12.0.0 → 12.1.0-alpha.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.
- package/lib/context/cart.js +21 -1
- package/lib/store/actions/cart/asyncActions.js +1 -1
- package/lib/talons/CartPage/ProductListing/EditModal/__fixtures__/configurableProduct.js +1 -0
- package/lib/talons/CartPage/ProductListing/EditModal/productForm.gql.js +7 -4
- package/lib/talons/CartPage/ProductListing/EditModal/productFormFragment.gql.js +1 -0
- package/lib/talons/CartPage/ProductListing/EditModal/useProductForm.js +2 -2
- package/lib/talons/CartPage/ProductListing/productListingFragments.gql.js +1 -0
- package/lib/talons/CartPage/ProductListing/useProduct.js +4 -4
- package/lib/talons/Gallery/useAddToCartButton.js +16 -2
- package/lib/talons/MiniCart/ProductList/productListFragments.gql.js +1 -0
- package/lib/talons/MiniCart/useItem.js +3 -3
- package/lib/talons/Newsletter/newsletter.gql.js +11 -0
- package/lib/talons/Newsletter/useNewsletter.js +51 -0
- package/lib/talons/ProductFullDetail/useProductFullDetail.js +7 -1
- package/lib/talons/RootComponents/Category/categoryFragments.gql.js +1 -0
- package/lib/talons/RootComponents/Product/product.gql.js +1 -0
- package/lib/talons/RootComponents/Product/productDetailFragment.gql.js +3 -0
- package/package.json +1 -1
package/lib/context/cart.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import 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({
|
|
@@ -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:
|
|
21
|
+
$cartItemId: ID!
|
|
21
22
|
$quantity: Float!
|
|
22
23
|
) {
|
|
23
24
|
updateCartItems(
|
|
24
25
|
input: {
|
|
25
26
|
cart_id: $cartId
|
|
26
|
-
cart_items: [
|
|
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:
|
|
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,
|
|
66
|
+
input: { cart_id: $cartId, cart_item_uid: $cartItemId }
|
|
64
67
|
) @connection(key: "removeItemFromCart") {
|
|
65
68
|
cart {
|
|
66
69
|
id
|
|
@@ -156,7 +156,7 @@ export const useProductForm = props => {
|
|
|
156
156
|
await updateConfigurableOptions({
|
|
157
157
|
variables: {
|
|
158
158
|
cartId,
|
|
159
|
-
cartItemId: cartItem.
|
|
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.
|
|
171
|
+
cartItemId: cartItem.uid,
|
|
172
172
|
quantity: formValues.quantity
|
|
173
173
|
}
|
|
174
174
|
});
|
|
@@ -128,14 +128,14 @@ export const useProduct = props => {
|
|
|
128
128
|
await removeItemFromCart({
|
|
129
129
|
variables: {
|
|
130
130
|
cartId,
|
|
131
|
-
itemId: item.
|
|
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.
|
|
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.
|
|
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.
|
|
155
|
+
[cartId, item.uid, updateItemQuantity]
|
|
156
156
|
);
|
|
157
157
|
|
|
158
158
|
useEffect(() => {
|
|
@@ -56,7 +56,12 @@ export const useAddToCartButton = props => {
|
|
|
56
56
|
cartId,
|
|
57
57
|
cartItem: {
|
|
58
58
|
quantity: 1,
|
|
59
|
-
|
|
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
|
-
}, [
|
|
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,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { useState, useCallback } from 'react';
|
|
2
2
|
|
|
3
3
|
export const useItem = props => {
|
|
4
|
-
const {
|
|
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(
|
|
11
|
-
}, [handleRemoveItem,
|
|
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) {
|
|
@@ -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
|