@abcagency/hc-ui-components 1.3.18 → 1.3.20

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 (190) hide show
  1. package/dist/apis/hcApi.js +85 -183
  2. package/dist/apis/hcApi.js.map +1 -1
  3. package/dist/components/HireControlMap.js +10 -5
  4. package/dist/components/HireControlMap.js.map +1 -1
  5. package/dist/components/modules/accordions/MapAccordionItem.js +10 -67
  6. package/dist/components/modules/accordions/MapAccordionItem.js.map +1 -1
  7. package/dist/components/modules/filter/index.js.map +1 -1
  8. package/dist/components/modules/filter/radio-item.js +1 -2
  9. package/dist/components/modules/filter/radio-item.js.map +1 -1
  10. package/dist/components/modules/jobListing/listing-details-container.js +45 -0
  11. package/dist/components/modules/jobListing/listing-details-container.js.map +1 -0
  12. package/dist/components/modules/jobListing/listing-details.js +25 -24
  13. package/dist/components/modules/jobListing/listing-details.js.map +1 -1
  14. package/dist/components/modules/{maps/list → list}/field-mapper.js +8 -7
  15. package/dist/components/modules/list/field-mapper.js.map +1 -0
  16. package/dist/components/modules/{maps/list → list}/header-item.js +2 -2
  17. package/dist/components/modules/list/header-item.js.map +1 -0
  18. package/dist/components/modules/{maps/list → list}/header.js +6 -4
  19. package/dist/components/modules/list/header.js.map +1 -0
  20. package/dist/components/modules/list/index.js +36 -0
  21. package/dist/components/modules/list/index.js.map +1 -0
  22. package/dist/components/modules/{maps/list → list}/item-expand-card/index.js +3 -1
  23. package/dist/components/modules/list/item-expand-card/index.js.map +1 -0
  24. package/dist/components/modules/{maps/list → list}/item-expand-card/recruiter-contact-nav.js +2 -2
  25. package/dist/components/modules/list/item-expand-card/recruiter-contact-nav.js.map +1 -0
  26. package/dist/components/modules/{maps/list → list}/item-expand-card/recruiter-details.js +1 -1
  27. package/dist/components/modules/list/item-expand-card/recruiter-details.js.map +1 -0
  28. package/dist/components/modules/list/item-expand-card/recruiter-headshot.js.map +1 -0
  29. package/dist/components/modules/list/item-list.js +131 -0
  30. package/dist/components/modules/list/item-list.js.map +1 -0
  31. package/dist/components/modules/list/list-item/index.js +75 -0
  32. package/dist/components/modules/list/list-item/index.js.map +1 -0
  33. package/dist/components/modules/list/list-item/list-item-container.js +47 -0
  34. package/dist/components/modules/list/list-item/list-item-container.js.map +1 -0
  35. package/dist/components/modules/{maps/list/list-item/index.js → list/list-item/list-item.js} +29 -33
  36. package/dist/components/modules/list/list-item/list-item.js.map +1 -0
  37. package/dist/components/modules/maps/map-list.js +3 -3
  38. package/dist/components/modules/maps/map-list.js.map +1 -1
  39. package/dist/contexts/mapContext.js +84 -113
  40. package/dist/contexts/mapContext.js.map +1 -1
  41. package/dist/contexts/mapListContext.js +181 -293
  42. package/dist/contexts/mapListContext.js.map +1 -1
  43. package/dist/contexts/trackEventContext.js +1 -1
  44. package/dist/services/configService.js +10 -28
  45. package/dist/services/configService.js.map +1 -1
  46. package/dist/services/googlePlacesNearbyService.js +33 -58
  47. package/dist/services/googlePlacesNearbyService.js.map +1 -1
  48. package/dist/services/listingAggregatorService.js +35 -75
  49. package/dist/services/listingAggregatorService.js.map +1 -1
  50. package/dist/services/listingEntityService.js +10 -31
  51. package/dist/services/listingEntityService.js.map +1 -1
  52. package/dist/services/listingService.js +26 -60
  53. package/dist/services/listingService.js.map +1 -1
  54. package/dist/services/recruiterService.js +11 -31
  55. package/dist/services/recruiterService.js.map +1 -1
  56. package/dist/types/apis/hcApi.d.ts +5 -0
  57. package/dist/types/clientToken.d.ts +2 -0
  58. package/dist/types/components/modules/accordions/MapAccordionItem.d.ts +9 -0
  59. package/dist/types/components/modules/accordions/default.d.ts +19 -0
  60. package/dist/types/components/modules/buttons/button-group-apply.d.ts +24 -0
  61. package/dist/types/components/modules/buttons/commute-pill.d.ts +5 -0
  62. package/dist/types/components/modules/buttons/default.d.ts +48 -0
  63. package/dist/types/components/modules/buttons/pill-wrapper.d.ts +3 -0
  64. package/dist/types/components/modules/dialogs/apply-dialog.d.ts +8 -0
  65. package/dist/types/components/modules/filter/sort.d.ts +8 -0
  66. package/dist/types/components/modules/grid.d.ts +8 -0
  67. package/dist/types/components/modules/icon.d.ts +10 -0
  68. package/dist/types/components/modules/jobListing/listing-details-container.d.ts +6 -0
  69. package/dist/types/components/modules/jobListing/listing-details.d.ts +18 -0
  70. package/dist/types/components/modules/list/field-mapper.d.ts +10 -0
  71. package/dist/types/components/modules/list/header-item.d.ts +11 -0
  72. package/dist/types/components/modules/list/header.d.ts +11 -0
  73. package/dist/types/components/modules/list/index.d.ts +9 -0
  74. package/dist/types/components/modules/list/item-expand-card/index.d.ts +7 -0
  75. package/dist/types/components/modules/list/item-expand-card/recruiter-contact-nav.d.ts +17 -0
  76. package/dist/types/components/modules/list/item-expand-card/recruiter-details.d.ts +21 -0
  77. package/dist/types/components/modules/list/item-expand-card/recruiter-headshot.d.ts +8 -0
  78. package/dist/types/components/modules/list/item-list.d.ts +21 -0
  79. package/dist/types/components/modules/list/list-item/index.d.ts +12 -0
  80. package/dist/types/components/modules/list/list-item/list-item-container.d.ts +14 -0
  81. package/dist/types/components/modules/list/list-item/list-item.d.ts +3 -0
  82. package/dist/types/constants/eventTypes.d.ts +13 -0
  83. package/dist/types/contexts/mapContext.d.ts +29 -0
  84. package/dist/types/contexts/mapListContext.d.ts +58 -0
  85. package/dist/types/contexts/trackEventContext.d.ts +6 -0
  86. package/dist/types/enums/SectionType.d.ts +9 -0
  87. package/dist/types/hooks/useList.d.ts +13 -0
  88. package/dist/types/services/configService.d.ts +6 -0
  89. package/dist/types/services/googlePlacesNearbyService.d.ts +5 -0
  90. package/dist/types/services/listingAggregatorService.d.ts +12 -0
  91. package/dist/types/services/listingEntityService.d.ts +6 -0
  92. package/dist/types/services/listingService.d.ts +9 -0
  93. package/dist/types/services/recruiterService.d.ts +6 -0
  94. package/dist/types/types/Address.d.ts +7 -0
  95. package/dist/types/types/ContentSection.d.ts +8 -0
  96. package/dist/types/types/GetListingParams.d.ts +8 -0
  97. package/dist/types/types/LatLng.d.ts +4 -0
  98. package/dist/types/types/ListingEntity.d.ts +10 -0
  99. package/dist/types/types/ListingFields.d.ts +20 -0
  100. package/dist/types/types/Listings.d.ts +31 -0
  101. package/dist/types/types/Recruiter.d.ts +9 -0
  102. package/dist/types/types/SimilarListing.d.ts +24 -0
  103. package/dist/types/types/config/Colors.d.ts +8 -0
  104. package/dist/types/types/config/MapConfig.d.ts +29 -0
  105. package/dist/types/types/config/PointsOfInterestConfig.d.ts +13 -0
  106. package/dist/types/types/config/SearchConfig.d.ts +4 -0
  107. package/dist/types/util/filterUtil.d.ts +28 -0
  108. package/dist/types/util/loading.d.ts +3 -0
  109. package/dist/types/util/localStorageUtil.d.ts +3 -0
  110. package/dist/types/util/mapUtil.d.ts +15 -0
  111. package/dist/types/util/sortUtil.d.ts +1 -0
  112. package/dist/types/util/stringUtils.d.ts +1 -0
  113. package/dist/util/filterUtil.js +1 -3
  114. package/dist/util/filterUtil.js.map +1 -1
  115. package/dist/util/localStorageUtil.js +37 -28
  116. package/dist/util/localStorageUtil.js.map +1 -1
  117. package/dist/util/mapUtil.js.map +1 -1
  118. package/package.json +23 -17
  119. package/rollup.config.mjs +23 -19
  120. package/src/apis/{hcApi.js → hcApi.ts} +27 -11
  121. package/src/components/HireControlMap.js +132 -129
  122. package/src/components/modules/accordions/MapAccordionItem.js +32 -74
  123. package/src/components/modules/filter/index.js +89 -89
  124. package/src/components/modules/filter/radio-item.js +0 -1
  125. package/src/components/modules/jobListing/listing-details-container.js +40 -0
  126. package/src/components/modules/jobListing/listing-details.js +209 -99
  127. package/src/components/modules/{maps/list → list}/field-mapper.js +114 -112
  128. package/src/components/modules/{maps/list → list}/header.js +49 -47
  129. package/src/components/modules/list/index.tsx +83 -0
  130. package/src/components/modules/{maps/list → list}/item-expand-card/index.js +24 -22
  131. package/src/components/modules/list/item-list.tsx +198 -0
  132. package/src/components/modules/list/list-item/index.js +70 -0
  133. package/src/components/modules/list/list-item/list-item-container.js +43 -0
  134. package/src/components/modules/{maps/list/list-item/index.js → list/list-item/list-item.js} +32 -38
  135. package/src/components/modules/maps/map-list.js +74 -74
  136. package/src/contexts/mapContext.tsx +129 -0
  137. package/src/contexts/mapListContext.tsx +297 -0
  138. package/src/enums/SectionType.ts +9 -0
  139. package/src/services/{configService.js → configService.ts} +16 -16
  140. package/src/services/{googlePlacesNearbyService.js → googlePlacesNearbyService.ts} +11 -2
  141. package/src/services/listingAggregatorService.ts +76 -0
  142. package/src/services/listingEntityService.ts +16 -0
  143. package/src/services/listingService.ts +40 -0
  144. package/src/services/{recruiterService.js → recruiterService.ts} +18 -17
  145. package/src/types/Address.ts +7 -0
  146. package/src/types/ContentSection.ts +9 -0
  147. package/src/types/GetListingParams.ts +8 -0
  148. package/src/types/LatLng.ts +4 -0
  149. package/src/types/ListingEntity.ts +11 -0
  150. package/src/types/ListingFields.ts +20 -0
  151. package/src/types/Listings.ts +32 -0
  152. package/src/types/Recruiter.ts +9 -0
  153. package/src/types/SimilarListing.ts +24 -0
  154. package/src/types/config/Colors.ts +8 -0
  155. package/src/types/config/MapConfig.ts +30 -0
  156. package/src/types/config/PointsOfInterestConfig.ts +13 -0
  157. package/src/types/config/SearchConfig.ts +4 -0
  158. package/src/util/filterUtil.js +239 -239
  159. package/src/util/localStorageUtil.ts +34 -0
  160. package/src/util/mapUtil.js +91 -91
  161. package/tsconfig.json +23 -0
  162. package/dist/components/modules/maps/list/field-mapper.js.map +0 -1
  163. package/dist/components/modules/maps/list/header-item.js.map +0 -1
  164. package/dist/components/modules/maps/list/header.js.map +0 -1
  165. package/dist/components/modules/maps/list/index.js +0 -102
  166. package/dist/components/modules/maps/list/index.js.map +0 -1
  167. package/dist/components/modules/maps/list/item-expand-card/index.js.map +0 -1
  168. package/dist/components/modules/maps/list/item-expand-card/recruiter-contact-nav.js.map +0 -1
  169. package/dist/components/modules/maps/list/item-expand-card/recruiter-details.js.map +0 -1
  170. package/dist/components/modules/maps/list/item-expand-card/recruiter-headshot.js.map +0 -1
  171. package/dist/components/modules/maps/list/list-item/index.js.map +0 -1
  172. package/dist/services/_virtual/_rollupPluginBabelHelpers.js +0 -372
  173. package/dist/services/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
  174. package/dist/services/apis/hcApi.js +0 -189
  175. package/dist/services/apis/hcApi.js.map +0 -1
  176. package/dist/services/clientToken.js +0 -7
  177. package/dist/services/clientToken.js.map +0 -1
  178. package/dist/services/styles/index.css +0 -3
  179. package/src/components/modules/maps/list/index.js +0 -112
  180. package/src/contexts/mapContext.js +0 -101
  181. package/src/contexts/mapListContext.js +0 -242
  182. package/src/services/listingAggregatorService.js +0 -50
  183. package/src/services/listingEntityService.js +0 -15
  184. package/src/services/listingService.js +0 -26
  185. package/src/util/localStorageUtil.js +0 -27
  186. /package/dist/components/modules/{maps/list → list}/item-expand-card/recruiter-headshot.js +0 -0
  187. /package/src/components/modules/{maps/list → list}/header-item.js +0 -0
  188. /package/src/components/modules/{maps/list → list}/item-expand-card/recruiter-contact-nav.js +0 -0
  189. /package/src/components/modules/{maps/list → list}/item-expand-card/recruiter-details.js +0 -0
  190. /package/src/components/modules/{maps/list → list}/item-expand-card/recruiter-headshot.js +0 -0
@@ -0,0 +1,297 @@
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
+
6
+ import { getListingEntities } from "~/services/listingEntityService";
7
+ import fetchListings from '~/services/listingAggregatorService';
8
+
9
+ import { Listing } from '~/types/Listings';
10
+ import { ListingEntity } from '~/types/ListingEntity';
11
+ import { Recruiter } from '~/types/Recruiter';
12
+ import { MapConfig, MapConfig as SiteConfig } from '~/types/config/MapConfig';
13
+
14
+ interface MapListContextProps {
15
+ loading: boolean;
16
+ allListings: Listing[];
17
+ filteredListings: Listing[];
18
+ mapItems: any;
19
+ query: string | null;
20
+ setNewFilteredListings: (filteredListings: Listing[]) => void;
21
+ setQuery: (query: string | null) => void;
22
+ listingEntities: Record<number, ListingEntity> | null;
23
+ selectedFilters: Record<string, any>;
24
+ setSelectedFilters: (filters: Record<string, any>) => void;
25
+ filterOptions: any;
26
+ recruiters: Record<number, Recruiter>;
27
+ handleFilterListingsByLocation: (selectedLocation: any) => void;
28
+ filterDialogIsOpen: boolean;
29
+ setFilterDialogIsOpen: (isOpen: boolean) => void;
30
+ setMobileTab: (tab: string) => void;
31
+ mobileTab: string;
32
+ siteConfig: SiteConfig;
33
+ favorites: number[];
34
+ handleSettingFavorites: (favorites: number[] | null) => void;
35
+ setFilterByFavorites: (filter: boolean) => void;
36
+ filterByFavorites: boolean;
37
+ commuteLocation: any | null;
38
+ setCommuteLocation: (location: any | null) => void;
39
+ navigateToDetails: (id: number) => void;
40
+ navigateToEasyApply: (id: number) => void;
41
+ Link: React.ComponentType<any>;
42
+ linkFormat: string;
43
+ sortSetting: { field: string; type: string };
44
+ setSortSetting: (setting: { field: string; type: string }) => void;
45
+ trackEvent: (event: string) => void;
46
+ }
47
+
48
+ const MapListContext = createContext<MapListContextProps | undefined>(undefined);
49
+
50
+ export const useMapList = () => {
51
+ const context = useContext(MapListContext);
52
+ if (!context) {
53
+ throw new Error('useMapList must be used within a MapListProvider');
54
+ }
55
+ return context;
56
+ };
57
+
58
+ const getQuery = (): string | null => {
59
+ let query: string | null = null;
60
+ if (typeof window !== 'undefined') {
61
+ query = localStorage.getItem('query');
62
+ }
63
+ return query;
64
+ };
65
+
66
+ interface MapListProviderProps {
67
+ children: ReactNode;
68
+ siteConfig: MapConfig;
69
+ resetFilters: boolean;
70
+ navigateToDetails: (id: number) => void;
71
+ navigateToEasyApply: (id: number) => void;
72
+ Link: React.ComponentType<any>;
73
+ linkFormat: string;
74
+ trackEvent: (event: string) => void;
75
+ listings?: Listing[];
76
+ }
77
+
78
+ export const MapListProvider: React.FC<MapListProviderProps> = ({
79
+ children,
80
+ siteConfig,
81
+ resetFilters,
82
+ navigateToDetails,
83
+ navigateToEasyApply,
84
+ Link,
85
+ linkFormat,
86
+ trackEvent,
87
+ listings = []
88
+ }) => {
89
+ const [allListings, setAllListings] = useState<Listing[]>(getStorageObject("listings", listings) || []);
90
+ const [filteredListings, setFilteredListings] = useState<Listing[]>([]);
91
+ const [loading, setLoading] = useState<boolean>(false);
92
+ const [mapItems, setMapItems] = useState<any>(getStorageObject('mapItems', []) || []);
93
+ const [query, setQuery] = useState<string | null>(() => resetFilters ? null : getQuery());
94
+ const [sortSetting, setSortSetting] = useState<{ field: string; type: string }>(getStorageObject('sortSetting', { field: 'position', type: 'asc' }) || { field: 'position', type: 'asc' });
95
+ const [listingEntities, setListingEntities] = useState<Record<number, ListingEntity> | null>(getStorageObject("listingEntities", null));
96
+ const [firstLoad, setFirstLoad] = useState<boolean>(true);
97
+ const [commuteLocation, setCommuteLocation] = useState<any | null>(getStorageObject('commuteLocation'));
98
+ const [selectedFilters, setSelectedFilters] = useState<Record<string, any>>(() => resetFilters ? {} : getStorageObject('selectedFilters', {}) || {});
99
+ const [filterOptions, setFilterOptions] = useState<any>();
100
+ const [recruiters, setRecruiters] = useState<Record<number, Recruiter>>(getStorageObject("recruiters", {}) || {});
101
+ const [filterDialogIsOpen, setFilterDialogIsOpen] = useState<boolean>(false);
102
+ const [mobileTab, setMobileTab] = useState<string>("listTab");
103
+ const [favorites, setFavorites] = useState<number[]>([]);
104
+ const [filterByFavorites, setFilterByFavorites] = useState<boolean>(false);
105
+
106
+ const setNewFilteredListings = (filteredListings: Listing[]) => {
107
+ setFilteredListings(filteredListings);
108
+ };
109
+
110
+ useEffect(() => {
111
+ if (!sortSetting) return;
112
+ localStorage.setItem('sortSetting', JSON.stringify(sortSetting));
113
+ setNewFilteredListings(filteredListings);
114
+ }, [sortSetting]);
115
+
116
+ useEffect(() => {
117
+ const loadedFavorites = JSON.parse(localStorage.getItem('favorites') || '[]');
118
+ setFavorites(loadedFavorites);
119
+ }, []);
120
+
121
+ useEffect(() => {
122
+ setStorageObject("commuteLocation", commuteLocation);
123
+ }, [commuteLocation]);
124
+
125
+ useEffect(() => {
126
+ if (!commuteLocation) return;
127
+
128
+ async function fetchEntities() {
129
+ const distinctEntityIds = [
130
+ ...new Set(allListings.map(listing => listing.entityId ?? -1))
131
+ ];
132
+ try {
133
+ const fetchedEntities = await getListingEntities(
134
+ distinctEntityIds,
135
+ `${commuteLocation.lat}, ${commuteLocation.lng}`
136
+ );
137
+ setListingEntities(fetchedEntities);
138
+ const newFilteredListings: Listing[] = [...filteredListings] ?? [];
139
+ for (let i = 0; i < allListings.length; i++) {
140
+ const listing = newFilteredListings[i];
141
+ if (
142
+ listing &&
143
+ listing.fields &&
144
+ listing.entityId !== undefined &&
145
+ listing.entityId !== -1
146
+ ) {
147
+ const entityId = listing.entityId;
148
+ const travelTime = fetchedEntities[entityId]?.travelTime;
149
+
150
+ if (travelTime !== undefined && listing.fields) {
151
+ listing.fields.travelTime = travelTime;
152
+ }
153
+ }
154
+ }
155
+
156
+ setNewFilteredListings(newFilteredListings);
157
+ } catch (error) {
158
+ console.error("Failed to fetch listing entities:", error);
159
+ }
160
+ }
161
+
162
+ fetchEntities();
163
+ }, [commuteLocation, allListings, siteConfig.companyId]);
164
+
165
+ useEffect(() => {
166
+ const handleFetchListings = async () => {
167
+ if (!getStorageObject('listings') ?? [].length) {
168
+ setLoading(true);
169
+ }
170
+
171
+ try {
172
+ const {
173
+ listingsResult,
174
+ fetchedRecruiters,
175
+ fetchedEntities,
176
+ distinctItems
177
+ } = await fetchListings(query ?? '', siteConfig, commuteLocation);
178
+ setAllListings(listingsResult);
179
+ setRecruiters(fetchedRecruiters);
180
+ setListingEntities(fetchedEntities);
181
+ setMapItems(distinctItems);
182
+ setStorageObject("mapItems", distinctItems);
183
+ setStorageObject("listingEntities", fetchedEntities);
184
+ setStorageObject("recruiters", fetchedRecruiters);
185
+ setStorageObject("listings", listingsResult);
186
+ } catch (error) {
187
+ console.log(error);
188
+ }
189
+ setLoading(false);
190
+ };
191
+ handleFetchListings();
192
+ }, [query, siteConfig]);
193
+
194
+ useEffect(() => {
195
+ const processListings = () => {
196
+ let filteredListings: Listing[];
197
+ const { mapItems, filteredListings: tempFilteredListings } = applyFilters(
198
+ allListings,
199
+ selectedFilters,
200
+ query,
201
+ listingEntities,
202
+ favorites,
203
+ siteConfig
204
+ );
205
+ filteredListings = tempFilteredListings;
206
+
207
+ if (filterByFavorites) {
208
+ filteredListings = filteredListings.filter((x: Listing) => favorites.includes(x.id));
209
+ }
210
+ setNewFilteredListings(filteredListings);
211
+ if (firstLoad && selectedFilters) {
212
+ // Update URL with filters if needed
213
+ } else if (Object.keys(selectedFilters).length === 0 && !firstLoad) {
214
+ localStorage.removeItem('selectedFilters');
215
+ } else if (!firstLoad) {
216
+ setStorageObject('selectedFilters', selectedFilters);
217
+ }
218
+ query != null ? localStorage.setItem('query', query) : localStorage.removeItem('query');
219
+ setMapItems(mapItems);
220
+
221
+ if (selectedFilters) {
222
+ const keys = Object.keys(selectedFilters);
223
+ const lastKey = keys[keys.length - 1];
224
+ const options = generateFilterOptions(
225
+ firstLoad ? allListings : filteredListings,
226
+ allListings,
227
+ siteConfig,
228
+ filterOptions,
229
+ lastKey,
230
+ favorites
231
+ );
232
+ if (options) {
233
+ setFilterOptions(options);
234
+ if (firstLoad) setFirstLoad(false);
235
+ }
236
+ }
237
+ };
238
+
239
+ processListings();
240
+ }, [selectedFilters, query, listingEntities, filterByFavorites, favorites]);
241
+
242
+ const handleFilterListingsByLocation = (selectedLocation: any) => {
243
+ const { filteredListings } = filterListingsByLocation(
244
+ allListings,
245
+ selectedLocation,
246
+ listingEntities
247
+ );
248
+ setNewFilteredListings(filteredListings);
249
+ };
250
+
251
+ const handleSettingFavorites = (newFavorites: number[] | null) => {
252
+ if (newFavorites == null) {
253
+ localStorage.removeItem('favorites');
254
+ } else {
255
+ setFavorites(newFavorites);
256
+ localStorage.setItem('favorites', JSON.stringify(newFavorites));
257
+ }
258
+ };
259
+
260
+ return (
261
+ <MapListContext.Provider value={{
262
+ loading,
263
+ allListings,
264
+ filteredListings,
265
+ mapItems,
266
+ query,
267
+ setNewFilteredListings,
268
+ setQuery,
269
+ listingEntities,
270
+ selectedFilters,
271
+ setSelectedFilters,
272
+ filterOptions,
273
+ recruiters,
274
+ handleFilterListingsByLocation,
275
+ filterDialogIsOpen,
276
+ setFilterDialogIsOpen,
277
+ setMobileTab,
278
+ mobileTab,
279
+ siteConfig,
280
+ favorites,
281
+ handleSettingFavorites,
282
+ setFilterByFavorites,
283
+ filterByFavorites,
284
+ commuteLocation,
285
+ setCommuteLocation,
286
+ navigateToDetails,
287
+ navigateToEasyApply,
288
+ Link,
289
+ linkFormat,
290
+ sortSetting,
291
+ setSortSetting,
292
+ trackEvent
293
+ }}>
294
+ {children}
295
+ </MapListContext.Provider>
296
+ );
297
+ };
@@ -0,0 +1,9 @@
1
+ export enum SectionType {
2
+ Default = -1,
3
+ Company = 1,
4
+ Category = 2,
5
+ CategoryClass = 3,
6
+ Entity = 4,
7
+ CustomVar = 5,
8
+ REGION = 7
9
+ }
@@ -1,16 +1,16 @@
1
- import api from '~/apis/hcApi';
2
-
3
- export const getMapConfig = async () => {
4
-
5
- try {
6
- const response = await api.get(`/MapConfig`);
7
- return response;
8
- } catch (error) {
9
- console.error("Error retrieving map configuration:", error);
10
- throw error;
11
- }
12
- };
13
-
14
- export default {
15
- getMapConfig
16
- };
1
+ import api from '~/apis/hcApi';
2
+ import { MapConfig } from '~/types/config/MapConfig';
3
+
4
+ export const getMapConfig = async (): Promise<MapConfig> => {
5
+ try {
6
+ const response = await api.get<MapConfig>(`/MapConfig`);
7
+ return response;
8
+ } catch (error) {
9
+ console.error("Error retrieving map configuration:", error);
10
+ throw error;
11
+ }
12
+ };
13
+
14
+ export default {
15
+ getMapConfig
16
+ };
@@ -1,8 +1,17 @@
1
- export const searchNearbyPlaces = async (typesArray, location, radius) => {
1
+ export interface Location {
2
+ latitude: number;
3
+ longitude: number;
4
+ }
5
+
6
+ export const searchNearbyPlaces = async (
7
+ typesArray: string[],
8
+ location: Location,
9
+ radius: number
10
+ ): Promise<any> => {
2
11
  const url = 'https://places.googleapis.com/v1/places:searchNearby';
3
12
  const headers = {
4
13
  'Content-Type': 'application/json',
5
- 'X-Goog-Api-Key': process.env.GOOGLE_MAPS_API_KEY,
14
+ 'X-Goog-Api-Key': process.env.GOOGLE_MAPS_API_KEY as string,
6
15
  'X-Goog-FieldMask': 'places.location,places.displayName,places.types'
7
16
  };
8
17
  const data = {
@@ -0,0 +1,76 @@
1
+ import { getListings } from '~/services/listingService';
2
+ import { getRecruiters } from '~/services/recruiterService';
3
+ import { getListingEntities } from '~/services/listingEntityService';
4
+
5
+ import { getDistinctItemsByProximity } from '~/util/mapUtil';
6
+ import { Listing } from '~/types/Listings';
7
+ import { Recruiter } from '~/types/Recruiter';
8
+ import { ListingEntity } from '~/types/ListingEntity';
9
+ import { MapConfig } from '~/types/config/MapConfig';
10
+ //import { ICommuteLocation } from '~/interfaces/ICommute';
11
+
12
+ interface SiteConfig {
13
+ companyId: number;
14
+ }
15
+
16
+ interface FetchListingsResult {
17
+ listingsResult: Listing[];
18
+ fetchedRecruiters: Recruiter[];
19
+ fetchedEntities: Record<number, ListingEntity>;
20
+ distinctItems: any; // Update this type based on the return type of getDistinctItemsByProximity
21
+ }
22
+
23
+ const fetchListings = async (
24
+ query: string,
25
+ siteConfig: MapConfig,
26
+ commuteLocation: any | null = null
27
+ ): Promise<FetchListingsResult> => {
28
+ try {
29
+ const listingsResult = await getListings(
30
+
31
+ );
32
+
33
+ const recruiterIds: number[] = [
34
+ ...new Set(listingsResult.map(listing => listing.recruiterId))
35
+ ] as number[];
36
+
37
+ const fetchedRecruiters = await getRecruiters(recruiterIds);
38
+
39
+ const distinctEntityIds: number[] = [
40
+ ...new Set(listingsResult.map(listing => listing.entityId))
41
+ ] as number[];
42
+
43
+ const fetchedEntities = !commuteLocation
44
+ ? await getListingEntities(distinctEntityIds)
45
+ : await getListingEntities(
46
+ distinctEntityIds,
47
+ `${commuteLocation.lat}, ${commuteLocation.lng}`
48
+ );
49
+ for (let i = 0; i < listingsResult.length; i++) {
50
+ const listing = listingsResult[i];
51
+ if (listing.entityId && listing.entityId !== -1 && listing.fields) {
52
+ const entity = fetchedEntities[listing.entityId];
53
+ if (entity) {
54
+ listing.fields.travelTime = entity.travelTime;
55
+ }
56
+ }
57
+ }
58
+
59
+ const distinctItems = getDistinctItemsByProximity(
60
+ listingsResult,
61
+ fetchedEntities
62
+ );
63
+
64
+ return {
65
+ listingsResult,
66
+ fetchedRecruiters,
67
+ fetchedEntities,
68
+ distinctItems
69
+ };
70
+ } catch (error) {
71
+ console.error("Error fetching listings:", error);
72
+ throw error;
73
+ }
74
+ };
75
+
76
+ export default fetchListings;
@@ -0,0 +1,16 @@
1
+ import api from '~/apis/hcApi';
2
+ import { ListingEntity } from '~/types/ListingEntity';
3
+
4
+ export const getListingEntities = async (entityIds: number[], origin = ''): Promise<ListingEntity[]> => {
5
+ try {
6
+ const response = await api.post<ListingEntity[]>(`/ListingEntities?origin=${origin}`, entityIds);
7
+ return response;
8
+ } catch (error) {
9
+ console.error("Error fetching listing entities:", error);
10
+ throw error;
11
+ }
12
+ };
13
+
14
+ export default {
15
+ getListingEntities
16
+ };
@@ -0,0 +1,40 @@
1
+ // listingService.ts
2
+ import { GetListingsParams } from '~/types/GetListingParams';
3
+ import api from '../apis/hcApi';
4
+ import { Listing } from '../types/Listings';
5
+
6
+ export const getListings = async (params?: GetListingsParams): Promise<Listing[]> => {
7
+ try {
8
+ const query = new URLSearchParams();
9
+
10
+ if (params) {
11
+ if (params.location) params.location.forEach(loc => query.append('location', loc));
12
+ if (params.category) params.category.forEach(cat => query.append('category', cat));
13
+ if (params.categoryClass) params.categoryClass.forEach(catClass => query.append('categoryClass', catClass));
14
+ if (params.education) params.education.forEach(edu => query.append('education', edu));
15
+ if (params.city) params.city.forEach(cty => query.append('city', cty));
16
+ if (params.state) params.state.forEach(st => query.append('state', st));
17
+ }
18
+
19
+ const response = await api.get(`/Listings?${query.toString()}`);
20
+ return response as Listing[];
21
+ } catch (error) {
22
+ console.error(error);
23
+ throw error;
24
+ }
25
+ };
26
+
27
+ export const getListingDetails = async (listingId: string) => {
28
+ try {
29
+ const response = await api.get(`/ListingDetails/${listingId}`);
30
+ return response;
31
+ } catch (error) {
32
+ console.error(error);
33
+ throw error;
34
+ }
35
+ };
36
+
37
+ export default {
38
+ getListings,
39
+ getListingDetails
40
+ };
@@ -1,17 +1,18 @@
1
- import api from '~/apis/hcApi';
2
-
3
- export const getRecruiters = async recruiterIds => {
4
- try {
5
- const params = recruiterIds.map(id => `recruiterIds=${id}`).join("&");
6
-
7
- const response = await api.get(`/Recruiters?${params}`);
8
- return response.data;
9
- } catch (error) {
10
- console.error("Error fetching recruiters:", error);
11
- throw error;
12
- }
13
- };
14
-
15
- export default {
16
- getRecruiters
17
- };
1
+ import api from '~/apis/hcApi';
2
+ import { Recruiter } from '~/types/Recruiter';
3
+
4
+ export const getRecruiters = async (recruiterIds: number[]): Promise<Recruiter[]> => {
5
+ try {
6
+ const params = recruiterIds.map(id => `recruiterIds=${id}`).join("&");
7
+
8
+ const response = await api.get<Recruiter[]>(`/Recruiters?${params}`);
9
+ return response;
10
+ } catch (error) {
11
+ console.error("Error fetching recruiters:", error);
12
+ throw error;
13
+ }
14
+ };
15
+
16
+ export default {
17
+ getRecruiters
18
+ };
@@ -0,0 +1,7 @@
1
+ export type Address = {
2
+ location?: string;
3
+ street?: string;
4
+ city?: string;
5
+ state?: string;
6
+ zip?: string;
7
+ }
@@ -0,0 +1,9 @@
1
+ import { SectionType } from '../enums/SectionType';
2
+
3
+ export type ContentSection = {
4
+ title?: string;
5
+ contentFormatted?: string;
6
+ contentRaw?: string;
7
+ sectionType: SectionType;
8
+ sortIndex: number;
9
+ }
@@ -0,0 +1,8 @@
1
+ export type GetListingsParams = {
2
+ location?: string[];
3
+ category?: string[];
4
+ categoryClass?: string[];
5
+ education?: string[];
6
+ city?: string[];
7
+ state?: string[];
8
+ };
@@ -0,0 +1,4 @@
1
+ export type LatLng = {
2
+ lat: number;
3
+ lng: number;
4
+ }
@@ -0,0 +1,11 @@
1
+ import { Address } from './Address';
2
+
3
+ export type ListingEntity = {
4
+ id: number;
5
+ listingId: number;
6
+ latitude: number;
7
+ longitude: number;
8
+ entityDisplayName?: string;
9
+ address?: Address;
10
+ travelTime?: string;
11
+ }
@@ -0,0 +1,20 @@
1
+ export type ListingFields = {
2
+ posted?: string;
3
+ subTitle?: string;
4
+ education?: string;
5
+ position?: string;
6
+ category?: string;
7
+ categoryClass?: string;
8
+ shift?: string;
9
+ cityState?: string;
10
+ city?: string;
11
+ state?: string;
12
+ schedule?: string;
13
+ customFlag1?: number;
14
+ bonus?: number;
15
+ remote?: number;
16
+ useClientJobUrl?: boolean;
17
+ dateCreated: Date;
18
+ dateLastEdited?: Date;
19
+ travelTime?: string;
20
+ }
@@ -0,0 +1,32 @@
1
+ import { ListingFields } from './ListingFields';
2
+ import { Recruiter } from './Recruiter';
3
+ import { ListingEntity } from './ListingEntity';
4
+ import { ContentSection } from './ContentSection';
5
+ import { SimilarListing } from './SimilarListing';
6
+
7
+ export type Listing = {
8
+ id: number;
9
+ fields?: ListingFields;
10
+ entityId?: number;
11
+ applyUrl?: string;
12
+ applyOnline?: number;
13
+ detailsUrl?: string;
14
+ displayOnSite: number;
15
+ displayRecruiter: number;
16
+ recruiterId?: number;
17
+ description1?: string;
18
+ description2?: string;
19
+ description3?: string;
20
+ description4?: string;
21
+ custom1: string;
22
+ custom2: string;
23
+ custom3: string;
24
+ custom4: string;
25
+ custom5: string;
26
+ customFlag1: number;
27
+ slug?: string;
28
+ recruiter?: Recruiter;
29
+ entity?: ListingEntity;
30
+ contentSections?: ContentSection[];
31
+ similarListings?: SimilarListing[];
32
+ }
@@ -0,0 +1,9 @@
1
+ export type Recruiter = {
2
+ id?: number;
3
+ email?: string;
4
+ firstName?: string;
5
+ lastName?: string;
6
+ linkedInUrl?: string;
7
+ mobilePhone?: string;
8
+ headshot?: string;
9
+ }
@@ -0,0 +1,24 @@
1
+ export type SimilarListing = {
2
+ id: number;
3
+ city: string;
4
+ companyName: string;
5
+ companyId: number;
6
+ domain: string;
7
+ refreshedPubDate?: Date;
8
+ clientJobUrl: string;
9
+ refreshNum: number;
10
+ requestURI: string;
11
+ schedule: string;
12
+ scheduleId?: number;
13
+ shift: string;
14
+ sponsored: boolean;
15
+ stateAbbrev: string;
16
+ subTitle: string;
17
+ title: string;
18
+ uniqueId: string;
19
+ zip: string;
20
+ slug?: string;
21
+ dateCreated: Date;
22
+ categoryId: number;
23
+ categoryClassId: number;
24
+ };
@@ -0,0 +1,8 @@
1
+ export type Colors = {
2
+ uiText: string;
3
+ uiAccent: string;
4
+ primary: string;
5
+ primaryDark: string;
6
+ secondary: string;
7
+ secondaryDark: string;
8
+ }