@magento/experience-platform-connector 1.0.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/intercept.js +24 -0
- package/package.json +30 -0
- package/src/__tests__/__snapshots__/utils.spec.js.snap +137 -0
- package/src/__tests__/utils.spec.js +52 -0
- package/src/config.js +31 -0
- package/src/handleEvent.js +9 -0
- package/src/handlers/__tests__/__mocks__/cartAddItem.js +36 -0
- package/src/handlers/__tests__/__mocks__/cartPageView.js +880 -0
- package/src/handlers/__tests__/__mocks__/categoryPageView.js +9 -0
- package/src/handlers/__tests__/__mocks__/checkoutPageView.js +138 -0
- package/src/handlers/__tests__/__mocks__/completeCheckout.js +156 -0
- package/src/handlers/__tests__/__mocks__/createAccount.js +9 -0
- package/src/handlers/__tests__/__mocks__/editAccount.js +9 -0
- package/src/handlers/__tests__/__mocks__/miniCartView.js +846 -0
- package/src/handlers/__tests__/__mocks__/orderConfirmationPageView.js +67 -0
- package/src/handlers/__tests__/__mocks__/pageView.js +7 -0
- package/src/handlers/__tests__/__mocks__/placeOrderButtonClicked.js +161 -0
- package/src/handlers/__tests__/__mocks__/productPageView.js +15 -0
- package/src/handlers/__tests__/__mocks__/searchPageRequest.js +22 -0
- package/src/handlers/__tests__/__mocks__/searchRequestSent.js +34 -0
- package/src/handlers/__tests__/__mocks__/searchResponseReceived.js +106 -0
- package/src/handlers/__tests__/__snapshots__/shoppingMiniCartView.spec.js.snap +137 -0
- package/src/handlers/__tests__/addToCart.spec.js +73 -0
- package/src/handlers/__tests__/categoryPageView.spec.js +55 -0
- package/src/handlers/__tests__/completeCheckout.spec.js +70 -0
- package/src/handlers/__tests__/createAccount.spec.js +43 -0
- package/src/handlers/__tests__/editAccount.spec.js +43 -0
- package/src/handlers/__tests__/pageView.spec.js +46 -0
- package/src/handlers/__tests__/placeOrder.spec.js +55 -0
- package/src/handlers/__tests__/productPageView.spec.js +64 -0
- package/src/handlers/__tests__/searchRequestSent.spec.js +119 -0
- package/src/handlers/__tests__/searchResponseReceived.spec.js +143 -0
- package/src/handlers/__tests__/shoppingCartPageView.spec.js +198 -0
- package/src/handlers/__tests__/shoppingMiniCartView.spec.js +36 -0
- package/src/handlers/__tests__/signIn.spec.js +73 -0
- package/src/handlers/__tests__/startCheckout.spec.js +193 -0
- package/src/handlers/addToCart.js +60 -0
- package/src/handlers/categoryPageView.js +34 -0
- package/src/handlers/completeCheckout.js +49 -0
- package/src/handlers/createAccount.js +25 -0
- package/src/handlers/editAccount.js +25 -0
- package/src/handlers/pageView.js +26 -0
- package/src/handlers/placeOrder.js +32 -0
- package/src/handlers/productPageView.js +41 -0
- package/src/handlers/searchRequestSent.js +38 -0
- package/src/handlers/searchResponseReceived.js +39 -0
- package/src/handlers/shoppingCartPageView.js +45 -0
- package/src/handlers/shoppingMiniCartView.js +31 -0
- package/src/handlers/signIn.js +29 -0
- package/src/handlers/startCheckout.js +45 -0
- package/src/hooks/useExtensionContext.js +21 -0
- package/src/main.js +116 -0
- package/src/queries/getExtensionContext.js +31 -0
- package/src/utils.js +101 -0
- package/src/wrappers/wrapUseAccountMenu.js +29 -0
- package/src/wrappers/wrapUseAutocomplete.js +48 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const canHandle = event => event.type === 'USER_ACCOUNT_UPDATE';
|
|
2
|
+
|
|
3
|
+
const handle = (sdk, event) => {
|
|
4
|
+
const { payload } = event;
|
|
5
|
+
|
|
6
|
+
const { email, firstName, lastName } = payload;
|
|
7
|
+
|
|
8
|
+
const accountContext = {
|
|
9
|
+
firstName,
|
|
10
|
+
lastName,
|
|
11
|
+
emailAddress: email
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
sdk.context.setAccount(accountContext);
|
|
15
|
+
sdk.publish.editAccount({
|
|
16
|
+
personalEmail: {
|
|
17
|
+
address: email
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
canHandle,
|
|
24
|
+
handle
|
|
25
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const canHandle = event => event.type === 'CMS_PAGE_VIEW';
|
|
2
|
+
|
|
3
|
+
const handle = (sdk, event) => {
|
|
4
|
+
const { payload } = event;
|
|
5
|
+
|
|
6
|
+
const { title } = payload;
|
|
7
|
+
|
|
8
|
+
const context = {
|
|
9
|
+
pageType: 'CMS',
|
|
10
|
+
pageName: title,
|
|
11
|
+
eventType: 'visibilityHidden',
|
|
12
|
+
maxXOffset: 0,
|
|
13
|
+
maxYOffset: 0,
|
|
14
|
+
minXOffset: 0,
|
|
15
|
+
minYOffset: 0
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
sdk.context.setPage(context);
|
|
19
|
+
|
|
20
|
+
sdk.publish.pageView();
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default {
|
|
24
|
+
canHandle,
|
|
25
|
+
handle
|
|
26
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const canHandle = event => event.type === 'CHECKOUT_PLACE_ORDER_BUTTON_CLICKED';
|
|
2
|
+
|
|
3
|
+
const handle = (sdk, event) => {
|
|
4
|
+
const { payload } = event;
|
|
5
|
+
|
|
6
|
+
const grandTotal = payload.amount.grand_total.value;
|
|
7
|
+
|
|
8
|
+
const { payment, shipping } = payload;
|
|
9
|
+
|
|
10
|
+
const orderContext = {
|
|
11
|
+
grandTotal: grandTotal,
|
|
12
|
+
orderType: 'checkout',
|
|
13
|
+
payments: [
|
|
14
|
+
{
|
|
15
|
+
paymentMethodCode: payment.title,
|
|
16
|
+
paymentMethodName: payment.title,
|
|
17
|
+
total: grandTotal
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
shipping: {
|
|
21
|
+
shippingMethod: shipping[0].method_title,
|
|
22
|
+
shippingAmount: shipping[0].amount.value
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
sdk.context.setOrder(orderContext);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default {
|
|
30
|
+
canHandle,
|
|
31
|
+
handle
|
|
32
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const canHandle = event => event.type === 'PRODUCT_PAGE_VIEW';
|
|
2
|
+
|
|
3
|
+
const handle = (sdk, event) => {
|
|
4
|
+
const { payload } = event;
|
|
5
|
+
|
|
6
|
+
const { name, id, currency_code, price_range, sku, url_key } = payload;
|
|
7
|
+
|
|
8
|
+
const pageContext = {
|
|
9
|
+
pageType: 'PDP',
|
|
10
|
+
pageName: name,
|
|
11
|
+
eventType: 'visibilityHidden',
|
|
12
|
+
maxXOffset: 0,
|
|
13
|
+
maxYOffset: 0,
|
|
14
|
+
minXOffset: 0,
|
|
15
|
+
minYOffset: 0
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
sdk.context.setPage(pageContext);
|
|
19
|
+
|
|
20
|
+
sdk.publish.pageView();
|
|
21
|
+
|
|
22
|
+
const productContext = {
|
|
23
|
+
productId: id,
|
|
24
|
+
name,
|
|
25
|
+
sku,
|
|
26
|
+
pricing: {
|
|
27
|
+
currencyCode: currency_code,
|
|
28
|
+
maximalPrice: price_range.maximum_price.final_price
|
|
29
|
+
},
|
|
30
|
+
canonicalUrl: url_key
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
sdk.context.setProduct(productContext);
|
|
34
|
+
|
|
35
|
+
sdk.publish.productPageView();
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default {
|
|
39
|
+
canHandle,
|
|
40
|
+
handle
|
|
41
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const canHandle = event =>
|
|
2
|
+
['SEARCH_REQUEST', 'SEARCHBAR_REQUEST'].includes(event.type);
|
|
3
|
+
|
|
4
|
+
const handle = (sdk, event) => {
|
|
5
|
+
const { payload } = event;
|
|
6
|
+
|
|
7
|
+
const { query, pageSize, currentPage, refinements, sort } = payload;
|
|
8
|
+
|
|
9
|
+
const filter = refinements.map(refinement => {
|
|
10
|
+
const { attribute, value } = refinement;
|
|
11
|
+
return {
|
|
12
|
+
attribute: attribute,
|
|
13
|
+
in: Array.from(value.values())
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const requestContext = {
|
|
18
|
+
units: [
|
|
19
|
+
{
|
|
20
|
+
searchUnitId: 'productPage',
|
|
21
|
+
queryTypes: ['products'],
|
|
22
|
+
phrase: query,
|
|
23
|
+
pageSize: pageSize,
|
|
24
|
+
currentPage: currentPage,
|
|
25
|
+
filter: filter,
|
|
26
|
+
sort: [{ attribute: sort?.attribute, direction: sort?.order }]
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
sdk.context.setSearchInput(requestContext);
|
|
32
|
+
sdk.publish.searchRequestSent();
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default {
|
|
36
|
+
canHandle,
|
|
37
|
+
handle
|
|
38
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const canHandle = event => event.type === 'SEARCH_RESPONSE';
|
|
2
|
+
|
|
3
|
+
const handle = (sdk, event) => {
|
|
4
|
+
const { payload } = event;
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
categories,
|
|
8
|
+
facets,
|
|
9
|
+
page,
|
|
10
|
+
perPage,
|
|
11
|
+
products,
|
|
12
|
+
searchRequestId,
|
|
13
|
+
searchUnitId,
|
|
14
|
+
suggestions
|
|
15
|
+
} = payload;
|
|
16
|
+
|
|
17
|
+
const searchResultsContext = {
|
|
18
|
+
units: [
|
|
19
|
+
{
|
|
20
|
+
categories,
|
|
21
|
+
facets,
|
|
22
|
+
page,
|
|
23
|
+
perPage,
|
|
24
|
+
products,
|
|
25
|
+
searchRequestId,
|
|
26
|
+
searchUnitId,
|
|
27
|
+
suggestions
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
sdk.context.setSearchResults(searchResultsContext);
|
|
33
|
+
sdk.publish.searchResponseReceived(searchUnitId, searchResultsContext);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default {
|
|
37
|
+
canHandle,
|
|
38
|
+
handle
|
|
39
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { getCartTotal, getCurrency, getFormattedProducts } from '../utils';
|
|
2
|
+
|
|
3
|
+
const canHandle = event => event.type === 'CART_PAGE_VIEW';
|
|
4
|
+
|
|
5
|
+
const handle = (sdk, event) => {
|
|
6
|
+
const { payload } = event;
|
|
7
|
+
|
|
8
|
+
const { cart_id: id, products } = payload;
|
|
9
|
+
|
|
10
|
+
const cartContext = {
|
|
11
|
+
id,
|
|
12
|
+
prices: {
|
|
13
|
+
subtotalExcludingTax: {
|
|
14
|
+
value: getCartTotal(products),
|
|
15
|
+
currency: getCurrency(products)
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
items: getFormattedProducts(products),
|
|
19
|
+
possibleOnepageCheckout: false,
|
|
20
|
+
giftMessageSelected: false,
|
|
21
|
+
giftWrappingSelected: false
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
sdk.context.setShoppingCart(cartContext);
|
|
25
|
+
sdk.publish.shoppingCartView();
|
|
26
|
+
|
|
27
|
+
// Send out page view event
|
|
28
|
+
const pageContext = {
|
|
29
|
+
pageType: 'Cart',
|
|
30
|
+
pageName: 'Cart',
|
|
31
|
+
eventType: 'visibilityHidden',
|
|
32
|
+
maxXOffset: 0,
|
|
33
|
+
maxYOffset: 0,
|
|
34
|
+
minXOffset: 0,
|
|
35
|
+
minYOffset: 0
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
sdk.context.setPage(pageContext);
|
|
39
|
+
sdk.publish.pageView();
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default {
|
|
43
|
+
canHandle,
|
|
44
|
+
handle
|
|
45
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getCartTotal, getCurrency, getFormattedProducts } from '../utils';
|
|
2
|
+
|
|
3
|
+
const canHandle = event => event.type === 'MINI_CART_VIEW';
|
|
4
|
+
|
|
5
|
+
const handle = (sdk, event) => {
|
|
6
|
+
const { payload } = event;
|
|
7
|
+
|
|
8
|
+
const { cartId: id, products } = payload;
|
|
9
|
+
|
|
10
|
+
const cartContext = {
|
|
11
|
+
id: id,
|
|
12
|
+
prices: {
|
|
13
|
+
subtotalExcludingTax: {
|
|
14
|
+
value: getCartTotal(products),
|
|
15
|
+
currency: getCurrency(products)
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
items: getFormattedProducts(products),
|
|
19
|
+
possibleOnepageCheckout: false,
|
|
20
|
+
giftMessageSelected: false,
|
|
21
|
+
giftWrappingSelected: false
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
sdk.context.setShoppingCart(cartContext);
|
|
25
|
+
sdk.publish.shoppingCartView();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default {
|
|
29
|
+
canHandle,
|
|
30
|
+
handle
|
|
31
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const canHandle = event => event.type === 'USER_SIGN_IN';
|
|
2
|
+
|
|
3
|
+
const handle = (sdk, event) => {
|
|
4
|
+
const { payload } = event;
|
|
5
|
+
|
|
6
|
+
sdk.context.setShopper({
|
|
7
|
+
shopperId: 'logged-in'
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const { firstname, lastname, email } = payload;
|
|
11
|
+
|
|
12
|
+
const accountContext = {
|
|
13
|
+
firstName: firstname,
|
|
14
|
+
lastName: lastname,
|
|
15
|
+
emailAddress: email
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
sdk.context.setAccount(accountContext);
|
|
19
|
+
sdk.publish.signIn({
|
|
20
|
+
personalEmail: {
|
|
21
|
+
address: email
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default {
|
|
27
|
+
canHandle,
|
|
28
|
+
handle
|
|
29
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { getCartTotal, getCurrency, getFormattedProducts } from '../utils';
|
|
2
|
+
|
|
3
|
+
const canHandle = event => event.type === 'CHECKOUT_PAGE_VIEW';
|
|
4
|
+
|
|
5
|
+
const handle = (sdk, event) => {
|
|
6
|
+
const { payload } = event;
|
|
7
|
+
|
|
8
|
+
const { cart_id, products } = payload;
|
|
9
|
+
|
|
10
|
+
// Send out page view event
|
|
11
|
+
const pageContext = {
|
|
12
|
+
pageType: 'Checkout',
|
|
13
|
+
pageName: 'Checkout',
|
|
14
|
+
eventType: 'visibilityHidden',
|
|
15
|
+
maxXOffset: 0,
|
|
16
|
+
maxYOffset: 0,
|
|
17
|
+
minXOffset: 0,
|
|
18
|
+
minYOffset: 0
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
sdk.context.setPage(pageContext);
|
|
22
|
+
sdk.publish.pageView();
|
|
23
|
+
|
|
24
|
+
const cartContext = {
|
|
25
|
+
id: cart_id,
|
|
26
|
+
prices: {
|
|
27
|
+
subtotalExcludingTax: {
|
|
28
|
+
value: getCartTotal(products),
|
|
29
|
+
currency: getCurrency(products)
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
items: getFormattedProducts(products),
|
|
33
|
+
possibleOnepageCheckout: false,
|
|
34
|
+
giftMessageSelected: false,
|
|
35
|
+
giftWrappingSelected: false
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
sdk.context.setShoppingCart(cartContext);
|
|
39
|
+
sdk.publish.initiateCheckout();
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default {
|
|
43
|
+
canHandle,
|
|
44
|
+
handle
|
|
45
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useLazyQuery } from '@apollo/client';
|
|
2
|
+
import { GET_EXTENSION_CONTEXT } from '../queries/getExtensionContext.js';
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
|
+
|
|
5
|
+
const useExtensionContext = () => {
|
|
6
|
+
const [
|
|
7
|
+
fetchExtensionContext,
|
|
8
|
+
{ called, data, loading, error }
|
|
9
|
+
] = useLazyQuery(GET_EXTENSION_CONTEXT);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
fetchExtensionContext();
|
|
12
|
+
}, [fetchExtensionContext]);
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
ready: called && !loading,
|
|
16
|
+
data,
|
|
17
|
+
error
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default useExtensionContext;
|
package/src/main.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { useEventingContext } from '@magento/peregrine/lib/context/eventing';
|
|
2
|
+
import { useUserContext } from '@magento/peregrine/lib/context/user';
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { default as handleEvent } from './handleEvent';
|
|
5
|
+
import useExtensionContext from './hooks/useExtensionContext';
|
|
6
|
+
|
|
7
|
+
export default original => props => {
|
|
8
|
+
const [{ isSignedIn, currentUser }] = useUserContext();
|
|
9
|
+
const [observable] = useEventingContext();
|
|
10
|
+
|
|
11
|
+
const [sdk, setSdk] = useState();
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
data: storefrontData,
|
|
15
|
+
ready: storefrontDataReady,
|
|
16
|
+
errors
|
|
17
|
+
} = useExtensionContext();
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (errors) {
|
|
21
|
+
console.error('Experience Platform Connector Error', errors);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (storefrontDataReady && storefrontData) {
|
|
26
|
+
const {
|
|
27
|
+
dataServicesStorefrontInstanceContext: storefrontContext,
|
|
28
|
+
experienceConnectorContext: connectorContext
|
|
29
|
+
} = storefrontData;
|
|
30
|
+
|
|
31
|
+
import('@adobe/magento-storefront-events-sdk').then(mse => {
|
|
32
|
+
if (!window.magentoStorefrontEvents) {
|
|
33
|
+
window.magentoStorefrontEvents = mse;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const orgId = storefrontContext.ims_org_id;
|
|
37
|
+
const datastreamId = connectorContext.datastream_id;
|
|
38
|
+
|
|
39
|
+
if (orgId && datastreamId) {
|
|
40
|
+
mse.context.setAEP({
|
|
41
|
+
imsOrgId: orgId,
|
|
42
|
+
datastreamId: datastreamId
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
mse.context.setEventForwarding({
|
|
46
|
+
aep: true
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Set storefront context
|
|
50
|
+
mse.context.setStorefrontInstance({
|
|
51
|
+
environmentId: storefrontContext.environment_id,
|
|
52
|
+
environment: storefrontContext.environment,
|
|
53
|
+
storeUrl: storefrontContext.store_url,
|
|
54
|
+
websiteId: storefrontContext.website_id,
|
|
55
|
+
websiteCode: storefrontContext.website_code,
|
|
56
|
+
storeId: storefrontContext.store_id,
|
|
57
|
+
storeCode: storefrontContext.store_code,
|
|
58
|
+
storeViewId: storefrontContext.store_view_id,
|
|
59
|
+
storeViewCode: storefrontContext.store_view_code,
|
|
60
|
+
websiteName: storefrontContext.website_name,
|
|
61
|
+
storeName: storefrontContext.store_name,
|
|
62
|
+
storeViewName: storefrontContext.store_view_name,
|
|
63
|
+
baseCurrencyCode: storefrontContext.base_currency_code,
|
|
64
|
+
storeViewCurrencyCode:
|
|
65
|
+
storefrontContext.store_view_currency_code,
|
|
66
|
+
catalogExtensionVersion:
|
|
67
|
+
storefrontContext.catalog_extension_version
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
import('@adobe/magento-storefront-event-collector').then(
|
|
71
|
+
msec => {
|
|
72
|
+
msec;
|
|
73
|
+
setSdk(mse);
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}, [storefrontDataReady, storefrontData, setSdk, errors]);
|
|
80
|
+
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (sdk) {
|
|
83
|
+
const sub = observable.subscribe(async event => {
|
|
84
|
+
handleEvent(sdk, event);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return () => {
|
|
88
|
+
sub.unsubscribe();
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}, [sdk, observable]);
|
|
92
|
+
|
|
93
|
+
// Sets shopper context on initial load (when shopper context is null)
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (sdk && !sdk.context.getShopper()) {
|
|
96
|
+
if (isSignedIn) {
|
|
97
|
+
sdk.context.setShopper({
|
|
98
|
+
shopperId: 'logged-in'
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
sdk.context.setAccount({
|
|
102
|
+
firstName: currentUser.firstname,
|
|
103
|
+
lastName: currentUser.lastname,
|
|
104
|
+
emailAddress: currentUser.email,
|
|
105
|
+
accountType: currentUser.__typename
|
|
106
|
+
});
|
|
107
|
+
} else {
|
|
108
|
+
sdk.context.setShopper({
|
|
109
|
+
shopperId: 'guest'
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}, [sdk, isSignedIn, currentUser]);
|
|
114
|
+
|
|
115
|
+
return original(props);
|
|
116
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { gql } from '@apollo/client';
|
|
2
|
+
|
|
3
|
+
export const GET_EXTENSION_CONTEXT = gql`
|
|
4
|
+
query experiencePlatformConnectorContext {
|
|
5
|
+
dataServicesStorefrontInstanceContext {
|
|
6
|
+
environment_id
|
|
7
|
+
environment
|
|
8
|
+
store_url
|
|
9
|
+
website_id
|
|
10
|
+
website_code
|
|
11
|
+
store_id
|
|
12
|
+
store_code
|
|
13
|
+
store_view_id
|
|
14
|
+
store_view_code
|
|
15
|
+
website_name
|
|
16
|
+
store_name
|
|
17
|
+
store_view_name
|
|
18
|
+
base_currency_code
|
|
19
|
+
store_view_currency_code
|
|
20
|
+
catalog_extension_version
|
|
21
|
+
ims_org_id
|
|
22
|
+
}
|
|
23
|
+
experienceConnectorContext {
|
|
24
|
+
datastream_id
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
export default {
|
|
30
|
+
getExtensionContext: GET_EXTENSION_CONTEXT
|
|
31
|
+
};
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/** Cart focused utils **/
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns the total sum from an array of cart products
|
|
5
|
+
*
|
|
6
|
+
* @param {Array} products
|
|
7
|
+
* @returns {Number} Sum of all product prices in the array
|
|
8
|
+
*/
|
|
9
|
+
export const getCartTotal = products => {
|
|
10
|
+
return products
|
|
11
|
+
? products.reduce(
|
|
12
|
+
(previous, current) =>
|
|
13
|
+
current.prices.price.value * current.quantity + previous,
|
|
14
|
+
0
|
|
15
|
+
)
|
|
16
|
+
: 0;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get the currency from the first product item in an array of cart products
|
|
21
|
+
*
|
|
22
|
+
* @param {Array} products
|
|
23
|
+
* @returns {String} Currency code from the first product item or null if array is empty
|
|
24
|
+
*/
|
|
25
|
+
export const getCurrency = products =>
|
|
26
|
+
products && products.length > 0 ? products[0].prices.price.currency : null;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Transforms an array of cart products into a format compatible with the
|
|
30
|
+
* Magento Storefront Event SDK
|
|
31
|
+
*
|
|
32
|
+
* @param {Array} products
|
|
33
|
+
* @returns {Array} Array of data compatible with the Magento Storefront Event SDK
|
|
34
|
+
*/
|
|
35
|
+
export const getFormattedProducts = products => {
|
|
36
|
+
return products
|
|
37
|
+
? products.map(item => {
|
|
38
|
+
const {
|
|
39
|
+
uid,
|
|
40
|
+
product,
|
|
41
|
+
prices,
|
|
42
|
+
quantity,
|
|
43
|
+
configurable_options: options
|
|
44
|
+
} = item;
|
|
45
|
+
|
|
46
|
+
const {
|
|
47
|
+
name,
|
|
48
|
+
sku,
|
|
49
|
+
__typename: type,
|
|
50
|
+
url_key: url,
|
|
51
|
+
small_image: image,
|
|
52
|
+
thumbnail
|
|
53
|
+
} = product;
|
|
54
|
+
|
|
55
|
+
const formattedOptions = options
|
|
56
|
+
? options.map(option => {
|
|
57
|
+
const {
|
|
58
|
+
id,
|
|
59
|
+
option_label,
|
|
60
|
+
value_label,
|
|
61
|
+
configurable_product_option_value_uid: valueId
|
|
62
|
+
} = option;
|
|
63
|
+
return {
|
|
64
|
+
id: id,
|
|
65
|
+
optionLabel: option_label,
|
|
66
|
+
valueId: valueId,
|
|
67
|
+
valueLabel: value_label
|
|
68
|
+
};
|
|
69
|
+
})
|
|
70
|
+
: null;
|
|
71
|
+
|
|
72
|
+
const imageUrl = image
|
|
73
|
+
? image.url
|
|
74
|
+
: thumbnail
|
|
75
|
+
? thumbnail.url
|
|
76
|
+
: null;
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
formattedPrice: '',
|
|
80
|
+
id: uid,
|
|
81
|
+
prices: prices,
|
|
82
|
+
product: {
|
|
83
|
+
name: name,
|
|
84
|
+
sku: sku,
|
|
85
|
+
productType: type,
|
|
86
|
+
pricing: {
|
|
87
|
+
regularPrice: prices.price.value,
|
|
88
|
+
minimalPrice: prices.price.value,
|
|
89
|
+
maximalPrice: prices.price.value,
|
|
90
|
+
currencyCode: prices.price.currency
|
|
91
|
+
},
|
|
92
|
+
canonicalUrl: url,
|
|
93
|
+
mainImageUrl: imageUrl
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
configurableOptions: formattedOptions,
|
|
97
|
+
quantity: quantity
|
|
98
|
+
};
|
|
99
|
+
})
|
|
100
|
+
: null;
|
|
101
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
// Wrapper for the useAccountMenu() talon
|
|
4
|
+
const wrapUseAccountMenu = useAccountMenu => {
|
|
5
|
+
return props => {
|
|
6
|
+
const talonProps = useAccountMenu(props);
|
|
7
|
+
|
|
8
|
+
const { handleSignOut, ...restProps } = talonProps;
|
|
9
|
+
|
|
10
|
+
const sdk = window.magentoStorefrontEvents;
|
|
11
|
+
|
|
12
|
+
// Need to publish the sign out event before actually calling the original sign out
|
|
13
|
+
// callback to make sure data is sent before the page refreshes
|
|
14
|
+
const newHandleSignOut = useCallback(async () => {
|
|
15
|
+
if (sdk) {
|
|
16
|
+
sdk.publish.signOut();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
handleSignOut();
|
|
20
|
+
}, [sdk, handleSignOut]);
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
handleSignOut: newHandleSignOut,
|
|
24
|
+
...restProps
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default wrapUseAccountMenu;
|