@abcagency/hc-ui-components 1.0.0
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/globals.css +3 -0
- package/dist/index.js +4644 -0
- package/dist/output.css +784 -0
- package/dist/services/globals.css +3 -0
- package/dist/services/listingService.js +606 -0
- package/package.json +38 -0
- package/postcss.config.js +15 -0
- package/rollup.config.js +67 -0
- package/src/apis/hcApi.js +68 -0
- package/src/clientToken.js +9 -0
- package/src/components/layout/footer.js +34 -0
- package/src/components/layout/header.js +23 -0
- package/src/components/layout/layout.js +36 -0
- package/src/components/modules/accordions/MapAccordionItem.js +69 -0
- package/src/components/modules/accordions/default.js +173 -0
- package/src/components/modules/accordions/filterItem.js +53 -0
- package/src/components/modules/accordions/filters.js +44 -0
- package/src/components/modules/animations/slidein.js +41 -0
- package/src/components/modules/buttons/button-group-apply.js +75 -0
- package/src/components/modules/buttons/commute-pill.js +21 -0
- package/src/components/modules/buttons/default.js +196 -0
- package/src/components/modules/buttons/items-pill.js +31 -0
- package/src/components/modules/buttons/pill-wrapper.js +26 -0
- package/src/components/modules/buttons/show-all-button.js +20 -0
- package/src/components/modules/cards/default.js +168 -0
- package/src/components/modules/cards/filter.js +55 -0
- package/src/components/modules/dialogs/apply-dialog.js +47 -0
- package/src/components/modules/filter/commute.js +149 -0
- package/src/components/modules/filter/index.js +86 -0
- package/src/components/modules/filter/item.js +77 -0
- package/src/components/modules/filter/location.js +69 -0
- package/src/components/modules/filter/points-of-interest.js +43 -0
- package/src/components/modules/filter/radio-item.js +51 -0
- package/src/components/modules/filter/search.js +89 -0
- package/src/components/modules/filter/search.js.rej +9 -0
- package/src/components/modules/filter/sort.js +83 -0
- package/src/components/modules/form.js +362 -0
- package/src/components/modules/grid.js +75 -0
- package/src/components/modules/icon.js +33 -0
- package/src/components/modules/jobListing/listing-details.js +87 -0
- package/src/components/modules/jumbotron.js +81 -0
- package/src/components/modules/maps/info-window-card.js +17 -0
- package/src/components/modules/maps/info-window-content.js +60 -0
- package/src/components/modules/maps/list/field-mapper.js +113 -0
- package/src/components/modules/maps/list/header-item.js +90 -0
- package/src/components/modules/maps/list/header.js +46 -0
- package/src/components/modules/maps/list/index.js +104 -0
- package/src/components/modules/maps/list/item-expand-card/index.js +21 -0
- package/src/components/modules/maps/list/item-expand-card/recruiter-contact-nav.js +48 -0
- package/src/components/modules/maps/list/item-expand-card/recruiter-details.js +67 -0
- package/src/components/modules/maps/list/item-expand-card/recruiter-headshot.js +22 -0
- package/src/components/modules/maps/list/list-item/index.js +133 -0
- package/src/components/modules/maps/map-list.js +73 -0
- package/src/components/modules/maps/map-marker.js +84 -0
- package/src/components/modules/maps/map.js +218 -0
- package/src/components/modules/maps/place-marker.js +41 -0
- package/src/components/modules/maps/tabs.js +79 -0
- package/src/components/modules/navigation/nav-link.js +65 -0
- package/src/components/modules/navigation/navbar.js +109 -0
- package/src/components/modules/navigation/skip-link.js +21 -0
- package/src/components/modules/navigation/social.js +29 -0
- package/src/components/modules/sections/default.js +59 -0
- package/src/components/modules/sections/sectionContext.js +4 -0
- package/src/components/modules/video-player.js +126 -0
- package/src/constants/placeTypes.js +8 -0
- package/src/contexts/mapContext.js +116 -0
- package/src/contexts/mapListContext.js +212 -0
- package/src/contexts/placesContext.js +98 -0
- package/src/hooks/useClickOutside.js +16 -0
- package/src/hooks/useEventListener.js +25 -0
- package/src/hooks/useEventTracker.js +19 -0
- package/src/hooks/useList.js +102 -0
- package/src/hooks/useRefScrollProgress.js +24 -0
- package/src/hooks/useScript.js +63 -0
- package/src/hooks/useScrollDirection.js +39 -0
- package/src/hooks/useSectionTracker.js +95 -0
- package/src/hooks/useUserAgent.js +43 -0
- package/src/hooks/useWindowSize.js +28 -0
- package/src/index.css +25 -0
- package/src/index.js +116 -0
- package/src/services/configService.js +16 -0
- package/src/services/googlePlacesNearbyService.js +33 -0
- package/src/services/listingAggregatorService.js +42 -0
- package/src/services/listingEntityService.js +14 -0
- package/src/services/listingService.js +28 -0
- package/src/services/recruiterService.js +17 -0
- package/src/styles/fonts.js +0 -0
- package/src/styles/globals.css +25 -0
- package/src/tailwind/preset.default.js +15 -0
- package/src/tailwind/tailwind.config.js +126 -0
- package/src/util/arrayUtil.js +3 -0
- package/src/util/fieldMapper.js +19 -0
- package/src/util/filterUtil.js +195 -0
- package/src/util/loading.js +17 -0
- package/src/util/localStorageUtil.js +27 -0
- package/src/util/mapIconUtil.js +179 -0
- package/src/util/mapUtil.js +91 -0
- package/src/util/page-head.js +62 -0
- package/src/util/provider.js +12 -0
- package/src/util/sortUtil.js +33 -0
- package/src/util/stringUtils.js +6 -0
- package/src/util/urlFilterUtil.js +91 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { useForm, Controller } from 'react-hook-form';
|
|
3
|
+
import { yupResolver } from '@hookform/resolvers/yup';
|
|
4
|
+
import Slider from 'react-slider';
|
|
5
|
+
import * as Yup from 'yup';
|
|
6
|
+
|
|
7
|
+
let validationSchema = Yup.object().shape({
|
|
8
|
+
name: Yup.string()
|
|
9
|
+
.required("is required"),
|
|
10
|
+
email: Yup.string()
|
|
11
|
+
.email("Invalid email address format")
|
|
12
|
+
.required("is required"),
|
|
13
|
+
message: Yup.string()
|
|
14
|
+
.required("is required"),
|
|
15
|
+
transportation: Yup.array()
|
|
16
|
+
.min(1, "Select a transportation type"),
|
|
17
|
+
state: Yup.string()
|
|
18
|
+
.required("is required"),
|
|
19
|
+
distance: Yup.number()
|
|
20
|
+
.min(1, "is required")
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const ContactForm = () => {
|
|
24
|
+
const {
|
|
25
|
+
register,
|
|
26
|
+
handleSubmit,
|
|
27
|
+
setValue,
|
|
28
|
+
control,
|
|
29
|
+
trigger,
|
|
30
|
+
reset,
|
|
31
|
+
formState:{ errors }
|
|
32
|
+
} = useForm({
|
|
33
|
+
mode: 'onBlur',
|
|
34
|
+
defaultValues: {
|
|
35
|
+
name: '',
|
|
36
|
+
email: '',
|
|
37
|
+
message: '',
|
|
38
|
+
transportation: [],
|
|
39
|
+
favoriteColor: 'pink',
|
|
40
|
+
state: '',
|
|
41
|
+
distance: 0
|
|
42
|
+
},
|
|
43
|
+
resolver: yupResolver(validationSchema)
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
47
|
+
|
|
48
|
+
const onSubmit = values => {
|
|
49
|
+
setIsSubmitting(true);
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
alert(JSON.stringify(values, null, 2));
|
|
52
|
+
reset();
|
|
53
|
+
setIsSubmitting(false);
|
|
54
|
+
}, 1000);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const transportationOptions = ['Car', 'Boat', 'Plane'];
|
|
58
|
+
const favoriteColorOptions = ['blue', 'green', 'pink', 'red', 'yellow'];
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<form
|
|
62
|
+
onSubmit={handleSubmit(onSubmit)}
|
|
63
|
+
>
|
|
64
|
+
<div className="sm:grid grid-cols-2 gap-4">
|
|
65
|
+
<div className="mb-6">
|
|
66
|
+
<label
|
|
67
|
+
className="inline-block mb-2 text-xs font-bold uppercase"
|
|
68
|
+
htmlFor="name"
|
|
69
|
+
>
|
|
70
|
+
Name
|
|
71
|
+
</label>
|
|
72
|
+
|
|
73
|
+
{errors.name &&
|
|
74
|
+
<span
|
|
75
|
+
id="name-error"
|
|
76
|
+
name="name"
|
|
77
|
+
className="inline-block text-red-500 uppercase text-xs font-bold ml-1"
|
|
78
|
+
>
|
|
79
|
+
{errors.name?.message}
|
|
80
|
+
</span>
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
<input
|
|
84
|
+
{...register("name")}
|
|
85
|
+
type="text"
|
|
86
|
+
name="name"
|
|
87
|
+
placeholder="First and Last Name"
|
|
88
|
+
className={`w-full rounded-md transition-colors ${
|
|
89
|
+
errors.name ? "border-red-500" : "border-gray-800"
|
|
90
|
+
}`}
|
|
91
|
+
aria-invalid={errors.name ? 'true' : null}
|
|
92
|
+
aria-describedby={errors.name ? 'name-error' : null}
|
|
93
|
+
aria-required="true"
|
|
94
|
+
disabled={isSubmitting}
|
|
95
|
+
/>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<div className="mb-6">
|
|
99
|
+
<label
|
|
100
|
+
className="inline-block mb-2 text-xs font-bold uppercase"
|
|
101
|
+
htmlFor="email"
|
|
102
|
+
>
|
|
103
|
+
Email
|
|
104
|
+
</label>
|
|
105
|
+
|
|
106
|
+
{errors.email &&
|
|
107
|
+
<span
|
|
108
|
+
id="email-error"
|
|
109
|
+
name="email"
|
|
110
|
+
className="inline-block text-red-500 uppercase text-xs font-bold ml-1"
|
|
111
|
+
>
|
|
112
|
+
{errors.email?.message}
|
|
113
|
+
</span>
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
<input
|
|
117
|
+
{...register("email")}
|
|
118
|
+
type="email"
|
|
119
|
+
name="email"
|
|
120
|
+
placeholder="user@domain.com"
|
|
121
|
+
className={`w-full rounded-md transition-colors ${
|
|
122
|
+
errors.email ? "border-red-500" : "border-gray-800"
|
|
123
|
+
}`}
|
|
124
|
+
aria-invalid={errors.email ? 'true' : null}
|
|
125
|
+
aria-describedby={errors.email? 'email-error' : null}
|
|
126
|
+
aria-required="true"
|
|
127
|
+
disabled={isSubmitting}
|
|
128
|
+
/>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div className="grid grid-cols-2 gap-4">
|
|
133
|
+
<div className="mb-6">
|
|
134
|
+
<h2 id="transportation-group-title" className="inline-block text-xs uppercase font-bold mb-2">Transportation</h2>
|
|
135
|
+
|
|
136
|
+
{errors.transportation &&
|
|
137
|
+
<span
|
|
138
|
+
id="transportation-error"
|
|
139
|
+
name="email"
|
|
140
|
+
className="inline-block text-red-500 uppercase text-xs font-bold ml-1"
|
|
141
|
+
>
|
|
142
|
+
{errors.transportation?.message}
|
|
143
|
+
</span>
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
<div role="group" aria-labelledby="transportation-group-title" className="flex flex-col items-start">
|
|
147
|
+
{transportationOptions.map(value => (
|
|
148
|
+
<label
|
|
149
|
+
key={value}
|
|
150
|
+
className="inline-flex items-center mb-3"
|
|
151
|
+
>
|
|
152
|
+
<input
|
|
153
|
+
{...register(`transportation`)}
|
|
154
|
+
id={`transportation${value}`}
|
|
155
|
+
value={value}
|
|
156
|
+
type="checkbox"
|
|
157
|
+
className="rounded h-5 w-5 text-indigo-700 border-gray-800 transition-colors"
|
|
158
|
+
/>
|
|
159
|
+
<span className="ml-2">{value}</span>
|
|
160
|
+
</label>
|
|
161
|
+
))}
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<div className="mb-6">
|
|
166
|
+
<h2 id="favorite-color-group-title" className="inline-block text-xs uppercase font-bold mb-2">Favorite color</h2>
|
|
167
|
+
|
|
168
|
+
<div role="group" aria-labelledby="favorite-color-group-title" className="flex flex-col items-start">
|
|
169
|
+
{favoriteColorOptions.map(value => (
|
|
170
|
+
<label
|
|
171
|
+
key={value}
|
|
172
|
+
className="inline-flex items-center mb-3"
|
|
173
|
+
>
|
|
174
|
+
<input
|
|
175
|
+
{...register(`favoriteColor`)}
|
|
176
|
+
id={`favoriteColor${value}`}
|
|
177
|
+
value={value}
|
|
178
|
+
type="radio"
|
|
179
|
+
name="favoriteColor"
|
|
180
|
+
className="rounded-full h-5 w-5 text-indigo-700 border-gray-800 transition-colors"
|
|
181
|
+
/>
|
|
182
|
+
<span className="ml-2 capitalize">{value}</span>
|
|
183
|
+
</label>
|
|
184
|
+
))}
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
|
|
189
|
+
<div className="grid grid-cols-2 gap-4">
|
|
190
|
+
<div className="mb-6">
|
|
191
|
+
<label
|
|
192
|
+
className="inline-block mb-2 text-xs font-bold uppercase"
|
|
193
|
+
htmlFor="state"
|
|
194
|
+
>
|
|
195
|
+
State
|
|
196
|
+
</label>
|
|
197
|
+
|
|
198
|
+
{errors.state &&
|
|
199
|
+
<span
|
|
200
|
+
id="state-error"
|
|
201
|
+
name="state"
|
|
202
|
+
className="inline-block text-red-500 uppercase text-xs font-bold ml-1"
|
|
203
|
+
>
|
|
204
|
+
{errors.state?.message}
|
|
205
|
+
</span>
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
<select
|
|
209
|
+
{...register(`state`)}
|
|
210
|
+
className={`w-full rounded-md transition-colors ${
|
|
211
|
+
errors.state ? "border-red-500" : "border-gray-800"
|
|
212
|
+
}`}
|
|
213
|
+
aria-invalid={errors.state ? 'true' : null}
|
|
214
|
+
aria-describedby={errors.state ? 'state-error' : null}
|
|
215
|
+
aria-required="true"
|
|
216
|
+
disabled={isSubmitting}
|
|
217
|
+
>
|
|
218
|
+
<option value="">Select a state</option>
|
|
219
|
+
<option value="AL">Alabama</option>
|
|
220
|
+
<option value="AK">Alaska</option>
|
|
221
|
+
<option value="AZ">Arizona</option>
|
|
222
|
+
<option value="AR">Arkansas</option>
|
|
223
|
+
<option value="CA">California</option>
|
|
224
|
+
<option value="CO">Colorado</option>
|
|
225
|
+
<option value="CT">Connecticut</option>
|
|
226
|
+
<option value="DE">Delaware</option>
|
|
227
|
+
<option value="DC">District Of Columbia</option>
|
|
228
|
+
<option value="FL">Florida</option>
|
|
229
|
+
<option value="GA">Georgia</option>
|
|
230
|
+
<option value="HI">Hawaii</option>
|
|
231
|
+
<option value="ID">Idaho</option>
|
|
232
|
+
<option value="IL">Illinois</option>
|
|
233
|
+
<option value="IN">Indiana</option>
|
|
234
|
+
<option value="IA">Iowa</option>
|
|
235
|
+
<option value="KS">Kansas</option>
|
|
236
|
+
<option value="KY">Kentucky</option>
|
|
237
|
+
<option value="LA">Louisiana</option>
|
|
238
|
+
<option value="ME">Maine</option>
|
|
239
|
+
<option value="MD">Maryland</option>
|
|
240
|
+
<option value="MA">Massachusetts</option>
|
|
241
|
+
<option value="MI">Michigan</option>
|
|
242
|
+
<option value="MN">Minnesota</option>
|
|
243
|
+
<option value="MS">Mississippi</option>
|
|
244
|
+
<option value="MO">Missouri</option>
|
|
245
|
+
<option value="MT">Montana</option>
|
|
246
|
+
<option value="NE">Nebraska</option>
|
|
247
|
+
<option value="NV">Nevada</option>
|
|
248
|
+
<option value="NH">New Hampshire</option>
|
|
249
|
+
<option value="NJ">New Jersey</option>
|
|
250
|
+
<option value="NM">New Mexico</option>
|
|
251
|
+
<option value="NY">New York</option>
|
|
252
|
+
<option value="NC">North Carolina</option>
|
|
253
|
+
<option value="ND">North Dakota</option>
|
|
254
|
+
<option value="OH">Ohio</option>
|
|
255
|
+
<option value="OK">Oklahoma</option>
|
|
256
|
+
<option value="OR">Oregon</option>
|
|
257
|
+
<option value="PA">Pennsylvania</option>
|
|
258
|
+
<option value="RI">Rhode Island</option>
|
|
259
|
+
<option value="SC">South Carolina</option>
|
|
260
|
+
<option value="SD">South Dakota</option>
|
|
261
|
+
<option value="TN">Tennessee</option>
|
|
262
|
+
<option value="TX">Texas</option>
|
|
263
|
+
<option value="UT">Utah</option>
|
|
264
|
+
<option value="VT">Vermont</option>
|
|
265
|
+
<option value="VA">Virginia</option>
|
|
266
|
+
<option value="WA">Washington</option>
|
|
267
|
+
<option value="WV">West Virginia</option>
|
|
268
|
+
<option value="WI">Wisconsin</option>
|
|
269
|
+
<option value="WY">Wyoming</option>
|
|
270
|
+
</select>
|
|
271
|
+
</div>
|
|
272
|
+
<div className="mb-6 overflow-hidden">
|
|
273
|
+
<label
|
|
274
|
+
className="inline-block mb-2 text-xs font-bold uppercase"
|
|
275
|
+
htmlFor="distance"
|
|
276
|
+
>
|
|
277
|
+
Distance
|
|
278
|
+
</label>
|
|
279
|
+
|
|
280
|
+
{errors.distance &&
|
|
281
|
+
<span
|
|
282
|
+
id="distance-error"
|
|
283
|
+
name="distance"
|
|
284
|
+
className="inline-block text-red-500 uppercase text-xs font-bold ml-1"
|
|
285
|
+
>
|
|
286
|
+
{errors.distance?.message}
|
|
287
|
+
</span>
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
<Controller
|
|
291
|
+
name="distance"
|
|
292
|
+
control={control}
|
|
293
|
+
render={({ field }) =>
|
|
294
|
+
<>
|
|
295
|
+
<input
|
|
296
|
+
{...field}
|
|
297
|
+
type="hidden"
|
|
298
|
+
aria-invalid={errors.distance ? 'true' : null}
|
|
299
|
+
aria-describedby={errors.distance ? 'distance-error' : null}
|
|
300
|
+
aria-required="true"
|
|
301
|
+
/>
|
|
302
|
+
|
|
303
|
+
<Slider
|
|
304
|
+
max={99}
|
|
305
|
+
className="py-4"
|
|
306
|
+
thumbClassName={`p-2 w-10 rounded-full bg-gray-100 text-gray-700 transform -translate-y-1/3 text-center outline-none cursor-grab focus:bg-indigo-700 focus:text-white transition-colors ${errors.distance && "!text-red-500"}`}
|
|
307
|
+
trackClassName="bg-gray-300 h-3 rounded-md transition-colors"
|
|
308
|
+
renderThumb={(props, state) => <div {...props}>{state.valueNow}</div>}
|
|
309
|
+
onChange={v => setValue('distance', v)}
|
|
310
|
+
onAfterChange={() => trigger('distance')}
|
|
311
|
+
/>
|
|
312
|
+
</>
|
|
313
|
+
}
|
|
314
|
+
/>
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
|
|
318
|
+
<div className="mb-6">
|
|
319
|
+
<label
|
|
320
|
+
className="inline-block mb-2 text-xs font-bold uppercase"
|
|
321
|
+
htmlFor="message"
|
|
322
|
+
>
|
|
323
|
+
Message
|
|
324
|
+
</label>
|
|
325
|
+
|
|
326
|
+
{errors.message &&
|
|
327
|
+
<span
|
|
328
|
+
id="message-error"
|
|
329
|
+
name="message"
|
|
330
|
+
className="inline-block text-red-500 uppercase text-xs font-bold ml-1"
|
|
331
|
+
>
|
|
332
|
+
{errors.message?.message}
|
|
333
|
+
</span>
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
<textarea
|
|
337
|
+
{...register(`message`)}
|
|
338
|
+
id="message"
|
|
339
|
+
placeholder="Say something..."
|
|
340
|
+
rows="8"
|
|
341
|
+
className={`w-full rounded-md transition-colors ${
|
|
342
|
+
errors.message ? "border-red-500" : "border-gray-800"
|
|
343
|
+
}`}
|
|
344
|
+
aria-invalid={errors.message ? 'true' : null}
|
|
345
|
+
aria-describedby={errors.message ? 'state-error' : null}
|
|
346
|
+
aria-required="true"
|
|
347
|
+
disabled={isSubmitting}
|
|
348
|
+
/>
|
|
349
|
+
</div>
|
|
350
|
+
|
|
351
|
+
<button
|
|
352
|
+
type="submit"
|
|
353
|
+
className="px-4 py-2 text-sm font-bold text-white bg-gray-700 border-b-4 border-gray-800 rounded hover:border-gray-700 hover:bg-gray-600 transfrom disabled:bg-gray-200 disabled:text-gray-400 transition-colors"
|
|
354
|
+
disabled={isSubmitting}
|
|
355
|
+
>
|
|
356
|
+
{isSubmitting ? "Please wait..." : "Submit"}
|
|
357
|
+
</button>
|
|
358
|
+
</form>
|
|
359
|
+
);
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
export default ContactForm;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import SlideIn from '~/components/modules/animations/slidein';
|
|
5
|
+
|
|
6
|
+
const Grid = forwardRef((props, ref) => {
|
|
7
|
+
const {
|
|
8
|
+
as = 'div',
|
|
9
|
+
isAnimated = true,
|
|
10
|
+
children,
|
|
11
|
+
className,
|
|
12
|
+
autoRows = true,
|
|
13
|
+
columns = 'md:grid-cols-2',
|
|
14
|
+
gap = 'gap-12 lg:gap-16',
|
|
15
|
+
...rest
|
|
16
|
+
} = props;
|
|
17
|
+
|
|
18
|
+
const Container = as;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
isAnimated ?
|
|
22
|
+
<SlideIn>
|
|
23
|
+
<Container
|
|
24
|
+
ref={ref}
|
|
25
|
+
className={twMerge(
|
|
26
|
+
'grid',
|
|
27
|
+
gap,
|
|
28
|
+
autoRows ? 'auto-rows-min' : '',
|
|
29
|
+
'grid-cols-1',
|
|
30
|
+
columns,
|
|
31
|
+
className ?? ''
|
|
32
|
+
)}
|
|
33
|
+
{...rest}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</Container>
|
|
37
|
+
</SlideIn>
|
|
38
|
+
:
|
|
39
|
+
<Container
|
|
40
|
+
ref={ref}
|
|
41
|
+
className={twMerge(
|
|
42
|
+
'grid',
|
|
43
|
+
gap,
|
|
44
|
+
autoRows ? 'auto-rows-min' : '',
|
|
45
|
+
'grid-cols-1',
|
|
46
|
+
columns,
|
|
47
|
+
className ?? ''
|
|
48
|
+
)}
|
|
49
|
+
{...rest}
|
|
50
|
+
>
|
|
51
|
+
{children}
|
|
52
|
+
</Container>
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export const GridItem = ({
|
|
57
|
+
as = 'div',
|
|
58
|
+
children,
|
|
59
|
+
className
|
|
60
|
+
}) => {
|
|
61
|
+
const Container = as;
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<Container
|
|
65
|
+
className={className ?? ''}
|
|
66
|
+
>
|
|
67
|
+
{children}
|
|
68
|
+
</Container>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
Grid.Item = GridItem;
|
|
73
|
+
|
|
74
|
+
Grid.displayName = 'Grid';
|
|
75
|
+
export default Grid;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Icon } from '@iconify/react';
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
const IconContained = ({
|
|
5
|
+
className,
|
|
6
|
+
size,
|
|
7
|
+
icon,
|
|
8
|
+
iconClasses,
|
|
9
|
+
title,
|
|
10
|
+
...iconProps
|
|
11
|
+
}) => {
|
|
12
|
+
return (
|
|
13
|
+
<span
|
|
14
|
+
title={title}
|
|
15
|
+
className={`
|
|
16
|
+
inline-block align-middle
|
|
17
|
+
${className ?? ''}
|
|
18
|
+
${size ?? ''}
|
|
19
|
+
`}
|
|
20
|
+
>
|
|
21
|
+
<Icon
|
|
22
|
+
icon={icon}
|
|
23
|
+
className={`
|
|
24
|
+
${iconClasses ?? ''}
|
|
25
|
+
${size ?? ''}
|
|
26
|
+
`}
|
|
27
|
+
{...iconProps}
|
|
28
|
+
/>
|
|
29
|
+
</span>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default IconContained;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
import RecruiterHeadshot from "../maps/list/item-expand-card/recruiter-headshot";
|
|
3
|
+
import RecruiterDetails from "../maps/list/item-expand-card/recruiter-details";
|
|
4
|
+
import ApplyButtonGroup from "../buttons/button-group-apply";
|
|
5
|
+
import RecruiterContactNav from "../maps/list/item-expand-card/recruiter-contact-nav";
|
|
6
|
+
import { useMap } from "~/contexts/mapContext";
|
|
7
|
+
import { useMapList } from "~/contexts/mapListContext";
|
|
8
|
+
import CommutePill from "../buttons/commute-pill";
|
|
9
|
+
|
|
10
|
+
const ListingDetails = ({ item, recruiters }) => {
|
|
11
|
+
const { travelTime } = useMap();
|
|
12
|
+
const { siteConfig } = useMapList();
|
|
13
|
+
if (!item) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
let matchingRecruiter = !recruiters ? null : recruiters[item?.recruiterId];
|
|
17
|
+
return (<div className="w-full">
|
|
18
|
+
<div className="grow flex flex-wrap items-center gap-4">
|
|
19
|
+
{matchingRecruiter?.headshot && (
|
|
20
|
+
<RecruiterHeadshot
|
|
21
|
+
image={`https:${matchingRecruiter.headshot}`}
|
|
22
|
+
alt={matchingRecruiter?.firstName}
|
|
23
|
+
className="bg-gray-300"
|
|
24
|
+
/>
|
|
25
|
+
)}
|
|
26
|
+
{matchingRecruiter && (
|
|
27
|
+
<RecruiterDetails
|
|
28
|
+
contactNav={
|
|
29
|
+
<RecruiterContactNav>
|
|
30
|
+
{matchingRecruiter?.mobilePhone && (
|
|
31
|
+
<RecruiterContactNav.Button
|
|
32
|
+
href={`tel:${matchingRecruiter.mobilePhone}`}
|
|
33
|
+
title={`Call ${matchingRecruiter.mobilePhone}`}
|
|
34
|
+
icon="fluent:phone-32-regular"
|
|
35
|
+
/>
|
|
36
|
+
)}
|
|
37
|
+
{matchingRecruiter?.email && (
|
|
38
|
+
<RecruiterContactNav.Button
|
|
39
|
+
href={`mailto:${matchingRecruiter.email}`}
|
|
40
|
+
title={`email ${matchingRecruiter.email}`}
|
|
41
|
+
icon="bi:envelope-at"
|
|
42
|
+
/>
|
|
43
|
+
)}
|
|
44
|
+
{matchingRecruiter?.linkedIn && (
|
|
45
|
+
<RecruiterContactNav.Button
|
|
46
|
+
href={matchingRecruiter.linkedIn}
|
|
47
|
+
title="LinkedIn"
|
|
48
|
+
icon="ant-design:linkedin-outlined"
|
|
49
|
+
/>
|
|
50
|
+
)}
|
|
51
|
+
</RecruiterContactNav>
|
|
52
|
+
}
|
|
53
|
+
>
|
|
54
|
+
{matchingRecruiter?.firstName && matchingRecruiter?.lastName && (
|
|
55
|
+
<RecruiterDetails.Title>
|
|
56
|
+
{`${matchingRecruiter?.firstName} ${matchingRecruiter?.lastName}`}
|
|
57
|
+
</RecruiterDetails.Title>
|
|
58
|
+
)}
|
|
59
|
+
{item.details?.recruiter?.title && (
|
|
60
|
+
<RecruiterDetails.Text>
|
|
61
|
+
{item.details.recruiter.title}
|
|
62
|
+
</RecruiterDetails.Text>
|
|
63
|
+
)}
|
|
64
|
+
</RecruiterDetails>
|
|
65
|
+
)}
|
|
66
|
+
<ApplyButtonGroup
|
|
67
|
+
useDetailsPostMessage={siteConfig.useDetailsPostMessage}
|
|
68
|
+
includeDialog={siteConfig.useApplyDialog}
|
|
69
|
+
internalApplyLink={siteConfig.internalApplyLink}
|
|
70
|
+
companyName={siteConfig.companyName}
|
|
71
|
+
applyUrl={item?.applyUrl}
|
|
72
|
+
itemId={item.id}
|
|
73
|
+
detailsUrl={item.useClientJobUrl ? item?.detailsUrl : `${siteConfig.jobsDomain}${item.id}`}
|
|
74
|
+
className={`
|
|
75
|
+
lg:flex-col lg:w-auto order-first lg:order-last md:self-center py-2 lg:p-0 lg:mb-0 border-b lg:border-none border-uiAccent/20
|
|
76
|
+
${matchingRecruiter ? "lg:flex-col lg:w-auto" : "lg:flex-row"}
|
|
77
|
+
`}
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
<div className="w-full">
|
|
81
|
+
<CommutePill travelTime={travelTime} className="ml-0" />
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export default ListingDetails;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { twMerge } from 'tailwind-merge';
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
const Jumbotron = ({
|
|
5
|
+
className,
|
|
6
|
+
contentClasses,
|
|
7
|
+
image,
|
|
8
|
+
children,
|
|
9
|
+
...rest
|
|
10
|
+
}) => {
|
|
11
|
+
return (
|
|
12
|
+
<section
|
|
13
|
+
className={twMerge(
|
|
14
|
+
'relative grid grid-cols-1 auto-rows-min md:grid-rows-1 overflow-hidden bg-gray-800 text-white',
|
|
15
|
+
className ?? ''
|
|
16
|
+
)}
|
|
17
|
+
{...rest}
|
|
18
|
+
>
|
|
19
|
+
<div
|
|
20
|
+
className={twMerge(
|
|
21
|
+
'md:row-span-full col-span-full grid place-content-center relative z-10 container p-4',
|
|
22
|
+
contentClasses ?? ''
|
|
23
|
+
)}
|
|
24
|
+
>
|
|
25
|
+
{children}
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
{image && image}
|
|
29
|
+
</section>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const JumbotronTitle = ({
|
|
34
|
+
className,
|
|
35
|
+
children
|
|
36
|
+
}) => {
|
|
37
|
+
return (
|
|
38
|
+
<h1
|
|
39
|
+
className={twMerge(
|
|
40
|
+
'text-3xl font-bold',
|
|
41
|
+
className ?? ''
|
|
42
|
+
)}
|
|
43
|
+
>
|
|
44
|
+
{children}
|
|
45
|
+
</h1>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const JumbotronImage = ({
|
|
50
|
+
image,
|
|
51
|
+
alt,
|
|
52
|
+
className,
|
|
53
|
+
containerClassName,
|
|
54
|
+
...rest
|
|
55
|
+
}) => {
|
|
56
|
+
return (
|
|
57
|
+
<div
|
|
58
|
+
className={twMerge(
|
|
59
|
+
'relative order-first md:order-last row-span-full col-span-full',
|
|
60
|
+
containerClassName ?? ''
|
|
61
|
+
)}
|
|
62
|
+
>
|
|
63
|
+
<img
|
|
64
|
+
src={image || image.src}
|
|
65
|
+
width={image.width ? image.width : null}
|
|
66
|
+
height={image.height ? image.height : null}
|
|
67
|
+
alt={alt ?? ''}
|
|
68
|
+
className={twMerge(
|
|
69
|
+
'md:col-start-1 h-full w-full object-cover object-center opacity-70 md:opacity-20',
|
|
70
|
+
className ?? ''
|
|
71
|
+
)}
|
|
72
|
+
{...rest}
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
Jumbotron.Title = JumbotronTitle;
|
|
79
|
+
Jumbotron.Image = JumbotronImage;
|
|
80
|
+
|
|
81
|
+
export default Jumbotron;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
const CardInfoWindow = ({ className, content, id }) => {
|
|
4
|
+
return (
|
|
5
|
+
<div
|
|
6
|
+
id={id}
|
|
7
|
+
className={`
|
|
8
|
+
relative flex flex-col break-words bg-clip-border
|
|
9
|
+
${className ?? ""}
|
|
10
|
+
`}
|
|
11
|
+
>
|
|
12
|
+
{content}
|
|
13
|
+
</div>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default CardInfoWindow;
|