@abcagency/hc-ui-components 1.3.23 → 1.3.25
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/package.json +4 -5
- package/src/.editorconfig +12 -0
- package/src/apis/hcApi.ts +109 -0
- package/src/bundleIndex.js +14 -0
- package/src/clientToken.js +9 -0
- package/src/components/HireControlMap.js +135 -0
- package/src/components/containers/accordions/filter-container.js +48 -0
- package/src/components/containers/accordions/filter-item-container.js +66 -0
- package/src/components/containers/accordions/map-accordion-item-container.js +70 -0
- package/src/components/containers/filter/commute-container.js +89 -0
- package/src/components/containers/filter/filter-container.js +76 -0
- package/src/components/containers/filter/filter-item-container.js +71 -0
- package/src/components/containers/filter/location-container.js +45 -0
- package/src/components/containers/filter/points-of-interest-container.js +33 -0
- package/src/components/containers/filter/points-of-interest-radio-item-container.js +35 -0
- package/src/components/containers/filter/search-container.js +50 -0
- package/src/components/containers/jobListing/listing-details-container.js +40 -0
- package/src/components/containers/list/item-list-container.tsx +81 -0
- package/src/components/containers/list/list-item/list-item-container.js +43 -0
- package/src/components/containers/maps/info-window-content-container.js +51 -0
- package/src/components/containers/maps/map-container.js +204 -0
- package/src/components/containers/maps/map-list-container.js +48 -0
- package/src/components/containers/maps/map-marker-container.js +78 -0
- package/src/components/modules/accordions/MapAccordionItem.js +30 -0
- package/src/components/modules/accordions/default.js +171 -0
- package/src/components/modules/accordions/filterItem.js +27 -0
- package/src/components/modules/accordions/filters.js +32 -0
- package/src/components/modules/buttons/button-group-apply.js +123 -0
- package/src/components/modules/buttons/commute-pill.js +22 -0
- package/src/components/modules/buttons/default.js +194 -0
- package/src/components/modules/buttons/items-pill.js +35 -0
- package/src/components/modules/buttons/pill-wrapper.js +27 -0
- package/src/components/modules/buttons/show-all-button.js +20 -0
- package/src/components/modules/cards/default.js +167 -0
- package/src/components/modules/cards/filter.js +56 -0
- package/src/components/modules/dialogs/apply-dialog.js +48 -0
- package/src/components/modules/filter/commute.js +108 -0
- package/src/components/modules/filter/index.js +55 -0
- package/src/components/modules/filter/item.js +48 -0
- package/src/components/modules/filter/location.js +48 -0
- package/src/components/modules/filter/radio-item.js +42 -0
- package/src/components/modules/filter/search.js +65 -0
- package/src/components/modules/filter/sort.js +83 -0
- package/src/components/modules/grid.js +54 -0
- package/src/components/modules/icon.js +33 -0
- package/src/components/modules/jobListing/listing-details.js +109 -0
- package/src/components/modules/list/field-mapper.js +114 -0
- package/src/components/modules/list/header-item.js +91 -0
- package/src/components/modules/list/header.js +49 -0
- package/src/components/modules/list/item-expand-card/index.js +22 -0
- package/src/components/modules/list/item-expand-card/recruiter-contact-nav.js +50 -0
- package/src/components/modules/list/item-expand-card/recruiter-details.js +68 -0
- package/src/components/modules/list/item-expand-card/recruiter-headshot.js +22 -0
- package/src/components/modules/list/item-list.tsx +84 -0
- package/src/components/modules/list/list-item/list-item.js +130 -0
- package/src/components/modules/maps/info-window-card.js +17 -0
- package/src/components/modules/maps/info-window-content.js +35 -0
- package/src/components/modules/maps/map-list.js +28 -0
- package/src/components/modules/maps/map-marker.js +29 -0
- package/src/components/modules/maps/map.js +76 -0
- package/src/components/modules/maps/place-marker.js +41 -0
- package/src/components/modules/maps/tabs.js +81 -0
- package/src/constants/eventTypes.js +13 -0
- package/src/constants/placeTypes.js +8 -0
- package/src/contexts/mapContext.tsx +129 -0
- package/src/contexts/mapListContext.tsx +311 -0
- package/src/contexts/placesContext.js +102 -0
- package/src/contexts/trackEventContext.js +14 -0
- package/src/enums/SectionType.ts +9 -0
- package/src/hooks/useList.js +89 -0
- package/src/index.js +3 -0
- package/src/services/configService.ts +16 -0
- package/src/services/googlePlacesNearbyService.ts +42 -0
- package/src/services/listingAggregatorService.ts +76 -0
- package/src/services/listingEntityService.ts +16 -0
- package/src/services/listingService.ts +40 -0
- package/src/services/recruiterService.ts +18 -0
- package/src/styles/bundle.css +268 -0
- package/src/styles/index.css +24 -0
- package/src/types/Address.ts +7 -0
- package/src/types/ContentSection.ts +9 -0
- package/src/types/GetListingParams.ts +8 -0
- package/src/types/LatLng.ts +4 -0
- package/src/types/ListingEntity.ts +11 -0
- package/src/types/ListingFields.ts +25 -0
- package/src/types/Listings.ts +32 -0
- package/src/types/Recruiter.ts +9 -0
- package/src/types/SimilarListing.ts +24 -0
- package/src/types/config/Colors.ts +8 -0
- package/src/types/config/MapConfig.ts +31 -0
- package/src/types/config/PointsOfInterestConfig.ts +13 -0
- package/src/types/config/SearchConfig.ts +4 -0
- package/src/util/arrayUtil.js +3 -0
- package/src/util/fieldMapper.js +22 -0
- package/src/util/filterUtil.js +239 -0
- package/src/util/loading.js +17 -0
- package/src/util/localStorageUtil.ts +34 -0
- package/src/util/mapIconUtil.js +180 -0
- package/src/util/mapUtil.js +91 -0
- package/src/util/sortUtil.js +33 -0
- package/src/util/stringUtils.js +6 -0
- package/src/util/urlFilterUtil.js +85 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import List from '~/components/containers/list/item-list-container';
|
|
4
|
+
import Map from '~/components/containers/maps/map-container';
|
|
5
|
+
import Filter from '~/components/modules/filter';
|
|
6
|
+
import MapList from '~/components/modules/maps/map-list';
|
|
7
|
+
|
|
8
|
+
const MapListContainer = ({
|
|
9
|
+
loading = false,
|
|
10
|
+
mapDetails,
|
|
11
|
+
markerConfigs,
|
|
12
|
+
itemExpandedContent,
|
|
13
|
+
fieldsShown,
|
|
14
|
+
specialFeatures,
|
|
15
|
+
fieldNames,
|
|
16
|
+
showMap,
|
|
17
|
+
placeMappings
|
|
18
|
+
}) => {
|
|
19
|
+
|
|
20
|
+
const listProps = {
|
|
21
|
+
fieldsShown,
|
|
22
|
+
fieldNames,
|
|
23
|
+
itemExpandedContent,
|
|
24
|
+
loading,
|
|
25
|
+
showMap,
|
|
26
|
+
specialFeatures
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const mapProps = {
|
|
30
|
+
mapDetails,
|
|
31
|
+
markerConfigs,
|
|
32
|
+
placeMappings,
|
|
33
|
+
clusterGridSize: 60,
|
|
34
|
+
showMap
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<MapList
|
|
39
|
+
showMap={showMap}
|
|
40
|
+
loading={loading}
|
|
41
|
+
list={<List {...listProps} />}
|
|
42
|
+
map={<Map {...mapProps} />}
|
|
43
|
+
filter={<Filter showMap={showMap} className="md:hc-hidden" />}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default MapListContainer;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import MapMarker from '~/components/modules/maps/map-marker';
|
|
3
|
+
import { InfoWindow } from '@react-google-maps/api';
|
|
4
|
+
import InfoWindowCard from '~/components/modules/maps/info-window-card';
|
|
5
|
+
import InfoWindowContent from "~/components/containers/maps/info-window-content-container";
|
|
6
|
+
|
|
7
|
+
import { useMap } from "~/contexts/mapContext";
|
|
8
|
+
import { useMapList } from "~/contexts/mapListContext";
|
|
9
|
+
import { useTrackEvent } from '~/contexts/trackEventContext';
|
|
10
|
+
|
|
11
|
+
const MapMarkerContainer = ({
|
|
12
|
+
item,
|
|
13
|
+
markerRefs,
|
|
14
|
+
infoWindowClasses,
|
|
15
|
+
markerClickHandler,
|
|
16
|
+
clusterer,
|
|
17
|
+
markerIconSelected,
|
|
18
|
+
markerIcon,
|
|
19
|
+
selectedLocation,
|
|
20
|
+
setMapInteracted
|
|
21
|
+
}) => {
|
|
22
|
+
const { setLocation, commuteLocation } = useMap();
|
|
23
|
+
const isSelected = item.id === selectedLocation?.id;
|
|
24
|
+
const markerRef = useRef(null);
|
|
25
|
+
const { trackEvent, eventTypes } = useTrackEvent();
|
|
26
|
+
const { handleFilterListingsByLocation } = useMapList();
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
markerRefs.current[item.id] = markerRef.current;
|
|
30
|
+
}, []);
|
|
31
|
+
|
|
32
|
+
const onMarkerClick = () => {
|
|
33
|
+
trackEvent(eventTypes.MAP_MARKER_CLICKED, {
|
|
34
|
+
entityDisplayName: item.entityDisplayName,
|
|
35
|
+
lat: item.latitude,
|
|
36
|
+
lng: item.longitude,
|
|
37
|
+
travelTime: item.travelTime
|
|
38
|
+
});
|
|
39
|
+
setMapInteracted(true);
|
|
40
|
+
markerClickHandler(item);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<MapMarker
|
|
45
|
+
position={{ lat: item.latitude, lng: item.longitude }}
|
|
46
|
+
title={item.name}
|
|
47
|
+
icon={isSelected ? markerIconSelected : markerIcon}
|
|
48
|
+
zIndex={isSelected ? 9999 : 1}
|
|
49
|
+
onLoad={marker => (markerRef.current = marker)}
|
|
50
|
+
onClick={onMarkerClick}
|
|
51
|
+
clusterer={clusterer}
|
|
52
|
+
>
|
|
53
|
+
{isSelected && (
|
|
54
|
+
<InfoWindow
|
|
55
|
+
position={{ lat: item.latitude, lng: item.longitude }}
|
|
56
|
+
anchor={markerRefs.current[item.id]}
|
|
57
|
+
onCloseClick={() => {
|
|
58
|
+
setMapInteracted(true);
|
|
59
|
+
setLocation(null);
|
|
60
|
+
}}
|
|
61
|
+
options={{ maxWidth: 400 }}
|
|
62
|
+
>
|
|
63
|
+
<InfoWindowCard
|
|
64
|
+
className={infoWindowClasses}
|
|
65
|
+
id={item.id}
|
|
66
|
+
content={<InfoWindowContent
|
|
67
|
+
item={item}
|
|
68
|
+
commuteLocation={commuteLocation}
|
|
69
|
+
filterListingsByLocation={() => handleFilterListingsByLocation(selectedLocation)}
|
|
70
|
+
/>}
|
|
71
|
+
/>
|
|
72
|
+
</InfoWindow>
|
|
73
|
+
)}
|
|
74
|
+
</MapMarker>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default MapMarkerContainer;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Accordion from '~/components/modules/accordions/default';
|
|
3
|
+
import ItemExpandCard from '~/components/modules/list/item-expand-card';
|
|
4
|
+
|
|
5
|
+
const MapAccordionItem = ({
|
|
6
|
+
item,
|
|
7
|
+
itemRefs,
|
|
8
|
+
itemExpandedContent,
|
|
9
|
+
isActive,
|
|
10
|
+
recruiter,
|
|
11
|
+
children
|
|
12
|
+
}) => {
|
|
13
|
+
return (
|
|
14
|
+
<Accordion.Item key={item.id} id={item.id}>
|
|
15
|
+
<Accordion.Trigger.Blank>
|
|
16
|
+
<div ref={el => (itemRefs.current[item.id] = el)}>
|
|
17
|
+
{children}
|
|
18
|
+
</div>
|
|
19
|
+
</Accordion.Trigger.Blank>
|
|
20
|
+
{isActive &&
|
|
21
|
+
|
|
22
|
+
<Accordion.Content bodyClassName="hc-px-2 hc-py-2 hc-pt-0 hc-bg-uiAccent/5 hc-border-secondary hc-border hc-border-t-0">
|
|
23
|
+
{ <ItemExpandCard content={itemExpandedContent(item, recruiter)} />}
|
|
24
|
+
</Accordion.Content>
|
|
25
|
+
}
|
|
26
|
+
</Accordion.Item>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default MapAccordionItem;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import * as RadixAccordion from '@radix-ui/react-accordion';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
|
|
5
|
+
import Icon from '~/components/modules/icon';
|
|
6
|
+
|
|
7
|
+
const Accordion = ({
|
|
8
|
+
className,
|
|
9
|
+
type = 'single',
|
|
10
|
+
defaultValue,
|
|
11
|
+
collapsible = true,
|
|
12
|
+
children
|
|
13
|
+
}) => {
|
|
14
|
+
return (
|
|
15
|
+
<RadixAccordion.Root
|
|
16
|
+
type={type}
|
|
17
|
+
value={defaultValue ?? null}
|
|
18
|
+
collapsible={collapsible}
|
|
19
|
+
className={className ?? ''}
|
|
20
|
+
>
|
|
21
|
+
{children}
|
|
22
|
+
</RadixAccordion.Root>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const AccordionItem = forwardRef((
|
|
27
|
+
{
|
|
28
|
+
id,
|
|
29
|
+
children,
|
|
30
|
+
className,
|
|
31
|
+
...props
|
|
32
|
+
},
|
|
33
|
+
forwardedRef
|
|
34
|
+
) => {
|
|
35
|
+
return (
|
|
36
|
+
<RadixAccordion.Item
|
|
37
|
+
ref={forwardedRef}
|
|
38
|
+
value={id}
|
|
39
|
+
className={className ?? ''}
|
|
40
|
+
{...props}
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</RadixAccordion.Item>
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export const AccordionTrigger = forwardRef((
|
|
48
|
+
{
|
|
49
|
+
children,
|
|
50
|
+
className,
|
|
51
|
+
...props
|
|
52
|
+
},
|
|
53
|
+
forwardedRef
|
|
54
|
+
) => (
|
|
55
|
+
<RadixAccordion.Header asChild>
|
|
56
|
+
<RadixAccordion.Trigger
|
|
57
|
+
ref={forwardedRef}
|
|
58
|
+
className={twMerge(
|
|
59
|
+
'hc-group hc-flex hc-justify-between hc-w-full hc-p-4 hc-font-bold hc-text-left hc-text-uiText focus:hc-outline-none hfocus-visible:hcring focus-visible:hc-ring-uiAccent focus-visible:hc-ring-opacity-75 hover:hc-text-primary focus:hc-text-primary hc-transition data-[state=open]:hc-text-primary',
|
|
60
|
+
className ?? ''
|
|
61
|
+
)}
|
|
62
|
+
{...props}
|
|
63
|
+
>
|
|
64
|
+
{children}
|
|
65
|
+
<Icon
|
|
66
|
+
icon="uil:angle-down"
|
|
67
|
+
size="hc-size-5"
|
|
68
|
+
className="hc-transition-transform group-data-[state=open]:!hc-rotate-180"
|
|
69
|
+
aria-hidden="true"
|
|
70
|
+
/>
|
|
71
|
+
</RadixAccordion.Trigger>
|
|
72
|
+
</RadixAccordion.Header>
|
|
73
|
+
));
|
|
74
|
+
|
|
75
|
+
export const AccordionTriggerHasHeader = forwardRef((
|
|
76
|
+
{
|
|
77
|
+
header,
|
|
78
|
+
headerClassName,
|
|
79
|
+
iconClassName,
|
|
80
|
+
children,
|
|
81
|
+
className,
|
|
82
|
+
...props
|
|
83
|
+
},
|
|
84
|
+
forwardedRef
|
|
85
|
+
) => (
|
|
86
|
+
<RadixAccordion.Header
|
|
87
|
+
className={twMerge(
|
|
88
|
+
'hc-group hc-flex hc-items-start hc-justify-between hc-w-full hc-p-4 hc-pr-3 hc-font-bold hc-text-left hc-text-uiText focus:hc-outline-none focus-visible:hc-ring focus-visible:hc-ring-uiAccent focus-visible:hc-ring-opacity-75 hover:hc-text-primary focus:hc-text-primary hc-transition data-[state=open]:hc-text-primary',
|
|
89
|
+
headerClassName ?? ''
|
|
90
|
+
)}
|
|
91
|
+
>
|
|
92
|
+
<RadixAccordion.Trigger
|
|
93
|
+
ref={forwardedRef}
|
|
94
|
+
className={twMerge('hc-flex hc-items-center hc-justify-between hc-w-full', className ?? '')}
|
|
95
|
+
{...props}
|
|
96
|
+
>
|
|
97
|
+
{children}
|
|
98
|
+
<Icon
|
|
99
|
+
icon="uil:angle-down"
|
|
100
|
+
size="w-5 h-5"
|
|
101
|
+
className={twMerge(
|
|
102
|
+
'hc-transition-transform group-data-[state=open]:!hc-rotate-180',
|
|
103
|
+
iconClassName ?? ''
|
|
104
|
+
)}
|
|
105
|
+
aria-hidden="true"
|
|
106
|
+
/>
|
|
107
|
+
{header}
|
|
108
|
+
</RadixAccordion.Trigger>
|
|
109
|
+
</RadixAccordion.Header>
|
|
110
|
+
));
|
|
111
|
+
|
|
112
|
+
export const AccordionTriggerBlank = forwardRef((
|
|
113
|
+
{
|
|
114
|
+
children,
|
|
115
|
+
className,
|
|
116
|
+
...props
|
|
117
|
+
},
|
|
118
|
+
forwardedRef
|
|
119
|
+
) => (
|
|
120
|
+
<RadixAccordion.Header asChild>
|
|
121
|
+
<RadixAccordion.Trigger
|
|
122
|
+
asChild
|
|
123
|
+
ref={forwardedRef}
|
|
124
|
+
{...props}
|
|
125
|
+
>
|
|
126
|
+
{children}
|
|
127
|
+
</RadixAccordion.Trigger>
|
|
128
|
+
</RadixAccordion.Header>
|
|
129
|
+
));
|
|
130
|
+
|
|
131
|
+
export const AccordionContent = forwardRef((
|
|
132
|
+
{
|
|
133
|
+
children,
|
|
134
|
+
className,
|
|
135
|
+
bodyClassName,
|
|
136
|
+
...props
|
|
137
|
+
},
|
|
138
|
+
forwardedRef
|
|
139
|
+
) => (
|
|
140
|
+
<RadixAccordion.Content
|
|
141
|
+
ref={forwardedRef}
|
|
142
|
+
className={twMerge(
|
|
143
|
+
'data-[state=open]:hc-animate-slideDown data-[state=closed]:hc-animate-slideUp hc-overflow-hidden',
|
|
144
|
+
className ?? ''
|
|
145
|
+
)}
|
|
146
|
+
{...props}
|
|
147
|
+
>
|
|
148
|
+
<div
|
|
149
|
+
className={twMerge(
|
|
150
|
+
'hc-p-4 hc-pt-0.5',
|
|
151
|
+
bodyClassName ?? ''
|
|
152
|
+
)}
|
|
153
|
+
>
|
|
154
|
+
{children}
|
|
155
|
+
</div>
|
|
156
|
+
</RadixAccordion.Content>
|
|
157
|
+
));
|
|
158
|
+
|
|
159
|
+
Accordion.Item = AccordionItem;
|
|
160
|
+
Accordion.Trigger = AccordionTrigger;
|
|
161
|
+
Accordion.Trigger.Blank = AccordionTriggerBlank;
|
|
162
|
+
Accordion.Trigger.HasHeader = AccordionTriggerHasHeader;
|
|
163
|
+
Accordion.Content = AccordionContent;
|
|
164
|
+
|
|
165
|
+
AccordionItem.displayName = 'AccordionItem';
|
|
166
|
+
AccordionTrigger.displayName = 'AccordionTrigger';
|
|
167
|
+
AccordionTriggerBlank.displayName = 'AccordionTriggerBlank';
|
|
168
|
+
AccordionTriggerHasHeader.displayName = 'AccordionTriggerHasHeader';
|
|
169
|
+
AccordionContent.displayName = 'AccordionContent';
|
|
170
|
+
|
|
171
|
+
export default Accordion;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Accordion from '~/components/modules/accordions/default';
|
|
3
|
+
|
|
4
|
+
const AccordionFilterItem = ({
|
|
5
|
+
id,
|
|
6
|
+
setDefaultValue,
|
|
7
|
+
header,
|
|
8
|
+
body
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<Accordion.Item key={id} id={id}>
|
|
12
|
+
<Accordion.Trigger.HasHeader
|
|
13
|
+
onClick={() => setDefaultValue(id)}
|
|
14
|
+
className="hc-stretched-link hc-text-left"
|
|
15
|
+
iconClassName="hc-order-last"
|
|
16
|
+
headerClassName="hc-relative hc-py-2 hc-rounded hc-border hc-border-uiAccent/20 hc-bg-white hc-text-sm hc-transition data-[state=open]:hc-border-b-transparent data-[state=open]:hc-rounded-b-none"
|
|
17
|
+
>
|
|
18
|
+
{header}
|
|
19
|
+
</Accordion.Trigger.HasHeader>
|
|
20
|
+
<Accordion.Content bodyClassName="hc-px-2 hc-py-1 hc-bg-white hc-rounded-b hc-border hc-border-uiAccent/20 hc-border-t-0 hc-max-h-[20vh] md:hc-max-h-[25vh] hc-overflow-auto">
|
|
21
|
+
{body}
|
|
22
|
+
</Accordion.Content>
|
|
23
|
+
</Accordion.Item>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default AccordionFilterItem;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Accordion from '~/components/modules/accordions/default';
|
|
3
|
+
import FilterCard from '~/components/modules/cards/filter';
|
|
4
|
+
import Loading from '~/util/loading';
|
|
5
|
+
|
|
6
|
+
const AccordionFilters = ({
|
|
7
|
+
className,
|
|
8
|
+
defaultValue,
|
|
9
|
+
children,
|
|
10
|
+
filterOptions
|
|
11
|
+
}) => {
|
|
12
|
+
return (
|
|
13
|
+
<FilterCard className={className ?? ""}>
|
|
14
|
+
<FilterCard.Title icon="fa-solid:sliders-h">
|
|
15
|
+
<span>
|
|
16
|
+
Filter <span className="md:hc-hidden lg:hc-inline">your search</span>
|
|
17
|
+
</span>
|
|
18
|
+
</FilterCard.Title>
|
|
19
|
+
|
|
20
|
+
<Accordion defaultValue={defaultValue} className="hc-space-y-4" >
|
|
21
|
+
{!filterOptions?.filters && (
|
|
22
|
+
<Accordion.Item>
|
|
23
|
+
<Loading />
|
|
24
|
+
</Accordion.Item>
|
|
25
|
+
)}
|
|
26
|
+
{filterOptions?.filters && children}
|
|
27
|
+
</Accordion>
|
|
28
|
+
</FilterCard>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default AccordionFilters;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
|
|
4
|
+
import Button from '~/components/modules/buttons/default';
|
|
5
|
+
import ApplyDialog from '../dialogs/apply-dialog';
|
|
6
|
+
|
|
7
|
+
const ButtonGroupApply = ({
|
|
8
|
+
applyUrl,
|
|
9
|
+
useDetailsPostMessage,
|
|
10
|
+
navigateToDetails,
|
|
11
|
+
navigateToEasyApply,
|
|
12
|
+
Link,
|
|
13
|
+
linkFormat,
|
|
14
|
+
applyText = 'Apply Now',
|
|
15
|
+
detailsUrl,
|
|
16
|
+
detailsText = 'View Details',
|
|
17
|
+
className,
|
|
18
|
+
buttonSize = 'sm',
|
|
19
|
+
applyButtonVariant = 'primary',
|
|
20
|
+
detailsButtonVariant = 'outline',
|
|
21
|
+
includeDialog = false,
|
|
22
|
+
internalApplyLink,
|
|
23
|
+
itemId,
|
|
24
|
+
item,
|
|
25
|
+
companyName,
|
|
26
|
+
trackEvent,
|
|
27
|
+
eventTypes
|
|
28
|
+
}) => {
|
|
29
|
+
const href = linkFormat.replace('[slug]', item.slug ?? item.id);
|
|
30
|
+
|
|
31
|
+
const trackApply = () => {
|
|
32
|
+
trackEvent(eventTypes.APPLY_NOW_CLICKED, { jobTitle: item.fields.position, jobCategory: item.fields.category, entityDisplayName: item?.mapDetails?.entityDisplayName });
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const trackViewDetails = () => {
|
|
36
|
+
trackEvent(eventTypes.VIEW_DETAILS_CLICKED, { jobTitle: item.fields.position, jobCategory: item.fields.category, entityDisplayName: item?.mapDetails?.entityDisplayName });
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<nav
|
|
41
|
+
className={twMerge`
|
|
42
|
+
hc-flex hc-flex-row hc-justify-between hc-gap-2 hc-w-full
|
|
43
|
+
${className ?? ''}
|
|
44
|
+
`}
|
|
45
|
+
>
|
|
46
|
+
{Link &&
|
|
47
|
+
<Button.Link
|
|
48
|
+
Link={Link}
|
|
49
|
+
href={href}
|
|
50
|
+
variant={detailsButtonVariant}
|
|
51
|
+
size={buttonSize}
|
|
52
|
+
onClick={trackViewDetails}
|
|
53
|
+
>
|
|
54
|
+
{detailsText}
|
|
55
|
+
</Button.Link>
|
|
56
|
+
}
|
|
57
|
+
{navigateToDetails &&
|
|
58
|
+
<Button.Anchor
|
|
59
|
+
href={href}
|
|
60
|
+
onClick={e => {
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
navigateToDetails(item);
|
|
63
|
+
trackViewDetails();
|
|
64
|
+
}}
|
|
65
|
+
variant={detailsButtonVariant}
|
|
66
|
+
size={buttonSize}
|
|
67
|
+
>
|
|
68
|
+
{detailsText}
|
|
69
|
+
</Button.Anchor>
|
|
70
|
+
}
|
|
71
|
+
{detailsUrl && useDetailsPostMessage !== true && navigateToDetails === null &&
|
|
72
|
+
<Button.Anchor
|
|
73
|
+
href={detailsUrl}
|
|
74
|
+
variant={detailsButtonVariant}
|
|
75
|
+
size={buttonSize}
|
|
76
|
+
onClick={trackViewDetails}
|
|
77
|
+
>
|
|
78
|
+
{detailsText}
|
|
79
|
+
</Button.Anchor>
|
|
80
|
+
}
|
|
81
|
+
{useDetailsPostMessage === true && navigateToDetails === null &&
|
|
82
|
+
<Button.Btn
|
|
83
|
+
onClick={() => {trackViewDetails; window.parent.postMessage({ itemId: itemId, type: 'LISTING_ID' }, '*'); }}
|
|
84
|
+
variant={detailsButtonVariant}
|
|
85
|
+
size={buttonSize}
|
|
86
|
+
>
|
|
87
|
+
{detailsText}
|
|
88
|
+
</Button.Btn>}
|
|
89
|
+
{applyUrl && !includeDialog && navigateToEasyApply == null &&
|
|
90
|
+
<Button.Anchor
|
|
91
|
+
href={applyUrl}
|
|
92
|
+
variant={applyButtonVariant}
|
|
93
|
+
size={buttonSize}
|
|
94
|
+
onClick={trackApply}
|
|
95
|
+
>
|
|
96
|
+
{applyText}
|
|
97
|
+
</Button.Anchor>
|
|
98
|
+
}
|
|
99
|
+
{applyUrl && !includeDialog && navigateToEasyApply != null &&
|
|
100
|
+
<Button.Btn
|
|
101
|
+
onClick={() => { navigateToEasyApply(item); trackApply(); }}
|
|
102
|
+
variant={applyButtonVariant}
|
|
103
|
+
size={buttonSize}
|
|
104
|
+
>
|
|
105
|
+
{applyText}
|
|
106
|
+
</Button.Btn>
|
|
107
|
+
}
|
|
108
|
+
{applyUrl && includeDialog &&
|
|
109
|
+
<ApplyDialog applyUrl={applyUrl} internalApplyLink={internalApplyLink} companyName={companyName}>
|
|
110
|
+
<Button.Anchor
|
|
111
|
+
variant={applyButtonVariant}
|
|
112
|
+
size={buttonSize}
|
|
113
|
+
onClick={trackApply}
|
|
114
|
+
>
|
|
115
|
+
{applyText}
|
|
116
|
+
</Button.Anchor>
|
|
117
|
+
</ApplyDialog>
|
|
118
|
+
}
|
|
119
|
+
</nav>
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export default ButtonGroupApply;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import Icon from '~/components/modules/icon';
|
|
4
|
+
import PillWrapper from '~/components/modules/buttons/pill-wrapper';
|
|
5
|
+
|
|
6
|
+
const CommutePill = ({ travelTime }) => {
|
|
7
|
+
if (!travelTime) return;
|
|
8
|
+
return (
|
|
9
|
+
<div className="pt-2">
|
|
10
|
+
<PillWrapper >
|
|
11
|
+
<Icon
|
|
12
|
+
icon="ri:pin-distance-fill"
|
|
13
|
+
size="hc-size-5"
|
|
14
|
+
className="hc-text-uiAccent/30"
|
|
15
|
+
/>
|
|
16
|
+
commute time = {travelTime}
|
|
17
|
+
</PillWrapper>
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default CommutePill;
|