@abcagency/hc-ui-components 1.4.9 → 1.4.12
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.
- package/dist/components/HireControlMap.js +14 -5
- package/dist/components/HireControlMap.js.map +1 -1
- package/dist/components/containers/accordions/filter-item-container.js +2 -2
- package/dist/components/containers/accordions/filter-item-container.js.map +1 -1
- package/dist/components/containers/accordions/map-accordion-item-container.js +6 -2
- package/dist/components/containers/accordions/map-accordion-item-container.js.map +1 -1
- package/dist/components/containers/filter/filter-item-container.js +10 -10
- package/dist/components/containers/filter/filter-item-container.js.map +1 -1
- package/dist/components/containers/maps/info-window-content-container.js.map +1 -1
- package/dist/components/containers/maps/map-container.js +0 -1
- package/dist/components/containers/maps/map-container.js.map +1 -1
- package/dist/components/modules/buttons/button-group-apply.js +12 -12
- package/dist/components/modules/buttons/button-group-apply.js.map +1 -1
- package/dist/components/modules/dialogs/apply-dialog.js +4 -4
- package/dist/components/modules/dialogs/apply-dialog.js.map +1 -1
- package/dist/components/modules/list/field-mapper-desktop.js +2 -2
- package/dist/components/modules/list/field-mapper-desktop.js.map +1 -1
- package/dist/components/modules/list/field-mapper-mobile.js +8 -8
- package/dist/components/modules/list/field-mapper-mobile.js.map +1 -1
- package/dist/components/modules/list/header-item.js +1 -1
- package/dist/components/modules/list/header-item.js.map +1 -1
- package/dist/contexts/mapListContext.js +17 -15
- package/dist/contexts/mapListContext.js.map +1 -1
- package/dist/services/listingAggregatorService.js +7 -8
- package/dist/services/listingAggregatorService.js.map +1 -1
- package/dist/services/listingEntityService.js +3 -2
- package/dist/services/listingEntityService.js.map +1 -1
- package/dist/services/listingService.js +1 -16
- package/dist/services/listingService.js.map +1 -1
- package/dist/types/contexts/mapListContext.d.ts +1 -1
- package/dist/types/services/listingAggregatorService.d.ts +2 -2
- package/dist/types/services/listingEntityService.d.ts +2 -3
- package/dist/types/types/GetListingParams.d.ts +1 -1
- package/dist/types/types/ListingEntity.d.ts +2 -1
- package/dist/types/types/ListingFields.d.ts +4 -2
- package/dist/types/types/Listings.d.ts +0 -1
- package/dist/types/util/mapUtil.d.ts +3 -3
- package/dist/util/filterUtil.js +5 -5
- package/dist/util/filterUtil.js.map +1 -1
- package/dist/util/mapUtil.js +33 -25
- package/dist/util/mapUtil.js.map +1 -1
- package/package.json +1 -1
- package/src/components/HireControlMap.js +15 -6
- package/src/components/containers/accordions/filter-item-container.js +2 -2
- package/src/components/containers/accordions/map-accordion-item-container.js +6 -2
- package/src/components/containers/filter/filter-item-container.js +10 -10
- package/src/components/containers/maps/info-window-content-container.js +1 -1
- package/src/components/containers/maps/map-container.js +2 -1
- package/src/components/modules/buttons/button-group-apply.js +8 -8
- package/src/components/modules/dialogs/apply-dialog.js +2 -2
- package/src/components/modules/list/field-mapper-desktop.jsx +2 -2
- package/src/components/modules/list/field-mapper-mobile.jsx +8 -8
- package/src/components/modules/list/header-item.js +1 -1
- package/src/contexts/mapListContext.tsx +37 -40
- package/src/services/listingAggregatorService.ts +12 -11
- package/src/services/listingEntityService.ts +3 -3
- package/src/services/listingService.ts +1 -11
- package/src/types/GetListingParams.ts +1 -1
- package/src/types/ListingEntity.ts +2 -1
- package/src/types/ListingFields.ts +4 -2
- package/src/types/Listings.ts +0 -1
- package/src/util/filterUtil.js +6 -6
- package/src/util/mapUtil.js +48 -41
|
@@ -31,19 +31,19 @@ const ButtonGroupApply = ({
|
|
|
31
31
|
|
|
32
32
|
const trackApplyNow = () => {
|
|
33
33
|
//console.log('calling trackApplyNow');
|
|
34
|
-
trackEvent(eventTypes.APPLY_NOW_CLICKED, { jobCategory: item.fields.
|
|
34
|
+
trackEvent(eventTypes.APPLY_NOW_CLICKED, { jobCategory: item.fields.subCategory, jobCategoryClass: item.fields.category, jobEntity: item.fields.entityName, jobListingId: item.id, jobSchedule: item.fields.schedule });
|
|
35
35
|
};
|
|
36
36
|
const trackApplyOpen = () => {
|
|
37
37
|
//console.log('calling trackApplyOpen');
|
|
38
|
-
trackEvent(eventTypes.APPLY_OPEN_CLICKED, { jobCategory: item.fields.
|
|
38
|
+
trackEvent(eventTypes.APPLY_OPEN_CLICKED, { jobCategory: item.fields.subCategory, jobCategoryClass: item.fields.category, jobEntity: item.fields.entityName, jobListingId: item.id, jobSchedule: item.fields.schedule });
|
|
39
39
|
};
|
|
40
40
|
const trackEasyApply = () => {
|
|
41
41
|
//console.log('calling trackEasyApply');
|
|
42
|
-
trackEvent(eventTypes.EASY_APPLY_CLICKED, { jobCategory: item.fields.
|
|
42
|
+
trackEvent(eventTypes.EASY_APPLY_CLICKED, { jobCategory: item.fields.subCategory, jobCategoryClass: item.fields.category, jobEntity: item.fields.entityName, jobListingId: item.id, jobSchedule: item.fields.schedule });
|
|
43
43
|
};
|
|
44
44
|
const trackViewDetails = () => {
|
|
45
45
|
//console.log('calling trackViewDetails');
|
|
46
|
-
trackEvent(eventTypes.VIEW_DETAILS_CLICKED, { jobCategory: item.fields.
|
|
46
|
+
trackEvent(eventTypes.VIEW_DETAILS_CLICKED, { jobCategory: item.fields.subCategory, jobCategoryClass: item.fields.category, jobEntity: item.fields.entityName, jobListingId: item.id, jobSchedule: item.fields.schedule });
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
return (
|
|
@@ -78,9 +78,9 @@ const ButtonGroupApply = ({
|
|
|
78
78
|
</Button.Anchor>
|
|
79
79
|
) : null}
|
|
80
80
|
|
|
81
|
-
{item.applyOnline ==
|
|
81
|
+
{item.fields.applyOnline == true && item.fields.applyUrl && !includeDialog &&
|
|
82
82
|
<Button.Anchor
|
|
83
|
-
href={item.applyUrl}
|
|
83
|
+
href={item.fields.applyUrl}
|
|
84
84
|
variant={applyButtonVariant}
|
|
85
85
|
size={buttonSize}
|
|
86
86
|
className={"map-apply-now-button"}
|
|
@@ -91,8 +91,8 @@ const ButtonGroupApply = ({
|
|
|
91
91
|
{applyNowText}
|
|
92
92
|
</Button.Anchor>
|
|
93
93
|
}
|
|
94
|
-
{item.applyOnline ==
|
|
95
|
-
<ApplyDialog applyUrl={item.applyUrl} internalApplyLink={internalApplyLink} companyName={companyName} item={item} trackEvent={trackEvent} eventTypes={eventTypes} isIframe={isIframe}>
|
|
94
|
+
{item.fields.applyOnline == true && item.fields.applyUrl && includeDialog &&
|
|
95
|
+
<ApplyDialog applyUrl={item.fields.applyUrl} internalApplyLink={internalApplyLink} companyName={companyName} item={item} trackEvent={trackEvent} eventTypes={eventTypes} isIframe={isIframe}>
|
|
96
96
|
<Button.Anchor
|
|
97
97
|
variant={applyButtonVariant}
|
|
98
98
|
size={buttonSize}
|
|
@@ -7,11 +7,11 @@ import Icon from '~/components/modules/icon';
|
|
|
7
7
|
const ApplyDialog = ({ children, applyUrl, internalApplyLink, companyName, item, trackEvent, eventTypes, isIframe }) => {
|
|
8
8
|
const trackApplyOption1 = () => {
|
|
9
9
|
//console.log('calling trackApplyOption1');
|
|
10
|
-
trackEvent(eventTypes.APPLY_OPTION_1_CLICKED, { jobCategory: item.fields.
|
|
10
|
+
trackEvent(eventTypes.APPLY_OPTION_1_CLICKED, { jobCategory: item.fields.subCategory, jobCategoryClass: item.fields.category, jobEntity: item.fields.entityName, jobListingId: item.id, jobSchedule: item.fields.schedule });
|
|
11
11
|
};
|
|
12
12
|
const trackApplyOption2 = () => {
|
|
13
13
|
//console.log('calling trackApplyOption2');
|
|
14
|
-
trackEvent(eventTypes.APPLY_OPTION_2_CLICKED, { jobCategory: item.fields.
|
|
14
|
+
trackEvent(eventTypes.APPLY_OPTION_2_CLICKED, { jobCategory: item.fields.subCategory, jobCategoryClass: item.fields.category, jobEntity: item.fields.entityName, jobListingId: item.id, jobSchedule: item.fields.schedule });
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
return (
|
|
@@ -11,7 +11,7 @@ const FieldMapperDesktop = ({
|
|
|
11
11
|
const orderedFields = fieldsShown.filter(field => field in item.fields);
|
|
12
12
|
|
|
13
13
|
const specialFeaturePills = field => {
|
|
14
|
-
return field === '
|
|
14
|
+
return field === 'title' && specialFeatures &&
|
|
15
15
|
Object.entries(specialFeatures).map(([featureKey, featureLabel]) => {
|
|
16
16
|
return item.fields[featureKey] == 1 && (
|
|
17
17
|
<PillWrapper key={featureKey}>{featureLabel}</PillWrapper>
|
|
@@ -29,7 +29,7 @@ const FieldMapperDesktop = ({
|
|
|
29
29
|
className={`
|
|
30
30
|
hc-hidden md:hc-block hc-px-2
|
|
31
31
|
${index === 0 ? "hc-pl-7" : ""}
|
|
32
|
-
${field.toLowerCase() === "
|
|
32
|
+
${field.toLowerCase() === "title" ? "hc-col-span-4 hc-text-balance hc-font-semibold" : (field.toLowerCase() === "state" || field.toLowerCase() == "favorite") ? "hc-col-span-1" : "hc-col-span-2"}
|
|
33
33
|
`}
|
|
34
34
|
>
|
|
35
35
|
<span className="hc-sr-only">{capitalize(field)}</span>
|
|
@@ -12,7 +12,7 @@ const FieldMapperMobile = ({
|
|
|
12
12
|
includeFavorite = true
|
|
13
13
|
}) => {
|
|
14
14
|
const specialFeaturePills = field => {
|
|
15
|
-
return field === '
|
|
15
|
+
return field === 'title' && specialFeatures &&
|
|
16
16
|
Object.entries(specialFeatures).map(([featureKey, featureLabel]) => {
|
|
17
17
|
return item.fields[featureKey] == 1 && (
|
|
18
18
|
<PillWrapper key={featureKey}>{featureLabel}</PillWrapper>
|
|
@@ -22,11 +22,11 @@ const FieldMapperMobile = ({
|
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
24
|
<Grid.Item className="md:hc-hidden">
|
|
25
|
-
{fieldsShown.includes("
|
|
25
|
+
{fieldsShown.includes("title") &&
|
|
26
26
|
<>
|
|
27
27
|
<div className="hc-flex hc-items-start">
|
|
28
28
|
<div className="hc-flex hc-justify-between hc-items-center hc-min-w-[100%]">
|
|
29
|
-
<h3 className="hc-font-bold hc-mb-3 hc-flex-1">{item.fields.
|
|
29
|
+
<h3 className="hc-font-bold hc-mb-3 hc-flex-1">{item.fields.title}</h3>
|
|
30
30
|
{includeFavorite && <div className="hc-flex hc-justify-end hc-pb-2">
|
|
31
31
|
<Icon
|
|
32
32
|
icon={isFavorite ? "mdi:heart" : "mdi:heart-outline"}
|
|
@@ -41,20 +41,20 @@ const FieldMapperMobile = ({
|
|
|
41
41
|
}
|
|
42
42
|
</div>
|
|
43
43
|
</div>
|
|
44
|
-
{specialFeatures && <div className='hc-pb-4'>{specialFeaturePills("
|
|
44
|
+
{specialFeatures && <div className='hc-pb-4'>{specialFeaturePills("title", true)} </div>}
|
|
45
45
|
</>
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
<ul className="hc-space-y-2 hc-text-xs">
|
|
49
49
|
{[
|
|
50
50
|
{
|
|
51
|
-
field: "
|
|
52
|
-
name: "
|
|
51
|
+
field: "category",
|
|
52
|
+
name: "category",
|
|
53
53
|
icon: "icon-park-solid:tree-list"
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
|
-
field: "
|
|
57
|
-
name: "
|
|
56
|
+
field: "subCategory",
|
|
57
|
+
name: "subCategory",
|
|
58
58
|
icon: "icon-park-solid:tree-list"
|
|
59
59
|
},
|
|
60
60
|
{
|
|
@@ -57,7 +57,7 @@ const HeaderItem = ({
|
|
|
57
57
|
size="none"
|
|
58
58
|
className={`
|
|
59
59
|
hc-p-2 hc-rounded-none hc-text-left hc-normal-case hover:hc-bg-uiAccent/5 focus:hc-bg-uiAccent/5
|
|
60
|
-
${field.toLowerCase() === "
|
|
60
|
+
${field.toLowerCase() === "title" ? "hc-pl-7 hc-col-span-4" : (field.toLowerCase() === "state" || field.toLowerCase() == "favorite") ? "hc-col-span-1" : "hc-col-span-2"}
|
|
61
61
|
${className ?? ""}
|
|
62
62
|
`}
|
|
63
63
|
{...rest}
|
|
@@ -93,7 +93,7 @@ interface MapListProviderProps {
|
|
|
93
93
|
defaultFilters?: Record<string, any>;
|
|
94
94
|
containerStyle?: any;
|
|
95
95
|
localStorageKey: string;
|
|
96
|
-
getListingEntitiesCallback?: (
|
|
96
|
+
getListingEntitiesCallback?: (origin?: string) => Promise<any>;
|
|
97
97
|
ExpandListComponent?: React.ComponentType<{ listing: Listing }> | ((listing: Listing) => JSX.Element) | null;
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -160,34 +160,31 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
|
|
|
160
160
|
setStorageObject("commuteLocation", commuteLocation);
|
|
161
161
|
}, [commuteLocation]);
|
|
162
162
|
|
|
163
|
+
|
|
163
164
|
useEffect(() => {
|
|
164
165
|
if (!commuteLocation) return;
|
|
165
166
|
|
|
166
167
|
async function fetchEntities() {
|
|
167
|
-
const distinctEntityIds = [
|
|
168
|
-
...new Set(allListings.map(listing => listing.entityId ?? -1))
|
|
169
|
-
];
|
|
170
168
|
try {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
);
|
|
169
|
+
let fetchedEntities;
|
|
170
|
+
if (getListingEntitiesCallback) {
|
|
171
|
+
fetchedEntities = await getListingEntitiesCallback(`${commuteLocation.lat}, ${commuteLocation.lng}`);
|
|
172
|
+
} else {
|
|
173
|
+
fetchedEntities = await getListingEntities(`${commuteLocation.lat}, ${commuteLocation.lng}`);
|
|
174
|
+
}
|
|
178
175
|
setListingEntities(fetchedEntities);
|
|
179
|
-
|
|
176
|
+
// Update travelTime on listings
|
|
177
|
+
const newFilteredListings: Listing[] = [...filteredListings];
|
|
180
178
|
for (let i = 0; i < allListings.length; i++) {
|
|
181
179
|
const listing = newFilteredListings[i];
|
|
182
180
|
if (
|
|
183
181
|
listing &&
|
|
184
182
|
listing.fields &&
|
|
185
|
-
listing.
|
|
186
|
-
listing.
|
|
183
|
+
listing.fields.entityKey &&
|
|
184
|
+
listing.fields.entityKey !== ''
|
|
187
185
|
) {
|
|
188
|
-
const
|
|
189
|
-
const travelTime = fetchedEntities[
|
|
190
|
-
|
|
186
|
+
const entityKey = listing.fields.entityKey;
|
|
187
|
+
const travelTime = fetchedEntities[entityKey]?.travelTime;
|
|
191
188
|
if (travelTime !== undefined && listing.fields) {
|
|
192
189
|
listing.fields.travelTime = travelTime;
|
|
193
190
|
}
|
|
@@ -199,35 +196,35 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
|
|
|
199
196
|
}
|
|
200
197
|
|
|
201
198
|
fetchEntities();
|
|
202
|
-
}, [commuteLocation, allListings, siteConfig.companyId]);
|
|
199
|
+
}, [commuteLocation, allListings, siteConfig.companyId, getListingEntitiesCallback]);
|
|
203
200
|
|
|
204
201
|
useEffect(() => {
|
|
205
202
|
const handleFetchListings = async () => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
203
|
+
if (!(getStorageObject('listings', []) || []).length) {
|
|
204
|
+
setLoading(true);
|
|
205
|
+
}
|
|
209
206
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
207
|
+
try {
|
|
208
|
+
const {
|
|
209
|
+
listingsResult,
|
|
210
|
+
entitiesByKey,
|
|
211
|
+
distinctItems
|
|
212
|
+
} = await fetchListings(commuteLocation, entities, listings, getListingEntitiesCallback);
|
|
213
|
+
if (defaultFilters) {
|
|
214
|
+
const filteredListings = listingsResult.filter(listing => {
|
|
215
|
+
if (!listing.fields) return false;
|
|
219
216
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
});
|
|
217
|
+
return Object.keys(defaultFilters).every(filterKey => {
|
|
218
|
+
const filterValues = defaultFilters[filterKey as keyof typeof defaultFilters];
|
|
219
|
+
const listingValue = listing.fields ? listing.fields[filterKey as keyof typeof listing.fields] : null;
|
|
220
|
+
return filterValues.includes(listingValue);
|
|
225
221
|
});
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
222
|
+
});
|
|
223
|
+
setAllListings(filteredListings);
|
|
224
|
+
} else {
|
|
225
|
+
setAllListings(listingsResult);
|
|
226
|
+
}
|
|
227
|
+
setListingEntities(entitiesByKey);
|
|
231
228
|
setMapItems(distinctItems);
|
|
232
229
|
} catch (error) {
|
|
233
230
|
console.log(error);
|
|
@@ -6,7 +6,8 @@ import { ListingEntity } from '~/types/ListingEntity';
|
|
|
6
6
|
|
|
7
7
|
interface FetchListingsResult {
|
|
8
8
|
listingsResult: Listing[];
|
|
9
|
-
|
|
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,25 +15,25 @@ const fetchListings = async (
|
|
|
14
15
|
commuteLocation: any | null = null,
|
|
15
16
|
entities: ListingEntity[] | null,
|
|
16
17
|
listings: Listing[] | null,
|
|
17
|
-
getListingEntitiesCallback?: (
|
|
18
|
+
getListingEntitiesCallback?: (origin?: string) => Promise<ListingEntity[]>,
|
|
18
19
|
): Promise<FetchListingsResult> => {
|
|
19
20
|
try {
|
|
20
21
|
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
22
|
|
|
25
23
|
const fetchedEntities = !commuteLocation
|
|
26
|
-
? entities && entities.length > 0 ? entities : !getListingEntitiesCallback ? await getListingEntities(
|
|
24
|
+
? entities && entities.length > 0 ? entities : !getListingEntitiesCallback ? await getListingEntities() : await getListingEntitiesCallback()
|
|
27
25
|
: !getListingEntitiesCallback ? await getListingEntities(
|
|
28
|
-
|
|
26
|
+
|
|
29
27
|
`${commuteLocation.lat}, ${commuteLocation.lng}`
|
|
30
|
-
) : await getListingEntitiesCallback(
|
|
28
|
+
) : await getListingEntitiesCallback(
|
|
31
29
|
`${commuteLocation.lat}, ${commuteLocation.lng}`);
|
|
30
|
+
const entitiesByKey = fetchedEntities;
|
|
32
31
|
for (let i = 0; i < listingsResult.length; i++) {
|
|
33
32
|
const listing = listingsResult[i];
|
|
34
|
-
|
|
35
|
-
const entity =
|
|
33
|
+
if (listing.fields && listing.fields.entityKey && listing.fields.entityKey !== '' && listing.fields) {
|
|
34
|
+
const entity = entitiesByKey[listing.fields.entityKey];
|
|
35
|
+
console.log("Entity for listing with travel time", listing.fields.entityKey, entity);
|
|
36
|
+
|
|
36
37
|
if (entity) {
|
|
37
38
|
listing.fields.travelTime = entity.travelTime;
|
|
38
39
|
}
|
|
@@ -46,7 +47,7 @@ const fetchListings = async (
|
|
|
46
47
|
|
|
47
48
|
return {
|
|
48
49
|
listingsResult,
|
|
49
|
-
|
|
50
|
+
entitiesByKey,
|
|
50
51
|
distinctItems
|
|
51
52
|
};
|
|
52
53
|
} 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 (
|
|
3
|
+
export const getListingEntities = async (origin = ''): Promise<any> => {
|
|
5
4
|
try {
|
|
6
|
-
|
|
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
|
|
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);
|
|
@@ -2,9 +2,10 @@ export type ListingFields = {
|
|
|
2
2
|
posted?: string;
|
|
3
3
|
subTitle?: string;
|
|
4
4
|
education?: string;
|
|
5
|
-
|
|
5
|
+
title?: string;
|
|
6
6
|
category?: string;
|
|
7
|
-
|
|
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
|
}
|
package/src/types/Listings.ts
CHANGED
package/src/util/filterUtil.js
CHANGED
|
@@ -82,17 +82,17 @@ export const generateFilterOptions = (
|
|
|
82
82
|
if (fieldName === parentField && filterOptions?.filters) {
|
|
83
83
|
return filterOptions.filters.find(filter => filter.id === fieldName);
|
|
84
84
|
}
|
|
85
|
-
if(fieldName == '
|
|
85
|
+
if(fieldName == 'category'){
|
|
86
86
|
return {
|
|
87
87
|
id: fieldName,
|
|
88
88
|
title: siteConfig.fieldNames[fieldName],
|
|
89
89
|
items: getFilterOptions(allListings, allListings, fieldName)
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
|
-
if(fieldName == '
|
|
93
|
-
const
|
|
92
|
+
if(fieldName == 'subCategory' && selectedFilters.category){
|
|
93
|
+
const categoryKeys = Object.keys(selectedFilters.category);
|
|
94
94
|
const filteredListings = allListings.filter(
|
|
95
|
-
x =>
|
|
95
|
+
x => categoryKeys.includes(x.fields?.category)
|
|
96
96
|
);
|
|
97
97
|
return {
|
|
98
98
|
id: fieldName,
|
|
@@ -255,9 +255,9 @@ function searchResults(results, query) {
|
|
|
255
255
|
'fields.posted',
|
|
256
256
|
'fields.subtitle',
|
|
257
257
|
'fields.education',
|
|
258
|
-
'fields.
|
|
258
|
+
'fields.title',
|
|
259
259
|
'fields.category',
|
|
260
|
-
'fields.
|
|
260
|
+
'fields.subCategory',
|
|
261
261
|
'fields.shift',
|
|
262
262
|
'fields.citystate',
|
|
263
263
|
'fields.city',
|
package/src/util/mapUtil.js
CHANGED
|
@@ -1,54 +1,55 @@
|
|
|
1
|
-
export const getDistinctItemsByProximity = (items,
|
|
1
|
+
export const getDistinctItemsByProximity = (items, listingEntitiesDetailsInput) => {
|
|
2
2
|
const clusters = {};
|
|
3
3
|
|
|
4
|
-
if (!
|
|
4
|
+
if (!listingEntitiesDetailsInput) return [];
|
|
5
|
+
|
|
6
|
+
const listingEntitiesDetails = Array.isArray(listingEntitiesDetailsInput)
|
|
7
|
+
? listingEntitiesDetailsInput.reduce((acc, entity) => {
|
|
8
|
+
if (entity?.entityKey) acc[entity.entityKey] = entity;
|
|
9
|
+
return acc;
|
|
10
|
+
}, {})
|
|
11
|
+
: listingEntitiesDetailsInput;
|
|
5
12
|
|
|
6
13
|
const closeItemPairs = findCloseItems(listingEntitiesDetails);
|
|
7
14
|
if (closeItemPairs.length > 0) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
closeItemPairs
|
|
11
|
-
);
|
|
15
|
+
const adjusted = adjustItemPositions(listingEntitiesDetails, closeItemPairs);
|
|
16
|
+
Object.assign(listingEntitiesDetails, adjusted);
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
items?.forEach(item => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
20
|
+
const entityKey = item?.fields?.entityKey;
|
|
21
|
+
if (!entityKey || entityKey === '-1') return;
|
|
22
|
+
const entityDetails = listingEntitiesDetails[entityKey];
|
|
23
|
+
if (!entityDetails) {
|
|
24
|
+
console.error(`Details not found for entityKey: ${entityKey}`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
item.mapDetails = entityDetails;
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
if (!clusters[entityKey]) {
|
|
31
|
+
clusters[entityKey] = {
|
|
32
|
+
...entityDetails,
|
|
33
|
+
items: { [item.id]: item }
|
|
34
|
+
};
|
|
35
|
+
} else {
|
|
36
|
+
clusters[entityKey].items[item.id] = item;
|
|
37
|
+
}
|
|
34
38
|
});
|
|
35
39
|
|
|
36
40
|
return Object.values(clusters);
|
|
37
41
|
};
|
|
38
42
|
|
|
39
|
-
export const findCloseItems =
|
|
43
|
+
export const findCloseItems = entitiesByKey => {
|
|
40
44
|
const closeItems = [];
|
|
41
|
-
const items = Object.values(
|
|
45
|
+
const items = Object.values(entitiesByKey); // Convert object to array
|
|
42
46
|
const proximityThreshold = 0.0001;
|
|
43
47
|
|
|
44
48
|
for (let i = 0; i < items.length; i++) {
|
|
45
49
|
for (let j = i + 1; j < items.length; j++) {
|
|
46
50
|
const distanceLat = Math.abs(items[i].latitude - items[j].latitude);
|
|
47
51
|
const distanceLng = Math.abs(items[i].longitude - items[j].longitude);
|
|
48
|
-
if (
|
|
49
|
-
distanceLat < proximityThreshold &&
|
|
50
|
-
distanceLng < proximityThreshold
|
|
51
|
-
) {
|
|
52
|
+
if (distanceLat < proximityThreshold && distanceLng < proximityThreshold) {
|
|
52
53
|
closeItems.push({ item1: items[i], item2: items[j] });
|
|
53
54
|
}
|
|
54
55
|
}
|
|
@@ -57,14 +58,18 @@ export const findCloseItems = itemsObj => {
|
|
|
57
58
|
return closeItems;
|
|
58
59
|
};
|
|
59
60
|
|
|
60
|
-
export const adjustItemPositions = (
|
|
61
|
+
export const adjustItemPositions = (entitiesByKey, closeItemPairs) => {
|
|
61
62
|
const adjustmentValue = 0.0001;
|
|
62
|
-
const adjustedItems = { ...
|
|
63
|
+
const adjustedItems = { ...entitiesByKey };
|
|
63
64
|
|
|
64
65
|
closeItemPairs.forEach(pair => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
adjustedItems[
|
|
66
|
+
const key2 = pair.item2.entityKey;
|
|
67
|
+
if (adjustedItems[key2]) {
|
|
68
|
+
adjustedItems[key2] = {
|
|
69
|
+
...adjustedItems[key2],
|
|
70
|
+
latitude: adjustedItems[key2].latitude + adjustmentValue,
|
|
71
|
+
longitude: adjustedItems[key2].longitude + adjustmentValue
|
|
72
|
+
};
|
|
68
73
|
}
|
|
69
74
|
});
|
|
70
75
|
|
|
@@ -74,13 +79,15 @@ export const adjustItemPositions = (itemsObj, closeItemPairs) => {
|
|
|
74
79
|
export const clusterOptions = (clusterGridSize, fillColor) => {
|
|
75
80
|
return {
|
|
76
81
|
gridSize: clusterGridSize,
|
|
77
|
-
maxZoom:15,
|
|
78
|
-
styles:[
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
maxZoom: 15,
|
|
83
|
+
styles: [
|
|
84
|
+
{
|
|
85
|
+
url: createSvgDataUri(fillColor),
|
|
86
|
+
textColor: 'white',
|
|
87
|
+
height: 40,
|
|
88
|
+
width: 40
|
|
89
|
+
}
|
|
90
|
+
]
|
|
84
91
|
};
|
|
85
92
|
};
|
|
86
93
|
|