@abcagency/hc-ui-components 1.3.59 → 1.3.61

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 (277) hide show
  1. package/dist/apis/hcApi.js +85 -85
  2. package/dist/apis/hcApi.js.map +1 -1
  3. package/dist/clientToken.js.map +1 -1
  4. package/dist/components/HireControlMap.js +11 -1
  5. package/dist/components/HireControlMap.js.map +1 -1
  6. package/dist/components/containers/accordions/filter-container.js.map +1 -1
  7. package/dist/components/containers/accordions/filter-item-container.js.map +1 -1
  8. package/dist/components/containers/accordions/map-accordion-item-container.js.map +1 -1
  9. package/dist/components/containers/filter/commute-container.js +1 -1
  10. package/dist/components/containers/filter/commute-container.js.map +1 -1
  11. package/dist/components/containers/filter/filter-container.js.map +1 -1
  12. package/dist/components/containers/filter/filter-item-container.js.map +1 -1
  13. package/dist/components/containers/filter/location-container.js.map +1 -1
  14. package/dist/components/containers/filter/points-of-interest-container.js.map +1 -1
  15. package/dist/components/containers/filter/points-of-interest-radio-item-container.js.map +1 -1
  16. package/dist/components/containers/filter/search-container.js.map +1 -1
  17. package/dist/components/containers/jobListing/listing-details-container.js +5 -1
  18. package/dist/components/containers/jobListing/listing-details-container.js.map +1 -1
  19. package/dist/components/containers/list/item-list-container.js +21 -21
  20. package/dist/components/containers/list/item-list-container.js.map +1 -1
  21. package/dist/components/containers/list/list-item/list-item-container.js.map +1 -1
  22. package/dist/components/containers/maps/info-window-content-container.js.map +1 -1
  23. package/dist/components/containers/maps/map-container.js +1 -1
  24. package/dist/components/containers/maps/map-container.js.map +1 -1
  25. package/dist/components/containers/maps/map-list-container.js.map +1 -1
  26. package/dist/components/containers/maps/map-marker-container.js +1 -1
  27. package/dist/components/containers/maps/map-marker-container.js.map +1 -1
  28. package/dist/components/modules/accordions/MapAccordionItem.js.map +1 -1
  29. package/dist/components/modules/accordions/default.js +2 -2
  30. package/dist/components/modules/accordions/default.js.map +1 -1
  31. package/dist/components/modules/accordions/filterItem.js.map +1 -1
  32. package/dist/components/modules/accordions/filters.js.map +1 -1
  33. package/dist/components/modules/buttons/button-group-apply.js +45 -54
  34. package/dist/components/modules/buttons/button-group-apply.js.map +1 -1
  35. package/dist/components/modules/buttons/commute-pill.js.map +1 -1
  36. package/dist/components/modules/buttons/default.js +2 -2
  37. package/dist/components/modules/buttons/default.js.map +1 -1
  38. package/dist/components/modules/buttons/items-pill.js.map +1 -1
  39. package/dist/components/modules/buttons/pill-wrapper.js.map +1 -1
  40. package/dist/components/modules/buttons/show-all-button.js.map +1 -1
  41. package/dist/components/modules/cards/default.js +2 -2
  42. package/dist/components/modules/cards/default.js.map +1 -1
  43. package/dist/components/modules/cards/filter.js.map +1 -1
  44. package/dist/components/modules/dialogs/apply-dialog.js +1 -1
  45. package/dist/components/modules/dialogs/apply-dialog.js.map +1 -1
  46. package/dist/components/modules/filter/commute.js +2 -2
  47. package/dist/components/modules/filter/commute.js.map +1 -1
  48. package/dist/components/modules/filter/index.js.map +1 -1
  49. package/dist/components/modules/filter/item.js.map +1 -1
  50. package/dist/components/modules/filter/location.js.map +1 -1
  51. package/dist/components/modules/filter/radio-item.js.map +1 -1
  52. package/dist/components/modules/filter/search.js.map +1 -1
  53. package/dist/components/modules/filter/sort.js +2 -2
  54. package/dist/components/modules/filter/sort.js.map +1 -1
  55. package/dist/components/modules/grid.js +1 -1
  56. package/dist/components/modules/grid.js.map +1 -1
  57. package/dist/components/modules/icon.js +1 -1
  58. package/dist/components/modules/icon.js.map +1 -1
  59. package/dist/components/modules/jobListing/listing-details.js +8 -7
  60. package/dist/components/modules/jobListing/listing-details.js.map +1 -1
  61. package/dist/components/modules/list/field-mapper.js.map +1 -1
  62. package/dist/components/modules/list/header-item.js.map +1 -1
  63. package/dist/components/modules/list/header.js +1 -1
  64. package/dist/components/modules/list/header.js.map +1 -1
  65. package/dist/components/modules/list/item-expand-card/index.js +1 -1
  66. package/dist/components/modules/list/item-expand-card/index.js.map +1 -1
  67. package/dist/components/modules/list/item-expand-card/recruiter-contact-nav.js +38 -38
  68. package/dist/components/modules/list/item-expand-card/recruiter-details.js +40 -40
  69. package/dist/components/modules/list/item-expand-card/recruiter-headshot.js +20 -20
  70. package/dist/components/modules/list/item-list.js +43 -43
  71. package/dist/components/modules/list/item-list.js.map +1 -1
  72. package/dist/components/modules/list/list-item/list-item.js.map +1 -1
  73. package/dist/components/modules/maps/info-window-card.js.map +1 -1
  74. package/dist/components/modules/maps/info-window-content.js.map +1 -1
  75. package/dist/components/modules/maps/map-list.js.map +1 -1
  76. package/dist/components/modules/maps/map-marker.js +1 -1
  77. package/dist/components/modules/maps/map-marker.js.map +1 -1
  78. package/dist/components/modules/maps/map.js +1 -1
  79. package/dist/components/modules/maps/map.js.map +1 -1
  80. package/dist/components/modules/maps/place-marker.js +1 -1
  81. package/dist/components/modules/maps/place-marker.js.map +1 -1
  82. package/dist/components/modules/maps/tabs.js +1 -1
  83. package/dist/components/modules/maps/tabs.js.map +1 -1
  84. package/dist/constants/eventTypes.js +1 -0
  85. package/dist/constants/eventTypes.js.map +1 -1
  86. package/dist/constants/placeTypes.js.map +1 -1
  87. package/dist/contexts/mapContext.js +83 -83
  88. package/dist/contexts/mapContext.js.map +1 -1
  89. package/dist/contexts/mapListContext.js +192 -190
  90. package/dist/contexts/mapListContext.js.map +1 -1
  91. package/dist/contexts/placesContext.js.map +1 -1
  92. package/dist/contexts/themeContext.js.map +1 -1
  93. package/dist/contexts/trackEventContext.js.map +1 -1
  94. package/dist/hooks/useList.js.map +1 -1
  95. package/dist/services/configService.js +9 -9
  96. package/dist/services/configService.js.map +1 -1
  97. package/dist/services/googlePlacesNearbyService.js +32 -32
  98. package/dist/services/googlePlacesNearbyService.js.map +1 -1
  99. package/dist/services/listingAggregatorService.js +34 -34
  100. package/dist/services/listingAggregatorService.js.map +1 -1
  101. package/dist/services/listingEntityService.js +9 -9
  102. package/dist/services/listingEntityService.js.map +1 -1
  103. package/dist/services/listingService.js +24 -24
  104. package/dist/services/listingService.js.map +1 -1
  105. package/dist/services/recruiterService.js +10 -10
  106. package/dist/services/recruiterService.js.map +1 -1
  107. package/dist/types/apis/hcApi.d.ts +5 -5
  108. package/dist/types/clientToken.d.ts +2 -2
  109. package/dist/types/components/containers/accordions/map-accordion-item-container.d.ts +12 -12
  110. package/dist/types/components/containers/jobListing/listing-details-container.d.ts +6 -6
  111. package/dist/types/components/containers/list/item-list-container.d.ts +9 -9
  112. package/dist/types/components/containers/list/list-item/list-item-container.d.ts +14 -14
  113. package/dist/types/components/modules/accordions/MapAccordionItem.d.ts +10 -10
  114. package/dist/types/components/modules/accordions/default.d.ts +19 -19
  115. package/dist/types/components/modules/buttons/button-group-apply.d.ts +24 -24
  116. package/dist/types/components/modules/buttons/commute-pill.d.ts +5 -5
  117. package/dist/types/components/modules/buttons/default.d.ts +48 -48
  118. package/dist/types/components/modules/buttons/pill-wrapper.d.ts +3 -3
  119. package/dist/types/components/modules/dialogs/apply-dialog.d.ts +8 -8
  120. package/dist/types/components/modules/filter/sort.d.ts +8 -8
  121. package/dist/types/components/modules/grid.d.ts +8 -8
  122. package/dist/types/components/modules/icon.d.ts +10 -10
  123. package/dist/types/components/modules/jobListing/listing-details.d.ts +20 -18
  124. package/dist/types/components/modules/list/field-mapper.d.ts +10 -10
  125. package/dist/types/components/modules/list/header-item.d.ts +11 -11
  126. package/dist/types/components/modules/list/header.d.ts +12 -12
  127. package/dist/types/components/modules/list/item-expand-card/index.d.ts +7 -7
  128. package/dist/types/components/modules/list/item-expand-card/recruiter-contact-nav.d.ts +17 -17
  129. package/dist/types/components/modules/list/item-expand-card/recruiter-details.d.ts +21 -21
  130. package/dist/types/components/modules/list/item-expand-card/recruiter-headshot.d.ts +8 -8
  131. package/dist/types/components/modules/list/item-list.d.ts +20 -20
  132. package/dist/types/components/modules/list/list-item/list-item.d.ts +3 -3
  133. package/dist/types/constants/eventTypes.d.ts +15 -14
  134. package/dist/types/contexts/mapContext.d.ts +29 -29
  135. package/dist/types/contexts/mapListContext.d.ts +65 -61
  136. package/dist/types/contexts/trackEventContext.d.ts +6 -6
  137. package/dist/types/enums/SectionType.d.ts +9 -9
  138. package/dist/types/hooks/useList.d.ts +13 -13
  139. package/dist/types/services/configService.d.ts +6 -6
  140. package/dist/types/services/googlePlacesNearbyService.d.ts +5 -5
  141. package/dist/types/services/listingAggregatorService.d.ts +12 -12
  142. package/dist/types/services/listingEntityService.d.ts +6 -6
  143. package/dist/types/services/listingService.d.ts +9 -9
  144. package/dist/types/services/recruiterService.d.ts +6 -6
  145. package/dist/types/types/Address.d.ts +7 -7
  146. package/dist/types/types/ContentSection.d.ts +8 -8
  147. package/dist/types/types/GetListingParams.d.ts +8 -8
  148. package/dist/types/types/LatLng.d.ts +4 -4
  149. package/dist/types/types/ListingEntity.d.ts +10 -10
  150. package/dist/types/types/ListingFields.d.ts +25 -25
  151. package/dist/types/types/Listings.d.ts +31 -31
  152. package/dist/types/types/Recruiter.d.ts +9 -9
  153. package/dist/types/types/SimilarListing.d.ts +24 -24
  154. package/dist/types/types/config/Colors.d.ts +8 -8
  155. package/dist/types/types/config/MapConfig.d.ts +30 -30
  156. package/dist/types/types/config/PointsOfInterestConfig.d.ts +13 -13
  157. package/dist/types/types/config/SearchConfig.d.ts +4 -4
  158. package/dist/types/util/filterUtil.d.ts +28 -28
  159. package/dist/types/util/loading.d.ts +3 -3
  160. package/dist/types/util/localStorageUtil.d.ts +3 -3
  161. package/dist/types/util/mapUtil.d.ts +16 -16
  162. package/dist/types/util/sortUtil.d.ts +1 -1
  163. package/dist/types/util/stringUtils.d.ts +1 -1
  164. package/dist/types/util/urlFilterUtil.d.ts +8 -8
  165. package/dist/util/filterUtil.js +1 -1
  166. package/dist/util/filterUtil.js.map +1 -1
  167. package/dist/util/loading.js.map +1 -1
  168. package/dist/util/localStorageUtil.js +37 -37
  169. package/dist/util/localStorageUtil.js.map +1 -1
  170. package/dist/util/mapIconUtil.js.map +1 -1
  171. package/dist/util/mapUtil.js.map +1 -1
  172. package/dist/util/sortUtil.js.map +1 -1
  173. package/dist/util/stringUtils.js.map +1 -1
  174. package/dist/util/urlFilterUtil.js.map +1 -1
  175. package/package.json +90 -90
  176. package/src/.editorconfig +12 -12
  177. package/src/apis/hcApi.ts +109 -109
  178. package/src/bundleIndex.js +14 -14
  179. package/src/clientToken.js +9 -9
  180. package/src/components/HireControlMap.js +148 -142
  181. package/src/components/containers/accordions/filter-container.js +48 -48
  182. package/src/components/containers/accordions/filter-item-container.js +83 -83
  183. package/src/components/containers/accordions/map-accordion-item-container.js +70 -70
  184. package/src/components/containers/filter/commute-container.js +89 -89
  185. package/src/components/containers/filter/filter-container.js +76 -76
  186. package/src/components/containers/filter/filter-item-container.js +117 -117
  187. package/src/components/containers/filter/location-container.js +45 -45
  188. package/src/components/containers/filter/points-of-interest-container.js +33 -33
  189. package/src/components/containers/filter/points-of-interest-radio-item-container.js +35 -35
  190. package/src/components/containers/filter/search-container.js +61 -61
  191. package/src/components/containers/jobListing/listing-details-container.js +42 -40
  192. package/src/components/containers/list/item-list-container.tsx +81 -81
  193. package/src/components/containers/list/list-item/list-item-container.js +43 -43
  194. package/src/components/containers/maps/info-window-content-container.js +53 -53
  195. package/src/components/containers/maps/map-container.js +249 -249
  196. package/src/components/containers/maps/map-list-container.js +50 -50
  197. package/src/components/containers/maps/map-marker-container.js +78 -78
  198. package/src/components/modules/accordions/MapAccordionItem.js +30 -30
  199. package/src/components/modules/accordions/default.js +171 -171
  200. package/src/components/modules/accordions/filterItem.js +27 -27
  201. package/src/components/modules/accordions/filters.js +32 -32
  202. package/src/components/modules/buttons/button-group-apply.js +115 -135
  203. package/src/components/modules/buttons/commute-pill.js +22 -22
  204. package/src/components/modules/buttons/default.js +194 -194
  205. package/src/components/modules/buttons/items-pill.js +35 -35
  206. package/src/components/modules/buttons/pill-wrapper.js +27 -27
  207. package/src/components/modules/buttons/show-all-button.js +19 -19
  208. package/src/components/modules/cards/default.js +167 -167
  209. package/src/components/modules/cards/filter.js +56 -56
  210. package/src/components/modules/dialogs/apply-dialog.js +48 -48
  211. package/src/components/modules/filter/commute.js +108 -108
  212. package/src/components/modules/filter/index.js +55 -55
  213. package/src/components/modules/filter/item.js +69 -69
  214. package/src/components/modules/filter/location.js +51 -51
  215. package/src/components/modules/filter/radio-item.js +42 -42
  216. package/src/components/modules/filter/search.js +79 -79
  217. package/src/components/modules/filter/sort.js +83 -83
  218. package/src/components/modules/grid.js +54 -54
  219. package/src/components/modules/icon.js +33 -33
  220. package/src/components/modules/jobListing/listing-details.js +110 -108
  221. package/src/components/modules/list/field-mapper.js +130 -130
  222. package/src/components/modules/list/header-item.js +92 -92
  223. package/src/components/modules/list/header.js +51 -51
  224. package/src/components/modules/list/item-expand-card/index.js +22 -22
  225. package/src/components/modules/list/item-expand-card/recruiter-contact-nav.js +50 -50
  226. package/src/components/modules/list/item-expand-card/recruiter-details.js +68 -68
  227. package/src/components/modules/list/item-expand-card/recruiter-headshot.js +22 -22
  228. package/src/components/modules/list/item-list.tsx +117 -117
  229. package/src/components/modules/list/list-item/list-item.js +130 -130
  230. package/src/components/modules/maps/info-window-card.js +17 -17
  231. package/src/components/modules/maps/info-window-content.js +64 -64
  232. package/src/components/modules/maps/map-list.js +38 -38
  233. package/src/components/modules/maps/map-marker.js +29 -29
  234. package/src/components/modules/maps/map.js +64 -64
  235. package/src/components/modules/maps/place-marker.js +41 -41
  236. package/src/components/modules/maps/tabs.js +81 -81
  237. package/src/constants/eventTypes.js +15 -14
  238. package/src/constants/placeTypes.js +8 -8
  239. package/src/contexts/mapContext.tsx +129 -129
  240. package/src/contexts/mapListContext.tsx +326 -318
  241. package/src/contexts/placesContext.js +102 -102
  242. package/src/contexts/themeContext.js +40 -40
  243. package/src/contexts/trackEventContext.js +14 -14
  244. package/src/enums/SectionType.ts +9 -9
  245. package/src/hooks/useList.js +89 -89
  246. package/src/index.js +3 -3
  247. package/src/services/configService.ts +16 -16
  248. package/src/services/googlePlacesNearbyService.ts +42 -42
  249. package/src/services/listingAggregatorService.ts +76 -76
  250. package/src/services/listingEntityService.ts +16 -16
  251. package/src/services/listingService.ts +40 -40
  252. package/src/services/recruiterService.ts +18 -18
  253. package/src/styles/bundle.css +268 -268
  254. package/src/styles/index.css +33 -33
  255. package/src/types/Address.ts +7 -7
  256. package/src/types/ContentSection.ts +9 -9
  257. package/src/types/GetListingParams.ts +8 -8
  258. package/src/types/LatLng.ts +4 -4
  259. package/src/types/ListingEntity.ts +11 -11
  260. package/src/types/ListingFields.ts +25 -25
  261. package/src/types/Listings.ts +32 -32
  262. package/src/types/Recruiter.ts +9 -9
  263. package/src/types/SimilarListing.ts +24 -24
  264. package/src/types/config/Colors.ts +8 -8
  265. package/src/types/config/MapConfig.ts +31 -31
  266. package/src/types/config/PointsOfInterestConfig.ts +13 -13
  267. package/src/types/config/SearchConfig.ts +4 -4
  268. package/src/util/arrayUtil.js +3 -3
  269. package/src/util/fieldMapper.js +22 -22
  270. package/src/util/filterUtil.js +311 -311
  271. package/src/util/loading.js +17 -17
  272. package/src/util/localStorageUtil.ts +34 -34
  273. package/src/util/mapIconUtil.js +180 -180
  274. package/src/util/mapUtil.js +92 -92
  275. package/src/util/sortUtil.js +32 -32
  276. package/src/util/stringUtils.js +6 -6
  277. package/src/util/urlFilterUtil.js +85 -85
@@ -1,318 +1,326 @@
1
- import React, { createContext, useState, useEffect, useContext, ReactNode } from 'react';
2
-
3
- import { generateFilterOptions, applyFilters, filterListingsByLocation } from '~/util/filterUtil';
4
- import { getStorageObject, setStorageObject } from '~/util/localStorageUtil';
5
- import { updateURLWithFilters, filtersFromURL } from '~/util/urlFilterUtil';
6
-
7
- import { getListingEntities } from "~/services/listingEntityService";
8
- import fetchListings from '~/services/listingAggregatorService';
9
-
10
- import { Listing } from '~/types/Listings';
11
- import { ListingEntity } from '~/types/ListingEntity';
12
- import { Recruiter } from '~/types/Recruiter';
13
- import { MapConfig, MapConfig as SiteConfig } from '~/types/config/MapConfig';
14
-
15
- interface MapListContextProps {
16
- loading: boolean;
17
- allListings: Listing[];
18
- filteredListings: Listing[];
19
- mapItems: any;
20
- query: string | null;
21
- setNewFilteredListings: (filteredListings: Listing[]) => void;
22
- setQuery: (query: string | null) => void;
23
- listingEntities: Record<number, ListingEntity> | null;
24
- selectedFilters: Record<string, any>;
25
- setSelectedFilters: (filters: Record<string, any>) => void;
26
- filterOptions: any;
27
- recruiters: Record<number, Recruiter>;
28
- handleFilterListingsByLocation: (selectedLocation: any) => void;
29
- filterDialogIsOpen: boolean;
30
- setFilterDialogIsOpen: (isOpen: boolean) => void;
31
- setMobileTab: (tab: string) => void;
32
- mobileTab: string;
33
- siteConfig: SiteConfig;
34
- favorites: number[];
35
- resetEntityFilter: () => void;
36
- handleSettingFavorites: (favorites: number[] | null) => void;
37
- setFilterByFavorites: (filter: boolean) => void;
38
- filterByFavorites: boolean;
39
- commuteLocation: any | null;
40
- setCommuteLocation: (location: any | null) => void;
41
- navigateToDetails: (id: number) => void;
42
- navigateToEasyApply: (id: number) => void;
43
- Link: React.ComponentType<any>;
44
- linkFormat: string;
45
- sortSetting: { field: string; type: string };
46
- setSortSetting: (setting: { field: string; type: string }) => void;
47
- trackEvent: (event: string) => void;
48
- }
49
-
50
- const MapListContext = createContext<MapListContextProps | undefined>(undefined);
51
-
52
- export const useMapList = () => {
53
- const context = useContext(MapListContext);
54
- if (!context) {
55
- throw new Error('useMapList must be used within a MapListProvider');
56
- }
57
- return context;
58
- };
59
-
60
- const getQuery = (): string | null => {
61
- let query: string | null = null;
62
- if (typeof window !== 'undefined') {
63
- query = localStorage.getItem('query');
64
- }
65
- return query;
66
- };
67
-
68
- interface MapListProviderProps {
69
- children: ReactNode;
70
- siteConfig: MapConfig;
71
- resetFilters: boolean;
72
- navigateToDetails: (id: number) => void;
73
- navigateToEasyApply: (id: number) => void;
74
- Link: React.ComponentType<any>;
75
- linkFormat: string;
76
- trackEvent: (event: string) => void;
77
- listings?: Listing[];
78
- setFiltersUrl?:boolean;
79
- handleUrlUpdate: (searchParams: string) => void;
80
- }
81
-
82
- export const MapListProvider: React.FC<MapListProviderProps> = ({
83
- children,
84
- siteConfig,
85
- resetFilters,
86
- navigateToDetails,
87
- navigateToEasyApply,
88
- Link,
89
- linkFormat,
90
- trackEvent,
91
- listings = [],
92
- setFiltersUrl,
93
- handleUrlUpdate,
94
- }) => {
95
- const firstLoadFilters = () =>{
96
- let urlFilters = filtersFromURL(window.location)?.filters;
97
- return (setFiltersUrl === true && urlFilters && Object.keys(urlFilters).length > 0) ? urlFilters : getStorageObject('selectedFilters', {}) || {}
98
- }
99
- const [allListings, setAllListings] = useState<Listing[]>([]);
100
- const [filteredListings, setFilteredListings] = useState<Listing[]>([]);
101
- const [loading, setLoading] = useState<boolean>(false);
102
- const [mapItems, setMapItems] = useState<any>(getStorageObject('mapItems', []) || []);
103
- const [query, setQuery] = useState<string | null>(() => resetFilters ? null : getQuery());
104
- const [sortSetting, setSortSetting] = useState<{ field: string; type: string }>(getStorageObject('sortSetting', { field: 'position', type: 'asc' }) || { field: 'position', type: 'asc' });
105
- const [listingEntities, setListingEntities] = useState<Record<number, ListingEntity> | null>({});
106
- const [firstLoad, setFirstLoad] = useState<boolean>(true);
107
- const [commuteLocation, setCommuteLocation] = useState<any | null>(getStorageObject('commuteLocation'));
108
- const [selectedFilters, setSelectedFilters] = useState<Record<string, any>>(() => resetFilters ? {} : firstLoadFilters());
109
- const [filterOptions, setFilterOptions] = useState<any>();
110
- const [recruiters, setRecruiters] = useState<Record<number, Recruiter>>({});
111
- const [filterDialogIsOpen, setFilterDialogIsOpen] = useState<boolean>(false);
112
- const [mobileTab, setMobileTab] = useState<string>("listTab");
113
- const [favorites, setFavorites] = useState<number[]>([]);
114
- const [filterByFavorites, setFilterByFavorites] = useState<boolean>(false);
115
-
116
- const setNewFilteredListings = (filteredListings: Listing[]) => {
117
- setFilteredListings(filteredListings);
118
- };
119
-
120
-
121
-
122
- useEffect(() => {
123
- if (!sortSetting) return;
124
- localStorage.setItem('sortSetting', JSON.stringify(sortSetting));
125
- setNewFilteredListings(filteredListings);
126
- }, [sortSetting]);
127
-
128
- useEffect(() => {
129
- const loadedFavorites = JSON.parse(localStorage.getItem('favorites') || '[]');
130
- setFavorites(loadedFavorites);
131
- }, []);
132
-
133
- useEffect(() => {
134
- setStorageObject("commuteLocation", commuteLocation);
135
- }, [commuteLocation]);
136
-
137
- useEffect(() => {
138
- if (!commuteLocation) return;
139
-
140
- async function fetchEntities() {
141
- const distinctEntityIds = [
142
- ...new Set(allListings.map(listing => listing.entityId ?? -1))
143
- ];
144
- try {
145
- const fetchedEntities = await getListingEntities(
146
- distinctEntityIds,
147
- `${commuteLocation.lat}, ${commuteLocation.lng}`
148
- );
149
- setListingEntities(fetchedEntities);
150
- const newFilteredListings: Listing[] = [...filteredListings] ?? [];
151
- for (let i = 0; i < allListings.length; i++) {
152
- const listing = newFilteredListings[i];
153
- if (
154
- listing &&
155
- listing.fields &&
156
- listing.entityId !== undefined &&
157
- listing.entityId !== -1
158
- ) {
159
- const entityId = listing.entityId;
160
- const travelTime = fetchedEntities[entityId]?.travelTime;
161
-
162
- if (travelTime !== undefined && listing.fields) {
163
- listing.fields.travelTime = travelTime;
164
- }
165
- }
166
- }
167
- } catch (error) {
168
- console.error("Failed to fetch listing entities:", error);
169
- }
170
- }
171
-
172
- fetchEntities();
173
- }, [commuteLocation, allListings, siteConfig.companyId]);
174
-
175
- useEffect(() => {
176
- const handleFetchListings = async () => {
177
- if (!getStorageObject('listings') ?? [].length) {
178
- setLoading(true);
179
- }
180
-
181
- try {
182
- const {
183
- listingsResult,
184
- fetchedRecruiters,
185
- fetchedEntities,
186
- distinctItems
187
- } = await fetchListings(query ?? '', siteConfig, commuteLocation);
188
- setAllListings(listingsResult);
189
- setRecruiters(fetchedRecruiters);
190
- setListingEntities(fetchedEntities);
191
- setMapItems(distinctItems);
192
- } catch (error) {
193
- console.log(error);
194
- }
195
- setLoading(false);
196
- };
197
- handleFetchListings();
198
- }, [query, siteConfig]);
199
-
200
- useEffect(() => {
201
- const processListings = () => {
202
- let filteredListings: Listing[];
203
- let tempSelectedFilters = selectedFilters;
204
- let tempQuery = query;
205
-
206
- const { mapItems, filteredListings: tempFilteredListings } = applyFilters(
207
- allListings,
208
- tempSelectedFilters,
209
- tempQuery,
210
- listingEntities,
211
- favorites,
212
- siteConfig
213
- );
214
- filteredListings = tempFilteredListings;
215
-
216
- if (filterByFavorites) {
217
- filteredListings = filteredListings.filter((x: Listing) => favorites.includes(x.id));
218
- }
219
- setNewFilteredListings(filteredListings);
220
- if (firstLoad && tempSelectedFilters) {
221
- // Update URL with filters if needed
222
- } else if (Object.keys(tempSelectedFilters).length === 0 && !firstLoad) {
223
- localStorage.removeItem('selectedFilters');
224
- } else if (!firstLoad) {
225
- setStorageObject('selectedFilters', tempSelectedFilters);
226
- }
227
- if(setFiltersUrl === true)
228
- {
229
- updateURLWithFilters(tempSelectedFilters, window.location, tempQuery, handleUrlUpdate);
230
- }
231
- tempQuery != null ? localStorage.setItem('query', tempQuery) : localStorage.removeItem('query');
232
- setMapItems(mapItems);
233
-
234
- if (tempSelectedFilters) {
235
- const keys = Object.keys(tempSelectedFilters);
236
- const lastKey = keys[keys.length - 1];
237
- const options = generateFilterOptions(
238
- filteredListings,
239
- allListings,
240
- siteConfig,
241
- filterOptions,
242
- lastKey,
243
- favorites,
244
- tempSelectedFilters
245
- );
246
- if (options) {
247
- setFilterOptions(options);
248
- if (firstLoad) setFirstLoad(false);
249
- }
250
- }
251
- };
252
-
253
- processListings();
254
- }, [selectedFilters, query, listingEntities, filterByFavorites, favorites]);
255
-
256
- const handleFilterListingsByLocation = (selectedLocation: any) => {
257
- const { filteredListings } = filterListingsByLocation(
258
- allListings,
259
- selectedLocation,
260
- listingEntities
261
- );
262
- setNewFilteredListings(filteredListings);
263
- };
264
-
265
- const resetEntityFilter = () => {
266
- let newFilters = {...selectedFilters};
267
- delete newFilters.entityId;
268
- setSelectedFilters(newFilters);
269
- }
270
-
271
- const handleSettingFavorites = (newFavorites: number[] | null) => {
272
- if (newFavorites == null) {
273
- localStorage.removeItem('favorites');
274
- } else {
275
- setFavorites(newFavorites);
276
- localStorage.setItem('favorites', JSON.stringify(newFavorites));
277
- }
278
- };
279
-
280
- return (
281
- <MapListContext.Provider value={{
282
- loading,
283
- allListings,
284
- filteredListings,
285
- mapItems,
286
- query,
287
- setNewFilteredListings,
288
- setQuery,
289
- listingEntities,
290
- selectedFilters,
291
- setSelectedFilters,
292
- filterOptions,
293
- recruiters,
294
- handleFilterListingsByLocation,
295
- filterDialogIsOpen,
296
- setFilterDialogIsOpen,
297
- setMobileTab,
298
- mobileTab,
299
- siteConfig,
300
- favorites,
301
- handleSettingFavorites,
302
- resetEntityFilter,
303
- setFilterByFavorites,
304
- filterByFavorites,
305
- commuteLocation,
306
- setCommuteLocation,
307
- navigateToDetails,
308
- navigateToEasyApply,
309
- Link,
310
- linkFormat,
311
- sortSetting,
312
- setSortSetting,
313
- trackEvent
314
- }}>
315
- {children}
316
- </MapListContext.Provider>
317
- );
318
- };
1
+ import React, { createContext, useState, useEffect, useContext, ReactNode } from 'react';
2
+
3
+ import { generateFilterOptions, applyFilters, filterListingsByLocation } from '~/util/filterUtil';
4
+ import { getStorageObject, setStorageObject } from '~/util/localStorageUtil';
5
+ import { updateURLWithFilters, filtersFromURL } from '~/util/urlFilterUtil';
6
+
7
+ import { getListingEntities } from "~/services/listingEntityService";
8
+ import fetchListings from '~/services/listingAggregatorService';
9
+
10
+ import { Listing } from '~/types/Listings';
11
+ import { ListingEntity } from '~/types/ListingEntity';
12
+ import { Recruiter } from '~/types/Recruiter';
13
+ import { MapConfig, MapConfig as SiteConfig } from '~/types/config/MapConfig';
14
+
15
+ interface MapListContextProps {
16
+ loading: boolean;
17
+ allListings: Listing[];
18
+ filteredListings: Listing[];
19
+ mapItems: any;
20
+ query: string | null;
21
+ setNewFilteredListings: (filteredListings: Listing[]) => void;
22
+ setQuery: (query: string | null) => void;
23
+ listingEntities: Record<number, ListingEntity> | null;
24
+ selectedFilters: Record<string, any>;
25
+ setSelectedFilters: (filters: Record<string, any>) => void;
26
+ filterOptions: any;
27
+ recruiters: Record<number, Recruiter>;
28
+ handleFilterListingsByLocation: (selectedLocation: any) => void;
29
+ filterDialogIsOpen: boolean;
30
+ setFilterDialogIsOpen: (isOpen: boolean) => void;
31
+ setMobileTab: (tab: string) => void;
32
+ mobileTab: string;
33
+ siteConfig: SiteConfig;
34
+ favorites: number[];
35
+ resetEntityFilter: () => void;
36
+ handleSettingFavorites: (favorites: number[] | null) => void;
37
+ setFilterByFavorites: (filter: boolean) => void;
38
+ filterByFavorites: boolean;
39
+ commuteLocation: any | null;
40
+ setCommuteLocation: (location: any | null) => void;
41
+ navigateToDetails: (id: number) => void;
42
+ navigateToEasyApply: (id: number) => void;
43
+ Link: React.ComponentType<any>;
44
+ linkFormat: string;
45
+ easyApplyUrl: string;
46
+ easyApplyText: string;
47
+ sortSetting: { field: string; type: string };
48
+ setSortSetting: (setting: { field: string; type: string }) => void;
49
+ trackEvent: (event: string) => void;
50
+ }
51
+
52
+ const MapListContext = createContext<MapListContextProps | undefined>(undefined);
53
+
54
+ export const useMapList = () => {
55
+ const context = useContext(MapListContext);
56
+ if (!context) {
57
+ throw new Error('useMapList must be used within a MapListProvider');
58
+ }
59
+ return context;
60
+ };
61
+
62
+ const getQuery = (): string | null => {
63
+ let query: string | null = null;
64
+ if (typeof window !== 'undefined') {
65
+ query = localStorage.getItem('query');
66
+ }
67
+ return query;
68
+ };
69
+
70
+ interface MapListProviderProps {
71
+ children: ReactNode;
72
+ siteConfig: MapConfig;
73
+ resetFilters: boolean;
74
+ navigateToDetails: (id: number) => void;
75
+ navigateToEasyApply: (id: number) => void;
76
+ Link: React.ComponentType<any>;
77
+ linkFormat: string;
78
+ easyApplyUrl: string;
79
+ easyApplyText: string;
80
+ trackEvent: (event: string) => void;
81
+ listings?: Listing[];
82
+ setFiltersUrl?:boolean;
83
+ handleUrlUpdate: (searchParams: string) => void;
84
+ }
85
+
86
+ export const MapListProvider: React.FC<MapListProviderProps> = ({
87
+ children,
88
+ siteConfig,
89
+ resetFilters,
90
+ navigateToDetails,
91
+ navigateToEasyApply,
92
+ Link,
93
+ linkFormat,
94
+ easyApplyUrl,
95
+ easyApplyText,
96
+ trackEvent,
97
+ listings = [],
98
+ setFiltersUrl,
99
+ handleUrlUpdate,
100
+ }) => {
101
+ const firstLoadFilters = () =>{
102
+ let urlFilters = filtersFromURL(window.location)?.filters;
103
+ return (setFiltersUrl === true && urlFilters && Object.keys(urlFilters).length > 0) ? urlFilters : getStorageObject('selectedFilters', {}) || {}
104
+ }
105
+ const [allListings, setAllListings] = useState<Listing[]>([]);
106
+ const [filteredListings, setFilteredListings] = useState<Listing[]>([]);
107
+ const [loading, setLoading] = useState<boolean>(false);
108
+ const [mapItems, setMapItems] = useState<any>(getStorageObject('mapItems', []) || []);
109
+ const [query, setQuery] = useState<string | null>(() => resetFilters ? null : getQuery());
110
+ const [sortSetting, setSortSetting] = useState<{ field: string; type: string }>(getStorageObject('sortSetting', { field: 'position', type: 'asc' }) || { field: 'position', type: 'asc' });
111
+ const [listingEntities, setListingEntities] = useState<Record<number, ListingEntity> | null>({});
112
+ const [firstLoad, setFirstLoad] = useState<boolean>(true);
113
+ const [commuteLocation, setCommuteLocation] = useState<any | null>(getStorageObject('commuteLocation'));
114
+ const [selectedFilters, setSelectedFilters] = useState<Record<string, any>>(() => resetFilters ? {} : firstLoadFilters());
115
+ const [filterOptions, setFilterOptions] = useState<any>();
116
+ const [recruiters, setRecruiters] = useState<Record<number, Recruiter>>({});
117
+ const [filterDialogIsOpen, setFilterDialogIsOpen] = useState<boolean>(false);
118
+ const [mobileTab, setMobileTab] = useState<string>("listTab");
119
+ const [favorites, setFavorites] = useState<number[]>([]);
120
+ const [filterByFavorites, setFilterByFavorites] = useState<boolean>(false);
121
+
122
+ const setNewFilteredListings = (filteredListings: Listing[]) => {
123
+ setFilteredListings(filteredListings);
124
+ };
125
+
126
+
127
+
128
+ useEffect(() => {
129
+ if (!sortSetting) return;
130
+ localStorage.setItem('sortSetting', JSON.stringify(sortSetting));
131
+ setNewFilteredListings(filteredListings);
132
+ }, [sortSetting]);
133
+
134
+ useEffect(() => {
135
+ const loadedFavorites = JSON.parse(localStorage.getItem('favorites') || '[]');
136
+ setFavorites(loadedFavorites);
137
+ }, []);
138
+
139
+ useEffect(() => {
140
+ setStorageObject("commuteLocation", commuteLocation);
141
+ }, [commuteLocation]);
142
+
143
+ useEffect(() => {
144
+ if (!commuteLocation) return;
145
+
146
+ async function fetchEntities() {
147
+ const distinctEntityIds = [
148
+ ...new Set(allListings.map(listing => listing.entityId ?? -1))
149
+ ];
150
+ try {
151
+ const fetchedEntities = await getListingEntities(
152
+ distinctEntityIds,
153
+ `${commuteLocation.lat}, ${commuteLocation.lng}`
154
+ );
155
+ setListingEntities(fetchedEntities);
156
+ const newFilteredListings: Listing[] = [...filteredListings] ?? [];
157
+ for (let i = 0; i < allListings.length; i++) {
158
+ const listing = newFilteredListings[i];
159
+ if (
160
+ listing &&
161
+ listing.fields &&
162
+ listing.entityId !== undefined &&
163
+ listing.entityId !== -1
164
+ ) {
165
+ const entityId = listing.entityId;
166
+ const travelTime = fetchedEntities[entityId]?.travelTime;
167
+
168
+ if (travelTime !== undefined && listing.fields) {
169
+ listing.fields.travelTime = travelTime;
170
+ }
171
+ }
172
+ }
173
+ } catch (error) {
174
+ console.error("Failed to fetch listing entities:", error);
175
+ }
176
+ }
177
+
178
+ fetchEntities();
179
+ }, [commuteLocation, allListings, siteConfig.companyId]);
180
+
181
+ useEffect(() => {
182
+ const handleFetchListings = async () => {
183
+ if (!getStorageObject('listings') ?? [].length) {
184
+ setLoading(true);
185
+ }
186
+
187
+ try {
188
+ const {
189
+ listingsResult,
190
+ fetchedRecruiters,
191
+ fetchedEntities,
192
+ distinctItems
193
+ } = await fetchListings(query ?? '', siteConfig, commuteLocation);
194
+ setAllListings(listingsResult);
195
+ setRecruiters(fetchedRecruiters);
196
+ setListingEntities(fetchedEntities);
197
+ setMapItems(distinctItems);
198
+ } catch (error) {
199
+ console.log(error);
200
+ }
201
+ setLoading(false);
202
+ };
203
+ handleFetchListings();
204
+ }, [query, siteConfig]);
205
+
206
+ useEffect(() => {
207
+ const processListings = () => {
208
+ let filteredListings: Listing[];
209
+ let tempSelectedFilters = selectedFilters;
210
+ let tempQuery = query;
211
+
212
+ const { mapItems, filteredListings: tempFilteredListings } = applyFilters(
213
+ allListings,
214
+ tempSelectedFilters,
215
+ tempQuery,
216
+ listingEntities,
217
+ favorites,
218
+ siteConfig
219
+ );
220
+ filteredListings = tempFilteredListings;
221
+
222
+ if (filterByFavorites) {
223
+ filteredListings = filteredListings.filter((x: Listing) => favorites.includes(x.id));
224
+ }
225
+ setNewFilteredListings(filteredListings);
226
+ if (firstLoad && tempSelectedFilters) {
227
+ // Update URL with filters if needed
228
+ } else if (Object.keys(tempSelectedFilters).length === 0 && !firstLoad) {
229
+ localStorage.removeItem('selectedFilters');
230
+ } else if (!firstLoad) {
231
+ setStorageObject('selectedFilters', tempSelectedFilters);
232
+ }
233
+ if(setFiltersUrl === true)
234
+ {
235
+ updateURLWithFilters(tempSelectedFilters, window.location, tempQuery, handleUrlUpdate);
236
+ }
237
+ tempQuery != null ? localStorage.setItem('query', tempQuery) : localStorage.removeItem('query');
238
+ setMapItems(mapItems);
239
+
240
+ if (tempSelectedFilters) {
241
+ const keys = Object.keys(tempSelectedFilters);
242
+ const lastKey = keys[keys.length - 1];
243
+ const options = generateFilterOptions(
244
+ filteredListings,
245
+ allListings,
246
+ siteConfig,
247
+ filterOptions,
248
+ lastKey,
249
+ favorites,
250
+ tempSelectedFilters
251
+ );
252
+ if (options) {
253
+ setFilterOptions(options);
254
+ if (firstLoad) setFirstLoad(false);
255
+ }
256
+ }
257
+ };
258
+
259
+ processListings();
260
+ }, [selectedFilters, query, listingEntities, filterByFavorites, favorites]);
261
+
262
+ const handleFilterListingsByLocation = (selectedLocation: any) => {
263
+ const { filteredListings } = filterListingsByLocation(
264
+ allListings,
265
+ selectedLocation,
266
+ listingEntities
267
+ );
268
+ setNewFilteredListings(filteredListings);
269
+ };
270
+
271
+ const resetEntityFilter = () => {
272
+ let newFilters = {...selectedFilters};
273
+ delete newFilters.entityId;
274
+ setSelectedFilters(newFilters);
275
+ }
276
+
277
+ const handleSettingFavorites = (newFavorites: number[] | null) => {
278
+ if (newFavorites == null) {
279
+ localStorage.removeItem('favorites');
280
+ } else {
281
+ setFavorites(newFavorites);
282
+ localStorage.setItem('favorites', JSON.stringify(newFavorites));
283
+ }
284
+ };
285
+
286
+ return (
287
+ <MapListContext.Provider value={{
288
+ loading,
289
+ allListings,
290
+ filteredListings,
291
+ mapItems,
292
+ query,
293
+ setNewFilteredListings,
294
+ setQuery,
295
+ listingEntities,
296
+ selectedFilters,
297
+ setSelectedFilters,
298
+ filterOptions,
299
+ recruiters,
300
+ handleFilterListingsByLocation,
301
+ filterDialogIsOpen,
302
+ setFilterDialogIsOpen,
303
+ setMobileTab,
304
+ mobileTab,
305
+ siteConfig,
306
+ favorites,
307
+ handleSettingFavorites,
308
+ resetEntityFilter,
309
+ setFilterByFavorites,
310
+ filterByFavorites,
311
+ commuteLocation,
312
+ setCommuteLocation,
313
+ navigateToDetails,
314
+ navigateToEasyApply,
315
+ Link,
316
+ linkFormat,
317
+ easyApplyUrl,
318
+ easyApplyText,
319
+ sortSetting,
320
+ setSortSetting,
321
+ trackEvent
322
+ }}>
323
+ {children}
324
+ </MapListContext.Provider>
325
+ );
326
+ };