@riosst100/pwa-marketplace 1.3.9 → 1.4.0

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@riosst100/pwa-marketplace",
3
3
  "author": "riosst100@gmail.com",
4
- "version": "1.3.9",
4
+ "version": "1.4.0",
5
5
  "main": "src/index.js",
6
6
  "pwa-studio": {
7
7
  "targets": {
@@ -36,4 +36,5 @@ module.exports = componentOverrideMapping = {
36
36
  [`@magento/venia-ui/lib/components/ProductImageCarousel/index.js`]: '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/ProductImageCarousel/index.js',
37
37
  [`@magento/venia-ui/lib/components/QuantityStepper/index.js`]: '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/QuantityStepper/index.js',
38
38
  [`@magento/venia-ui/lib/components/RichContent/index.js`]: '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/RichContent/index.js',
39
+ [`@magento/venia-ui/lib/components/RadioGroup/radio.js`]: '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/RadioGroup/radio.js',
39
40
  };
@@ -0,0 +1,54 @@
1
+ import { useAttributesBlock } from '@riosst100/pwa-marketplace/src/talons/AttributesBlock/useAttributesBlock';
2
+ import React from 'react';
3
+ import { Link } from 'react-router-dom';
4
+ import resourceUrl from '@magento/peregrine/lib/util/makeUrl';
5
+ import defaultClasses from './attributesBlock.module.css';
6
+ import { useStyle } from '@magento/venia-ui/lib/classify';
7
+
8
+ const AttributesBlock = props => {
9
+ const { attributesBlock, category } = props;
10
+
11
+ const talonProps = useAttributesBlock({ attributesBlock });
12
+
13
+ const classes = useStyle(defaultClasses, props.classes);
14
+
15
+ const {
16
+ categoryUrlSuffix,
17
+ getPath
18
+ } = talonProps;
19
+
20
+ const result = [];
21
+
22
+ attributesBlock && attributesBlock.map(({ label, code, items }, index) => {
23
+
24
+ const itemsResult = [];
25
+
26
+ items && items.map(({ label, value }, index) => {
27
+ const path = resourceUrl(
28
+ `/${category.url_path}${categoryUrlSuffix || ''}?${code}[filter]=${label},${value}`
29
+ );
30
+
31
+ itemsResult.push(
32
+ <>
33
+ <Link
34
+ key={index}
35
+ to={path}
36
+ >
37
+ <li className={classes.item}>{label}</li>
38
+ </Link>
39
+ </>
40
+ )
41
+ });
42
+
43
+ result.push(
44
+ <>
45
+ <div className={classes.title}>{label}</div>
46
+ <ul className={classes.root}>{itemsResult}</ul>
47
+ </>
48
+ )
49
+ });
50
+
51
+ return result;
52
+ };
53
+
54
+ export default AttributesBlock;
@@ -0,0 +1,28 @@
1
+ .root {
2
+ composes: flex from global;
3
+ composes: flex-wrap from global;
4
+ composes: mt-3 from global;
5
+ composes: gap-[15px] from global;
6
+ margin-bottom: 30px;
7
+ }
8
+
9
+ .item {
10
+ composes: px-4 from global;
11
+ composes: py-2 from global;
12
+ composes: transition-colors from global;
13
+ composes: duration-150 from global;
14
+ composes: border from global;
15
+ composes: border-solid from global;
16
+ composes: leading-normal from global;
17
+ composes: text-base from global;
18
+ composes: text-colorDefault from global;
19
+ composes: bg-white from global;
20
+ composes: border-gray-100 from global;
21
+ border-radius: 5px;
22
+ }
23
+
24
+ .title {
25
+ composes: pb-3 from global;
26
+ composes: font-bold from global;
27
+ composes: text-[14px] from global;
28
+ }
@@ -29,7 +29,7 @@ const SubCategory = props => {
29
29
  )
30
30
  });
31
31
 
32
- return <ul className={classes.root}>{subCategory}</ul>;
32
+ return subCategory.length ? <ul className={classes.root}>{subCategory}</ul> : '';
33
33
  };
34
34
 
35
35
  export default SubCategory;
@@ -29,6 +29,14 @@ export const GET_CATEGORY_CONTENT = gql`
29
29
  description
30
30
  url_key
31
31
  url_path
32
+ attributes_block {
33
+ label
34
+ code
35
+ items {
36
+ label
37
+ value
38
+ }
39
+ }
32
40
  parent {
33
41
  uid
34
42
  name
@@ -91,6 +91,9 @@ export const useCategoryContent = props => {
91
91
  categoryData && categoryData.categories.items.length
92
92
  ? categoryData.categories.items[0].children
93
93
  : null;
94
+ const attributesBlock = categoryData && categoryData.categories.items.length
95
+ ? categoryData.categories.items[0].attributes_block
96
+ : null;
94
97
  const parent =
95
98
  categoryData && categoryData.categories.items.length
96
99
  ? categoryData.categories.items[0].parent
@@ -99,6 +102,10 @@ export const useCategoryContent = props => {
99
102
  ? data.products.page_info.total_pages
100
103
  : null;
101
104
  const totalCount = data ? data.products.total_count : null;
105
+ const category =
106
+ categoryData && categoryData.categories.items.length
107
+ ? categoryData.categories.items[0]
108
+ : null;
102
109
  const categoryName =
103
110
  categoryData && categoryData.categories.items.length
104
111
  ? categoryData.categories.items[0].name
@@ -134,6 +141,8 @@ export const useCategoryContent = props => {
134
141
  totalCount,
135
142
  totalPagesFromData,
136
143
  children,
137
- parent
144
+ parent,
145
+ attributesBlock,
146
+ category
138
147
  };
139
148
  };
@@ -20,6 +20,7 @@
20
20
 
21
21
  .categoryTitle {
22
22
  composes: font-semibold from global;
23
+ composes: text-[20px] from global;
23
24
  }
24
25
 
25
26
  .heading {
@@ -25,6 +25,7 @@ import NoProductsFound from './NoProductsFound';
25
25
  import cn from 'classnames';
26
26
  import ProductListTab, { ProductListTabShimmer } from '@riosst100/pwa-marketplace/src/components/ProductListTab';
27
27
  import SubCategory from '@riosst100/pwa-marketplace/src/components/SubCategory/subCategory';
28
+ import AttributesBlock from '@riosst100/pwa-marketplace/src/components/AttributesBlock/attributesBlock';
28
29
 
29
30
  const FilterModal = React.lazy(() => import('@magento/venia-ui/lib/components/FilterModal'));
30
31
  const FilterSidebar = React.lazy(() =>
@@ -56,7 +57,9 @@ const CategoryContent = props => {
56
57
  items,
57
58
  children,
58
59
  totalCount,
59
- totalPagesFromData
60
+ totalPagesFromData,
61
+ attributesBlock,
62
+ category
60
63
  } = talonProps;
61
64
 
62
65
  const sidebarRef = useRef(null);
@@ -179,6 +182,7 @@ const CategoryContent = props => {
179
182
  {categoryDescriptionElement}
180
183
  </div>
181
184
  <SubCategory children={children} />
185
+ <AttributesBlock category={category} attributesBlock={attributesBlock} />
182
186
  <div className={classes.contentWrapper}>
183
187
  <div ref={sidebarRef} className={classes.sidebar}>
184
188
  <Suspense fallback={<FilterSidebarShimmer />}>
@@ -102,7 +102,7 @@ const FilterList = props => {
102
102
  // memoize item creation
103
103
  // search value is not referenced, so this array is stable
104
104
  const itemElements = useMemo(() => {
105
- if (filterFrontendInput === 'boolean') {
105
+ // if (filterFrontendInput === 'boolean') {
106
106
  const key = `item-${group}`;
107
107
  return (
108
108
  <li
@@ -121,7 +121,7 @@ const FilterList = props => {
121
121
  />
122
122
  </li>
123
123
  );
124
- }
124
+ // }
125
125
 
126
126
  return items.map((item, index) => {
127
127
  const { title, value } = item;
@@ -44,7 +44,8 @@
44
44
  /* TODO @TW: cannot compose */
45
45
  .action button {
46
46
  /* composes: text-base from global; */
47
- font-size: 13px;
47
+ font-size: 12px;
48
+ /* composes: text-[13px] from global; */
48
49
  /* composes: no-underline from global; */
49
50
  font-weight: 500;
50
51
  text-decoration: underline;
@@ -81,7 +81,7 @@ const Header = props => {
81
81
  className={''}
82
82
  data-cy="Header-logoContainer"
83
83
  >
84
- <div className='text-base'><b>TCG Collective</b></div>
84
+ <div className='text-[14px]'><b>TCG Collective</b></div>
85
85
  <small>Bringing Collectors Together</small>
86
86
  </Link>
87
87
  </div>
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import { Link } from 'react-router-dom';
3
3
 
4
4
  import resourceUrl from '@magento/peregrine/lib/util/makeUrl';
@@ -6,10 +6,13 @@ import resourceUrl from '@magento/peregrine/lib/util/makeUrl';
6
6
  import { useStyle } from '@magento/venia-ui/lib/classify';
7
7
  import defaultClasses from './submenuColumn.module.css';
8
8
  import PropTypes from 'prop-types';
9
+ import { useIntl } from 'react-intl';
9
10
 
10
11
  const ShopByColumn = props => {
11
12
  const classes = useStyle(defaultClasses, props.classes);
12
13
 
14
+ const { formatMessage } = useIntl();
15
+
13
16
  const {
14
17
  shopBy,
15
18
  category,
@@ -22,8 +25,15 @@ const ShopByColumn = props => {
22
25
 
23
26
  let items = null;
24
27
 
28
+ const itemCountToShow = 4;
29
+
25
30
  if (shopBy.items.length) {
26
31
  const childrenItems = shopBy.items.map((shopByItem, index) => {
32
+
33
+ if (index >= itemCountToShow) {
34
+ return null;
35
+ }
36
+
27
37
  const { name, option_id } = shopByItem;
28
38
  // const categoryUrl = resourceUrl(
29
39
  // `/${url_path}${categoryUrlSuffix || ''}`
@@ -47,7 +57,10 @@ const ShopByColumn = props => {
47
57
  className={classes.link}
48
58
  data-cy="MegaMenu-ShopByColumn-link"
49
59
  to={categoryUrl}
50
- onClick={handleCloseSubMenu}
60
+ onClick={() => {
61
+ handleCloseSubMenu();
62
+ onNavigate();
63
+ }}
51
64
  >
52
65
  {name}
53
66
  </Link>
@@ -58,11 +71,47 @@ const ShopByColumn = props => {
58
71
  items = <ul className={classes.submenuChild}>{childrenItems}</ul>;
59
72
  }
60
73
 
74
+ const viewAll = useMemo(() => {
75
+ if (shopBy.items.length <= itemCountToShow) {
76
+ return null;
77
+ }
78
+
79
+ const label = formatMessage({
80
+ id: 'filterList.viewAll',
81
+ defaultMessage: 'View All'
82
+ });
83
+
84
+ const categoryUrl = resourceUrl(
85
+ `/shop/${shopBy.code}`
86
+ );
87
+
88
+ return (
89
+ <li className={classes.submenuChildItem}>
90
+ <Link
91
+ // className={isActive ? classes.linkActive : classes.link}
92
+ className={classes.link}
93
+ data-cy="MegaMenu-ShopByColumn-link"
94
+ to={categoryUrl}
95
+ onClick={handleCloseSubMenu}
96
+ >
97
+ {label}
98
+ </Link>
99
+ </li>
100
+ );
101
+ }, [
102
+ // handleViewAll,
103
+ shopBy,
104
+ itemCountToShow,
105
+ formatMessage,
106
+ // classes
107
+ ]);
108
+
61
109
  return (
62
110
  <div className={classes.submenuItems}>
63
111
  <div className={classes.submenuColumn}>
64
112
  <span className={classes.heading}>{shopBy.name}</span>
65
113
  {items}
114
+ {viewAll}
66
115
  </div>
67
116
  </div>
68
117
  );
@@ -48,7 +48,10 @@ const SubmenuColumn = props => {
48
48
  className={isActive ? classes.linkActive : classes.link}
49
49
  data-cy="MegaMenu-SubmenuColumn-link"
50
50
  to={categoryUrl}
51
- onClick={onNavigate}
51
+ onClick={() => {
52
+ handleCloseSubMenu();
53
+ onNavigate();
54
+ }}
52
55
  >
53
56
  {name}
54
57
  </Link>
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ import { Circle } from 'react-feather';
3
+ import { node, shape, string } from 'prop-types';
4
+ import { Radio as InformedRadio } from 'informed';
5
+
6
+ import { useStyle } from '@magento/venia-ui/lib/classify';
7
+ import defaultClasses from './radio.module.css';
8
+
9
+ /* TODO: change lint config to use `label-has-associated-control` */
10
+ /* eslint-disable jsx-a11y/label-has-for */
11
+
12
+ const RadioOption = props => {
13
+ const {
14
+ ariaLabel,
15
+ classes: propClasses,
16
+ id,
17
+ label,
18
+ value,
19
+ ...rest
20
+ } = props;
21
+ const classes = useStyle(defaultClasses, propClasses);
22
+
23
+ return (
24
+ <label
25
+ className={classes.root}
26
+ htmlFor={id}
27
+ aria-label={ariaLabel ? ariaLabel : ''}
28
+ >
29
+ <InformedRadio
30
+ {...rest}
31
+ className={classes.input}
32
+ id={id}
33
+ value={value}
34
+ />
35
+ <span className={classes.icon}>
36
+ <Circle />
37
+ </span>
38
+ <span className={classes.label}>
39
+ {label || (value != null ? value : '')}
40
+ </span>
41
+ </label>
42
+ );
43
+ };
44
+
45
+ export default RadioOption;
46
+
47
+ RadioOption.propTypes = {
48
+ ariaLabel: string,
49
+ classes: shape({
50
+ icon: string,
51
+ input: string,
52
+ label: string,
53
+ root: string
54
+ }),
55
+ id: string.isRequired,
56
+ label: node.isRequired,
57
+ value: node.isRequired
58
+ };
59
+
60
+ /* eslint-enable jsx-a11y/label-has-for */
@@ -0,0 +1,70 @@
1
+ .root {
2
+ composes: gap-1 from global;
3
+ composes: grid from global;
4
+ composes: grid-flow-col from global;
5
+ composes: items-center from global;
6
+ composes: justify-items-center from global;
7
+ composes: leading-normal from global;
8
+ composes: m-0 from global;
9
+ composes: text-colorDefault from global;
10
+ grid-template-areas: 'input label';
11
+ grid-template-columns: min-content 1fr;
12
+ }
13
+
14
+ .input {
15
+ composes: appearance-none from global;
16
+ composes: bg-clip-content from global;
17
+ composes: bg-transparent from global;
18
+ composes: border-8 from global;
19
+ composes: border-solid from global;
20
+ composes: border-transparent from global;
21
+ composes: h-[1.5rem] from global;
22
+ composes: m-0 from global;
23
+ composes: rounded-full from global;
24
+ composes: w-[1.5rem] from global;
25
+ composes: z-foreground from global;
26
+ grid-area: input;
27
+
28
+ composes: active_outline-none from global;
29
+ /* composes: active_shadow-radioActive from global; */
30
+
31
+ composes: checked_bg-brand-dark from global;
32
+
33
+ composes: focus_outline-none from global;
34
+ /* composes: focus_shadow-radioFocus from global; */
35
+ }
36
+
37
+ .icon {
38
+ composes: h-[14px] from global;
39
+ composes: w-[14px] from global;
40
+ composes: z-surface from global;
41
+ grid-area: input;
42
+ }
43
+
44
+ /* TODO @TW: cannot compose */
45
+ .icon svg {
46
+ /* composes: stroke-gray-600 from global; */
47
+ stroke: rgb(var(--venia-global-color-gray-600));
48
+ width: 14px;
49
+ height: 14px;
50
+ }
51
+
52
+ .label {
53
+ composes: justify-self-start from global;
54
+ composes: text-base from global;
55
+ grid-area: label;
56
+ }
57
+
58
+ /* TODO @TW: cannot compose */
59
+ .input:checked + .icon svg {
60
+ /* composes: stroke-brand-base from global; */
61
+ stroke: rgb(var(--venia-brand-color-1-700));
62
+ }
63
+
64
+ .input_shimmer {
65
+ composes: h-[14px] from global;
66
+ composes: m-0 from global;
67
+ composes: rounded-full from global;
68
+ composes: w-[14px] from global;
69
+ composes: z-foreground from global;
70
+ }
@@ -0,0 +1,15 @@
1
+ import { gql } from '@apollo/client';
2
+
3
+ export const GET_STORE_CONFIG_DATA = gql`
4
+ query GetStoreConfigForBreadcrumbs {
5
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
6
+ storeConfig {
7
+ store_code
8
+ category_url_suffix
9
+ }
10
+ }
11
+ `;
12
+
13
+ export default {
14
+ getStoreConfigQuery: GET_STORE_CONFIG_DATA
15
+ };
@@ -0,0 +1,37 @@
1
+ import { useMemo } from 'react';
2
+ import { useQuery } from '@apollo/client';
3
+
4
+ import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
5
+
6
+ import DEFAULT_OPERATIONS from './attributesBlock.gql';
7
+
8
+ const getPath = (path, suffix) => {
9
+ if (path) {
10
+ return `/${path}${suffix || ''}`;
11
+ }
12
+
13
+ // If there is no path this is just a dead link.
14
+ return '#';
15
+ };
16
+
17
+ export const useAttributesBlock = props => {
18
+ const { attributesBlock } = props;
19
+
20
+ const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
21
+ const { getStoreConfigQuery } = operations;
22
+
23
+ const { data: storeConfigData } = useQuery(getStoreConfigQuery, {
24
+ fetchPolicy: 'cache-and-network'
25
+ });
26
+
27
+ const categoryUrlSuffix = useMemo(() => {
28
+ if (storeConfigData) {
29
+ return storeConfigData.storeConfig.category_url_suffix;
30
+ }
31
+ }, [storeConfigData]);
32
+
33
+ return {
34
+ categoryUrlSuffix,
35
+ getPath
36
+ };
37
+ };