@abcagency/hc-ui-components 1.3.14 → 1.3.16
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/_virtual/_rollupPluginBabelHelpers.js +1 -1
- package/dist/apis/hcApi.js +1 -1
- package/dist/apis/hcApi.js.map +1 -1
- package/dist/clientToken.js.map +1 -1
- package/dist/components/HireControlMap.js +15 -5
- package/dist/components/HireControlMap.js.map +1 -1
- package/dist/components/modules/accordions/MapAccordionItem.js +11 -1
- package/dist/components/modules/accordions/MapAccordionItem.js.map +1 -1
- package/dist/components/modules/accordions/default.js.map +1 -1
- package/dist/components/modules/accordions/filterItem.js +2 -1
- package/dist/components/modules/accordions/filterItem.js.map +1 -1
- package/dist/components/modules/accordions/filters.js +0 -3
- package/dist/components/modules/accordions/filters.js.map +1 -1
- package/dist/components/modules/buttons/button-group-apply.js +36 -15
- package/dist/components/modules/buttons/button-group-apply.js.map +1 -1
- package/dist/components/modules/buttons/commute-pill.js.map +1 -1
- package/dist/components/modules/buttons/default.js.map +1 -1
- package/dist/components/modules/buttons/items-pill.js.map +1 -1
- package/dist/components/modules/buttons/pill-wrapper.js.map +1 -1
- package/dist/components/modules/buttons/show-all-button.js.map +1 -1
- package/dist/components/modules/cards/default.js.map +1 -1
- package/dist/components/modules/cards/filter.js.map +1 -1
- package/dist/components/modules/dialogs/apply-dialog.js.map +1 -1
- package/dist/components/modules/filter/commute.js +22 -6
- package/dist/components/modules/filter/commute.js.map +1 -1
- package/dist/components/modules/filter/index.js +7 -0
- package/dist/components/modules/filter/index.js.map +1 -1
- package/dist/components/modules/filter/item.js +16 -1
- package/dist/components/modules/filter/item.js.map +1 -1
- package/dist/components/modules/filter/location.js +1 -1
- package/dist/components/modules/filter/location.js.map +1 -1
- package/dist/components/modules/filter/points-of-interest.js.map +1 -1
- package/dist/components/modules/filter/radio-item.js +7 -0
- package/dist/components/modules/filter/radio-item.js.map +1 -1
- package/dist/components/modules/filter/search.js.map +1 -1
- package/dist/components/modules/filter/sort.js.map +1 -1
- package/dist/components/modules/grid.js.map +1 -1
- package/dist/components/modules/icon.js.map +1 -1
- package/dist/components/modules/jobListing/listing-details.js +6 -0
- package/dist/components/modules/jobListing/listing-details.js.map +1 -1
- package/dist/components/modules/maps/info-window-card.js.map +1 -1
- package/dist/components/modules/maps/info-window-content.js +20 -0
- package/dist/components/modules/maps/info-window-content.js.map +1 -1
- package/dist/components/modules/maps/list/field-mapper.js.map +1 -1
- package/dist/components/modules/maps/list/header-item.js.map +1 -1
- package/dist/components/modules/maps/list/header.js.map +1 -1
- package/dist/components/modules/maps/list/index.js +21 -12
- package/dist/components/modules/maps/list/index.js.map +1 -1
- package/dist/components/modules/maps/list/item-expand-card/index.js.map +1 -1
- package/dist/components/modules/maps/list/item-expand-card/recruiter-contact-nav.js.map +1 -1
- package/dist/components/modules/maps/list/item-expand-card/recruiter-details.js.map +1 -1
- package/dist/components/modules/maps/list/item-expand-card/recruiter-headshot.js.map +1 -1
- package/dist/components/modules/maps/list/list-item/index.js +12 -2
- package/dist/components/modules/maps/list/list-item/index.js.map +1 -1
- package/dist/components/modules/maps/map-list.js.map +1 -1
- package/dist/components/modules/maps/map-marker.js +10 -0
- package/dist/components/modules/maps/map-marker.js.map +1 -1
- package/dist/components/modules/maps/map.js.map +1 -1
- package/dist/components/modules/maps/place-marker.js.map +1 -1
- package/dist/components/modules/maps/tabs.js.map +1 -1
- package/dist/constants/eventTypes.js +16 -0
- package/dist/constants/eventTypes.js.map +1 -0
- package/dist/constants/placeTypes.js.map +1 -1
- package/dist/contexts/mapContext.js +9 -27
- package/dist/contexts/mapContext.js.map +1 -1
- package/dist/contexts/mapListContext.js +57 -38
- package/dist/contexts/mapListContext.js.map +1 -1
- package/dist/contexts/placesContext.js.map +1 -1
- package/dist/contexts/trackEventContext.js +20 -0
- package/dist/contexts/trackEventContext.js.map +1 -0
- package/dist/hooks/useList.js +1 -13
- package/dist/hooks/useList.js.map +1 -1
- package/dist/services/apis/hcApi.js +1 -1
- package/dist/services/apis/hcApi.js.map +1 -1
- package/dist/services/clientToken.js.map +1 -1
- package/dist/services/configService.js.map +1 -1
- package/dist/services/googlePlacesNearbyService.js.map +1 -1
- package/dist/services/listingAggregatorService.js +43 -16
- package/dist/services/listingAggregatorService.js.map +1 -1
- package/dist/services/listingEntityService.js.map +1 -1
- package/dist/services/listingService.js.map +1 -1
- package/dist/services/recruiterService.js.map +1 -1
- package/dist/util/filterUtil.js.map +1 -1
- package/dist/util/loading.js.map +1 -1
- package/dist/util/localStorageUtil.js.map +1 -1
- package/dist/util/mapIconUtil.js.map +1 -1
- package/dist/util/mapUtil.js.map +1 -1
- package/dist/util/sortUtil.js.map +1 -1
- package/dist/util/stringUtils.js.map +1 -1
- package/jsconfig.json +7 -7
- package/package.json +60 -60
- package/postcss.config.js +13 -13
- package/preset.default.js +15 -15
- package/rollup.config.mjs +88 -87
- package/src/apis/hcApi.js +93 -93
- package/src/clientToken.js +9 -9
- package/src/components/HireControlMap.js +129 -124
- package/src/components/modules/accordions/MapAccordionItem.js +74 -72
- package/src/components/modules/accordions/default.js +171 -171
- package/src/components/modules/accordions/filterItem.js +55 -53
- package/src/components/modules/accordions/filters.js +47 -47
- package/src/components/modules/buttons/button-group-apply.js +123 -116
- package/src/components/modules/buttons/commute-pill.js +22 -22
- package/src/components/modules/buttons/default.js +194 -194
- package/src/components/modules/buttons/items-pill.js +35 -35
- package/src/components/modules/buttons/pill-wrapper.js +27 -27
- package/src/components/modules/buttons/show-all-button.js +20 -20
- package/src/components/modules/cards/default.js +167 -167
- package/src/components/modules/cards/filter.js +56 -56
- package/src/components/modules/dialogs/apply-dialog.js +48 -48
- package/src/components/modules/filter/commute.js +154 -149
- package/src/components/modules/filter/index.js +89 -87
- package/src/components/modules/filter/item.js +87 -76
- package/src/components/modules/filter/location.js +71 -71
- package/src/components/modules/filter/points-of-interest.js +44 -44
- package/src/components/modules/filter/radio-item.js +57 -53
- package/src/components/modules/filter/search.js +92 -92
- package/src/components/modules/filter/sort.js +83 -83
- package/src/components/modules/grid.js +54 -54
- package/src/components/modules/icon.js +33 -33
- package/src/components/modules/jobListing/listing-details.js +99 -95
- package/src/components/modules/maps/info-window-card.js +17 -17
- package/src/components/modules/maps/info-window-content.js +81 -74
- package/src/components/modules/maps/list/field-mapper.js +112 -112
- package/src/components/modules/maps/list/header-item.js +91 -91
- package/src/components/modules/maps/list/header.js +47 -47
- package/src/components/modules/maps/list/index.js +112 -107
- package/src/components/modules/maps/list/item-expand-card/index.js +22 -22
- package/src/components/modules/maps/list/item-expand-card/recruiter-contact-nav.js +50 -50
- package/src/components/modules/maps/list/item-expand-card/recruiter-details.js +68 -68
- package/src/components/modules/maps/list/item-expand-card/recruiter-headshot.js +22 -22
- package/src/components/modules/maps/list/list-item/index.js +135 -133
- package/src/components/modules/maps/map-list.js +74 -74
- package/src/components/modules/maps/map-marker.js +88 -86
- package/src/components/modules/maps/map.js +230 -230
- package/src/components/modules/maps/place-marker.js +41 -41
- package/src/components/modules/maps/tabs.js +81 -81
- package/src/constants/eventTypes.js +13 -0
- package/src/constants/placeTypes.js +8 -8
- package/src/contexts/mapContext.js +101 -115
- package/src/contexts/mapListContext.js +242 -222
- package/src/contexts/placesContext.js +102 -102
- package/src/contexts/trackEventContext.js +14 -0
- package/src/hooks/useList.js +89 -100
- package/src/index.js +3 -3
- package/src/services/configService.js +16 -16
- package/src/services/googlePlacesNearbyService.js +33 -33
- package/src/services/listingAggregatorService.js +50 -45
- package/src/services/listingEntityService.js +15 -15
- package/src/services/listingService.js +26 -26
- package/src/services/recruiterService.js +17 -17
- package/src/styles/index.css +23 -23
- package/src/util/arrayUtil.js +3 -3
- package/src/util/fieldMapper.js +22 -22
- package/src/util/filterUtil.js +195 -195
- package/src/util/loading.js +17 -17
- package/src/util/localStorageUtil.js +26 -26
- package/src/util/mapIconUtil.js +180 -180
- package/src/util/mapUtil.js +91 -91
- package/src/util/sortUtil.js +32 -32
- package/src/util/stringUtils.js +6 -6
- package/src/util/urlFilterUtil.js +90 -90
- package/tailwind.config.js +126 -126
- package/.editorconfig +0 -12
- package/.eslintrc +0 -105
- package/.prettierignore +0 -3
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import api from '~/apis/hcApi';
|
|
2
|
-
|
|
3
|
-
export const getListings = async () => {
|
|
4
|
-
try {
|
|
5
|
-
const response = await api.get(`/Listings`);
|
|
6
|
-
return response;
|
|
7
|
-
} catch (error) {
|
|
8
|
-
console.error(error);
|
|
9
|
-
throw error;
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const getListingDetails = async listingId => {
|
|
14
|
-
try {
|
|
15
|
-
const response = await api.get(`/ListingDetails/${listingId}`);
|
|
16
|
-
return response;
|
|
17
|
-
} catch (error) {
|
|
18
|
-
console.error(error);
|
|
19
|
-
throw error;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export default {
|
|
24
|
-
getListings,
|
|
25
|
-
getListingDetails
|
|
26
|
-
};
|
|
1
|
+
import api from '~/apis/hcApi';
|
|
2
|
+
|
|
3
|
+
export const getListings = async () => {
|
|
4
|
+
try {
|
|
5
|
+
const response = await api.get(`/Listings`);
|
|
6
|
+
return response;
|
|
7
|
+
} catch (error) {
|
|
8
|
+
console.error(error);
|
|
9
|
+
throw error;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const getListingDetails = async listingId => {
|
|
14
|
+
try {
|
|
15
|
+
const response = await api.get(`/ListingDetails/${listingId}`);
|
|
16
|
+
return response;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error(error);
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default {
|
|
24
|
+
getListings,
|
|
25
|
+
getListingDetails
|
|
26
|
+
};
|
|
@@ -1,17 +1,17 @@
|
|
|
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
|
+
|
|
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
|
+
};
|
package/src/styles/index.css
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
/* @layer base {
|
|
6
|
-
html {
|
|
7
|
-
@apply hc-text-400 hc-text-uiText [scroll-behavior:smooth];
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
@layer components {
|
|
12
|
-
.track * {
|
|
13
|
-
@apply hc-pointer-events-none;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.stretched-link::after {
|
|
17
|
-
@apply hc-content-[''] hc-absolute hc-inset-0 z-[1] hc-pointer-events-auto hc-bg-transparent;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
.fit-content{
|
|
22
|
-
height:fit-content;
|
|
23
|
-
} */
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
/* @layer base {
|
|
6
|
+
html {
|
|
7
|
+
@apply hc-text-400 hc-text-uiText [scroll-behavior:smooth];
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@layer components {
|
|
12
|
+
.track * {
|
|
13
|
+
@apply hc-pointer-events-none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.stretched-link::after {
|
|
17
|
+
@apply hc-content-[''] hc-absolute hc-inset-0 z-[1] hc-pointer-events-auto hc-bg-transparent;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.fit-content{
|
|
22
|
+
height:fit-content;
|
|
23
|
+
} */
|
package/src/util/arrayUtil.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export const onlyUnique = (value, index, array) => {
|
|
2
|
-
return array.indexOf(value) === index;
|
|
3
|
-
};
|
|
1
|
+
export const onlyUnique = (value, index, array) => {
|
|
2
|
+
return array.indexOf(value) === index;
|
|
3
|
+
};
|
package/src/util/fieldMapper.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import Grid from '~/components/modules/grid';
|
|
4
|
-
|
|
5
|
-
import { capitalize } from '~/util/stringUtils';
|
|
6
|
-
|
|
7
|
-
const mapFieldsToGridItems = (item, fieldsShown) => {
|
|
8
|
-
const orderedFields = fieldsShown.filter(field => field in item.fields);
|
|
9
|
-
|
|
10
|
-
return orderedFields.map(field => {
|
|
11
|
-
let value = item.fields[field];
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<Grid.Item key={field}>
|
|
15
|
-
<span className="hc-sr-only">{capitalize(field)}</span>
|
|
16
|
-
{value}
|
|
17
|
-
</Grid.Item>
|
|
18
|
-
);
|
|
19
|
-
});
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export default mapFieldsToGridItems;
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import Grid from '~/components/modules/grid';
|
|
4
|
+
|
|
5
|
+
import { capitalize } from '~/util/stringUtils';
|
|
6
|
+
|
|
7
|
+
const mapFieldsToGridItems = (item, fieldsShown) => {
|
|
8
|
+
const orderedFields = fieldsShown.filter(field => field in item.fields);
|
|
9
|
+
|
|
10
|
+
return orderedFields.map(field => {
|
|
11
|
+
let value = item.fields[field];
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<Grid.Item key={field}>
|
|
15
|
+
<span className="hc-sr-only">{capitalize(field)}</span>
|
|
16
|
+
{value}
|
|
17
|
+
</Grid.Item>
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default mapFieldsToGridItems;
|
package/src/util/filterUtil.js
CHANGED
|
@@ -1,195 +1,195 @@
|
|
|
1
|
-
import { getDistinctItemsByProximity } from '~/util/mapUtil';
|
|
2
|
-
|
|
3
|
-
export const getFilterOptions = (listings, filteredListings, field, excludeZeroCount = null) => {
|
|
4
|
-
const options = new Set();
|
|
5
|
-
listings.forEach(listing => {
|
|
6
|
-
if (listing.fields[field]) {
|
|
7
|
-
options.add(listing.fields[field]);
|
|
8
|
-
}
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
const optionCounts = {};
|
|
12
|
-
options.forEach(option => {
|
|
13
|
-
optionCounts[option] = 0;
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
filteredListings.forEach(listing => {
|
|
17
|
-
const value = listing.fields[field];
|
|
18
|
-
if (value && optionCounts.hasOwnProperty(value)) {
|
|
19
|
-
optionCounts[value] += 1;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
return Array.from(options)
|
|
24
|
-
.sort()
|
|
25
|
-
.map(option => ({
|
|
26
|
-
name: option,
|
|
27
|
-
count: optionCounts[option] || 0
|
|
28
|
-
}))
|
|
29
|
-
.filter(option => !(excludeZeroCount === true && option.count === 0));
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export const getSpecialFeatureOptions = (listings, filteredListings, siteConfig, favorites) => {
|
|
33
|
-
const specialFeatures = siteConfig.specialFeatures;
|
|
34
|
-
const featureCounts = Object.keys(specialFeatures).sort().reduce((acc, key) => {
|
|
35
|
-
acc[specialFeatures[key]] = 0;
|
|
36
|
-
return acc;
|
|
37
|
-
}, {});
|
|
38
|
-
|
|
39
|
-
filteredListings.forEach(listing => {
|
|
40
|
-
Object.entries(specialFeatures).forEach(([featureKey, featureName]) => {
|
|
41
|
-
if (listing.fields[featureKey] === 1) {
|
|
42
|
-
featureCounts[featureName] += 1;
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const specialFeatureOptions = Object.entries(featureCounts).map(([name, count]) => ({
|
|
48
|
-
name,
|
|
49
|
-
count
|
|
50
|
-
}));
|
|
51
|
-
|
|
52
|
-
for (let option of specialFeatureOptions) {
|
|
53
|
-
if (option.name === 'Favorite') {
|
|
54
|
-
option.count = filteredListings.filter(x => favorites.includes(x.id)).length;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return specialFeatureOptions;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const getPointsOfInterestOptions = pointsOfInterestNames => {
|
|
62
|
-
return Object.entries(pointsOfInterestNames).sort().map(([key, name]) => ({
|
|
63
|
-
key,
|
|
64
|
-
name
|
|
65
|
-
}));
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
export const generateFilterOptions = (
|
|
69
|
-
filteredListings,
|
|
70
|
-
allListings,
|
|
71
|
-
siteConfig,
|
|
72
|
-
filterOptions,
|
|
73
|
-
parentField = null,
|
|
74
|
-
favorites
|
|
75
|
-
) => {
|
|
76
|
-
if (allListings.length > 0) {
|
|
77
|
-
const dynamicFilters = siteConfig.fieldFiltersShown.map(fieldName => {
|
|
78
|
-
if (fieldName === parentField && filterOptions?.filters) {
|
|
79
|
-
return filterOptions.filters.find(filter => filter.id === fieldName);
|
|
80
|
-
}
|
|
81
|
-
if (fieldName == "specialFeatures") {
|
|
82
|
-
return {
|
|
83
|
-
id: fieldName,
|
|
84
|
-
title: siteConfig.fieldNames[fieldName],
|
|
85
|
-
items: getSpecialFeatureOptions(allListings, filteredListings, siteConfig, favorites).sort()
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
id: fieldName,
|
|
90
|
-
title: siteConfig.fieldNames[fieldName],
|
|
91
|
-
items: getFilterOptions(allListings, filteredListings, fieldName)
|
|
92
|
-
};
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
const locations =
|
|
96
|
-
siteConfig.locationFiltersShown.map((fieldName, index) => {
|
|
97
|
-
if (index === 0 && filterOptions?.locations) {
|
|
98
|
-
return filterOptions.locations.find(filter => filter.id === fieldName);
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
id: fieldName,
|
|
102
|
-
title: siteConfig.fieldNames[fieldName],
|
|
103
|
-
items: getFilterOptions(allListings, filteredListings, fieldName, true)
|
|
104
|
-
};
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const pointsOfInterest = {
|
|
108
|
-
id: "pointsOfInterest",
|
|
109
|
-
title: siteConfig.pointsOfInterestConfig.title,
|
|
110
|
-
items: getPointsOfInterestOptions(
|
|
111
|
-
siteConfig.pointsOfInterestConfig.pointsOfInterestNames
|
|
112
|
-
)
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
return {
|
|
116
|
-
filters: dynamicFilters,
|
|
117
|
-
locations: locations,
|
|
118
|
-
pointsOfInterest: pointsOfInterest
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return null;
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
export const applyFilters = (
|
|
126
|
-
allListings,
|
|
127
|
-
selectedFilters,
|
|
128
|
-
query,
|
|
129
|
-
listingEntities,
|
|
130
|
-
favorites,
|
|
131
|
-
siteConfig
|
|
132
|
-
) => {
|
|
133
|
-
let results = allListings;
|
|
134
|
-
let invertedSpecialFeaturesMap;
|
|
135
|
-
if (siteConfig.specialFeatures) {
|
|
136
|
-
invertedSpecialFeaturesMap = Object.entries(siteConfig.specialFeatures).reduce((acc, [key, value]) => {
|
|
137
|
-
acc[value] = key;
|
|
138
|
-
return acc;
|
|
139
|
-
}, {});
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
const hasFavorite = !!selectedFilters.specialFeatures && !!selectedFilters.specialFeatures.Favorite;
|
|
143
|
-
|
|
144
|
-
if (hasFavorite && selectedFilters.specialFeatures.Favorite == true) {
|
|
145
|
-
results = results.filter(x => favorites.includes(x.id));
|
|
146
|
-
}
|
|
147
|
-
var favorite;
|
|
148
|
-
if (hasFavorite) {
|
|
149
|
-
favorite = selectedFilters.specialFeatures.Favorite;
|
|
150
|
-
delete selectedFilters.specialFeatures.Favorite;
|
|
151
|
-
}
|
|
152
|
-
for (const [field, filterItems] of Object.entries(selectedFilters)) {
|
|
153
|
-
const formattedField = field;
|
|
154
|
-
if (field === "pointsOfInterest") continue;
|
|
155
|
-
if (field === "specialFeatures" && invertedSpecialFeaturesMap && Object.keys(filterItems).length > 0) {
|
|
156
|
-
results = results.filter(listing => {
|
|
157
|
-
return Object.entries(filterItems).some(([filterName, filterValue]) => {
|
|
158
|
-
const listingFieldName = invertedSpecialFeaturesMap[filterName];
|
|
159
|
-
return filterValue && listing.fields[listingFieldName] === 1;
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
} else if (Object.keys(filterItems).length > 0) {
|
|
163
|
-
results = results.filter(listing =>
|
|
164
|
-
filterItems.hasOwnProperty(listing.fields[formattedField])
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
if (query) {
|
|
169
|
-
results = results.filter(listing =>
|
|
170
|
-
Object.values(listing.fields)?.some(value =>
|
|
171
|
-
value?.toString().toLowerCase().includes(query.toLowerCase())
|
|
172
|
-
)
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
const distinctItems = getDistinctItemsByProximity(results, listingEntities);
|
|
176
|
-
if (hasFavorite) {
|
|
177
|
-
selectedFilters.specialFeatures.Favorite = favorite;
|
|
178
|
-
}
|
|
179
|
-
return { filteredListings: results, mapItems: distinctItems };
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
export const filterListingsByLocation = (
|
|
183
|
-
allListings,
|
|
184
|
-
selectedLocation,
|
|
185
|
-
listingEntities
|
|
186
|
-
) => {
|
|
187
|
-
let results = allListings;
|
|
188
|
-
if (selectedLocation !== null) {
|
|
189
|
-
results = results.filter(item =>
|
|
190
|
-
selectedLocation.items.hasOwnProperty(item.id)
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
const mapItems = getDistinctItemsByProximity(results, listingEntities);
|
|
194
|
-
return { filteredListings: results, mapItems: mapItems };
|
|
195
|
-
};
|
|
1
|
+
import { getDistinctItemsByProximity } from '~/util/mapUtil';
|
|
2
|
+
|
|
3
|
+
export const getFilterOptions = (listings, filteredListings, field, excludeZeroCount = null) => {
|
|
4
|
+
const options = new Set();
|
|
5
|
+
listings.forEach(listing => {
|
|
6
|
+
if (listing.fields[field]) {
|
|
7
|
+
options.add(listing.fields[field]);
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const optionCounts = {};
|
|
12
|
+
options.forEach(option => {
|
|
13
|
+
optionCounts[option] = 0;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
filteredListings.forEach(listing => {
|
|
17
|
+
const value = listing.fields[field];
|
|
18
|
+
if (value && optionCounts.hasOwnProperty(value)) {
|
|
19
|
+
optionCounts[value] += 1;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return Array.from(options)
|
|
24
|
+
.sort()
|
|
25
|
+
.map(option => ({
|
|
26
|
+
name: option,
|
|
27
|
+
count: optionCounts[option] || 0
|
|
28
|
+
}))
|
|
29
|
+
.filter(option => !(excludeZeroCount === true && option.count === 0));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const getSpecialFeatureOptions = (listings, filteredListings, siteConfig, favorites) => {
|
|
33
|
+
const specialFeatures = siteConfig.specialFeatures;
|
|
34
|
+
const featureCounts = Object.keys(specialFeatures).sort().reduce((acc, key) => {
|
|
35
|
+
acc[specialFeatures[key]] = 0;
|
|
36
|
+
return acc;
|
|
37
|
+
}, {});
|
|
38
|
+
|
|
39
|
+
filteredListings.forEach(listing => {
|
|
40
|
+
Object.entries(specialFeatures).forEach(([featureKey, featureName]) => {
|
|
41
|
+
if (listing.fields[featureKey] === 1) {
|
|
42
|
+
featureCounts[featureName] += 1;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const specialFeatureOptions = Object.entries(featureCounts).map(([name, count]) => ({
|
|
48
|
+
name,
|
|
49
|
+
count
|
|
50
|
+
}));
|
|
51
|
+
|
|
52
|
+
for (let option of specialFeatureOptions) {
|
|
53
|
+
if (option.name === 'Favorite') {
|
|
54
|
+
option.count = filteredListings.filter(x => favorites.includes(x.id)).length;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return specialFeatureOptions;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const getPointsOfInterestOptions = pointsOfInterestNames => {
|
|
62
|
+
return Object.entries(pointsOfInterestNames).sort().map(([key, name]) => ({
|
|
63
|
+
key,
|
|
64
|
+
name
|
|
65
|
+
}));
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const generateFilterOptions = (
|
|
69
|
+
filteredListings,
|
|
70
|
+
allListings,
|
|
71
|
+
siteConfig,
|
|
72
|
+
filterOptions,
|
|
73
|
+
parentField = null,
|
|
74
|
+
favorites
|
|
75
|
+
) => {
|
|
76
|
+
if (allListings.length > 0) {
|
|
77
|
+
const dynamicFilters = siteConfig.fieldFiltersShown.map(fieldName => {
|
|
78
|
+
if (fieldName === parentField && filterOptions?.filters) {
|
|
79
|
+
return filterOptions.filters.find(filter => filter.id === fieldName);
|
|
80
|
+
}
|
|
81
|
+
if (fieldName == "specialFeatures") {
|
|
82
|
+
return {
|
|
83
|
+
id: fieldName,
|
|
84
|
+
title: siteConfig.fieldNames[fieldName],
|
|
85
|
+
items: getSpecialFeatureOptions(allListings, filteredListings, siteConfig, favorites).sort()
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
id: fieldName,
|
|
90
|
+
title: siteConfig.fieldNames[fieldName],
|
|
91
|
+
items: getFilterOptions(allListings, filteredListings, fieldName)
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const locations =
|
|
96
|
+
siteConfig.locationFiltersShown.map((fieldName, index) => {
|
|
97
|
+
if (index === 0 && filterOptions?.locations) {
|
|
98
|
+
return filterOptions.locations.find(filter => filter.id === fieldName);
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
id: fieldName,
|
|
102
|
+
title: siteConfig.fieldNames[fieldName],
|
|
103
|
+
items: getFilterOptions(allListings, filteredListings, fieldName, true)
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const pointsOfInterest = {
|
|
108
|
+
id: "pointsOfInterest",
|
|
109
|
+
title: siteConfig.pointsOfInterestConfig.title,
|
|
110
|
+
items: getPointsOfInterestOptions(
|
|
111
|
+
siteConfig.pointsOfInterestConfig.pointsOfInterestNames
|
|
112
|
+
)
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
filters: dynamicFilters,
|
|
117
|
+
locations: locations,
|
|
118
|
+
pointsOfInterest: pointsOfInterest
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return null;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export const applyFilters = (
|
|
126
|
+
allListings,
|
|
127
|
+
selectedFilters,
|
|
128
|
+
query,
|
|
129
|
+
listingEntities,
|
|
130
|
+
favorites,
|
|
131
|
+
siteConfig
|
|
132
|
+
) => {
|
|
133
|
+
let results = allListings;
|
|
134
|
+
let invertedSpecialFeaturesMap;
|
|
135
|
+
if (siteConfig.specialFeatures) {
|
|
136
|
+
invertedSpecialFeaturesMap = Object.entries(siteConfig.specialFeatures).reduce((acc, [key, value]) => {
|
|
137
|
+
acc[value] = key;
|
|
138
|
+
return acc;
|
|
139
|
+
}, {});
|
|
140
|
+
|
|
141
|
+
}
|
|
142
|
+
const hasFavorite = !!selectedFilters.specialFeatures && !!selectedFilters.specialFeatures.Favorite;
|
|
143
|
+
|
|
144
|
+
if (hasFavorite && selectedFilters.specialFeatures.Favorite == true) {
|
|
145
|
+
results = results.filter(x => favorites.includes(x.id));
|
|
146
|
+
}
|
|
147
|
+
var favorite;
|
|
148
|
+
if (hasFavorite) {
|
|
149
|
+
favorite = selectedFilters.specialFeatures.Favorite;
|
|
150
|
+
delete selectedFilters.specialFeatures.Favorite;
|
|
151
|
+
}
|
|
152
|
+
for (const [field, filterItems] of Object.entries(selectedFilters)) {
|
|
153
|
+
const formattedField = field;
|
|
154
|
+
if (field === "pointsOfInterest") continue;
|
|
155
|
+
if (field === "specialFeatures" && invertedSpecialFeaturesMap && Object.keys(filterItems).length > 0) {
|
|
156
|
+
results = results.filter(listing => {
|
|
157
|
+
return Object.entries(filterItems).some(([filterName, filterValue]) => {
|
|
158
|
+
const listingFieldName = invertedSpecialFeaturesMap[filterName];
|
|
159
|
+
return filterValue && listing.fields[listingFieldName] === 1;
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
} else if (Object.keys(filterItems).length > 0) {
|
|
163
|
+
results = results.filter(listing =>
|
|
164
|
+
filterItems.hasOwnProperty(listing.fields[formattedField])
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (query) {
|
|
169
|
+
results = results.filter(listing =>
|
|
170
|
+
Object.values(listing.fields)?.some(value =>
|
|
171
|
+
value?.toString().toLowerCase().includes(query.toLowerCase())
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
const distinctItems = getDistinctItemsByProximity(results, listingEntities);
|
|
176
|
+
if (hasFavorite) {
|
|
177
|
+
selectedFilters.specialFeatures.Favorite = favorite;
|
|
178
|
+
}
|
|
179
|
+
return { filteredListings: results, mapItems: distinctItems };
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export const filterListingsByLocation = (
|
|
183
|
+
allListings,
|
|
184
|
+
selectedLocation,
|
|
185
|
+
listingEntities
|
|
186
|
+
) => {
|
|
187
|
+
let results = allListings;
|
|
188
|
+
if (selectedLocation !== null) {
|
|
189
|
+
results = results.filter(item =>
|
|
190
|
+
selectedLocation.items.hasOwnProperty(item.id)
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
const mapItems = getDistinctItemsByProximity(results, listingEntities);
|
|
194
|
+
return { filteredListings: results, mapItems: mapItems };
|
|
195
|
+
};
|
package/src/util/loading.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import Icon from '~/components/modules/icon';
|
|
3
|
-
|
|
4
|
-
const Loading = () => {
|
|
5
|
-
return (
|
|
6
|
-
<div className="hc-flex hc-items-center hc-justify-center hc-w-full hc-h-full">
|
|
7
|
-
<Icon
|
|
8
|
-
icon="ph:spinner"
|
|
9
|
-
className="hc-animate-spin hc-text-gray-300"
|
|
10
|
-
width="40"
|
|
11
|
-
height="40"
|
|
12
|
-
/>
|
|
13
|
-
</div>
|
|
14
|
-
);
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export default Loading;
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Icon from '~/components/modules/icon';
|
|
3
|
+
|
|
4
|
+
const Loading = () => {
|
|
5
|
+
return (
|
|
6
|
+
<div className="hc-flex hc-items-center hc-justify-center hc-w-full hc-h-full">
|
|
7
|
+
<Icon
|
|
8
|
+
icon="ph:spinner"
|
|
9
|
+
className="hc-animate-spin hc-text-gray-300"
|
|
10
|
+
width="40"
|
|
11
|
+
height="40"
|
|
12
|
+
/>
|
|
13
|
+
</div>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default Loading;
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
export const getStorageObject = (item, defaultItem = null) =>{
|
|
2
|
-
if(typeof window == 'undefined') return defaultItem;
|
|
3
|
-
if(localStorage.getItem(item) == null) return defaultItem;
|
|
4
|
-
if(localStorage.getItem(item) == 'undefined'){
|
|
5
|
-
localStorage.removeItem(item);
|
|
6
|
-
}
|
|
7
|
-
return JSON.parse(localStorage.getItem(item)) ?? defaultItem;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const getStorageItem = (item, defaultItem = null) =>{
|
|
11
|
-
if(typeof window == 'undefined') return defaultItem;
|
|
12
|
-
if(localStorage.getItem(item) == null) return defaultItem;
|
|
13
|
-
if(localStorage.getItem(item) == 'undefined'){
|
|
14
|
-
localStorage.removeItem(item);
|
|
15
|
-
}
|
|
16
|
-
return localStorage.getItem(item) ?? defaultItem;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const setStorageObject = (key, item) =>{
|
|
20
|
-
if(typeof window == 'undefined') return;
|
|
21
|
-
if(item == undefined)return;
|
|
22
|
-
try{
|
|
23
|
-
localStorage.setItem(key, JSON.stringify(item));
|
|
24
|
-
}catch(err){
|
|
25
|
-
console.log(err);
|
|
26
|
-
}
|
|
1
|
+
export const getStorageObject = (item, defaultItem = null) =>{
|
|
2
|
+
if(typeof window == 'undefined') return defaultItem;
|
|
3
|
+
if(localStorage.getItem(item) == null) return defaultItem;
|
|
4
|
+
if(localStorage.getItem(item) == 'undefined'){
|
|
5
|
+
localStorage.removeItem(item);
|
|
6
|
+
}
|
|
7
|
+
return JSON.parse(localStorage.getItem(item)) ?? defaultItem;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const getStorageItem = (item, defaultItem = null) =>{
|
|
11
|
+
if(typeof window == 'undefined') return defaultItem;
|
|
12
|
+
if(localStorage.getItem(item) == null) return defaultItem;
|
|
13
|
+
if(localStorage.getItem(item) == 'undefined'){
|
|
14
|
+
localStorage.removeItem(item);
|
|
15
|
+
}
|
|
16
|
+
return localStorage.getItem(item) ?? defaultItem;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const setStorageObject = (key, item) =>{
|
|
20
|
+
if(typeof window == 'undefined') return;
|
|
21
|
+
if(item == undefined)return;
|
|
22
|
+
try{
|
|
23
|
+
localStorage.setItem(key, JSON.stringify(item));
|
|
24
|
+
}catch(err){
|
|
25
|
+
console.log(err);
|
|
26
|
+
}
|
|
27
27
|
};
|