@abcagency/hc-ui-components 1.3.15 → 1.3.16

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 (62) hide show
  1. package/dist/components/HireControlMap.js +15 -5
  2. package/dist/components/HireControlMap.js.map +1 -1
  3. package/dist/components/modules/accordions/MapAccordionItem.js +11 -1
  4. package/dist/components/modules/accordions/MapAccordionItem.js.map +1 -1
  5. package/dist/components/modules/accordions/filterItem.js.map +1 -1
  6. package/dist/components/modules/accordions/filters.js.map +1 -1
  7. package/dist/components/modules/buttons/button-group-apply.js +36 -15
  8. package/dist/components/modules/buttons/button-group-apply.js.map +1 -1
  9. package/dist/components/modules/filter/commute.js +22 -6
  10. package/dist/components/modules/filter/commute.js.map +1 -1
  11. package/dist/components/modules/filter/index.js +7 -0
  12. package/dist/components/modules/filter/index.js.map +1 -1
  13. package/dist/components/modules/filter/item.js +10 -0
  14. package/dist/components/modules/filter/item.js.map +1 -1
  15. package/dist/components/modules/filter/location.js +2 -4
  16. package/dist/components/modules/filter/location.js.map +1 -1
  17. package/dist/components/modules/filter/radio-item.js +7 -0
  18. package/dist/components/modules/filter/radio-item.js.map +1 -1
  19. package/dist/components/modules/jobListing/listing-details.js +6 -0
  20. package/dist/components/modules/jobListing/listing-details.js.map +1 -1
  21. package/dist/components/modules/maps/info-window-content.js +20 -0
  22. package/dist/components/modules/maps/info-window-content.js.map +1 -1
  23. package/dist/components/modules/maps/list/index.js +10 -2
  24. package/dist/components/modules/maps/list/index.js.map +1 -1
  25. package/dist/components/modules/maps/list/list-item/index.js +12 -2
  26. package/dist/components/modules/maps/list/list-item/index.js.map +1 -1
  27. package/dist/components/modules/maps/map-marker.js +10 -0
  28. package/dist/components/modules/maps/map-marker.js.map +1 -1
  29. package/dist/constants/eventTypes.js +16 -0
  30. package/dist/constants/eventTypes.js.map +1 -0
  31. package/dist/contexts/mapContext.js.map +1 -1
  32. package/dist/contexts/mapListContext.js +4 -2
  33. package/dist/contexts/mapListContext.js.map +1 -1
  34. package/dist/contexts/trackEventContext.js +20 -0
  35. package/dist/contexts/trackEventContext.js.map +1 -0
  36. package/dist/hooks/useList.js.map +1 -1
  37. package/dist/services/listingAggregatorService.js.map +1 -1
  38. package/dist/util/mapIconUtil.js.map +1 -1
  39. package/package.json +60 -60
  40. package/src/components/HireControlMap.js +60 -55
  41. package/src/components/modules/accordions/MapAccordionItem.js +3 -1
  42. package/src/components/modules/accordions/filterItem.js +55 -55
  43. package/src/components/modules/accordions/filters.js +47 -47
  44. package/src/components/modules/buttons/button-group-apply.js +73 -66
  45. package/src/components/modules/filter/commute.js +7 -2
  46. package/src/components/modules/filter/index.js +89 -87
  47. package/src/components/modules/filter/item.js +87 -81
  48. package/src/components/modules/filter/location.js +71 -73
  49. package/src/components/modules/filter/radio-item.js +4 -0
  50. package/src/components/modules/jobListing/listing-details.js +4 -0
  51. package/src/components/modules/maps/info-window-content.js +8 -1
  52. package/src/components/modules/maps/list/index.js +112 -107
  53. package/src/components/modules/maps/list/list-item/index.js +3 -1
  54. package/src/components/modules/maps/map-marker.js +3 -1
  55. package/src/constants/eventTypes.js +13 -0
  56. package/src/contexts/mapContext.js +101 -101
  57. package/src/contexts/mapListContext.js +242 -240
  58. package/src/contexts/trackEventContext.js +14 -0
  59. package/src/hooks/useList.js +89 -89
  60. package/src/services/listingAggregatorService.js +50 -50
  61. package/src/util/mapIconUtil.js +18 -18
  62. package/src/util/urlFilterUtil.js +90 -90
@@ -1,107 +1,112 @@
1
- import React from 'react';
2
-
3
- import Accordion from '~/components/modules/accordions/default';
4
- import Header from '~/components/modules/maps/list/header';
5
- import MapAccordionItem from '~/components/modules/accordions/MapAccordionItem';
6
- import Sort from '~/components/modules/filter/sort';
7
- import ListingDetails from '~/components/modules/jobListing/listing-details';
8
-
9
- import useListLogic from '~/hooks/useList';
10
-
11
- import Loading from "~/util/loading";
12
-
13
- import { useMap } from '~/contexts/mapContext';
14
- import { useMapList } from '~/contexts/mapListContext';
15
-
16
- import { dynamicSort } from '~/util/sortUtil';
17
-
18
- const ItemsList = ({
19
- fieldNames,
20
- showMap,
21
- fieldsShown,
22
- specialFeatures
23
- }) => {
24
- const { mapItems, filteredListings, loading, commuteLocation, sortSetting, setSortSetting } = useMapList();
25
- const {
26
- itemLimit,
27
- loader,
28
- scrollContainerRef,
29
- itemRefs
30
- } = useListLogic(filteredListings);
31
- const { selectedListItem } = useMap();
32
-
33
- const itemExpandedContent = (item, recruiters) =>
34
- item ? <ListingDetails item={item} recruiters={recruiters} /> : null;
35
- if (!fieldsShown.includes('travelTime') && commuteLocation != null && Object.entries(commuteLocation).length > 0) {
36
- fieldsShown.push('travelTime');
37
- fieldNames['travelTime'] = 'Commute';
38
- } else if (fieldsShown.includes('travelTime') && !commuteLocation) {
39
- fieldsShown = fieldsShown.filter(x => x !== 'travelTime');
40
- }
41
-
42
- return (
43
- <div className="hc-relative hc-bg-white md:hc-px-4 hc-flex hc-flex-col">
44
- <div className="hc-flex hc-flex-wrap hc-items-center hc-justify-between hc-gap-4 md:hc-mb-2 hc-p-3 md:hc-p-0 hc-bg-uiAccent/10 md:hc-bg-transparent hc-border-b md:hc-border-none hc-border-uiAccent/20">
45
- <h2 className="hc-text-gray-500 hc-font-semibold hc-text-xs md:hc-text-sm">
46
- {loading &&
47
- <span>Loading...</span>
48
- }
49
- {!loading &&
50
- <span>{filteredListings.length} results</span>
51
- }
52
- </h2>
53
- <div className="hc-block md:hc-hidden">
54
- <Sort
55
- fields={fieldsShown}
56
- setSortSetting={setSortSetting}
57
- fieldNames={fieldNames}
58
- />
59
- </div>
60
- </div>
61
- <div>
62
- <Header
63
- setSortSetting={setSortSetting}
64
- sortSetting={sortSetting}
65
- fieldsShown={fieldsShown}
66
- fieldNames={fieldNames}
67
- />
68
- </div>
69
- <div
70
- ref={scrollContainerRef}
71
- className={`
72
- hc-flex-grow hc-overflow-y-auto
73
- ${showMap ? "md:hc-max-h-45vh hc-max-h-[100vh]" : "md:hc-max-h-95vh hc-max-h-[95vh]"}
74
- `}
75
- >
76
- {loading ? (
77
- <div className="hc-flex hc-justify-center hc-items-center hc-pt-20">
78
- <Loading />
79
- </div>
80
- ) : (
81
- <Accordion className="hc-divide-y hc-divide-uiAccent/10 hc-z-[1000]" defaultValue={selectedListItem?.id}>
82
- {(sortSetting ? dynamicSort(filteredListings, sortSetting.field, sortSetting.type) : filteredListings).slice(0, itemLimit).map(item => {
83
- return (<MapAccordionItem
84
- key={item.id}
85
- showMap={showMap}
86
- item={item}
87
- itemRefs={itemRefs}
88
- fieldsShown={fieldsShown}
89
- itemExpandedContent={itemExpandedContent}
90
- specialFeatures={specialFeatures}
91
- mapItems={mapItems}
92
- isActive={selectedListItem?.id == item.id}
93
- hasListItemSelected={selectedListItem != null}
94
- />
95
- );
96
- })}
97
- </Accordion>
98
- )}
99
- <div ref={loader} style={{ height: "100px", textAlign: "center" }}>
100
- {filteredListings.length >= itemLimit && <Loading />}
101
- </div>
102
- </div>
103
- </div>
104
- );
105
- };
106
-
107
- export default ItemsList;
1
+ import React from 'react';
2
+
3
+ import Accordion from '~/components/modules/accordions/default';
4
+ import Header from '~/components/modules/maps/list/header';
5
+ import MapAccordionItem from '~/components/modules/accordions/MapAccordionItem';
6
+ import Sort from '~/components/modules/filter/sort';
7
+ import ListingDetails from '~/components/modules/jobListing/listing-details';
8
+
9
+ import useListLogic from '~/hooks/useList';
10
+
11
+ import Loading from "~/util/loading";
12
+
13
+ import { useMap } from '~/contexts/mapContext';
14
+ import { useMapList } from '~/contexts/mapListContext';
15
+ import { useTrackEvent } from '~/contexts/trackEventContext';
16
+
17
+ import { dynamicSort } from '~/util/sortUtil';
18
+
19
+ const ItemsList = ({
20
+ fieldNames,
21
+ showMap,
22
+ fieldsShown,
23
+ specialFeatures
24
+ }) => {
25
+ const { mapItems, filteredListings, loading, commuteLocation, sortSetting, setSortSetting } = useMapList();
26
+ const {
27
+ itemLimit,
28
+ loader,
29
+ scrollContainerRef,
30
+ itemRefs
31
+ } = useListLogic(filteredListings);
32
+ const { selectedListItem } = useMap();
33
+ const { trackEvent, eventTypes } = useTrackEvent();
34
+ const itemExpandedContent = (item, recruiters) =>
35
+ item ? <ListingDetails item={item} recruiters={recruiters} /> : null;
36
+ if (!fieldsShown.includes('travelTime') && commuteLocation != null && Object.entries(commuteLocation).length > 0) {
37
+ fieldsShown.push('travelTime');
38
+ fieldNames['travelTime'] = 'Commute';
39
+ } else if (fieldsShown.includes('travelTime') && !commuteLocation) {
40
+ fieldsShown = fieldsShown.filter(x => x !== 'travelTime');
41
+ }
42
+
43
+ const setTrackedSortSetting = sortSetting => {
44
+ trackEvent(eventTypes.LIST_SORTED, sortSetting);
45
+ setSortSetting(sortSetting);
46
+ };
47
+ return (
48
+ <div className="hc-relative hc-bg-white md:hc-px-4 hc-flex hc-flex-col">
49
+ <div className="hc-flex hc-flex-wrap hc-items-center hc-justify-between hc-gap-4 md:hc-mb-2 hc-p-3 md:hc-p-0 hc-bg-uiAccent/10 md:hc-bg-transparent hc-border-b md:hc-border-none hc-border-uiAccent/20">
50
+ <h2 className="hc-text-gray-500 hc-font-semibold hc-text-xs md:hc-text-sm">
51
+ {loading &&
52
+ <span>Loading...</span>
53
+ }
54
+ {!loading &&
55
+ <span>{filteredListings.length} results</span>
56
+ }
57
+ </h2>
58
+ <div className="hc-block md:hc-hidden">
59
+ <Sort
60
+ fields={fieldsShown}
61
+ setSortSetting={setTrackedSortSetting}
62
+ fieldNames={fieldNames}
63
+ />
64
+ </div>
65
+ </div>
66
+ <div>
67
+ <Header
68
+ setSortSetting={setTrackedSortSetting}
69
+ sortSetting={sortSetting}
70
+ fieldsShown={fieldsShown}
71
+ fieldNames={fieldNames}
72
+ />
73
+ </div>
74
+ <div
75
+ ref={scrollContainerRef}
76
+ className={`
77
+ hc-flex-grow hc-overflow-y-auto
78
+ ${showMap ? "md:hc-max-h-45vh hc-max-h-[100vh]" : "md:hc-max-h-95vh hc-max-h-[95vh]"}
79
+ `}
80
+ >
81
+ {loading ? (
82
+ <div className="hc-flex hc-justify-center hc-items-center hc-pt-20">
83
+ <Loading />
84
+ </div>
85
+ ) : (
86
+ <Accordion className="hc-divide-y hc-divide-uiAccent/10 hc-z-[1000]" defaultValue={selectedListItem?.id}>
87
+ {(sortSetting ? dynamicSort(filteredListings, sortSetting.field, sortSetting.type) : filteredListings).slice(0, itemLimit).map(item => {
88
+ return (<MapAccordionItem
89
+ key={item.id}
90
+ showMap={showMap}
91
+ item={item}
92
+ itemRefs={itemRefs}
93
+ fieldsShown={fieldsShown}
94
+ itemExpandedContent={itemExpandedContent}
95
+ specialFeatures={specialFeatures}
96
+ mapItems={mapItems}
97
+ isActive={selectedListItem?.id == item.id}
98
+ hasListItemSelected={selectedListItem != null}
99
+ />
100
+ );
101
+ })}
102
+ </Accordion>
103
+ )}
104
+ <div ref={loader} style={{ height: "100px", textAlign: "center" }}>
105
+ {filteredListings.length >= itemLimit && <Loading />}
106
+ </div>
107
+ </div>
108
+ </div>
109
+ );
110
+ };
111
+
112
+ export default ItemsList;
@@ -5,6 +5,7 @@ import Icon from '~/components/modules/icon';
5
5
  import FieldMapper from '~/components/modules/maps/list/field-mapper';
6
6
 
7
7
  import { useMapList } from '~/contexts/mapListContext';
8
+ import { useTrackEvent } from '~/contexts/trackEventContext';
8
9
 
9
10
  const ListItem = forwardRef(
10
11
  (
@@ -25,6 +26,7 @@ const ListItem = forwardRef(
25
26
  ref
26
27
  ) => {
27
28
  const { siteConfig } = useMapList();
29
+ const { trackEvent, eventTypes } = useTrackEvent();
28
30
  const mapPinColor = siteConfig.colors.primary.replace("#", "");
29
31
 
30
32
  const handleClick = () => {
@@ -41,11 +43,11 @@ const ListItem = forwardRef(
41
43
  if (isFavorite) {
42
44
  updatedFavorites = favorites.filter(fav => fav !== item.id);
43
45
  } else {
46
+ trackEvent(eventTypes.FAVORITE_SELECTED, { jobTitle: item.fields.position, jobCategory: item.fields.category, entityDisplayName: item?.mapDetails?.entityDisplayName });
44
47
  updatedFavorites = [...favorites, item.id];
45
48
  }
46
49
  isFavorite = !isFavorite;
47
50
  setFavorites(updatedFavorites);
48
-
49
51
  };
50
52
 
51
53
  return (
@@ -6,6 +6,7 @@ import InfoWindowContent from "~/components/modules/maps/info-window-content";
6
6
 
7
7
  import { useMap } from "~/contexts/mapContext";
8
8
  import { useMapList } from "~/contexts/mapListContext";
9
+ import { useTrackEvent } from '~/contexts/trackEventContext';
9
10
 
10
11
  const MapMarker = ({
11
12
  item,
@@ -21,7 +22,7 @@ const MapMarker = ({
21
22
  const { setLocation, commuteLocation } = useMap();
22
23
  const isSelected = item.id === selectedLocation?.id;
23
24
  const markerRef = useRef(null);
24
-
25
+ const { trackEvent, eventTypes } = useTrackEvent();
25
26
  const {
26
27
  handleFilterListingsByLocation
27
28
  } = useMapList();
@@ -31,6 +32,7 @@ const MapMarker = ({
31
32
  }, []);
32
33
 
33
34
  const onMarkerClick = () => {
35
+ trackEvent(eventTypes.MAP_MARKER_CLICKED, { entityDisplayName: item.entityDisplayName, lat: item.latitude, lng: item.longitude, travelTime: item.travelTime });
34
36
  setMapInteracted(true);
35
37
  markerClickHandler(item);
36
38
  };
@@ -0,0 +1,13 @@
1
+ export const eventTypes = {
2
+ FILTER_APPLIED: "filter_applied",
3
+ MAP_MARKER_CLICKED: "map_marker_clicked",
4
+ JOB_LISTING_SELECTED: "job_listing_selected",
5
+ APPLY_NOW_CLICKED: "apply_now_clicked",
6
+ VIEW_DETAILS_CLICKED: "view_details_clicked",
7
+ COMMUTE_ORIGIN_ADDED: "commute_origin_added",
8
+ POI_APPLIED: "point_of_interest_applied",
9
+ VIEW_JOBS_AT_Location: "view_jobs_at_location_clicked",
10
+ FAVORITE_SELECTED: "favorite_job_selected",
11
+ LIST_SORTED: "jobs_list_sorted",
12
+ FILTERS_RESET: "filters_reset_button_clicked"
13
+ };
@@ -1,101 +1,101 @@
1
- import React, { createContext, useState, useContext, useEffect, useRef } from 'react';
2
- import { getStorageObject, setStorageObject } from '~/util/localStorageUtil';
3
-
4
- const MapContext = createContext();
5
-
6
- export const useMap = () => {
7
- const context = useContext(MapContext);
8
- if (!context) {
9
- throw new Error("useMap must be used within a MapProvider");
10
- }
11
- return context;
12
- };
13
-
14
- export const MapProvider = ({ children, resetFilters }) => {
15
- const [selectedListItem, setSelectedListItem] = useState(getStorageObject('selectedListItem'));
16
- const [location, setLocation] = useState(getStorageObject('location'));
17
- const [center, setCenter] = useState(getStorageObject("center", { lat: 39.8283, lng: -98.5795 }));
18
- const [zoom, setZoom] = useState(getStorageObject("zoom", 10));
19
- const [selectedPlaces, setSelectedPlaces] = useState([]);
20
- const [mapInteracted, setMapInteracted] = useState(false);
21
- const [firstLoadListItem] = useState(getStorageObject('selectedListItem') ?? { id: "defaultId" });
22
- const userSetZoom = useRef(true);
23
-
24
- useEffect(() => {
25
- setStorageObject("selectedListItem", selectedListItem);
26
- }, [selectedListItem]);
27
-
28
- useEffect(() => {
29
- localStorage.setItem("zoom", zoom);
30
- }, [zoom]);
31
-
32
- useEffect(() => {
33
- if (location == null) {
34
- localStorage.removeItem("location");
35
- } else {
36
- setStorageObject("location", location);
37
- }
38
- }, [location]);
39
-
40
- useEffect(() => {
41
- setStorageObject("center", center);
42
- }, [center]);
43
-
44
- const selectItem = (item, itemLocation, zoom, center) => {
45
- setSelectedListItem(item);
46
- if (mapInteracted === false && itemLocation != null) {
47
- setLocation(itemLocation);
48
- }
49
- if (mapInteracted === false || itemLocation != null) {
50
- setLocation(itemLocation);
51
- setCenter(center);
52
- }
53
- if (mapInteracted === false) {
54
- setZoom(zoom);
55
-
56
- }
57
- };
58
-
59
- const filterReset = () => {
60
- setSelectedPlaces({});
61
- setSelectedListItem(null);
62
- setLocation(null);
63
- setZoom(8);
64
- setMapInteracted(false);
65
- };
66
-
67
- if (resetFilters === true) {
68
- filterReset();
69
- }
70
- const selectLocationEntity = location => {
71
-
72
- localStorage.removeItem("selectedListItem");
73
- setTimeout(() => setLocation(location), 200);
74
- setSelectedListItem(null);
75
- };
76
-
77
- return (
78
- <MapContext.Provider
79
- value={{
80
- selectedListItem,
81
- setSelectedListItem,
82
- location,
83
- center,
84
- zoom,
85
- setZoom,
86
- selectItem,
87
- setSelectedPlaces,
88
- selectedPlaces,
89
- selectLocationEntity,
90
- setLocation,
91
- setMapInteracted,
92
- mapInteracted,
93
- userSetZoom,
94
- firstLoadListItem,
95
- filterReset
96
- }}
97
- >
98
- {children}
99
- </MapContext.Provider>
100
- );
101
- };
1
+ import React, { createContext, useState, useContext, useEffect, useRef } from 'react';
2
+ import { getStorageObject, setStorageObject } from '~/util/localStorageUtil';
3
+
4
+ const MapContext = createContext();
5
+
6
+ export const useMap = () => {
7
+ const context = useContext(MapContext);
8
+ if (!context) {
9
+ throw new Error("useMap must be used within a MapProvider");
10
+ }
11
+ return context;
12
+ };
13
+
14
+ export const MapProvider = ({ children, resetFilters }) => {
15
+ const [selectedListItem, setSelectedListItem] = useState(getStorageObject('selectedListItem'));
16
+ const [location, setLocation] = useState(getStorageObject('location'));
17
+ const [center, setCenter] = useState(getStorageObject("center", { lat: 39.8283, lng: -98.5795 }));
18
+ const [zoom, setZoom] = useState(getStorageObject("zoom", 10));
19
+ const [selectedPlaces, setSelectedPlaces] = useState([]);
20
+ const [mapInteracted, setMapInteracted] = useState(false);
21
+ const [firstLoadListItem] = useState(getStorageObject('selectedListItem') ?? { id: "defaultId" });
22
+ const userSetZoom = useRef(true);
23
+
24
+ useEffect(() => {
25
+ setStorageObject("selectedListItem", selectedListItem);
26
+ }, [selectedListItem]);
27
+
28
+ useEffect(() => {
29
+ localStorage.setItem("zoom", zoom);
30
+ }, [zoom]);
31
+
32
+ useEffect(() => {
33
+ if (location == null) {
34
+ localStorage.removeItem("location");
35
+ } else {
36
+ setStorageObject("location", location);
37
+ }
38
+ }, [location]);
39
+
40
+ useEffect(() => {
41
+ setStorageObject("center", center);
42
+ }, [center]);
43
+
44
+ const selectItem = (item, itemLocation, zoom, center) => {
45
+ setSelectedListItem(item);
46
+ if (mapInteracted === false && itemLocation != null) {
47
+ setLocation(itemLocation);
48
+ }
49
+ if (mapInteracted === false || itemLocation != null) {
50
+ setLocation(itemLocation);
51
+ setCenter(center);
52
+ }
53
+ if (mapInteracted === false) {
54
+ setZoom(zoom);
55
+
56
+ }
57
+ };
58
+
59
+ const filterReset = () => {
60
+ setSelectedPlaces({});
61
+ setSelectedListItem(null);
62
+ setLocation(null);
63
+ setZoom(8);
64
+ setMapInteracted(false);
65
+ };
66
+
67
+ if (resetFilters === true) {
68
+ filterReset();
69
+ }
70
+ const selectLocationEntity = location => {
71
+
72
+ localStorage.removeItem("selectedListItem");
73
+ setTimeout(() => setLocation(location), 200);
74
+ setSelectedListItem(null);
75
+ };
76
+
77
+ return (
78
+ <MapContext.Provider
79
+ value={{
80
+ selectedListItem,
81
+ setSelectedListItem,
82
+ location,
83
+ center,
84
+ zoom,
85
+ setZoom,
86
+ selectItem,
87
+ setSelectedPlaces,
88
+ selectedPlaces,
89
+ selectLocationEntity,
90
+ setLocation,
91
+ setMapInteracted,
92
+ mapInteracted,
93
+ userSetZoom,
94
+ firstLoadListItem,
95
+ filterReset
96
+ }}
97
+ >
98
+ {children}
99
+ </MapContext.Provider>
100
+ );
101
+ };