@abcagency/hc-ui-components 1.3.60 → 1.3.62

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