@abcagency/hc-ui-components 1.3.21 → 1.3.22

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