@abcagency/hc-ui-components 1.3.16 → 1.3.18
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/components/modules/filter/search.js +4 -4
- package/dist/components/modules/filter/search.js.map +1 -1
- package/dist/components/modules/maps/list/list-item/index.js.map +1 -1
- package/dist/constants/eventTypes.js +1 -1
- package/dist/constants/eventTypes.js.map +1 -1
- package/dist/contexts/mapListContext.js +4 -1
- package/dist/contexts/mapListContext.js.map +1 -1
- package/dist/services/apis/hcApi.js +1 -1
- package/dist/services/apis/hcApi.js.map +1 -1
- package/dist/util/filterUtil.js +33 -7
- package/dist/util/filterUtil.js.map +1 -1
- package/package.json +62 -60
- package/src/components/modules/filter/search.js +93 -92
- package/src/components/modules/maps/list/list-item/index.js +135 -135
- package/src/constants/eventTypes.js +13 -13
- package/src/contexts/mapListContext.js +242 -242
- package/src/util/filterUtil.js +239 -195
package/package.json
CHANGED
|
@@ -1,60 +1,62 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@abcagency/hc-ui-components",
|
|
3
|
-
"version": "1.3.
|
|
4
|
-
"description": "UI Components for HireControl",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"build": "cross-env NODE_ENV=production rollup -c",
|
|
8
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
-
},
|
|
10
|
-
"keywords": [
|
|
11
|
-
"hirecontrol",
|
|
12
|
-
"ui",
|
|
13
|
-
"components"
|
|
14
|
-
],
|
|
15
|
-
"author": "Aloysius Butler & Clark",
|
|
16
|
-
"license": "ISC",
|
|
17
|
-
"peerDependencies": {
|
|
18
|
-
"@react-google-maps/api": "^2.0.0",
|
|
19
|
-
"@radix-ui/react-accordion": "^1.1.2",
|
|
20
|
-
"@radix-ui/react-dialog": "^1.0.5",
|
|
21
|
-
"@radix-ui/react-select": "^2.0.0",
|
|
22
|
-
"@radix-ui/react-tabs": "^1.0.4",
|
|
23
|
-
"@iconify/react": "^1.0.0",
|
|
24
|
-
"@headlessui/react": "^1.0.0",
|
|
25
|
-
"use-places-autocomplete": "^1.0.0"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"eslint
|
|
31
|
-
"eslint-
|
|
32
|
-
"eslint-plugin-
|
|
33
|
-
"eslint-plugin-
|
|
34
|
-
"eslint-plugin-
|
|
35
|
-
"eslint-plugin-react
|
|
36
|
-
"
|
|
37
|
-
"@babel/
|
|
38
|
-
"@babel/
|
|
39
|
-
"@babel/
|
|
40
|
-
"@babel/preset-
|
|
41
|
-
"@
|
|
42
|
-
"@rollup/plugin-
|
|
43
|
-
"@rollup/plugin-
|
|
44
|
-
"@rollup/plugin-
|
|
45
|
-
"@rollup/plugin-
|
|
46
|
-
"@
|
|
47
|
-
"@
|
|
48
|
-
"@tailwindcss/
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"postcss
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"rollup
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@abcagency/hc-ui-components",
|
|
3
|
+
"version": "1.3.18",
|
|
4
|
+
"description": "UI Components for HireControl",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "cross-env NODE_ENV=production rollup -c",
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"hirecontrol",
|
|
12
|
+
"ui",
|
|
13
|
+
"components"
|
|
14
|
+
],
|
|
15
|
+
"author": "Aloysius Butler & Clark",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"@react-google-maps/api": "^2.0.0",
|
|
19
|
+
"@radix-ui/react-accordion": "^1.1.2",
|
|
20
|
+
"@radix-ui/react-dialog": "^1.0.5",
|
|
21
|
+
"@radix-ui/react-select": "^2.0.0",
|
|
22
|
+
"@radix-ui/react-tabs": "^1.0.4",
|
|
23
|
+
"@iconify/react": "^1.0.0",
|
|
24
|
+
"@headlessui/react": "^1.0.0",
|
|
25
|
+
"use-places-autocomplete": "^1.0.0",
|
|
26
|
+
"fuse.js": "^7.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"cross-env": "^7.0.3",
|
|
30
|
+
"eslint": "^8.0.0",
|
|
31
|
+
"eslint-config-prettier": "^9.1.0",
|
|
32
|
+
"eslint-plugin-import": "^2.29.1",
|
|
33
|
+
"eslint-plugin-jsx-a11y": "^6.8.0",
|
|
34
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
35
|
+
"eslint-plugin-react": "^7.34.2",
|
|
36
|
+
"eslint-plugin-react-hooks": "^4.6.2",
|
|
37
|
+
"@babel/eslint-parser": "^7.24.6",
|
|
38
|
+
"@babel/cli": "^7.24.6",
|
|
39
|
+
"@babel/core": "^7.24.6",
|
|
40
|
+
"@babel/preset-env": "^7.24.6",
|
|
41
|
+
"@babel/preset-react": "^7.24.6",
|
|
42
|
+
"@rollup/plugin-alias": "^5.1.0",
|
|
43
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
44
|
+
"@rollup/plugin-commonjs": "^25.0.8",
|
|
45
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
46
|
+
"@rollup/plugin-replace": "^5.0.5",
|
|
47
|
+
"@iconify/react": "^4.1.1",
|
|
48
|
+
"@tailwindcss/aspect-ratio": "^0.4.2",
|
|
49
|
+
"@tailwindcss/forms": "^0.5.7",
|
|
50
|
+
"@tailwindcss/typography": "^0.5.13",
|
|
51
|
+
"autoprefixer": "^10.4.19",
|
|
52
|
+
"dotenv": "^16.4.5",
|
|
53
|
+
"postcss": "^8.4.38",
|
|
54
|
+
"postcss-prefixer": "^3.0.0",
|
|
55
|
+
"postcss-preset-env": "^9.5.14",
|
|
56
|
+
"rollup": "^4.18.0",
|
|
57
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
58
|
+
"rollup-plugin-postcss": "^4.0.2",
|
|
59
|
+
"tailwindcss": "^3.4.3",
|
|
60
|
+
"tailwindcss-animate": "^1.0.7"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -1,92 +1,93 @@
|
|
|
1
|
-
import React, { useRef, useState, useEffect } from 'react';
|
|
2
|
-
|
|
3
|
-
import Button from '~/components/modules/buttons/default';
|
|
4
|
-
import Icon from '~/components/modules/icon';
|
|
5
|
-
import FilterCard from '~/components/modules/cards/filter';
|
|
6
|
-
|
|
7
|
-
import { useMapList } from '~/contexts/mapListContext';
|
|
8
|
-
|
|
9
|
-
const Search = ({
|
|
10
|
-
inputPlaceholder = "Keywords",
|
|
11
|
-
showSearchIcon = false,
|
|
12
|
-
className,
|
|
13
|
-
labelClassName
|
|
14
|
-
}) => {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
1
|
+
import React, { useRef, useState, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import Button from '~/components/modules/buttons/default';
|
|
4
|
+
import Icon from '~/components/modules/icon';
|
|
5
|
+
import FilterCard from '~/components/modules/cards/filter';
|
|
6
|
+
|
|
7
|
+
import { useMapList } from '~/contexts/mapListContext';
|
|
8
|
+
|
|
9
|
+
const Search = ({
|
|
10
|
+
inputPlaceholder = "Keywords",
|
|
11
|
+
showSearchIcon = false,
|
|
12
|
+
className,
|
|
13
|
+
labelClassName
|
|
14
|
+
}) => {
|
|
15
|
+
const {
|
|
16
|
+
query,
|
|
17
|
+
setQuery,
|
|
18
|
+
siteConfig
|
|
19
|
+
} = useMapList();
|
|
20
|
+
const [inputValue, setInputValue] = useState(query != null ? query : "");
|
|
21
|
+
const debounceTimer = useRef(null);
|
|
22
|
+
|
|
23
|
+
const handleInputChange = e => {
|
|
24
|
+
setInputValue(e.target.value);
|
|
25
|
+
if (debounceTimer.current) {
|
|
26
|
+
clearTimeout(debounceTimer.current);
|
|
27
|
+
}
|
|
28
|
+
debounceTimer.current = setTimeout(() => {
|
|
29
|
+
setQuery(e.target.value);
|
|
30
|
+
}, 500);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const handleReset = () => {
|
|
34
|
+
setInputValue("");
|
|
35
|
+
setQuery("");
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (query == null) {
|
|
40
|
+
setInputValue("");
|
|
41
|
+
}
|
|
42
|
+
}, [query]);
|
|
43
|
+
inputPlaceholder = siteConfig.searchConfig.placeholder;
|
|
44
|
+
return (
|
|
45
|
+
<FilterCard as="form" className={className ?? ""}>
|
|
46
|
+
<FilterCard.Title
|
|
47
|
+
as="label"
|
|
48
|
+
icon="fluent:search-12-filled"
|
|
49
|
+
className={labelClassName ?? ""}
|
|
50
|
+
>
|
|
51
|
+
<span>
|
|
52
|
+
{siteConfig.searchConfig.label}
|
|
53
|
+
</span>
|
|
54
|
+
</FilterCard.Title>
|
|
55
|
+
|
|
56
|
+
<div className="hc-relative hc-flex hc-items-center hc-px-2 hc-rounded hc-bg-white hc-border hc-border-uiAccent/20 focus-within:hc-ring-1 focus-within:hc-ring-uiAccent">
|
|
57
|
+
{showSearchIcon && (
|
|
58
|
+
<Icon
|
|
59
|
+
icon="fluent:search-12-filled"
|
|
60
|
+
size="hc-size-4"
|
|
61
|
+
className="hc-mr-2 hc-text-uiAccent/50"
|
|
62
|
+
/>
|
|
63
|
+
)}
|
|
64
|
+
<input
|
|
65
|
+
type="text"
|
|
66
|
+
name="search"
|
|
67
|
+
onKeyDown={e => {
|
|
68
|
+
if (e.key === 'Enter') {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
}
|
|
71
|
+
}}
|
|
72
|
+
placeholder={inputPlaceholder}
|
|
73
|
+
value={inputValue}
|
|
74
|
+
className="hc-w-full hc-px-0 hc-py-2 hc-text-sm hc-border-0 hc-transition-colors placeholder:hc-text-uiText/50 focus:hc-ring-0 focus:hc-outline-none"
|
|
75
|
+
onChange={handleInputChange}
|
|
76
|
+
/>
|
|
77
|
+
|
|
78
|
+
<Button.Btn
|
|
79
|
+
type="reset"
|
|
80
|
+
variant="icon"
|
|
81
|
+
size="sqsm"
|
|
82
|
+
className={`transition-opacity ${inputValue ? "hc-opacity-100" : "hc-opacity-0 hc-pointer-events-none"}`}
|
|
83
|
+
onClick={handleReset}
|
|
84
|
+
>
|
|
85
|
+
<span className="sr-only">Clear</span>
|
|
86
|
+
<Button.Icon icon="uil:times" className="hc-text-uiAccent" />
|
|
87
|
+
</Button.Btn>
|
|
88
|
+
</div>
|
|
89
|
+
</FilterCard>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export default Search;
|
|
@@ -1,135 +1,135 @@
|
|
|
1
|
-
import React, { forwardRef } from 'react';
|
|
2
|
-
|
|
3
|
-
import Grid from '~/components/modules/grid';
|
|
4
|
-
import Icon from '~/components/modules/icon';
|
|
5
|
-
import FieldMapper from '~/components/modules/maps/list/field-mapper';
|
|
6
|
-
|
|
7
|
-
import { useMapList } from '~/contexts/mapListContext';
|
|
8
|
-
import { useTrackEvent } from '~/contexts/trackEventContext';
|
|
9
|
-
|
|
10
|
-
const ListItem = forwardRef(
|
|
11
|
-
(
|
|
12
|
-
{
|
|
13
|
-
isActive,
|
|
14
|
-
bodyClassName,
|
|
15
|
-
className,
|
|
16
|
-
item,
|
|
17
|
-
fieldsShown,
|
|
18
|
-
specialFeatures,
|
|
19
|
-
onItemSelected,
|
|
20
|
-
showMap,
|
|
21
|
-
setMobileTab,
|
|
22
|
-
favorites,
|
|
23
|
-
setFavorites,
|
|
24
|
-
...props
|
|
25
|
-
},
|
|
26
|
-
ref
|
|
27
|
-
) => {
|
|
28
|
-
const { siteConfig } = useMapList();
|
|
29
|
-
const { trackEvent, eventTypes } = useTrackEvent();
|
|
30
|
-
const mapPinColor = siteConfig.colors.primary.replace("#", "");
|
|
31
|
-
|
|
32
|
-
const handleClick = () => {
|
|
33
|
-
if (onItemSelected) {
|
|
34
|
-
onItemSelected(item);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
let isFavorite = favorites.includes(item.id);
|
|
39
|
-
|
|
40
|
-
const handleFavouriteClick = event => {
|
|
41
|
-
event.stopPropagation();
|
|
42
|
-
let updatedFavorites;
|
|
43
|
-
if (isFavorite) {
|
|
44
|
-
updatedFavorites = favorites.filter(fav => fav !== item.id);
|
|
45
|
-
} else {
|
|
46
|
-
trackEvent(eventTypes.FAVORITE_SELECTED, { jobTitle: item.fields.position, jobCategory: item.fields.category, entityDisplayName: item?.mapDetails?.entityDisplayName });
|
|
47
|
-
updatedFavorites = [...favorites, item.id];
|
|
48
|
-
}
|
|
49
|
-
isFavorite = !isFavorite;
|
|
50
|
-
setFavorites(updatedFavorites);
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<button
|
|
55
|
-
ref={ref}
|
|
56
|
-
onClick={handleClick}
|
|
57
|
-
className={`
|
|
58
|
-
hc-group hc-relative hc-flex md:hc-flex-col hc-w-full md:hc-pl-4 hc-text-left hc-bg-clip-border hc-border hc-border-transparent hc-break-words hc-overflow-hidden hc-cursor-pointer hc-transition-colors hover:hc-bg-uiAccent/5 focus:hover:hc-bg-uiAccent/5
|
|
59
|
-
${isActive ? "hc-bg-uiAccent/5 hc-border-secondary hc-border" : "hc-text-uiText hc-bg-white"}
|
|
60
|
-
${className ?? ""}
|
|
61
|
-
`}
|
|
62
|
-
{...props}
|
|
63
|
-
>
|
|
64
|
-
<Grid
|
|
65
|
-
columns="hc-grid-flow-col hc-auto-cols-fr"
|
|
66
|
-
gap="hc-gap-2"
|
|
67
|
-
isAnimated={false}
|
|
68
|
-
className={`
|
|
69
|
-
hc-block md:hc-grid hc-p-2 hc-ps-4 hc-w-full hc-grow hc-leading-tight hc-text-sm md:hc-text-xs lg:hc-text-sm
|
|
70
|
-
${bodyClassName ?? ""}
|
|
71
|
-
`}
|
|
72
|
-
>
|
|
73
|
-
<Grid.Item className="hc-hidden md:hc-block md:hc-absolute md:hc-left-1.5 hc-top-1.5">
|
|
74
|
-
<span className="hc-sr-only">Expand row</span>
|
|
75
|
-
<Icon
|
|
76
|
-
icon="fluent-emoji-high-contrast:plus"
|
|
77
|
-
size="hc-size-2.5"
|
|
78
|
-
className={`
|
|
79
|
-
hc-opacity-0 hc-text-uiText/60 hc-transition group-hover:hc-opacity-100 group-active:hc-opacity-100
|
|
80
|
-
${isActive ? "hc-opacity-100 hc-rotate-45" : ""}
|
|
81
|
-
`}
|
|
82
|
-
/>
|
|
83
|
-
|
|
84
|
-
</Grid.Item>
|
|
85
|
-
|
|
86
|
-
<FieldMapper
|
|
87
|
-
item={item}
|
|
88
|
-
fieldsShown={fieldsShown}
|
|
89
|
-
specialFeatures={specialFeatures}
|
|
90
|
-
isFavorite={isFavorite}
|
|
91
|
-
handleFavouriteClick={handleFavouriteClick}
|
|
92
|
-
/>
|
|
93
|
-
<Grid.Item
|
|
94
|
-
key={"favorites"}
|
|
95
|
-
className="hc-hidden md:hc-block hc-col-span-1"
|
|
96
|
-
>
|
|
97
|
-
<Icon
|
|
98
|
-
icon={isFavorite ? "mdi:heart" : "mdi:heart-outline"}
|
|
99
|
-
size="hc-size-3.5"
|
|
100
|
-
iconClasses={isFavorite ? "hc-text-primary" : ""}
|
|
101
|
-
title={!isFavorite ? 'Add job to favorites' : 'Remove job from favorites'}
|
|
102
|
-
className={`
|
|
103
|
-
hc-pr-2 hc-transition-opacity hc-duration-300 hc-cursor-pointer hc-opacity-100"
|
|
104
|
-
`}
|
|
105
|
-
onClick={e => handleFavouriteClick(e)}
|
|
106
|
-
/>
|
|
107
|
-
</Grid.Item>
|
|
108
|
-
</Grid>
|
|
109
|
-
|
|
110
|
-
{showMap && (
|
|
111
|
-
<div onClick={() => { setMobileTab("mapTab"); handleClick(); }} className="md:hc-hidden hc-w-2/5 sm:hc-w-1/3 hc-p-1.5 hc-my-1 hc-bg-uiAccent/5 hc-border hc-border-uiAccent/10 hc-rounded-sm">
|
|
112
|
-
<img
|
|
113
|
-
src={`https://maps.googleapis.com/maps/api/staticmap?scale=2¢er=${item.mapDetails?.latitude},${item.mapDetails?.longitude}&zoom=10&size=240x180&maptype=roadmap&markers=color:0x${mapPinColor}%7Clabel:•%7C${item.mapDetails?.latitude},${item.mapDetails?.longitude}&key=${process.env.GOOGLE_MAPS_API_KEY}`}
|
|
114
|
-
alt={`Map of location for ${item.fields.position}`}
|
|
115
|
-
className="hc-w-full hc-h-full hc-object-cover"
|
|
116
|
-
/>
|
|
117
|
-
</div>
|
|
118
|
-
)}
|
|
119
|
-
</button>
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
ListItem.displayName = "ListItem";
|
|
125
|
-
|
|
126
|
-
export default React.memo(ListItem, (prevProps, nextProps) => {
|
|
127
|
-
return (
|
|
128
|
-
(prevProps.isActive === nextProps.isActive ||
|
|
129
|
-
prevProps.isActive !== nextProps.isActive) &&
|
|
130
|
-
prevProps.bodyClassName === nextProps.bodyClassName &&
|
|
131
|
-
prevProps.className === nextProps.className &&
|
|
132
|
-
prevProps.fieldsShown === nextProps.fieldsShown &&
|
|
133
|
-
prevProps.item.id === nextProps.item.id
|
|
134
|
-
);
|
|
135
|
-
});
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import Grid from '~/components/modules/grid';
|
|
4
|
+
import Icon from '~/components/modules/icon';
|
|
5
|
+
import FieldMapper from '~/components/modules/maps/list/field-mapper';
|
|
6
|
+
|
|
7
|
+
import { useMapList } from '~/contexts/mapListContext';
|
|
8
|
+
import { useTrackEvent } from '~/contexts/trackEventContext';
|
|
9
|
+
|
|
10
|
+
const ListItem = forwardRef(
|
|
11
|
+
(
|
|
12
|
+
{
|
|
13
|
+
isActive,
|
|
14
|
+
bodyClassName,
|
|
15
|
+
className,
|
|
16
|
+
item,
|
|
17
|
+
fieldsShown,
|
|
18
|
+
specialFeatures,
|
|
19
|
+
onItemSelected,
|
|
20
|
+
showMap,
|
|
21
|
+
setMobileTab,
|
|
22
|
+
favorites,
|
|
23
|
+
setFavorites,
|
|
24
|
+
...props
|
|
25
|
+
},
|
|
26
|
+
ref
|
|
27
|
+
) => {
|
|
28
|
+
const { siteConfig } = useMapList();
|
|
29
|
+
const { trackEvent, eventTypes } = useTrackEvent();
|
|
30
|
+
const mapPinColor = siteConfig.colors.primary.replace("#", "");
|
|
31
|
+
|
|
32
|
+
const handleClick = () => {
|
|
33
|
+
if (onItemSelected) {
|
|
34
|
+
onItemSelected(item);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
let isFavorite = favorites.includes(item.id);
|
|
39
|
+
|
|
40
|
+
const handleFavouriteClick = event => {
|
|
41
|
+
event.stopPropagation();
|
|
42
|
+
let updatedFavorites;
|
|
43
|
+
if (isFavorite) {
|
|
44
|
+
updatedFavorites = favorites.filter(fav => fav !== item.id);
|
|
45
|
+
} else {
|
|
46
|
+
trackEvent(eventTypes.FAVORITE_SELECTED, { jobTitle: item.fields.position, jobCategory: item.fields.category, entityDisplayName: item?.mapDetails?.entityDisplayName });
|
|
47
|
+
updatedFavorites = [...favorites, item.id];
|
|
48
|
+
}
|
|
49
|
+
isFavorite = !isFavorite;
|
|
50
|
+
setFavorites(updatedFavorites);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<button
|
|
55
|
+
ref={ref}
|
|
56
|
+
onClick={handleClick}
|
|
57
|
+
className={`
|
|
58
|
+
hc-group hc-relative hc-flex md:hc-flex-col hc-w-full md:hc-pl-4 hc-text-left hc-bg-clip-border hc-border hc-border-transparent hc-break-words hc-overflow-hidden hc-cursor-pointer hc-transition-colors hover:hc-bg-uiAccent/5 focus:hover:hc-bg-uiAccent/5
|
|
59
|
+
${isActive ? "hc-bg-uiAccent/5 hc-border-secondary hc-border" : "hc-text-uiText hc-bg-white"}
|
|
60
|
+
${className ?? ""}
|
|
61
|
+
`}
|
|
62
|
+
{...props}
|
|
63
|
+
>
|
|
64
|
+
<Grid
|
|
65
|
+
columns="hc-grid-flow-col hc-auto-cols-fr"
|
|
66
|
+
gap="hc-gap-2"
|
|
67
|
+
isAnimated={false}
|
|
68
|
+
className={`
|
|
69
|
+
hc-block md:hc-grid hc-p-2 hc-ps-4 hc-w-full hc-grow hc-leading-tight hc-text-sm md:hc-text-xs lg:hc-text-sm
|
|
70
|
+
${bodyClassName ?? ""}
|
|
71
|
+
`}
|
|
72
|
+
>
|
|
73
|
+
<Grid.Item className="hc-hidden md:hc-block md:hc-absolute md:hc-left-1.5 hc-top-1.5">
|
|
74
|
+
<span className="hc-sr-only">Expand row</span>
|
|
75
|
+
<Icon
|
|
76
|
+
icon="fluent-emoji-high-contrast:plus"
|
|
77
|
+
size="hc-size-2.5"
|
|
78
|
+
className={`
|
|
79
|
+
hc-opacity-0 hc-text-uiText/60 hc-transition group-hover:hc-opacity-100 group-active:hc-opacity-100
|
|
80
|
+
${isActive ? "hc-opacity-100 hc-rotate-45" : ""}
|
|
81
|
+
`}
|
|
82
|
+
/>
|
|
83
|
+
|
|
84
|
+
</Grid.Item>
|
|
85
|
+
|
|
86
|
+
<FieldMapper
|
|
87
|
+
item={item}
|
|
88
|
+
fieldsShown={fieldsShown}
|
|
89
|
+
specialFeatures={specialFeatures}
|
|
90
|
+
isFavorite={isFavorite}
|
|
91
|
+
handleFavouriteClick={handleFavouriteClick}
|
|
92
|
+
/>
|
|
93
|
+
<Grid.Item
|
|
94
|
+
key={"favorites"}
|
|
95
|
+
className="hc-hidden md:hc-block hc-col-span-1"
|
|
96
|
+
>
|
|
97
|
+
<Icon
|
|
98
|
+
icon={isFavorite ? "mdi:heart" : "mdi:heart-outline"}
|
|
99
|
+
size="hc-size-3.5"
|
|
100
|
+
iconClasses={isFavorite ? "hc-text-primary" : ""}
|
|
101
|
+
title={!isFavorite ? 'Add job to favorites' : 'Remove job from favorites'}
|
|
102
|
+
className={`
|
|
103
|
+
hc-pr-2 hc-transition-opacity hc-duration-300 hc-cursor-pointer hc-opacity-100"
|
|
104
|
+
`}
|
|
105
|
+
onClick={e => handleFavouriteClick(e)}
|
|
106
|
+
/>
|
|
107
|
+
</Grid.Item>
|
|
108
|
+
</Grid>
|
|
109
|
+
|
|
110
|
+
{showMap && (
|
|
111
|
+
<div onClick={() => { setMobileTab("mapTab"); handleClick(); }} className="md:hc-hidden hc-w-2/5 sm:hc-w-1/3 hc-p-1.5 hc-my-1 hc-bg-uiAccent/5 hc-border hc-border-uiAccent/10 hc-rounded-sm">
|
|
112
|
+
<img
|
|
113
|
+
src={`https://maps.googleapis.com/maps/api/staticmap?scale=2¢er=${item.mapDetails?.latitude},${item.mapDetails?.longitude}&zoom=10&size=240x180&maptype=roadmap&markers=color:0x${mapPinColor}%7Clabel:•%7C${item.mapDetails?.latitude},${item.mapDetails?.longitude}&key=${process.env.GOOGLE_MAPS_API_KEY}`}
|
|
114
|
+
alt={`Map of location for ${item.fields.position}`}
|
|
115
|
+
className="hc-w-full hc-h-full hc-object-cover"
|
|
116
|
+
/>
|
|
117
|
+
</div>
|
|
118
|
+
)}
|
|
119
|
+
</button>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
ListItem.displayName = "ListItem";
|
|
125
|
+
|
|
126
|
+
export default React.memo(ListItem, (prevProps, nextProps) => {
|
|
127
|
+
return (
|
|
128
|
+
(prevProps.isActive === nextProps.isActive ||
|
|
129
|
+
prevProps.isActive !== nextProps.isActive) &&
|
|
130
|
+
prevProps.bodyClassName === nextProps.bodyClassName &&
|
|
131
|
+
prevProps.className === nextProps.className &&
|
|
132
|
+
prevProps.fieldsShown === nextProps.fieldsShown &&
|
|
133
|
+
prevProps.item.id === nextProps.item.id
|
|
134
|
+
);
|
|
135
|
+
});
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export const eventTypes = {
|
|
2
|
-
FILTER_APPLIED: "filter_applied",
|
|
3
|
-
MAP_MARKER_CLICKED: "map_marker_clicked",
|
|
4
|
-
JOB_LISTING_SELECTED: "job_listing_selected",
|
|
5
|
-
APPLY_NOW_CLICKED: "apply_now_clicked",
|
|
6
|
-
VIEW_DETAILS_CLICKED: "view_details_clicked",
|
|
7
|
-
COMMUTE_ORIGIN_ADDED: "commute_origin_added",
|
|
8
|
-
POI_APPLIED: "point_of_interest_applied",
|
|
9
|
-
VIEW_JOBS_AT_Location: "view_jobs_at_location_clicked",
|
|
10
|
-
FAVORITE_SELECTED: "favorite_job_selected",
|
|
11
|
-
LIST_SORTED: "jobs_list_sorted",
|
|
12
|
-
FILTERS_RESET: "
|
|
13
|
-
};
|
|
1
|
+
export const eventTypes = {
|
|
2
|
+
FILTER_APPLIED: "filter_applied",
|
|
3
|
+
MAP_MARKER_CLICKED: "map_marker_clicked",
|
|
4
|
+
JOB_LISTING_SELECTED: "job_listing_selected",
|
|
5
|
+
APPLY_NOW_CLICKED: "apply_now_clicked",
|
|
6
|
+
VIEW_DETAILS_CLICKED: "view_details_clicked",
|
|
7
|
+
COMMUTE_ORIGIN_ADDED: "commute_origin_added",
|
|
8
|
+
POI_APPLIED: "point_of_interest_applied",
|
|
9
|
+
VIEW_JOBS_AT_Location: "view_jobs_at_location_clicked",
|
|
10
|
+
FAVORITE_SELECTED: "favorite_job_selected",
|
|
11
|
+
LIST_SORTED: "jobs_list_sorted",
|
|
12
|
+
FILTERS_RESET: "filter_reset_button_clicked"
|
|
13
|
+
};
|