@riosst100/pwa-marketplace 2.4.7 → 2.4.8

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 (30) hide show
  1. package/package.json +1 -1
  2. package/src/componentOverrideMapping.js +3 -0
  3. package/src/components/Seller/seller.js +8 -0
  4. package/src/components/SellerDetail/sellerDetail.js +4 -3
  5. package/src/components/SellerMegaMenu/index.js +1 -0
  6. package/src/components/SellerMegaMenu/sellerMegaMenu.js +92 -0
  7. package/src/components/SellerMegaMenu/sellerMegaMenu.module.css +12 -0
  8. package/src/components/SellerMegaMenu/sellerMegaMenuItem.js +164 -0
  9. package/src/components/SellerMegaMenu/sellerMegaMenuItem.module.css +31 -0
  10. package/src/components/SellerMegaMenu/sellerSubmenu.js +106 -0
  11. package/src/components/SellerMegaMenu/sellerSubmenu.module.css +57 -0
  12. package/src/components/SellerMegaMenu/sellerSubmenuColumn.js +173 -0
  13. package/src/components/SellerMegaMenu/sellerSubmenuColumn.module.css +33 -0
  14. package/src/components/SellerProducts/productContent.js +70 -11
  15. package/src/components/SellerProducts/sellerProducts.js +51 -12
  16. package/src/intercept.js +14 -0
  17. package/src/overwrites/peregrine/lib/context/cart.js +136 -0
  18. package/src/overwrites/peregrine/lib/store/actions/cart/asyncActions.js +589 -0
  19. package/src/overwrites/peregrine/lib/talons/CartPage/PriceSummary/usePriceSummary.js +4 -1
  20. package/src/overwrites/peregrine/lib/talons/CheckoutPage/useCheckoutPage.js +434 -0
  21. package/src/overwrites/venia-ui/lib/components/Adapter/adapter.js +0 -9
  22. package/src/overwrites/venia-ui/lib/components/CartPage/ProductListing/productListing.js +8 -8
  23. package/src/talons/Seller/useSeller.js +1 -1
  24. package/src/talons/SellerMegaMenu/megaMenu.gql.js +96 -0
  25. package/src/talons/SellerMegaMenu/useSellerMegaMenu.js +199 -0
  26. package/src/talons/SellerMegaMenu/useSellerMegaMenuItem.js +66 -0
  27. package/src/talons/SellerMegaMenu/useSellerSubMenu.js +21 -0
  28. package/src/talons/SellerProducts/sellerProducts.gql.js +24 -1
  29. package/src/talons/SellerProducts/useProductContent.js +17 -23
  30. package/src/talons/SellerProducts/useSellerProducts.js +44 -28
@@ -0,0 +1,199 @@
1
+ import { useMemo, useState, useCallback, useEffect } from 'react';
2
+ import { useLocation } from 'react-router-dom';
3
+ import { useInternalLink } from '@magento/peregrine/lib/hooks/useInternalLink';
4
+
5
+ import { useQuery } from '@apollo/client';
6
+ import { useEventListener } from '@magento/peregrine/lib/hooks/useEventListener';
7
+
8
+ import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
9
+ import DEFAULT_OPERATIONS from './megaMenu.gql';
10
+
11
+ /**
12
+ * The useSellerMegaMenu talon complements the SellerMegaMenu component.
13
+ *
14
+ * @param {Object} props
15
+ * @param {*} props.operations GraphQL operations used by talons
16
+ * @param {React.RefObject} props.mainNavRef Reference to main navigation DOM node
17
+ *
18
+ * @return {SellerMegaMenuTalonProps}
19
+ */
20
+ export const useSellerMegaMenu = (props = {}) => {
21
+ const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
22
+ const { getMegaMenuQuery, getStoreConfigQuery } = operations;
23
+
24
+ const location = useLocation();
25
+ const [activeCategoryId, setActiveCategoryId] = useState(null);
26
+ const [sellerSubMenuState, setSellerSubMenuState] = useState(false);
27
+ const [disableFocus, setDisableFocus] = useState(false);
28
+
29
+ const { data: storeConfigData } = useQuery(getStoreConfigQuery, {
30
+ fetchPolicy: 'cache-and-network'
31
+ });
32
+
33
+ const { data } = useQuery(getMegaMenuQuery, {
34
+ fetchPolicy: 'cache-and-network',
35
+ nextFetchPolicy: 'cache-first'
36
+ });
37
+
38
+ const categoryUrlSuffix = useMemo(() => {
39
+ if (storeConfigData) {
40
+ return storeConfigData.storeConfig.category_url_suffix;
41
+ }
42
+ }, [storeConfigData]);
43
+
44
+ /**
45
+ * Check if category should be visible on the storefront.
46
+ *
47
+ * @param {MegaMenuCategory} category
48
+ * @returns {boolean}
49
+ */
50
+ const shouldRenderSellerMegaMenuItem = category => {
51
+ return !!category.include_in_menu;
52
+ };
53
+
54
+ /**
55
+ * Check if category is the active category based on the current location.
56
+ *
57
+ * @param {MegaMenuCategory} category
58
+ * @returns {boolean}
59
+ */
60
+
61
+ const isActive = useCallback(
62
+ ({ url_path }) => {
63
+ if (!url_path) return false;
64
+
65
+ const categoryUrlPath = `/${url_path}${categoryUrlSuffix || ''}`;
66
+
67
+ return location.pathname === categoryUrlPath;
68
+ },
69
+ [location.pathname, categoryUrlSuffix]
70
+ );
71
+
72
+ /**
73
+ * Recursively map data returned by GraphQL query.
74
+ *
75
+ * @param {MegaMenuCategory} category
76
+ * @param {array} - path from the given category to the first level category
77
+ * @param {boolean} isRoot - describes is category a root category
78
+ * @return {MegaMenuCategory}
79
+ */
80
+ const processData = useCallback(
81
+ (category, path = [], isRoot = true) => {
82
+ if (!category) {
83
+ return;
84
+ }
85
+
86
+ const megaMenuCategory = Object.assign({}, category);
87
+
88
+ if (!isRoot) {
89
+ megaMenuCategory.path = [...path, category.uid];
90
+ }
91
+
92
+ megaMenuCategory.isActive = isActive(megaMenuCategory);
93
+
94
+ if (megaMenuCategory.children) {
95
+ megaMenuCategory.children = [...megaMenuCategory.children]
96
+ .filter(category => shouldRenderSellerMegaMenuItem(category))
97
+ .sort((a, b) => (a.position > b.position ? 1 : -1))
98
+ .map(child =>
99
+ processData(child, megaMenuCategory.path, false)
100
+ );
101
+ }
102
+
103
+ return megaMenuCategory;
104
+ },
105
+ [isActive]
106
+ );
107
+
108
+ const megaMenuData = useMemo(() => {
109
+ return data ? processData(data.categoryList[0]) : {};
110
+ }, [data, processData]);
111
+
112
+ const findActiveCategory = useCallback(
113
+ (pathname, category) => {
114
+ if (isActive(category)) {
115
+ return category;
116
+ }
117
+
118
+ if (category.children) {
119
+ return category.children.find(category =>
120
+ findActiveCategory(pathname, category)
121
+ );
122
+ }
123
+ },
124
+ [isActive]
125
+ );
126
+
127
+ const handleClickOutside = e => {
128
+ if (!props.mainNavRef.current.contains(e.target)) {
129
+ setSellerSubMenuState(false);
130
+ setDisableFocus(true);
131
+ }
132
+ };
133
+
134
+ useEventListener(globalThis, 'keydown', handleClickOutside);
135
+
136
+ const handleSellerSubMenuFocus = useCallback(() => {
137
+ setSellerSubMenuState(true);
138
+ }, [setSellerSubMenuState]);
139
+
140
+ useEffect(() => {
141
+ const activeCategory = findActiveCategory(
142
+ location.pathname,
143
+ megaMenuData
144
+ );
145
+
146
+ if (activeCategory) {
147
+ setActiveCategoryId(activeCategory.path[0]);
148
+ } else {
149
+ setActiveCategoryId(null);
150
+ }
151
+ }, [findActiveCategory, location.pathname, megaMenuData]);
152
+
153
+ /**
154
+ * Sets next root component to show proper loading effect
155
+ *
156
+ * @returns {void}
157
+ */
158
+ const { setShimmerType } = useInternalLink('category');
159
+
160
+ return {
161
+ megaMenuData,
162
+ activeCategoryId,
163
+ categoryUrlSuffix,
164
+ handleClickOutside,
165
+ sellerSubMenuState,
166
+ disableFocus,
167
+ handleSellerSubMenuFocus,
168
+ handleNavigate: setShimmerType
169
+ };
170
+ };
171
+
172
+ /** JSDocs type definitions */
173
+
174
+ /**
175
+ * @typedef {Object} MegaMenuTalonProps
176
+ *
177
+ * @property {MegaMenuCategory} megaMenuData - The Object with categories contains only categories
178
+ * with the include_in_menu = 1 flag. The categories are sorted
179
+ * based on the field position.
180
+ * @property {String} activeCategoryId returns the currently selected category uid.
181
+ * @property {String} categoryUrlSuffix store's category url suffix to construct category URL
182
+ * @property {Function} handleClickOutside function to handle mouse/key events.
183
+ * @property {Boolean} sellerSubMenuState maintaining sub-menu open/close state
184
+ * @property {Boolean} disableFocus state to disable focus
185
+ * @property {Function} handleSellerSubMenuFocus toggle function to handle sub-menu focus
186
+ * @property {function} handleNavigate - callback to fire on link click
187
+ */
188
+
189
+ /**
190
+ * Object type returned by the {@link useMegaMenu} talon.
191
+ * @typedef {Object} MegaMenuCategory
192
+ *
193
+ * @property {String} uid - uid of the category
194
+ * @property {int} include_in_menu - describes if category should be included in menu
195
+ * @property {String} name - name of the category
196
+ * @property {int} position - value used for sorting
197
+ * @property {String} url_path - URL path for a category
198
+ * @property {MegaMenuCategory} children - child category
199
+ */
@@ -0,0 +1,66 @@
1
+ import { useCallback, useMemo, useState } from 'react';
2
+
3
+ export const useSellerMegaMenuItem = props => {
4
+ const { category, activeCategoryId, sellerSubMenuState, disableFocus } = props;
5
+
6
+ const [isFocused, setIsFocused] = useState(false);
7
+ const isActive = category.id === activeCategoryId;
8
+
9
+ const handleMenuItemFocus = useCallback(() => {
10
+ setIsFocused(true);
11
+ }, [setIsFocused]);
12
+
13
+ const handleCloseSellerSubMenu = useCallback(() => {
14
+ setIsFocused(false);
15
+ }, [setIsFocused]);
16
+
17
+ const isMenuActive = useMemo(() => {
18
+ if (!isFocused) {
19
+ return false;
20
+ }
21
+ if (sellerSubMenuState) {
22
+ return true;
23
+ } else if (disableFocus) {
24
+ setIsFocused(false);
25
+ }
26
+ return false;
27
+ }, [isFocused, sellerSubMenuState, disableFocus]);
28
+
29
+ const handleKeyDown = useCallback(
30
+ event => {
31
+ const { key: pressedKey, shiftKey } = event;
32
+
33
+ // checking down arrow and spacebar
34
+ if (pressedKey === 'ArrowDown' || pressedKey === ' ') {
35
+ event.preventDefault();
36
+ if (category.children.length || category.name == "Lego") {
37
+ setIsFocused(true);
38
+ } else {
39
+ setIsFocused(false);
40
+ }
41
+
42
+ return;
43
+ }
44
+
45
+ //checking up arrow or escape
46
+ if (pressedKey === 'ArrowUp' || pressedKey === 'Escape') {
47
+ setIsFocused(false);
48
+ }
49
+
50
+ //checking Tab with Shift
51
+ if (shiftKey && pressedKey === 'Tab') {
52
+ setIsFocused(false);
53
+ }
54
+ },
55
+ [category.children.length, category.name]
56
+ );
57
+
58
+ return {
59
+ isFocused,
60
+ isActive,
61
+ handleMenuItemFocus,
62
+ handleCloseSellerSubMenu,
63
+ isMenuActive,
64
+ handleKeyDown
65
+ };
66
+ };
@@ -0,0 +1,21 @@
1
+ import { useKeyboard } from 'react-aria';
2
+
3
+ export const useSellerSubMenu = props => {
4
+ const { isFocused, sellerSubMenuState, handleCloseSellerSubMenu } = props;
5
+
6
+ const { keyboardProps } = useKeyboard({
7
+ onKeyDown: e => {
8
+ //checking for Tab without Shift
9
+ if (!e.shiftKey && e.key === 'Tab') {
10
+ e.target.addEventListener('blur', handleCloseSellerSubMenu);
11
+ } else {
12
+ e.target.removeEventListener('blur', handleCloseSellerSubMenu);
13
+ }
14
+ }
15
+ });
16
+
17
+ const isSellerSubMenuActive = isFocused && sellerSubMenuState;
18
+ // const isSellerSubMenuActive = true;
19
+
20
+ return { keyboardProps, isSellerSubMenuActive };
21
+ };
@@ -56,8 +56,31 @@ export const GET_CATEGORIES_DATA = gql`
56
56
  }
57
57
  `;
58
58
 
59
+ export const RESOLVE_URL = gql`
60
+ query ResolveURL($url: String!, $product_preview_token: String) {
61
+ route(url: $url, product_preview_token: $product_preview_token) {
62
+ relative_url
63
+ redirect_code
64
+ type
65
+ ... on CmsPage {
66
+ identifier
67
+ }
68
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
69
+ ... on ProductInterface {
70
+ uid
71
+ __typename
72
+ }
73
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
74
+ ... on CategoryInterface {
75
+ uid
76
+ }
77
+ }
78
+ }
79
+ `;
80
+
59
81
  export default {
60
82
  getProductsQuery: GET_PRODUCTS,
61
83
  getFilterInputsQuery: GET_FILTER_INPUTS,
62
- getCategoryDataQuery: GET_CATEGORIES_DATA
84
+ getCategoryDataQuery: GET_CATEGORIES_DATA,
85
+ resolveUrlQuery: RESOLVE_URL
63
86
  };
@@ -7,9 +7,10 @@ import { useEventingContext } from '@magento/peregrine/lib/context/eventing';
7
7
  import DEFAULT_OPERATIONS from './productContent.gql';
8
8
 
9
9
  export const useProductContent = props => {
10
- const { sellerId, data, pageSize = 6 } = props;
10
+ const { sellerId, categoryId, data, pageSize = 6 } = props;
11
11
 
12
- const categoryUid = 'MTI=';
12
+ // const categoryId = 'MTI=';
13
+ // alert(categoryId)
13
14
 
14
15
  const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
15
16
 
@@ -58,9 +59,9 @@ export const useProductContent = props => {
58
59
  {
59
60
  fetchPolicy: 'cache-and-network',
60
61
  nextFetchPolicy: 'cache-first',
61
- skip: !categoryUid,
62
+ skip: !categoryId,
62
63
  variables: {
63
- id: categoryUid
64
+ id: categoryId
64
65
  }
65
66
  }
66
67
  );
@@ -68,36 +69,32 @@ export const useProductContent = props => {
68
69
  const [, { dispatch }] = useEventingContext();
69
70
 
70
71
  useEffect(() => {
71
- if (categoryUid) {
72
+ if (categoryId) {
72
73
  getFilters({
73
74
  variables: {
74
75
  categoryIdFilter: {
75
- eq: categoryUid
76
+ eq: categoryId
76
77
  }
77
78
  }
78
79
  });
79
80
  }
80
- }, [categoryUid, getFilters]);
81
+ }, [categoryId, getFilters]);
81
82
 
82
83
  useEffect(() => {
83
- if (categoryUid) {
84
+ if (categoryId) {
84
85
  getSortMethods({
85
86
  variables: {
86
87
  categoryIdFilter: {
87
- in: categoryUid
88
+ in: categoryId
88
89
  }
89
90
  }
90
91
  });
91
92
  }
92
- }, [categoryUid, getSortMethods]);
93
-
94
- console.log('filterData')
95
- console.log(filterData)
93
+ }, [categoryId, getSortMethods]);
96
94
 
97
95
  const rawFilters = filterData ? filterData.products.aggregations : null;
98
96
  const items = data ? data.items : placeholderItems;
99
- // const category = null;
100
- // const children = null;
97
+
101
98
  const category =
102
99
  categoryData && categoryData.categories.items.length
103
100
  ? categoryData.categories.items[0]
@@ -109,9 +106,6 @@ export const useProductContent = props => {
109
106
 
110
107
  const filters = [];
111
108
 
112
- console.log('rawFilters')
113
- console.log(rawFilters)
114
-
115
109
  rawFilters && rawFilters.map((filter, index) => {
116
110
 
117
111
  const filterOptions = [];
@@ -141,7 +135,7 @@ export const useProductContent = props => {
141
135
 
142
136
  const attributesBlock = null;
143
137
  const parent = null;
144
- const categoryName = null;
138
+ // const categoryName = null;
145
139
  const categoryDescription = null;
146
140
 
147
141
  // const attributesBlock = categoryData && categoryData.categories.items.length
@@ -156,10 +150,10 @@ export const useProductContent = props => {
156
150
  : null;
157
151
  const totalCount = data ? data.total_count : null;
158
152
 
159
- // const categoryName =
160
- // categoryData && categoryData.categories.items.length
161
- // ? categoryData.categories.items[0].name
162
- // : null;
153
+ const categoryName =
154
+ categoryData && categoryData.categories.items.length
155
+ ? categoryData.categories.items[0].name
156
+ : null;
163
157
  // const categoryDescription =
164
158
  // categoryData && categoryData.categories.items.length
165
159
  // ? categoryData.categories.items[0].description
@@ -21,7 +21,7 @@ export const useSellerProducts = props => {
21
21
  } = props;
22
22
 
23
23
  const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
24
- const { getProductsQuery, getFilterInputsQuery, getCategoryDataQuery } = operations;
24
+ const { resolveUrlQuery, getProductsQuery, getFilterInputsQuery, getCategoryDataQuery } = operations;
25
25
 
26
26
  const { data: pageSizeData } = useQuery(getPageSize, {
27
27
  fetchPolicy: 'cache-and-network',
@@ -59,6 +59,11 @@ export const useSellerProducts = props => {
59
59
  }
60
60
  ] = useAppContext();
61
61
 
62
+ const [runResolveUrlQuery, queryResolveUrlResponse] = useLazyQuery(resolveUrlQuery, {
63
+ fetchPolicy: 'cache-and-network',
64
+ nextFetchPolicy: 'cache-first'
65
+ });
66
+
62
67
  const [runQuery, queryResponse] = useLazyQuery(getProductsQuery, {
63
68
  fetchPolicy: 'cache-and-network',
64
69
  nextFetchPolicy: 'cache-first'
@@ -81,13 +86,13 @@ export const useSellerProducts = props => {
81
86
  // console.log('======')
82
87
 
83
88
  const {
84
- called: categoryCalled,
85
- loading: categoryLoading,
86
- error: categoryError,
87
- data: categoryData
88
- } = queryGetCategoriesResponse;
89
+ called: routeCalled,
90
+ loading: routeLoading,
91
+ error: routeError,
92
+ data: routeData
93
+ } = queryResolveUrlResponse;
89
94
 
90
- const { search } = useLocation();
95
+ const { search, pathname } = useLocation();
91
96
 
92
97
  const isBackgroundLoading = !!data && productLoading;
93
98
 
@@ -109,33 +114,45 @@ export const useSellerProducts = props => {
109
114
  // const {
110
115
  // data: categoryData
111
116
  // } = useQuery(getCategoryDataQuery);
117
+ // const { pathname } = useLocation();
118
+ const slug = pathname.split('/').pop();
119
+ // alert(slug)
120
+ // const productUrlSuffix = storeConfigData?.storeConfig?.product_url_suffix;
121
+ // const productUrlSuffix = '.html';
122
+ // const categoryUrlKey = productUrlSuffix ? slug.replace(productUrlSuffix, '') : slug;
112
123
 
113
124
  useEffect(() => {
114
125
  // const filters = getFiltersFromSearch(search);
115
126
 
127
+
128
+
116
129
  // Construct the filter arg object.
117
- const newFilters = {};
118
- newFilters['url_key'] = { eq: "lego" };
130
+ // const newFilters = {};
131
+ // newFilters['url_key'] = { eq: categoryUrlKey };
119
132
 
120
- runGetCategoriesQuery({
133
+ runResolveUrlQuery({
121
134
  variables: {
122
- currentPage: Number(1),
123
- filters: newFilters,
124
- pageSize: Number(1)
135
+ // currentPage: Number(1),
136
+ // filters: newFilters,
137
+ // pageSize: Number(1)
138
+ url: slug
125
139
  }
126
140
  });
127
141
  }, [
128
- runGetCategoriesQuery,
129
- search
142
+ runResolveUrlQuery,
143
+ slug
130
144
  ]);
131
145
 
132
146
  const categoryId = useMemo(() => {
147
+ console.log('---===routerouterouterouteroute')
148
+ console.log(routeData)
133
149
  let uid = null;
134
- if (categoryData) {
135
- uid = categoryData?.categories?.items[0].id;
150
+ if (routeData) {
151
+ const { route } = routeData || {};
152
+ uid = route?.uid;
136
153
  }
137
154
  return uid;
138
- }, [categoryData]);
155
+ }, [routeData]);
139
156
 
140
157
 
141
158
 
@@ -156,9 +173,6 @@ export const useSellerProducts = props => {
156
173
  useEffect(() => {
157
174
  // console.log('=categoryData=')
158
175
  // console.log(categoryData)
159
- if (!categoryData) {
160
- return;
161
- }
162
176
  // Wait until we have the type map to fetch product data.
163
177
  if (!filterTypeMap.size || !pageSize) {
164
178
  return;
@@ -175,7 +189,7 @@ export const useSellerProducts = props => {
175
189
  // Use the category uid for the current category page regardless of the
176
190
  // applied filters. Follow-up in PWA-404.
177
191
  if (categoryId) {
178
- newFilters['category_id'] = { eq: categoryId };
192
+ newFilters['category_uid'] = { eq: categoryId };
179
193
  }
180
194
 
181
195
  runQuery({
@@ -194,8 +208,7 @@ export const useSellerProducts = props => {
194
208
  categoryId,
195
209
  pageSize,
196
210
  runQuery,
197
- search,
198
- categoryData
211
+ search
199
212
  ]);
200
213
 
201
214
  const totalPagesFromData = data
@@ -245,10 +258,12 @@ export const useSellerProducts = props => {
245
258
  const categoryNotFound = false;
246
259
 
247
260
  // When only productLoading is involved, noProductsFound component flashes for a moment
248
- const loading =
249
- (introspectionCalled && !categoryCalled) ||
250
- (productLoading && !data) ||
251
- introspectionLoading;
261
+ // const loading =
262
+ // (introspectionCalled && !categoryCalled) ||
263
+ // (productLoading && !data) ||
264
+ // introspectionLoading;
265
+
266
+ const loading = false;
252
267
 
253
268
  useScrollTopOnChange(currentPage);
254
269
 
@@ -256,6 +271,7 @@ export const useSellerProducts = props => {
256
271
  error,
257
272
  productData,
258
273
  loading,
274
+ categoryId,
259
275
  pageControl,
260
276
  sortProps,
261
277
  pageSize,