@abcagency/hc-ui-components 1.3.15 → 1.3.17

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 (66) hide show
  1. package/dist/apis/hcApi.js +1 -1
  2. package/dist/apis/hcApi.js.map +1 -1
  3. package/dist/components/HireControlMap.js +15 -5
  4. package/dist/components/HireControlMap.js.map +1 -1
  5. package/dist/components/modules/accordions/MapAccordionItem.js +11 -1
  6. package/dist/components/modules/accordions/MapAccordionItem.js.map +1 -1
  7. package/dist/components/modules/accordions/filterItem.js.map +1 -1
  8. package/dist/components/modules/accordions/filters.js.map +1 -1
  9. package/dist/components/modules/buttons/button-group-apply.js +36 -15
  10. package/dist/components/modules/buttons/button-group-apply.js.map +1 -1
  11. package/dist/components/modules/filter/commute.js +22 -6
  12. package/dist/components/modules/filter/commute.js.map +1 -1
  13. package/dist/components/modules/filter/index.js +7 -0
  14. package/dist/components/modules/filter/index.js.map +1 -1
  15. package/dist/components/modules/filter/item.js +10 -0
  16. package/dist/components/modules/filter/item.js.map +1 -1
  17. package/dist/components/modules/filter/location.js +2 -4
  18. package/dist/components/modules/filter/location.js.map +1 -1
  19. package/dist/components/modules/filter/radio-item.js +7 -0
  20. package/dist/components/modules/filter/radio-item.js.map +1 -1
  21. package/dist/components/modules/jobListing/listing-details.js +6 -0
  22. package/dist/components/modules/jobListing/listing-details.js.map +1 -1
  23. package/dist/components/modules/maps/info-window-content.js +20 -0
  24. package/dist/components/modules/maps/info-window-content.js.map +1 -1
  25. package/dist/components/modules/maps/list/index.js +10 -2
  26. package/dist/components/modules/maps/list/index.js.map +1 -1
  27. package/dist/components/modules/maps/list/list-item/index.js +12 -2
  28. package/dist/components/modules/maps/list/list-item/index.js.map +1 -1
  29. package/dist/components/modules/maps/map-marker.js +10 -0
  30. package/dist/components/modules/maps/map-marker.js.map +1 -1
  31. package/dist/constants/eventTypes.js +16 -0
  32. package/dist/constants/eventTypes.js.map +1 -0
  33. package/dist/contexts/mapContext.js.map +1 -1
  34. package/dist/contexts/mapListContext.js +4 -2
  35. package/dist/contexts/mapListContext.js.map +1 -1
  36. package/dist/contexts/trackEventContext.js +20 -0
  37. package/dist/contexts/trackEventContext.js.map +1 -0
  38. package/dist/hooks/useList.js.map +1 -1
  39. package/dist/services/apis/hcApi.js +1 -1
  40. package/dist/services/apis/hcApi.js.map +1 -1
  41. package/dist/services/listingAggregatorService.js.map +1 -1
  42. package/dist/util/mapIconUtil.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/components/HireControlMap.js +60 -55
  45. package/src/components/modules/accordions/MapAccordionItem.js +3 -1
  46. package/src/components/modules/accordions/filterItem.js +55 -55
  47. package/src/components/modules/accordions/filters.js +47 -47
  48. package/src/components/modules/buttons/button-group-apply.js +73 -66
  49. package/src/components/modules/filter/commute.js +7 -2
  50. package/src/components/modules/filter/index.js +89 -87
  51. package/src/components/modules/filter/item.js +87 -81
  52. package/src/components/modules/filter/location.js +71 -73
  53. package/src/components/modules/filter/radio-item.js +4 -0
  54. package/src/components/modules/jobListing/listing-details.js +4 -0
  55. package/src/components/modules/maps/info-window-content.js +8 -1
  56. package/src/components/modules/maps/list/index.js +112 -107
  57. package/src/components/modules/maps/list/list-item/index.js +3 -1
  58. package/src/components/modules/maps/map-marker.js +3 -1
  59. package/src/constants/eventTypes.js +13 -0
  60. package/src/contexts/mapContext.js +101 -101
  61. package/src/contexts/mapListContext.js +242 -240
  62. package/src/contexts/trackEventContext.js +14 -0
  63. package/src/hooks/useList.js +89 -89
  64. package/src/services/listingAggregatorService.js +50 -50
  65. package/src/util/mapIconUtil.js +18 -18
  66. package/src/util/urlFilterUtil.js +90 -90
@@ -1,89 +1,89 @@
1
- import { useEffect, useState, useRef } from 'react';
2
-
3
- import { getStorageObject } from '~/util/localStorageUtil';
4
-
5
- const getDefaultItemId = () => {
6
- let item = getStorageObject("selectedListItem");
7
- if (item?.expanded == true) {
8
- return item.id;
9
- } else {
10
- return null;
11
- }
12
- };
13
-
14
- const useListLogic = filteredListings => {
15
- const [itemLimit, setItemLimit] = useState(100);
16
- const [expandedId] = useState(getDefaultItemId());
17
- const [sortSetting, setSortSetting] = useState(getStorageObject('sortSetting', null));
18
- const [scrollPosition, setScrollPosition] = useState(getStorageObject('scrollPosition', 0));
19
- const loader = useRef(null);
20
- const scrollContainerRef = useRef(null);
21
- const itemRefs = useRef({});
22
- const observer = useRef(null);
23
-
24
- useEffect(() => {
25
- observer.current = new IntersectionObserver(handleObserver, {
26
- root: scrollContainerRef.current,
27
- rootMargin: "100px 0px",
28
- threshold: 0.5
29
- });
30
- const { current } = loader;
31
- if (current) {
32
- observer.current.observe(current);
33
- }
34
- return () => {
35
- if (observer.current && current) {
36
- observer.current.unobserve(current);
37
- }
38
- };
39
- // eslint-disable-next-line react-hooks/exhaustive-deps
40
- }, [filteredListings.length, itemLimit]);
41
-
42
- useEffect(() => {
43
- localStorage.setItem('scrollPosition', scrollPosition.toString());
44
- }, [scrollPosition]);
45
-
46
- useEffect(() => {
47
- const savedScrollPosition = scrollPosition;
48
- if (parseInt(savedScrollPosition) > 3000) {
49
- setItemLimit(savedScrollPosition / 10);
50
- }
51
- if (savedScrollPosition && scrollContainerRef.current) {
52
- setTimeout(() => {
53
- scrollContainerRef.current.scrollTop = parseInt(savedScrollPosition, 10);
54
- }, 300);
55
- }
56
- }, []);
57
-
58
- useEffect(() => {
59
- const { current } = scrollContainerRef;
60
- if (current) {
61
- current.addEventListener('scroll', handleScroll);
62
- }
63
- return () => {
64
- if (current) {
65
- current.removeEventListener('scroll', handleScroll);
66
- }
67
- };
68
- }, []);
69
-
70
- const handleObserver = entities => {
71
- const target = entities[0];
72
- if (!target.isIntersecting) return;
73
- if (filteredListings.length > itemLimit) {
74
- setItemLimit(prevLimit => prevLimit + 100);
75
- } else if (observer.current) {
76
- observer.current.disconnect();
77
- }
78
- };
79
-
80
- const handleScroll = () => {
81
- if (scrollContainerRef.current) {
82
- setScrollPosition(scrollContainerRef.current.scrollTop);
83
- }
84
- };
85
-
86
- return { itemLimit, expandedId, sortSetting, scrollPosition, loader, scrollContainerRef, itemRefs, setSortSetting, setScrollPosition, filteredListings };
87
- };
88
-
89
- export default useListLogic;
1
+ import { useEffect, useState, useRef } from 'react';
2
+
3
+ import { getStorageObject } from '~/util/localStorageUtil';
4
+
5
+ const getDefaultItemId = () => {
6
+ let item = getStorageObject("selectedListItem");
7
+ if (item?.expanded == true) {
8
+ return item.id;
9
+ } else {
10
+ return null;
11
+ }
12
+ };
13
+
14
+ const useListLogic = filteredListings => {
15
+ const [itemLimit, setItemLimit] = useState(100);
16
+ const [expandedId] = useState(getDefaultItemId());
17
+ const [sortSetting, setSortSetting] = useState(getStorageObject('sortSetting', null));
18
+ const [scrollPosition, setScrollPosition] = useState(getStorageObject('scrollPosition', 0));
19
+ const loader = useRef(null);
20
+ const scrollContainerRef = useRef(null);
21
+ const itemRefs = useRef({});
22
+ const observer = useRef(null);
23
+
24
+ useEffect(() => {
25
+ observer.current = new IntersectionObserver(handleObserver, {
26
+ root: scrollContainerRef.current,
27
+ rootMargin: "100px 0px",
28
+ threshold: 0.5
29
+ });
30
+ const { current } = loader;
31
+ if (current) {
32
+ observer.current.observe(current);
33
+ }
34
+ return () => {
35
+ if (observer.current && current) {
36
+ observer.current.unobserve(current);
37
+ }
38
+ };
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
40
+ }, [filteredListings.length, itemLimit]);
41
+
42
+ useEffect(() => {
43
+ localStorage.setItem('scrollPosition', scrollPosition.toString());
44
+ }, [scrollPosition]);
45
+
46
+ useEffect(() => {
47
+ const savedScrollPosition = scrollPosition;
48
+ if (parseInt(savedScrollPosition) > 3000) {
49
+ setItemLimit(savedScrollPosition / 10);
50
+ }
51
+ if (savedScrollPosition && scrollContainerRef.current) {
52
+ setTimeout(() => {
53
+ scrollContainerRef.current.scrollTop = parseInt(savedScrollPosition, 10);
54
+ }, 300);
55
+ }
56
+ }, []);
57
+
58
+ useEffect(() => {
59
+ const { current } = scrollContainerRef;
60
+ if (current) {
61
+ current.addEventListener('scroll', handleScroll);
62
+ }
63
+ return () => {
64
+ if (current) {
65
+ current.removeEventListener('scroll', handleScroll);
66
+ }
67
+ };
68
+ }, []);
69
+
70
+ const handleObserver = entities => {
71
+ const target = entities[0];
72
+ if (!target.isIntersecting) return;
73
+ if (filteredListings.length > itemLimit) {
74
+ setItemLimit(prevLimit => prevLimit + 100);
75
+ } else if (observer.current) {
76
+ observer.current.disconnect();
77
+ }
78
+ };
79
+
80
+ const handleScroll = () => {
81
+ if (scrollContainerRef.current) {
82
+ setScrollPosition(scrollContainerRef.current.scrollTop);
83
+ }
84
+ };
85
+
86
+ return { itemLimit, expandedId, sortSetting, scrollPosition, loader, scrollContainerRef, itemRefs, setSortSetting, setScrollPosition, filteredListings };
87
+ };
88
+
89
+ export default useListLogic;
@@ -1,50 +1,50 @@
1
- import { getListings } from '~/services/listingService';
2
- import { getRecruiters } from '~/services/recruiterService';
3
- import { getListingEntities } from '~/services/listingEntityService';
4
-
5
- import { getDistinctItemsByProximity } from '~/util/mapUtil';
6
-
7
- const fetchListings = async (query, siteConfig, commuteLocation = null) => {
8
- try {
9
- const listingsResult = await getListings(
10
- siteConfig.companyId,
11
- 5000,
12
- 1,
13
- query
14
- );
15
- const recruiterIds = [
16
- // eslint-disable-next-line no-undef
17
- ...new Set(listingsResult.map(listing => listing.recruiterId))
18
- ];
19
- const fetchedRecruiters = await getRecruiters(recruiterIds);
20
-
21
- const distinctEntityIds = [
22
- // eslint-disable-next-line no-undef
23
- ...new Set(listingsResult.map(listing => listing.entityId))
24
- ];
25
-
26
- const fetchedEntities = !commuteLocation ? await getListingEntities(
27
- distinctEntityIds) : await getListingEntities(
28
- distinctEntityIds,`${commuteLocation.lat}, ${commuteLocation.lng}`);
29
- for (var i = 0; i < listingsResult.length; i++) {
30
- if (listingsResult[i].entityId != -1) {
31
- listingsResult[i].fields.travelTime = fetchedEntities[listingsResult[i].entityId].travelTime;
32
- }
33
- }
34
- const distinctItems = getDistinctItemsByProximity(
35
- listingsResult,
36
- fetchedEntities
37
- );
38
- return {
39
- listingsResult,
40
- fetchedRecruiters,
41
- fetchedEntities,
42
- distinctItems
43
- };
44
- } catch (error) {
45
- console.error("Error fetching listings:", error);
46
- throw error;
47
- }
48
- };
49
-
50
- export default fetchListings;
1
+ import { getListings } from '~/services/listingService';
2
+ import { getRecruiters } from '~/services/recruiterService';
3
+ import { getListingEntities } from '~/services/listingEntityService';
4
+
5
+ import { getDistinctItemsByProximity } from '~/util/mapUtil';
6
+
7
+ const fetchListings = async (query, siteConfig, commuteLocation = null) => {
8
+ try {
9
+ const listingsResult = await getListings(
10
+ siteConfig.companyId,
11
+ 5000,
12
+ 1,
13
+ query
14
+ );
15
+ const recruiterIds = [
16
+ // eslint-disable-next-line no-undef
17
+ ...new Set(listingsResult.map(listing => listing.recruiterId))
18
+ ];
19
+ const fetchedRecruiters = await getRecruiters(recruiterIds);
20
+
21
+ const distinctEntityIds = [
22
+ // eslint-disable-next-line no-undef
23
+ ...new Set(listingsResult.map(listing => listing.entityId))
24
+ ];
25
+
26
+ const fetchedEntities = !commuteLocation ? await getListingEntities(
27
+ distinctEntityIds) : await getListingEntities(
28
+ distinctEntityIds,`${commuteLocation.lat}, ${commuteLocation.lng}`);
29
+ for (var i = 0; i < listingsResult.length; i++) {
30
+ if (listingsResult[i].entityId != -1) {
31
+ listingsResult[i].fields.travelTime = fetchedEntities[listingsResult[i].entityId].travelTime;
32
+ }
33
+ }
34
+ const distinctItems = getDistinctItemsByProximity(
35
+ listingsResult,
36
+ fetchedEntities
37
+ );
38
+ return {
39
+ listingsResult,
40
+ fetchedRecruiters,
41
+ fetchedEntities,
42
+ distinctItems
43
+ };
44
+ } catch (error) {
45
+ console.error("Error fetching listings:", error);
46
+ throw error;
47
+ }
48
+ };
49
+
50
+ export default fetchListings;
@@ -10,8 +10,8 @@ const customSVGIcon = (
10
10
  ) => {
11
11
  let svg = "";
12
12
  switch (type) {
13
- case placeTypes.FOOD:
14
- svg = `
13
+ case placeTypes.FOOD:
14
+ svg = `
15
15
  <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
16
16
  viewBox="0 0 60.8 89.6" preserveAspectRatio="xMidYMid meet" style="enable-background:new 0 0 60.8 89.6;" xml:space="preserve">
17
17
  <style type="text/css">
@@ -25,9 +25,9 @@ const customSVGIcon = (
25
25
  c1.1-2.4,3.9-4,5.6-4C40,18.3,40,52.4,40,52.4z"/>
26
26
  </svg>
27
27
  `;
28
- break;
29
- case placeTypes.TOURIST_ATTRACTION:
30
- svg = `<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
28
+ break;
29
+ case placeTypes.TOURIST_ATTRACTION:
30
+ svg = `<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
31
31
  viewBox="0 0 60.8 89.6" preserveAspectRatio="xMidYMid meet" style="enable-background:new 0 0 60.8 89.6;" xml:space="preserve">
32
32
  <style type="text/css">
33
33
  .st0{fill:${fillColor}; stroke:${strokeColor};}
@@ -41,9 +41,9 @@ const customSVGIcon = (
41
41
  S32.3,28.7,30.4,28.7z"/>
42
42
  </svg>
43
43
  `;
44
- break;
45
- case placeTypes.SCHOOL:
46
- svg = `
44
+ break;
45
+ case placeTypes.SCHOOL:
46
+ svg = `
47
47
  <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
48
48
  viewBox="0 0 60.8 89.6" preserveAspectRatio="xMidYMid meet" style="enable-background:new 0 0 60.8 89.6;" xml:space="preserve">
49
49
  <style type="text/css">
@@ -55,9 +55,9 @@ const customSVGIcon = (
55
55
  <polygon class="st0" points="44.4,40.4 41.8,40.4 41.8,31.4 30.1,37.8 15.8,30 30.1,22.2 44.4,30 "/>
56
56
  </svg>
57
57
  `;
58
- break;
59
- case placeTypes.STORE:
60
- svg = `<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
58
+ break;
59
+ case placeTypes.STORE:
60
+ svg = `<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
61
61
  viewBox="0 0 60.8 89.6" preserveAspectRatio="xMidYMid meet" style="enable-background:new 0 0 60.8 89.6;" xml:space="preserve">
62
62
  <style type="text/css">
63
63
  .st0{fill:${fillColor}; stroke:${strokeColor};}
@@ -75,9 +75,9 @@ const customSVGIcon = (
75
75
  <path d="M24,45.5c0-0.4-0.3-0.7-0.7-0.7s-0.7,0.3-0.7,0.7C22.6,46.2,24,46.2,24,45.5z"/>
76
76
  </svg>
77
77
  `;
78
- break;
79
- case placeTypes.TRANSIT_STATION:
80
- svg = `<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
78
+ break;
79
+ case placeTypes.TRANSIT_STATION:
80
+ svg = `<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
81
81
  viewBox="0 0 60.8 89.6" preserveAspectRatio="xMidYMid meet" style="enable-background:new 0 0 60.8 89.6;" xml:space="preserve">
82
82
  <style type="text/css">
83
83
  .st0{fill:${fillColor}; stroke:${strokeColor};}
@@ -97,9 +97,9 @@ const customSVGIcon = (
97
97
  <polygon points="31,30.2 29.6,34.4 42.4,34.4 40.9,30.2 "/>
98
98
  </svg>
99
99
  `;
100
- break;
101
- case placeTypes.PLACE_OF_WORSHIP:
102
- svg = `<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
100
+ break;
101
+ case placeTypes.PLACE_OF_WORSHIP:
102
+ svg = `<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
103
103
  viewBox="0 0 60.8 89.6" style="enable-background:new 0 0 60.8 89.6;" xml:space="preserve">
104
104
  <style type="text/css">
105
105
  .st0{fill:${fillColor}; stroke:${strokeColor};}
@@ -113,7 +113,7 @@ const customSVGIcon = (
113
113
  <path class="st0" d="M45.6,38.5c0,1.3-1,2.3-2.3,2.3h-3.8V29.5l4.9,2.7c0.7,0.4,1.2,1.2,1.2,2C45.6,34.2,45.6,38.5,45.6,38.5z"/>
114
114
  </svg>
115
115
  `;
116
- break;
116
+ break;
117
117
  }
118
118
 
119
119
  const iconUrl = `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
@@ -1,90 +1,90 @@
1
- export const updateURLWithFilters = (filters, location, navigate, query) => {
2
- const searchParams = new URLSearchParams(location.search);
3
-
4
- Object.keys(Object.fromEntries(searchParams)).forEach(key => {
5
- if (!key.includes('.') && key !== 'query') {
6
- searchParams.set(key, searchParams.get(key));
7
- }
8
- });
9
-
10
- if (query) {
11
- searchParams.set('query', query);
12
- }
13
-
14
- Object.keys(filters).forEach(category => {
15
- Object.keys(filters[category]).forEach(filter => {
16
- const key = `${category}.${filter}`;
17
- if (filters[category][filter]) {
18
- searchParams.set(key, 'true');
19
- } else {
20
- searchParams.delete(key);
21
- }
22
- });
23
- });
24
-
25
- navigate({
26
- search: searchParams.toString()
27
- }, { replace: true });
28
-
29
- notifyParentOfUrlChange();
30
- };
31
-
32
- function notifyParentOfUrlChange() {
33
- setTimeout(() => {
34
- var message = {
35
- type: 'URL_CHANGE',
36
- url: window.location.href
37
- };
38
- window.parent.postMessage(message, "*");
39
- }, 500);
40
- }
41
-
42
- export const parseQueryParams = search => {
43
- const queryParams = {};
44
- if (!search) return queryParams;
45
- let queryString = search.split('?')[1];
46
- if (!queryString) {
47
- return queryParams;
48
- }
49
- queryString = queryString.replaceAll('+', ' ');
50
- queryString.split('&').forEach(param => {
51
- const [key, value] = param.split('=');
52
- queryParams[decodeURIComponent(key)] = decodeURIComponent(value);
53
- });
54
- return queryParams;
55
- };
56
-
57
- export const filtersFromURL = location => {
58
- if (!location || !location.search) return;
59
- const filters = {};
60
- let queryParam = null;
61
- const queryParams = parseQueryParams(location.search);
62
- if (!queryParams) return;
63
- Object.keys(queryParams).forEach(key => {
64
- if (key && key.includes('.')) {
65
- const [category, filter] = key.split('.');
66
- if (!filters[category]) {
67
- filters[category] = {};
68
- }
69
- filters[category][filter] = queryParams[key] === 'true';
70
- } else if (key === 'query') {
71
- queryParam = queryParams[key];
72
- }
73
- });
74
-
75
- return { filters, query: queryParam };
76
- };
77
-
78
- export const hasFiltersInURL = location => {
79
- if (!location || !location.search) return;
80
- const queryParams = parseQueryParams(location.search);
81
- if (!queryParams) return;
82
- return Object.keys(queryParams).some(key => key.includes('.'));
83
- };
84
-
85
- export const hasQueryInUrl = location => {
86
- if (!location || !location.search) return;
87
- const queryParams = parseQueryParams(location.search);
88
- if (!queryParams) return;
89
- return Object.keys(queryParams).includes('query');
90
- };
1
+ export const updateURLWithFilters = (filters, location, navigate, query) => {
2
+ const searchParams = new URLSearchParams(location.search);
3
+
4
+ Object.keys(Object.fromEntries(searchParams)).forEach(key => {
5
+ if (!key.includes('.') && key !== 'query') {
6
+ searchParams.set(key, searchParams.get(key));
7
+ }
8
+ });
9
+
10
+ if (query) {
11
+ searchParams.set('query', query);
12
+ }
13
+
14
+ Object.keys(filters).forEach(category => {
15
+ Object.keys(filters[category]).forEach(filter => {
16
+ const key = `${category}.${filter}`;
17
+ if (filters[category][filter]) {
18
+ searchParams.set(key, 'true');
19
+ } else {
20
+ searchParams.delete(key);
21
+ }
22
+ });
23
+ });
24
+
25
+ navigate({
26
+ search: searchParams.toString()
27
+ }, { replace: true });
28
+
29
+ notifyParentOfUrlChange();
30
+ };
31
+
32
+ function notifyParentOfUrlChange() {
33
+ setTimeout(() => {
34
+ var message = {
35
+ type: 'URL_CHANGE',
36
+ url: window.location.href
37
+ };
38
+ window.parent.postMessage(message, "*");
39
+ }, 500);
40
+ }
41
+
42
+ export const parseQueryParams = search => {
43
+ const queryParams = {};
44
+ if (!search) return queryParams;
45
+ let queryString = search.split('?')[1];
46
+ if (!queryString) {
47
+ return queryParams;
48
+ }
49
+ queryString = queryString.replaceAll('+', ' ');
50
+ queryString.split('&').forEach(param => {
51
+ const [key, value] = param.split('=');
52
+ queryParams[decodeURIComponent(key)] = decodeURIComponent(value);
53
+ });
54
+ return queryParams;
55
+ };
56
+
57
+ export const filtersFromURL = location => {
58
+ if (!location || !location.search) return;
59
+ const filters = {};
60
+ let queryParam = null;
61
+ const queryParams = parseQueryParams(location.search);
62
+ if (!queryParams) return;
63
+ Object.keys(queryParams).forEach(key => {
64
+ if (key && key.includes('.')) {
65
+ const [category, filter] = key.split('.');
66
+ if (!filters[category]) {
67
+ filters[category] = {};
68
+ }
69
+ filters[category][filter] = queryParams[key] === 'true';
70
+ } else if (key === 'query') {
71
+ queryParam = queryParams[key];
72
+ }
73
+ });
74
+
75
+ return { filters, query: queryParam };
76
+ };
77
+
78
+ export const hasFiltersInURL = location => {
79
+ if (!location || !location.search) return;
80
+ const queryParams = parseQueryParams(location.search);
81
+ if (!queryParams) return;
82
+ return Object.keys(queryParams).some(key => key.includes('.'));
83
+ };
84
+
85
+ export const hasQueryInUrl = location => {
86
+ if (!location || !location.search) return;
87
+ const queryParams = parseQueryParams(location.search);
88
+ if (!queryParams) return;
89
+ return Object.keys(queryParams).includes('query');
90
+ };