@abcagency/hc-ui-components 1.5.1 → 1.5.3

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 (173) hide show
  1. package/dist/components/HireControlMap.js +52 -22
  2. package/dist/components/HireControlMap.js.map +1 -1
  3. package/dist/components/containers/accordions/filter-container.js +13 -5
  4. package/dist/components/containers/accordions/filter-container.js.map +1 -1
  5. package/dist/components/containers/accordions/filter-item-container.js +9 -9
  6. package/dist/components/containers/accordions/filter-item-container.js.map +1 -1
  7. package/dist/components/containers/accordions/map-accordion-item-container.js +10 -5
  8. package/dist/components/containers/accordions/map-accordion-item-container.js.map +1 -1
  9. package/dist/components/containers/filter/commute-container.js +3 -3
  10. package/dist/components/containers/filter/commute-container.js.map +1 -1
  11. package/dist/components/containers/filter/filter-container.js +6 -5
  12. package/dist/components/containers/filter/filter-container.js.map +1 -1
  13. package/dist/components/containers/filter/filter-item-container.js +12 -12
  14. package/dist/components/containers/filter/filter-item-container.js.map +1 -1
  15. package/dist/components/containers/filter/location-container.js +6 -5
  16. package/dist/components/containers/filter/location-container.js.map +1 -1
  17. package/dist/components/containers/filter/points-of-interest-container.js +5 -5
  18. package/dist/components/containers/filter/points-of-interest-container.js.map +1 -1
  19. package/dist/components/containers/filter/points-of-interest-radio-item-container.js +2 -2
  20. package/dist/components/containers/filter/points-of-interest-radio-item-container.js.map +1 -1
  21. package/dist/components/containers/filter/search-container.js +2 -2
  22. package/dist/components/containers/filter/search-container.js.map +1 -1
  23. package/dist/components/containers/jobListing/listing-details-container.js +2 -2
  24. package/dist/components/containers/jobListing/listing-details-container.js.map +1 -1
  25. package/dist/components/containers/list/item-list-container.js +8 -8
  26. package/dist/components/containers/list/item-list-container.js.map +1 -1
  27. package/dist/components/containers/list/list-item/list-item-container.js +2 -2
  28. package/dist/components/containers/list/list-item/list-item-container.js.map +1 -1
  29. package/dist/components/containers/maps/info-window-content-container.js +2 -2
  30. package/dist/components/containers/maps/info-window-content-container.js.map +1 -1
  31. package/dist/components/containers/maps/map-container.js +8 -9
  32. package/dist/components/containers/maps/map-container.js.map +1 -1
  33. package/dist/components/containers/maps/map-list-container.js +5 -5
  34. package/dist/components/containers/maps/map-list-container.js.map +1 -1
  35. package/dist/components/containers/maps/map-marker-container.js +6 -6
  36. package/dist/components/containers/maps/map-marker-container.js.map +1 -1
  37. package/dist/components/modules/accordions/MapAccordionItem.js +5 -5
  38. package/dist/components/modules/accordions/MapAccordionItem.js.map +1 -1
  39. package/dist/components/modules/accordions/default.js +15 -15
  40. package/dist/components/modules/accordions/default.js.map +1 -1
  41. package/dist/components/modules/accordions/filterItem.js +4 -4
  42. package/dist/components/modules/accordions/filterItem.js.map +1 -1
  43. package/dist/components/modules/accordions/filters.js +6 -6
  44. package/dist/components/modules/accordions/filters.js.map +1 -1
  45. package/dist/components/modules/buttons/button-group-apply.js +19 -19
  46. package/dist/components/modules/buttons/button-group-apply.js.map +1 -1
  47. package/dist/components/modules/buttons/default.js +9 -9
  48. package/dist/components/modules/buttons/default.js.map +1 -1
  49. package/dist/components/modules/buttons/items-pill.js +2 -2
  50. package/dist/components/modules/buttons/items-pill.js.map +1 -1
  51. package/dist/components/modules/buttons/pill-wrapper.js +2 -2
  52. package/dist/components/modules/buttons/pill-wrapper.js.map +1 -1
  53. package/dist/components/modules/buttons/show-all-button.js +3 -3
  54. package/dist/components/modules/buttons/show-all-button.js.map +1 -1
  55. package/dist/components/modules/cards/default.js +11 -11
  56. package/dist/components/modules/cards/default.js.map +1 -1
  57. package/dist/components/modules/cards/filter.js +5 -5
  58. package/dist/components/modules/cards/filter.js.map +1 -1
  59. package/dist/components/modules/dialogs/apply-dialog.js +19 -19
  60. package/dist/components/modules/dialogs/apply-dialog.js.map +1 -1
  61. package/dist/components/modules/filter/commute.js +18 -19
  62. package/dist/components/modules/filter/commute.js.map +1 -1
  63. package/dist/components/modules/filter/index.js +10 -10
  64. package/dist/components/modules/filter/index.js.map +1 -1
  65. package/dist/components/modules/filter/item.js +6 -6
  66. package/dist/components/modules/filter/item.js.map +1 -1
  67. package/dist/components/modules/filter/location.js +6 -6
  68. package/dist/components/modules/filter/location.js.map +1 -1
  69. package/dist/components/modules/filter/radio-item.js +6 -6
  70. package/dist/components/modules/filter/radio-item.js.map +1 -1
  71. package/dist/components/modules/filter/search.js +10 -10
  72. package/dist/components/modules/filter/search.js.map +1 -1
  73. package/dist/components/modules/filter/sort.js +28 -28
  74. package/dist/components/modules/filter/sort.js.map +1 -1
  75. package/dist/components/modules/grid.js +4 -4
  76. package/dist/components/modules/grid.js.map +1 -1
  77. package/dist/components/modules/icon.js +4 -4
  78. package/dist/components/modules/icon.js.map +1 -1
  79. package/dist/components/modules/jobListing/listing-details.js +4 -4
  80. package/dist/components/modules/jobListing/listing-details.js.map +1 -1
  81. package/dist/components/modules/list/field-mapper-desktop.js +8 -8
  82. package/dist/components/modules/list/field-mapper-desktop.js.map +1 -1
  83. package/dist/components/modules/list/field-mapper-mobile.js +18 -18
  84. package/dist/components/modules/list/field-mapper-mobile.js.map +1 -1
  85. package/dist/components/modules/list/header-item.js +7 -7
  86. package/dist/components/modules/list/header-item.js.map +1 -1
  87. package/dist/components/modules/list/header.js +5 -5
  88. package/dist/components/modules/list/header.js.map +1 -1
  89. package/dist/components/modules/list/item-expand-card/index.js +3 -3
  90. package/dist/components/modules/list/item-expand-card/index.js.map +1 -1
  91. package/dist/components/modules/list/item-list.js +15 -15
  92. package/dist/components/modules/list/item-list.js.map +1 -1
  93. package/dist/components/modules/list/list-item/list-item.js +13 -13
  94. package/dist/components/modules/list/list-item/list-item.js.map +1 -1
  95. package/dist/components/modules/maps/info-window-card.js +2 -2
  96. package/dist/components/modules/maps/info-window-card.js.map +1 -1
  97. package/dist/components/modules/maps/info-window-content.js +5 -5
  98. package/dist/components/modules/maps/info-window-content.js.map +1 -1
  99. package/dist/components/modules/maps/map-list.js +5 -5
  100. package/dist/components/modules/maps/map-list.js.map +1 -1
  101. package/dist/components/modules/maps/map-marker.js +3 -3
  102. package/dist/components/modules/maps/map-marker.js.map +1 -1
  103. package/dist/components/modules/maps/map.js +5 -5
  104. package/dist/components/modules/maps/map.js.map +1 -1
  105. package/dist/components/modules/maps/place-marker.js +5 -5
  106. package/dist/components/modules/maps/place-marker.js.map +1 -1
  107. package/dist/components/modules/maps/tabs.js +21 -21
  108. package/dist/components/modules/maps/tabs.js.map +1 -1
  109. package/dist/contexts/mapContext.js +18 -18
  110. package/dist/contexts/mapContext.js.map +1 -1
  111. package/dist/contexts/mapListContext.js +28 -24
  112. package/dist/contexts/mapListContext.js.map +1 -1
  113. package/dist/contexts/placesContext.js +2 -2
  114. package/dist/contexts/placesContext.js.map +1 -1
  115. package/dist/contexts/themeContext.js +2 -2
  116. package/dist/contexts/themeContext.js.map +1 -1
  117. package/dist/contexts/trackEventContext.js +2 -2
  118. package/dist/contexts/trackEventContext.js.map +1 -1
  119. package/dist/services/listingAggregatorService.js +19 -15
  120. package/dist/services/listingAggregatorService.js.map +1 -1
  121. package/dist/services/listingEntityService.js +3 -2
  122. package/dist/services/listingEntityService.js.map +1 -1
  123. package/dist/services/listingService.js +1 -16
  124. package/dist/services/listingService.js.map +1 -1
  125. package/dist/styles/index.css +1 -3
  126. package/dist/types/contexts/mapContext.d.ts +1 -0
  127. package/dist/types/services/listingAggregatorService.d.ts +2 -2
  128. package/dist/types/services/listingEntityService.d.ts +2 -3
  129. package/dist/types/types/GetListingParams.d.ts +1 -1
  130. package/dist/types/types/ListingEntity.d.ts +2 -1
  131. package/dist/types/types/ListingFields.d.ts +4 -2
  132. package/dist/types/types/Listings.d.ts +0 -1
  133. package/dist/types/util/algoliaSearchUtil.d.ts +4 -0
  134. package/dist/types/util/filterUtil.d.ts +2 -2
  135. package/dist/types/util/mapUtil.d.ts +3 -3
  136. package/dist/util/algoliaSearchUtil.js +133 -0
  137. package/dist/util/algoliaSearchUtil.js.map +1 -0
  138. package/dist/util/filterUtil.js +129 -66
  139. package/dist/util/filterUtil.js.map +1 -1
  140. package/dist/util/loading.js +3 -3
  141. package/dist/util/loading.js.map +1 -1
  142. package/dist/util/mapUtil.js +37 -25
  143. package/dist/util/mapUtil.js.map +1 -1
  144. package/package.json +60 -17
  145. package/src/components/HireControlMap.js +35 -9
  146. package/src/components/containers/accordions/filter-container.js +6 -1
  147. package/src/components/containers/accordions/filter-item-container.js +2 -2
  148. package/src/components/containers/accordions/map-accordion-item-container.js +6 -2
  149. package/src/components/containers/filter/filter-container.js +3 -2
  150. package/src/components/containers/filter/filter-item-container.js +10 -10
  151. package/src/components/containers/filter/location-container.js +3 -3
  152. package/src/components/containers/list/item-list-container.tsx +3 -3
  153. package/src/components/containers/maps/info-window-content-container.js +1 -1
  154. package/src/components/containers/maps/map-container.js +2 -1
  155. package/src/components/modules/buttons/button-group-apply.js +8 -8
  156. package/src/components/modules/dialogs/apply-dialog.js +2 -2
  157. package/src/components/modules/list/field-mapper-desktop.jsx +2 -2
  158. package/src/components/modules/list/field-mapper-mobile.jsx +8 -8
  159. package/src/components/modules/list/header-item.js +1 -1
  160. package/src/components/modules/maps/map-list.js +1 -1
  161. package/src/contexts/mapContext.tsx +17 -16
  162. package/src/contexts/mapListContext.tsx +55 -49
  163. package/src/services/listingAggregatorService.ts +29 -21
  164. package/src/services/listingEntityService.ts +3 -3
  165. package/src/services/listingService.ts +1 -11
  166. package/src/styles/components.css +30 -0
  167. package/src/types/GetListingParams.ts +1 -1
  168. package/src/types/ListingEntity.ts +2 -1
  169. package/src/types/ListingFields.ts +4 -2
  170. package/src/types/Listings.ts +0 -1
  171. package/src/util/algoliaSearchUtil.js +91 -0
  172. package/src/util/filterUtil.js +19 -8
  173. package/src/util/mapUtil.js +52 -41
@@ -53,6 +53,7 @@ interface MapListContextProps {
53
53
  hiddenFilters?: string[];
54
54
  containerStyle?: any;
55
55
  ExpandListComponent?: React.ComponentType<{ listing: any }> | ((listing: any) => JSX.Element) | null;
56
+ noEntities?: boolean;
56
57
  }
57
58
 
58
59
  const MapListContext = createContext<MapListContextProps | undefined>(undefined);
@@ -93,8 +94,11 @@ interface MapListProviderProps {
93
94
  defaultFilters?: Record<string, any>;
94
95
  containerStyle?: any;
95
96
  localStorageKey: string;
96
- getListingEntitiesCallback?: (entityIds: number[], origin?: string) => Promise<ListingEntity[]>;
97
+ getListingEntitiesCallback?: (origin?: string) => Promise<any>;
97
98
  ExpandListComponent?: React.ComponentType<{ listing: Listing }> | ((listing: Listing) => JSX.Element) | null;
99
+ hideMap?: boolean;
100
+ hideFilters?: boolean;
101
+ noEntities?: boolean;
98
102
  }
99
103
 
100
104
  export const MapListProvider: React.FC<MapListProviderProps> = ({
@@ -118,13 +122,16 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
118
122
  containerStyle,
119
123
  ExpandListComponent,
120
124
  getListingEntitiesCallback,
121
- localStorageKey
125
+ localStorageKey,
126
+ hideMap = false,
127
+ hideFilters = false,
128
+ noEntities = false
122
129
  }) => {
123
130
  const firstLoadFilters = () =>{
124
131
  let urlFilters = filtersFromURL(window.location)?.filters;
125
132
  return (setFiltersUrl === true && urlFilters && Object.keys(urlFilters).length > 0) ? urlFilters : getStorageObject(localStorageKey + 'selectedFilters', {}) || {}
126
133
  }
127
-
134
+
128
135
  const firstLoadQuery = (): string | null => {
129
136
  if (resetFilters) return null;
130
137
  // Check URL first
@@ -135,7 +142,7 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
135
142
  // Fall back to localStorage
136
143
  return getQuery(localStorageKey);
137
144
  }
138
-
145
+
139
146
  const [allListings, setAllListings] = useState<Listing[]>([]);
140
147
  const [filteredListings, setFilteredListings] = useState<Listing[]>([]);
141
148
  const [loading, setLoading] = useState<boolean>(false);
@@ -144,7 +151,7 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
144
151
  const [sortSetting, setSortSetting] = useState<{ field: string; type: string }>(getStorageObject(localStorageKey + 'sortSetting', { field: 'position', type: 'asc' }) || { field: 'position', type: 'asc' });
145
152
  const [listingEntities, setListingEntities] = useState<Record<number, ListingEntity> | null>({});
146
153
  const [firstLoad, setFirstLoad] = useState<boolean>(true);
147
- const [commuteLocation, setCommuteLocation] = useState<any | null>(getStorageObject('commuteLocation'));
154
+ const [commuteLocation, setCommuteLocation] = useState<any | null>(getStorageObject(localStorageKey + 'commuteLocation'));
148
155
  const [selectedFilters, setSelectedFilters] = useState<Record<string, any>>(() => resetFilters ? {} : firstLoadFilters());
149
156
  const [filterOptions, setFilterOptions] = useState<any>();
150
157
  const [recruiters, setRecruiters] = useState<Record<number, Recruiter>>({});
@@ -161,7 +168,7 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
161
168
  if (!sortSetting) return;
162
169
  localStorage.setItem(localStorageKey + 'sortSetting', JSON.stringify(sortSetting));
163
170
  setNewFilteredListings(filteredListings);
164
- }, [sortSetting, localStorageKey]);
171
+ }, [sortSetting, localStorageKey, filteredListings]);
165
172
 
166
173
  useEffect(() => {
167
174
  const loadedFavorites = JSON.parse(localStorage.getItem(localStorageKey + 'favorites') || '[]');
@@ -172,34 +179,32 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
172
179
  setStorageObject(localStorageKey + "commuteLocation", commuteLocation);
173
180
  }, [commuteLocation, localStorageKey]);
174
181
 
182
+
175
183
  useEffect(() => {
176
- if (!commuteLocation) return;
184
+ if (!commuteLocation || noEntities) return;
177
185
 
178
186
  async function fetchEntities() {
179
- const distinctEntityIds = [
180
- ...new Set(allListings.map(listing => listing.entityId ?? -1))
181
- ];
182
187
  try {
183
- console.log(getListingEntitiesCallback);
184
- console.log("fetching entities")
185
- const fetchedEntities = getListingEntitiesCallback !== null && getListingEntitiesCallback !== undefined ? await getListingEntitiesCallback(distinctEntityIds,
186
- `${commuteLocation.lat}, ${commuteLocation.lng}`) : await getListingEntities(
187
- distinctEntityIds,
188
- `${commuteLocation.lat}, ${commuteLocation.lng}`
189
- );
188
+ let fetchedEntities;
189
+ if (getListingEntitiesCallback) {
190
+ fetchedEntities = await getListingEntitiesCallback(`${commuteLocation.lat}, ${commuteLocation.lng}`);
191
+ } else {
192
+ fetchedEntities = await getListingEntities(`${commuteLocation.lat}, ${commuteLocation.lng}`);
193
+ }
190
194
  setListingEntities(fetchedEntities);
191
- const newFilteredListings: Listing[] = [...filteredListings] ?? [];
195
+ // Update travelTime on listings
196
+ const newFilteredListings: Listing[] = [...filteredListings];
192
197
  for (let i = 0; i < allListings.length; i++) {
193
198
  const listing = newFilteredListings[i];
194
199
  if (
195
200
  listing &&
196
201
  listing.fields &&
197
- listing.entityId !== undefined &&
198
- listing.entityId !== -1
202
+ listing.fields.entityKey &&
203
+ listing.fields.entityKey !== ''
199
204
  ) {
200
- const entityId = listing.entityId;
201
- const travelTime = fetchedEntities[entityId]?.travelTime;
202
-
205
+ const entityKey = listing.fields.entityKey;
206
+ // Try exact match first, then lowercase match for case-insensitive lookup
207
+ const travelTime = (fetchedEntities[entityKey] || fetchedEntities[entityKey.toLowerCase()])?.travelTime;
203
208
  if (travelTime !== undefined && listing.fields) {
204
209
  listing.fields.travelTime = travelTime;
205
210
  }
@@ -211,35 +216,35 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
211
216
  }
212
217
 
213
218
  fetchEntities();
214
- }, [commuteLocation, allListings, siteConfig.companyId]);
219
+ }, [commuteLocation, allListings, siteConfig.companyId, getListingEntitiesCallback, noEntities]);
215
220
 
216
221
  useEffect(() => {
217
222
  const handleFetchListings = async () => {
218
- if (!getStorageObject(localStorageKey + 'listings') ?? [].length) {
219
- setLoading(true);
220
- }
223
+ if (!(getStorageObject(localStorageKey + 'listings', []) || []).length) {
224
+ setLoading(true);
225
+ }
221
226
 
222
- try {
223
- const {
224
- listingsResult,
225
- fetchedEntities,
226
- distinctItems
227
- } = await fetchListings(commuteLocation, entities, listings, getListingEntitiesCallback);
228
- if (defaultFilters) {
229
- const filteredListings = listingsResult.filter(listing => {
230
- if (!listing.fields) return false;
227
+ try {
228
+ const {
229
+ listingsResult,
230
+ entitiesByKey,
231
+ distinctItems
232
+ } = await fetchListings(commuteLocation, entities, listings, getListingEntitiesCallback, noEntities);
233
+ if (defaultFilters) {
234
+ const filteredListings = listingsResult.filter(listing => {
235
+ if (!listing.fields) return false;
231
236
 
232
- return Object.keys(defaultFilters).every(filterKey => {
233
- const filterValues = defaultFilters[filterKey as keyof typeof defaultFilters];
234
- const listingValue = listing.fields ? listing.fields[filterKey as keyof typeof listing.fields] : null;
235
- return filterValues.includes(listingValue);
236
- });
237
+ return Object.keys(defaultFilters).every(filterKey => {
238
+ const filterValues = defaultFilters[filterKey as keyof typeof defaultFilters];
239
+ const listingValue = listing.fields ? listing.fields[filterKey as keyof typeof listing.fields] : null;
240
+ return filterValues.includes(listingValue);
237
241
  });
238
- setAllListings(filteredListings);
239
- } else {
240
- setAllListings(listingsResult);
241
- }
242
- setListingEntities(fetchedEntities);
242
+ });
243
+ setAllListings(filteredListings);
244
+ } else {
245
+ setAllListings(listingsResult);
246
+ }
247
+ setListingEntities(entitiesByKey);
243
248
  setMapItems(distinctItems);
244
249
  } catch (error) {
245
250
  console.log(error);
@@ -250,12 +255,12 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
250
255
  }, [query, siteConfig, commuteLocation]);
251
256
 
252
257
  useEffect(() => {
253
- const processListings = () => {
258
+ const processListings = async () => {
254
259
  let filteredListings: Listing[];
255
260
  let tempSelectedFilters = selectedFilters;
256
261
  let tempQuery = query;
257
262
 
258
- const { mapItems, filteredListings: tempFilteredListings } = applyFilters(
263
+ const { mapItems, filteredListings: tempFilteredListings } = await applyFilters(
259
264
  allListings,
260
265
  tempSelectedFilters,
261
266
  tempQuery,
@@ -369,7 +374,8 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
369
374
  defaultFilters,
370
375
  hiddenFilters,
371
376
  containerStyle,
372
- ExpandListComponent
377
+ ExpandListComponent,
378
+ noEntities
373
379
  }}>
374
380
  {children}
375
381
  </MapListContext.Provider>
@@ -6,7 +6,8 @@ import { ListingEntity } from '~/types/ListingEntity';
6
6
 
7
7
  interface FetchListingsResult {
8
8
  listingsResult: Listing[];
9
- fetchedEntities: Record<number, ListingEntity>;
9
+ entitiesByKey: Record<string, ListingEntity>;
10
+
10
11
  distinctItems: any; // Update this type based on the return type of getDistinctItemsByProximity
11
12
  }
12
13
 
@@ -14,39 +15,46 @@ const fetchListings = async (
14
15
  commuteLocation: any | null = null,
15
16
  entities: ListingEntity[] | null,
16
17
  listings: Listing[] | null,
17
- getListingEntitiesCallback?: (entityIds: number[], origin?: string) => Promise<ListingEntity[]>,
18
+ getListingEntitiesCallback?: (origin?: string) => Promise<ListingEntity[]>,
19
+ noEntities: boolean = false
18
20
  ): Promise<FetchListingsResult> => {
19
21
  try {
20
22
  const listingsResult = listings && listings.length > 0 ? listings : await getListings();
21
- const distinctEntityIds: number[] = [
22
- ...new Set(listingsResult.map(listing => listing.entityId))
23
- ] as number[];
24
-
25
- const fetchedEntities = !commuteLocation
26
- ? entities && entities.length > 0 ? entities : !getListingEntitiesCallback ? await getListingEntities(distinctEntityIds) : await getListingEntitiesCallback(distinctEntityIds)
27
- : !getListingEntitiesCallback ? await getListingEntities(
28
- distinctEntityIds,
29
- `${commuteLocation.lat}, ${commuteLocation.lng}`
30
- ) : await getListingEntitiesCallback( distinctEntityIds,
31
- `${commuteLocation.lat}, ${commuteLocation.lng}`);
32
- for (let i = 0; i < listingsResult.length; i++) {
33
- const listing = listingsResult[i];
34
- if (listing.entityId && listing.entityId !== -1 && listing.fields) {
35
- const entity = fetchedEntities[listing.entityId];
36
- if (entity) {
37
- listing.fields.travelTime = entity.travelTime;
23
+
24
+ // Only fetch entities if noEntities is false
25
+ const fetchedEntities = noEntities ? {} : (
26
+ !commuteLocation
27
+ ? entities && entities.length > 0 ? entities : !getListingEntitiesCallback ? await getListingEntities() : await getListingEntitiesCallback()
28
+ : !getListingEntitiesCallback ? await getListingEntities(
29
+ `${commuteLocation.lat}, ${commuteLocation.lng}`
30
+ ) : await getListingEntitiesCallback(
31
+ `${commuteLocation.lat}, ${commuteLocation.lng}`)
32
+ );
33
+ const entitiesByKey = fetchedEntities;
34
+ // Update travel time only if entities were fetched
35
+ if (!noEntities && entitiesByKey) {
36
+ for (let i = 0; i < listingsResult.length; i++) {
37
+ const listing = listingsResult[i];
38
+ if (listing.fields && listing.fields.entityKey && listing.fields.entityKey !== '' && listing.fields) {
39
+ // Try exact match first, then lowercase match for case-insensitive lookup
40
+ const entity = entitiesByKey[listing.fields.entityKey] || entitiesByKey[listing.fields.entityKey.toLowerCase()];
41
+ console.log("Entity for listing with travel time", listing.fields.entityKey, entity);
42
+
43
+ if (entity) {
44
+ listing.fields.travelTime = entity.travelTime;
45
+ }
38
46
  }
39
47
  }
40
48
  }
41
49
 
42
50
  const distinctItems = getDistinctItemsByProximity(
43
51
  listingsResult,
44
- fetchedEntities
52
+ entitiesByKey || {}
45
53
  );
46
54
 
47
55
  return {
48
56
  listingsResult,
49
- fetchedEntities,
57
+ entitiesByKey,
50
58
  distinctItems
51
59
  };
52
60
  } catch (error) {
@@ -1,9 +1,9 @@
1
1
  import api from '~/apis/hcApi';
2
- import { ListingEntity } from '~/types/ListingEntity';
3
2
 
4
- export const getListingEntities = async (entityIds: number[], origin = ''): Promise<ListingEntity[]> => {
3
+ export const getListingEntities = async (origin = ''): Promise<any> => {
5
4
  try {
6
- const response = await api.post<ListingEntity[]>(`/ListingEntities?origin=${origin}`, entityIds);
5
+ //need to update / or add better endpoint fo this to match original functioanlity
6
+ const response = await api.get<any>(`/listingentities/MapEntities?origin=${origin}`);
7
7
  return response;
8
8
  } catch (error) {
9
9
  console.error("Error fetching listing entities:", error);
@@ -5,18 +5,8 @@ import { Listing } from '../types/Listings';
5
5
 
6
6
  export const getListings = async (params?: GetListingsParams): Promise<Listing[]> => {
7
7
  try {
8
- const query = new URLSearchParams();
8
+ const response = await api.get(`/joblistings/maplistings`);
9
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
10
  return response as Listing[];
21
11
  } catch (error) {
22
12
  console.error(error);
@@ -0,0 +1,30 @@
1
+ @config "../../tailwind.config.js";
2
+
3
+ /* Only include components and utilities - no base styles */
4
+ @tailwind components;
5
+ @tailwind utilities;
6
+
7
+ @layer components {
8
+ .track * {
9
+ @apply hc-pointer-events-none;
10
+ }
11
+
12
+ .stretched-link::after {
13
+ @apply hc-content-[''] hc-absolute hc-inset-0 hc-z-[1] hc-pointer-events-auto hc-bg-transparent;
14
+ }
15
+ }
16
+
17
+ /* Component-specific utilities */
18
+ .fit-content {
19
+ height: fit-content;
20
+ }
21
+
22
+ /* CSS Variables for theming - these should be set by the consuming app */
23
+ :root {
24
+ --ui-text: #000000;
25
+ --ui-accent: #959595;
26
+ --primary: #959595;
27
+ --primary-dark: #959595;
28
+ --secondary: #959595;
29
+ --secondary-dark: #959595;
30
+ }
@@ -1,7 +1,7 @@
1
1
  export type GetListingsParams = {
2
2
  location?: string[];
3
3
  category?: string[];
4
- categoryClass?: string[];
4
+ subCategory?: string[];
5
5
  education?: string[];
6
6
  city?: string[];
7
7
  state?: string[];
@@ -1,9 +1,10 @@
1
1
  import { Address } from './Address';
2
2
 
3
3
  export type ListingEntity = {
4
- id: number;
4
+ id: string;
5
5
  listingId: number;
6
6
  latitude: number;
7
+ entityKey: string;
7
8
  longitude: number;
8
9
  entityDisplayName?: string;
9
10
  address?: Address;
@@ -2,9 +2,10 @@ export type ListingFields = {
2
2
  posted?: string;
3
3
  subTitle?: string;
4
4
  education?: string;
5
- position?: string;
5
+ title?: string;
6
6
  category?: string;
7
- categoryClass?: string;
7
+ subCategory?: string;
8
+ applyUrl?: string;
8
9
  shift?: string;
9
10
  custom1?: string;
10
11
  custom2?: string;
@@ -22,5 +23,6 @@ export type ListingFields = {
22
23
  useClientJobUrl?: boolean;
23
24
  dateCreated: Date;
24
25
  dateLastEdited?: Date;
26
+ entityKey: string;
25
27
  travelTime?: string;
26
28
  }
@@ -7,7 +7,6 @@ import { SimilarListing } from './SimilarListing';
7
7
  export type Listing = {
8
8
  id: number;
9
9
  fields?: ListingFields;
10
- entityId?: number;
11
10
  applyUrl?: string;
12
11
  applyOnline?: number;
13
12
  detailsUrl?: string;
@@ -0,0 +1,91 @@
1
+ import { liteClient as algoliasearch } from 'algoliasearch/lite';
2
+
3
+ let algoliaClient = null;
4
+ let algoliaIndexName = null;
5
+
6
+ /**
7
+ * Initialize Algolia search client
8
+ * @param {string} appId - Algolia Application ID
9
+ * @param {string} apiKey - Algolia Search API Key
10
+ * @param {string} indexName - Algolia Index Name
11
+ */
12
+ export const initializeAlgoliaSearch = (appId, apiKey, indexName) => {
13
+ if (!appId || !apiKey || !indexName) {
14
+ console.warn('Algolia search not initialized: missing configuration');
15
+ return false;
16
+ }
17
+
18
+ try {
19
+ algoliaClient = algoliasearch(appId, apiKey);
20
+ algoliaIndexName = indexName;
21
+ return true;
22
+ } catch (error) {
23
+ console.error('Failed to initialize Algolia:', error);
24
+ return false;
25
+ }
26
+ };
27
+
28
+ /**
29
+ * Check if Algolia is initialized and available
30
+ */
31
+ export const isAlgoliaAvailable = () => {
32
+ return algoliaClient !== null && algoliaIndexName !== null;
33
+ };
34
+
35
+ /**
36
+ * Search using Algolia and return matching listing IDs
37
+ * @param {string} query - Search query
38
+ * @returns {Promise<number[]>} Array of listing IDs that match the search
39
+ */
40
+ export const searchAlgolia = async (query) => {
41
+ if (!isAlgoliaAvailable()) {
42
+ throw new Error('Algolia search is not initialized');
43
+ }
44
+
45
+ try {
46
+ const { results } = await algoliaClient.search({
47
+ requests: [
48
+ {
49
+ indexName: algoliaIndexName,
50
+ query: query,
51
+ hitsPerPage: 1000 // Adjust based on your needs
52
+ }
53
+ ]
54
+ });
55
+
56
+ // Extract IDs from the results
57
+ const hits = results[0]?.hits || [];
58
+ const listingIds = hits.map(hit => {
59
+ // Algolia objectID might be the listing ID, or it might be in a field
60
+ // Adjust this based on your Algolia index structure
61
+ return hit.id || parseInt(hit.objectID);
62
+ }).filter(id => !isNaN(id));
63
+
64
+ return listingIds;
65
+ } catch (error) {
66
+ console.error('Algolia search failed:', error);
67
+ throw error;
68
+ }
69
+ };
70
+
71
+ /**
72
+ * Filter listings by Algolia search results
73
+ * @param {Array} listings - All listings to filter
74
+ * @param {string} query - Search query
75
+ * @returns {Promise<Array>} Filtered listings
76
+ */
77
+ export const filterListingsByAlgoliaSearch = async (listings, query) => {
78
+ if (!query || !isAlgoliaAvailable()) {
79
+ return listings;
80
+ }
81
+
82
+ try {
83
+ const matchingIds = await searchAlgolia(query);
84
+
85
+ // Filter listings to only include those with matching IDs
86
+ return listings.filter(listing => matchingIds.includes(listing.id));
87
+ } catch (error) {
88
+ console.error('Failed to filter by Algolia search, returning all listings:', error);
89
+ return listings;
90
+ }
91
+ };
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable no-undef */
2
2
  import { getDistinctItemsByProximity } from '~/util/mapUtil';
3
+ import { isAlgoliaAvailable, filterListingsByAlgoliaSearch } from '~/util/algoliaSearchUtil';
3
4
 
4
5
  import Fuse from 'fuse.js';
5
6
 
@@ -82,17 +83,17 @@ export const generateFilterOptions = (
82
83
  if (fieldName === parentField && filterOptions?.filters) {
83
84
  return filterOptions.filters.find(filter => filter.id === fieldName);
84
85
  }
85
- if(fieldName == 'categoryClass'){
86
+ if(fieldName == 'category'){
86
87
  return {
87
88
  id: fieldName,
88
89
  title: siteConfig.fieldNames[fieldName],
89
90
  items: getFilterOptions(allListings, allListings, fieldName)
90
91
  };
91
92
  }
92
- if(fieldName == 'category' && selectedFilters.categoryClass){
93
- const categoryClassKeys = Object.keys(selectedFilters.categoryClass);
93
+ if(fieldName == 'subCategory' && selectedFilters.category){
94
+ const categoryKeys = Object.keys(selectedFilters.category);
94
95
  const filteredListings = allListings.filter(
95
- x => categoryClassKeys.includes(x.fields?.categoryClass)
96
+ x => categoryKeys.includes(x.fields?.category)
96
97
  );
97
98
  return {
98
99
  id: fieldName,
@@ -195,7 +196,7 @@ export const generateFilterOptions = (
195
196
  return null;
196
197
  };
197
198
 
198
- export const applyFilters = (
199
+ export const applyFilters = async (
199
200
  allListings,
200
201
  selectedFilters,
201
202
  query,
@@ -239,7 +240,17 @@ export const applyFilters = (
239
240
  }
240
241
  }
241
242
  if (query) {
242
- results = searchResults(results, query);
243
+ // Use Algolia if available, otherwise fall back to Fuse.js
244
+ if (isAlgoliaAvailable()) {
245
+ try {
246
+ results = await filterListingsByAlgoliaSearch(results, query);
247
+ } catch (error) {
248
+ console.error('Algolia search failed, falling back to Fuse.js:', error);
249
+ results = searchResults(results, query);
250
+ }
251
+ } else {
252
+ results = searchResults(results, query);
253
+ }
243
254
  }
244
255
  const distinctItems = getDistinctItemsByProximity(results, listingEntities);
245
256
  if (hasFavorite) {
@@ -255,9 +266,9 @@ function searchResults(results, query) {
255
266
  'fields.posted',
256
267
  'fields.subtitle',
257
268
  'fields.education',
258
- 'fields.position',
269
+ 'fields.title',
259
270
  'fields.category',
260
- 'fields.categoryclass',
271
+ 'fields.subCategory',
261
272
  'fields.shift',
262
273
  'fields.citystate',
263
274
  'fields.city',