@riosst100/pwa-marketplace 1.6.0 → 1.6.2
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 +3 -2
- package/src/components/AlphaFilter/alphaFilter.js +86 -0
- package/src/components/AlphaFilter/alphaFilter.module.css +38 -0
- package/src/components/AlphaFilter/alphaFilter.shimmer.js +50 -0
- package/src/components/AlphaFilter/index.js +2 -0
- package/src/components/CollectibleGameSets/collectibleGameSets.js +1 -1
- package/src/components/CrossSeller/crossSellerBuy.js +19 -0
- package/src/components/CrossSeller/index.js +15 -0
- package/src/components/CrossSeller/item.js +79 -0
- package/src/components/CrossSeller/logo_seller.png +0 -0
- package/src/components/CrossSeller/starIcon.js +14 -0
- package/src/components/CrossSeller/verifyIcon.js +12 -0
- package/src/components/CustomSortBy/productSort.module.css +65 -0
- package/src/components/CustomSortBy/productSort.shimmer.js +28 -0
- package/src/components/CustomSortBy/productSort.shimmer.module.css +10 -0
- package/src/components/CustomSubCategory/subCategory.js +48 -0
- package/src/components/CustomSubCategory/subCategory.module.css +22 -0
- package/src/components/FilterTop/CurrentTopFilters/currentTopFilter.js +47 -0
- package/src/components/FilterTop/CurrentTopFilters/currentTopFilter.module.css +22 -0
- package/src/components/FilterTop/CurrentTopFilters/currentTopFilters.js +50 -0
- package/src/components/FilterTop/CurrentTopFilters/currentTopFilters.module.css +21 -0
- package/src/components/FilterTop/CurrentTopFilters/index.js +1 -0
- package/src/components/FilterTop/CustomFilters/customFilters.js +68 -30
- package/src/components/FilterTop/FilterBlockList/filterBlockList.js +50 -0
- package/src/components/FilterTop/FilterBlockList/filterBlockList.module.css +8 -0
- package/src/components/FilterTop/FilterBlockList/filterTopItem.js +40 -0
- package/src/components/FilterTop/FilterBlockList/filterTopItem.module.css +14 -0
- package/src/components/FilterTop/FilterBlockList/filterTopItemGroup.js +91 -0
- package/src/components/FilterTop/FilterBlockList/filterTopItemGroup.module.css +23 -0
- package/src/components/FilterTop/FilterBlockList/index.js +1 -0
- package/src/components/FilterTop/filterTop.js +131 -13
- package/src/components/FilterTop/filterTop.module.css +23 -58
- package/src/components/FilterTop/filterTop.shimmer.js +24 -24
- package/src/components/FilterTop/filterTopBlock.js +54 -0
- package/src/components/FilterTop/index.js +2 -2
- package/src/components/FilterTopBackup/CustomFilters/customFilter.js +83 -0
- package/src/components/FilterTopBackup/CustomFilters/customFilter.module.css +22 -0
- package/src/components/FilterTopBackup/CustomFilters/customFilters.js +132 -0
- package/src/components/FilterTopBackup/CustomFilters/customFilters.module.css +23 -0
- package/src/components/FilterTopBackup/CustomFilters/index.js +1 -0
- package/src/components/FilterTopBackup/filterTop.js +14 -0
- package/src/components/FilterTopBackup/filterTop.module.css +23 -0
- package/src/components/FilterTopBackup/filterTop.shimmer.js +24 -0
- package/src/components/FilterTopBackup/index.js +2 -0
- package/src/components/RelatedProduct/index.js +16 -0
- package/src/components/RelatedProduct/relatedProduct.js +112 -0
- package/src/components/RelatedProduct/sample.json +154 -0
- package/src/components/SubCategory/subCategory.js +2 -2
- package/src/overwrites/venia-ui/lib/RootComponents/Category/NoProductsFound/noProductsFound.js +0 -13
- package/src/overwrites/venia-ui/lib/RootComponents/Category/categoryContent.js +30 -7
- package/src/overwrites/venia-ui/lib/components/Breadcrumbs/breadcrumbs.js +3 -2
- package/src/overwrites/venia-ui/lib/components/Gallery/gallery.js +7 -2
- package/src/overwrites/venia-ui/lib/components/Gallery/item.js +3 -1
- package/src/overwrites/venia-ui/lib/components/Newsletter/newsletter.js +2 -2
- package/src/overwrites/venia-ui/lib/components/ProductFullDetail/CustomAttributes/customAttributes.js +1 -1
- package/src/overwrites/venia-ui/lib/components/ProductFullDetail/productFullDetail.js +13 -1
- package/src/overwrites/venia-ui/lib/components/QuantityStepper/quantityStepper.js +2 -2
- package/src/overwrites/venia-ui/lib/components/SearchBar/searchBar.js +1 -1
- package/src/talons/CustomFilters/useCustomFilters.js +163 -5
- package/src/talons/FilterTop/customFilters.gql.js +45 -0
- package/src/talons/FilterTop/filterTop.gql.js +45 -0
- package/src/talons/FilterTop/index.js +1 -0
- package/src/talons/FilterTop/useFilterTop.js +330 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { useHistory, useLocation } from 'react-router-dom';
|
|
3
|
+
|
|
4
|
+
import { useAppContext } from '@magento/peregrine/lib/context/app';
|
|
5
|
+
|
|
6
|
+
import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
|
|
7
|
+
import { useFilterState } from '@magento/peregrine/lib/talons/FilterModal';
|
|
8
|
+
import { useLazyQuery, useQuery } from '@apollo/client';
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
getFiltersFromSearch,
|
|
12
|
+
getFilterInput,
|
|
13
|
+
getSearchFromState,
|
|
14
|
+
getStateFromSearch,
|
|
15
|
+
sortFiltersArray,
|
|
16
|
+
stripHtml
|
|
17
|
+
} from '@magento/peregrine/lib/talons/FilterModal/helpers';
|
|
18
|
+
|
|
19
|
+
import DEFAULT_OPERATIONS from './filterTop.gql';
|
|
20
|
+
|
|
21
|
+
const DRAWER_NAME = 'filter';
|
|
22
|
+
|
|
23
|
+
export const useFilterTop = props => {
|
|
24
|
+
const { filters } = props;
|
|
25
|
+
|
|
26
|
+
const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
|
|
27
|
+
const { getFilterInputsQuery, getCustomFilters } = operations;
|
|
28
|
+
|
|
29
|
+
const [runQuery, queryResponse] = useLazyQuery(getCustomFilters, {
|
|
30
|
+
fetchPolicy: 'cache-and-network',
|
|
31
|
+
nextFetchPolicy: 'cache-first'
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const [isApplying, setIsApplying] = useState(false);
|
|
35
|
+
const [{ drawer }, { toggleDrawer, closeDrawer }] = useAppContext();
|
|
36
|
+
const [filterState, filterApi] = useFilterState();
|
|
37
|
+
const prevDrawer = useRef(null);
|
|
38
|
+
const isOpen = drawer === DRAWER_NAME;
|
|
39
|
+
|
|
40
|
+
const history = useHistory();
|
|
41
|
+
const { pathname, search } = useLocation();
|
|
42
|
+
|
|
43
|
+
const { data: introspectionData } = useQuery(getFilterInputsQuery);
|
|
44
|
+
|
|
45
|
+
const filterTypeMap = useMemo(() => {
|
|
46
|
+
const typeMap = new Map();
|
|
47
|
+
if (introspectionData) {
|
|
48
|
+
introspectionData.__type.inputFields.forEach(({ name, type }) => {
|
|
49
|
+
typeMap.set(name, type.name);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return typeMap;
|
|
53
|
+
}, [introspectionData]);
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
|
|
57
|
+
if (!filterTypeMap.size) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const filters = getFiltersFromSearch(search);
|
|
62
|
+
|
|
63
|
+
// Construct the filter arg object.
|
|
64
|
+
const newFilters = {};
|
|
65
|
+
filters.forEach((values, key) => {
|
|
66
|
+
newFilters[key] = getFilterInput(values, filterTypeMap.get(key));
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Use the category uid for the current category page regardless of the
|
|
70
|
+
// applied filters. Follow-up in PWA-404.
|
|
71
|
+
// newFilters['category_uid'] = { eq: id };
|
|
72
|
+
|
|
73
|
+
runQuery({
|
|
74
|
+
variables: {
|
|
75
|
+
filters: newFilters
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}, [
|
|
79
|
+
runQuery,
|
|
80
|
+
filterTypeMap,
|
|
81
|
+
search
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
const attributeCodes = useMemo(
|
|
85
|
+
() => filters.map(({ attribute_code }) => attribute_code),
|
|
86
|
+
[filters]
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// Create a set of disabled filters.
|
|
90
|
+
const DISABLED_FILTERS = useMemo(() => {
|
|
91
|
+
const disabled = new Set();
|
|
92
|
+
// Disable category filtering when not on a search page.
|
|
93
|
+
if (pathname !== '/search.html') {
|
|
94
|
+
// disabled.add('category_id');
|
|
95
|
+
// disabled.add('category_uid');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return disabled;
|
|
99
|
+
}, [pathname]);
|
|
100
|
+
|
|
101
|
+
// console.log(introspectionData)
|
|
102
|
+
|
|
103
|
+
// Get "allowed" filters by intersection of filter attribute codes and
|
|
104
|
+
// schema input field types. This restricts the displayed filters to those
|
|
105
|
+
// that the api will understand.
|
|
106
|
+
const possibleFilters = useMemo(() => {
|
|
107
|
+
const nextFilters = new Set();
|
|
108
|
+
const inputFields = introspectionData
|
|
109
|
+
? introspectionData.__type.inputFields
|
|
110
|
+
: [];
|
|
111
|
+
|
|
112
|
+
// perform mapping and filtering in the same cycle
|
|
113
|
+
for (const { name } of inputFields) {
|
|
114
|
+
const isValid = attributeCodes.includes(name);
|
|
115
|
+
const isEnabled = !DISABLED_FILTERS.has(name);
|
|
116
|
+
|
|
117
|
+
if (isValid && isEnabled) {
|
|
118
|
+
nextFilters.add(name);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
nextFilters.add('card_print_version');
|
|
123
|
+
|
|
124
|
+
return nextFilters;
|
|
125
|
+
}, [DISABLED_FILTERS, attributeCodes, introspectionData]);
|
|
126
|
+
|
|
127
|
+
const isBooleanFilter = options => {
|
|
128
|
+
const optionsString = JSON.stringify(options);
|
|
129
|
+
return (
|
|
130
|
+
options.length <= 2 &&
|
|
131
|
+
(optionsString.includes(
|
|
132
|
+
JSON.stringify({
|
|
133
|
+
__typename: 'AggregationOption',
|
|
134
|
+
label: '0',
|
|
135
|
+
value: '0'
|
|
136
|
+
})
|
|
137
|
+
) ||
|
|
138
|
+
optionsString.includes(
|
|
139
|
+
JSON.stringify({
|
|
140
|
+
__typename: 'AggregationOption',
|
|
141
|
+
label: '1',
|
|
142
|
+
value: '1'
|
|
143
|
+
})
|
|
144
|
+
))
|
|
145
|
+
);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const {
|
|
149
|
+
called: called,
|
|
150
|
+
loading: customFiltersLoading,
|
|
151
|
+
error,
|
|
152
|
+
data
|
|
153
|
+
} = queryResponse;
|
|
154
|
+
|
|
155
|
+
const customFiltersData = customFiltersLoading && !data ? null : (data ? data.customSubFilters : null);
|
|
156
|
+
|
|
157
|
+
// useEffect(() => {
|
|
158
|
+
// if (data) {
|
|
159
|
+
// filters.concat(customFiltersData);
|
|
160
|
+
// }
|
|
161
|
+
// }, [customFiltersData])
|
|
162
|
+
|
|
163
|
+
// const customFilters = [];
|
|
164
|
+
|
|
165
|
+
// iterate over filters once to set up all the collections we need
|
|
166
|
+
const [
|
|
167
|
+
filterNames,
|
|
168
|
+
filterKeys,
|
|
169
|
+
filterItems,
|
|
170
|
+
filterFrontendInput,
|
|
171
|
+
customFilters
|
|
172
|
+
] = useMemo(() => {
|
|
173
|
+
const names = new Map();
|
|
174
|
+
const keys = new Set();
|
|
175
|
+
const frontendInput = new Map();
|
|
176
|
+
const itemsByGroup = new Map();
|
|
177
|
+
const customFiltersMap = [];
|
|
178
|
+
|
|
179
|
+
const sortedFilters = sortFiltersArray([...filters]);
|
|
180
|
+
|
|
181
|
+
for (const filter of sortedFilters) {
|
|
182
|
+
const { options, label: name, attribute_code: group } = filter;
|
|
183
|
+
|
|
184
|
+
// If this aggregation is not a possible filter, just back out.
|
|
185
|
+
if (possibleFilters.has(group)) {
|
|
186
|
+
const items = [];
|
|
187
|
+
|
|
188
|
+
// add filter name
|
|
189
|
+
names.set(group, name);
|
|
190
|
+
|
|
191
|
+
// add filter key permutations
|
|
192
|
+
keys.add(`${group}[filter]`);
|
|
193
|
+
|
|
194
|
+
// Add frontend input type
|
|
195
|
+
frontendInput.set(group, null);
|
|
196
|
+
// add items
|
|
197
|
+
for (const { label, value, path } of options) {
|
|
198
|
+
items.push({ title: stripHtml(label), value, path });
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
itemsByGroup.set(group, items);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (customFiltersData) {
|
|
206
|
+
customFiltersData.map(({ attribute_code, options }, index) => {
|
|
207
|
+
|
|
208
|
+
customFiltersMap.push(attribute_code)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
const items = [];
|
|
212
|
+
|
|
213
|
+
names.set(attribute_code, '');
|
|
214
|
+
frontendInput.set(attribute_code, null);
|
|
215
|
+
|
|
216
|
+
// add filter key permutations
|
|
217
|
+
keys.add(`${attribute_code}[filter]`);
|
|
218
|
+
|
|
219
|
+
// add items
|
|
220
|
+
for (const { label, value, path } of options) {
|
|
221
|
+
items.push({ title: stripHtml(label), value, path });
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
itemsByGroup.set(attribute_code, items);
|
|
225
|
+
})
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return [names, keys, itemsByGroup, frontendInput, customFiltersMap];
|
|
229
|
+
}, [filters, customFiltersData, possibleFilters]);
|
|
230
|
+
|
|
231
|
+
// on apply, write filter state to location
|
|
232
|
+
useEffect(() => {
|
|
233
|
+
if (isApplying) {
|
|
234
|
+
const nextSearch = getSearchFromState(
|
|
235
|
+
search,
|
|
236
|
+
filterKeys,
|
|
237
|
+
filterState
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
// write filter state to history
|
|
241
|
+
history.push({ pathname, search: nextSearch });
|
|
242
|
+
|
|
243
|
+
// mark the operation as complete
|
|
244
|
+
setIsApplying(false);
|
|
245
|
+
}
|
|
246
|
+
}, [filterKeys, filterState, history, isApplying, pathname, search]);
|
|
247
|
+
|
|
248
|
+
const handleOpen = useCallback(() => {
|
|
249
|
+
toggleDrawer(DRAWER_NAME);
|
|
250
|
+
}, [toggleDrawer]);
|
|
251
|
+
|
|
252
|
+
const handleClose = useCallback(() => {
|
|
253
|
+
closeDrawer();
|
|
254
|
+
}, [closeDrawer]);
|
|
255
|
+
|
|
256
|
+
const handleApply = useCallback(() => {
|
|
257
|
+
setIsApplying(true);
|
|
258
|
+
handleClose();
|
|
259
|
+
}, [handleClose]);
|
|
260
|
+
|
|
261
|
+
const handleReset = useCallback(() => {
|
|
262
|
+
filterApi.clear();
|
|
263
|
+
setIsApplying(true);
|
|
264
|
+
}, [filterApi, setIsApplying]);
|
|
265
|
+
|
|
266
|
+
const handleKeyDownActions = useCallback(
|
|
267
|
+
event => {
|
|
268
|
+
// do not handle keyboard actions when the modal is closed
|
|
269
|
+
if (!isOpen) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
switch (event.keyCode) {
|
|
274
|
+
// when "Esc" key fired -> close the modal
|
|
275
|
+
case 27:
|
|
276
|
+
handleClose();
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
[isOpen, handleClose]
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
useEffect(() => {
|
|
284
|
+
const justOpened =
|
|
285
|
+
prevDrawer.current === null && drawer === DRAWER_NAME;
|
|
286
|
+
const justClosed =
|
|
287
|
+
prevDrawer.current === DRAWER_NAME && drawer === null;
|
|
288
|
+
|
|
289
|
+
// on drawer toggle, read filter state from location
|
|
290
|
+
if (justOpened || justClosed) {
|
|
291
|
+
const nextState = getStateFromSearch(
|
|
292
|
+
search,
|
|
293
|
+
filterKeys,
|
|
294
|
+
filterItems
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
filterApi.setItems(nextState);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// on drawer close, update the modal visibility state
|
|
301
|
+
if (justClosed) {
|
|
302
|
+
handleClose();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
prevDrawer.current = drawer;
|
|
306
|
+
}, [drawer, filterApi, filterItems, filterKeys, search, handleClose]);
|
|
307
|
+
|
|
308
|
+
useEffect(() => {
|
|
309
|
+
const nextState = getStateFromSearch(search, filterKeys, filterItems);
|
|
310
|
+
|
|
311
|
+
filterApi.setItems(nextState);
|
|
312
|
+
}, [filterApi, filterItems, filterKeys, search]);
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
filterApi,
|
|
316
|
+
filterItems,
|
|
317
|
+
filterKeys,
|
|
318
|
+
filterNames,
|
|
319
|
+
filterFrontendInput,
|
|
320
|
+
filterState,
|
|
321
|
+
handleApply,
|
|
322
|
+
handleClose,
|
|
323
|
+
handleKeyDownActions,
|
|
324
|
+
handleOpen,
|
|
325
|
+
handleReset,
|
|
326
|
+
isApplying,
|
|
327
|
+
isOpen,
|
|
328
|
+
customFilters
|
|
329
|
+
};
|
|
330
|
+
};
|