Passed
Push — dev ( fe3a39...db5d9e )
by Grant
04:10 queued 11s
created

JobWorkEnv.tsx ➔ convertSliderIdToJob   A

Complexity

Conditions 2

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 2
1
/* eslint-disable jsx-a11y/label-has-associated-control, camelcase, @typescript-eslint/camelcase */
2
import React, { useState, useRef } from "react";
3
import { Form, Formik, FormikTouched, FormikErrors, FastField } from "formik";
4
import * as Yup from "yup";
5
import nprogress from "nprogress";
6
import {
7
  FormattedMessage,
8
  MessageDescriptor,
9
  IntlShape,
10
  useIntl,
11
} from "react-intl";
12
import RadioGroup from "../../Form/RadioGroup";
13
import ContextBlock from "../../ContextBlock/ContextBlock";
14
import ContextBlockItem from "../../ContextBlock/ContextBlockItem";
15
import CopyToClipboardButton from "../../CopyToClipboardButton";
16
import JobWorkEnvModal from "./JobWorkEnvModal";
17
import RadioInput from "../../Form/RadioInput";
18
import NumberInput from "../../Form/NumberInput";
19
import TextAreaInput from "../../Form/TextAreaInput";
20
import { validationMessages } from "../../Form/Messages";
21
import { Job } from "../../../models/types";
22
import { emptyJob } from "../../../models/jobUtil";
23
import {
24
  notEmpty,
25
  hasKey,
26
  mapToObjectTrans,
27
  identity,
28
} from "../../../helpers/queries";
29
import {
30
  physEnvOptions,
31
  techOptions,
32
  amenitiesOptions,
33
  phyEnvDescriptions,
34
  techDescriptions,
35
  amenitiesDescriptions,
36
} from "./WorkEnvFeatures";
37
import { localizeField, getLocale } from "../../../helpers/localize";
38
import {
39
  formMessages,
40
  culturePaceMessages,
41
  mgmtStyleMessages,
42
  experimentalMessages,
43
  facingMessages,
44
  collaborativenessMessages,
45
} from "./JobWorkEnvMessages";
46
import CheckboxGroupField from "../../Form/CheckboxGroupField";
47
48
type CulturePaceId =
49
  | "culturePace01"
50
  | "culturePace02"
51
  | "culturePace03"
52
  | "culturePace04";
53
const culturePaceList: {
54
  id: CulturePaceId;
55
  title: MessageDescriptor;
56
  subtext: MessageDescriptor;
57
}[] = [
58
  {
59
    id: "culturePace01",
60
    title: culturePaceMessages.pace01Title,
61
    subtext: culturePaceMessages.pace01Description,
62
  },
63
  {
64
    id: "culturePace02",
65
    title: culturePaceMessages.pace02Title,
66
    subtext: culturePaceMessages.pace02Description,
67
  },
68
  {
69
    id: "culturePace03",
70
    title: culturePaceMessages.pace03Title,
71
    subtext: culturePaceMessages.pace03Description,
72
  },
73
  {
74
    id: "culturePace04",
75
    title: culturePaceMessages.pace04Title,
76
    subtext: culturePaceMessages.pace04Description,
77
  },
78
];
79
80
type MgmtStyleId =
81
  | "mgmtStyle01"
82
  | "mgmtStyle02"
83
  | "mgmtStyle03"
84
  | "mgmtStyle04";
85
const managementList: {
86
  id: MgmtStyleId;
87
  title: MessageDescriptor;
88
  subtext: MessageDescriptor;
89
}[] = [
90
  {
91
    id: "mgmtStyle01",
92
    title: mgmtStyleMessages.style01Title,
93
    subtext: mgmtStyleMessages.style01Description,
94
  },
95
  {
96
    id: "mgmtStyle02",
97
    title: mgmtStyleMessages.style02Title,
98
    subtext: mgmtStyleMessages.style02Description,
99
  },
100
  {
101
    id: "mgmtStyle03",
102
    title: mgmtStyleMessages.style03Title,
103
    subtext: mgmtStyleMessages.style03Description,
104
  },
105
  {
106
    id: "mgmtStyle04",
107
    title: mgmtStyleMessages.style04Title,
108
    subtext: mgmtStyleMessages.style04Description,
109
  },
110
];
111
112
type ExperiementalId =
113
  | "experimental01"
114
  | "experimental02"
115
  | "experimental03"
116
  | "experimental04";
117
const experimentalList: {
118
  id: ExperiementalId;
119
  title: MessageDescriptor;
120
  subtext: MessageDescriptor;
121
}[] = [
122
  {
123
    id: "experimental01",
124
    title: experimentalMessages.experimental01Title,
125
    subtext: experimentalMessages.experimental01Description,
126
  },
127
  {
128
    id: "experimental02",
129
    title: experimentalMessages.experimental02Title,
130
    subtext: experimentalMessages.experimental02Description,
131
  },
132
  {
133
    id: "experimental03",
134
    title: experimentalMessages.experimental03Title,
135
    subtext: experimentalMessages.experimental03Description,
136
  },
137
  {
138
    id: "experimental04",
139
    title: experimentalMessages.experimental04Title,
140
    subtext: experimentalMessages.experimental04Description,
141
  },
142
];
143
144
type FacingId = "facing01" | "facing02" | "facing03" | "facing04";
145
const facingList: {
146
  id: FacingId;
147
  title: MessageDescriptor;
148
  subtext: MessageDescriptor;
149
}[] = [
150
  {
151
    id: "facing01",
152
    title: facingMessages.facing01Title,
153
    subtext: facingMessages.facing01Description,
154
  },
155
  {
156
    id: "facing02",
157
    title: facingMessages.facing02Title,
158
    subtext: facingMessages.facing02Description,
159
  },
160
  {
161
    id: "facing03",
162
    title: facingMessages.facing03Title,
163
    subtext: facingMessages.facing03Description,
164
  },
165
  {
166
    id: "facing04",
167
    title: facingMessages.facing04Title,
168
    subtext: facingMessages.facing04Description,
169
  },
170
];
171
172
type CollaborativenessId =
173
  | "collaborativeness01"
174
  | "collaborativeness02"
175
  | "collaborativeness03"
176
  | "collaborativeness04";
177
const collaborativenessList: {
178
  id: CollaborativenessId;
179
  title: MessageDescriptor;
180
  subtext: MessageDescriptor;
181
}[] = [
182
  {
183
    id: "collaborativeness01",
184
    title: collaborativenessMessages.collaborativeness01Title,
185
    subtext: collaborativenessMessages.collaborativeness01Description,
186
  },
187
  {
188
    id: "collaborativeness02",
189
    title: collaborativenessMessages.collaborativeness02Title,
190
    subtext: collaborativenessMessages.collaborativeness02Description,
191
  },
192
  {
193
    id: "collaborativeness03",
194
    title: collaborativenessMessages.collaborativeness03Title,
195
    subtext: collaborativenessMessages.collaborativeness03Description,
196
  },
197
  {
198
    id: "collaborativeness04",
199
    title: collaborativenessMessages.collaborativeness04Title,
200
    subtext: collaborativenessMessages.collaborativeness04Description,
201
  },
202
];
203
204
// shape of values used in Form
205
export interface JobWorkEnvValues {
206
  teamSize: number | "";
207
  physicalEnv: string[];
208
  technology: string[];
209
  amenities: string[];
210
  envDescription: string;
211
  culturePace?: CulturePaceId;
212
  management?: MgmtStyleId;
213
  experimental?: ExperiementalId;
214
  facing?: FacingId;
215
  collaborativeness?: CollaborativenessId;
216
  cultureSummary: string;
217
  moreCultureSummary: string;
218
}
219
220
function convertSliderIdFromJob<T>(
221
  key: string,
222
  formSliderArray: { id: T }[],
223
  jobSliderId: number | null,
224
): { [key: string]: T } | {} {
225
  return jobSliderId && jobSliderId > 0 && jobSliderId <= formSliderArray.length
226
    ? {
227
        [key]: formSliderArray[jobSliderId - 1].id,
228
      }
229
    : { [key]: undefined };
230
}
231
232
const jobToValues = (
233
  {
234
    team_size,
235
    fast_vs_steady,
236
    horizontal_vs_vertical,
237
    experimental_vs_ongoing,
238
    citizen_facing_vs_back_office,
239
    collaborative_vs_independent,
240
    work_env_features,
241
    ...job
242
  }: Job,
243
  locale: "en" | "fr",
244
): JobWorkEnvValues => {
245
  const isTrueInEnvFeatures = (option: string): boolean =>
246
    work_env_features !== null &&
247
    hasKey(work_env_features, option) &&
248
    work_env_features[option];
249
250
  return {
251
    teamSize: team_size || "",
252
    physicalEnv: physEnvOptions.filter(isTrueInEnvFeatures),
253
    technology: techOptions.filter(isTrueInEnvFeatures),
254
    amenities: amenitiesOptions.filter(isTrueInEnvFeatures),
255
    ...convertSliderIdFromJob("culturePace", culturePaceList, fast_vs_steady),
256
    ...convertSliderIdFromJob(
257
      "management",
258
      managementList,
259
      horizontal_vs_vertical,
260
    ),
261
    ...convertSliderIdFromJob(
262
      "experimental",
263
      experimentalList,
264
      experimental_vs_ongoing,
265
    ),
266
    ...convertSliderIdFromJob(
267
      "facing",
268
      facingList,
269
      citizen_facing_vs_back_office,
270
    ),
271
    ...convertSliderIdFromJob(
272
      "collaborativeness",
273
      collaborativenessList,
274
      collaborative_vs_independent,
275
    ),
276
    envDescription: localizeField(locale, job, "work_env_description") || "",
277
    cultureSummary: localizeField(locale, job, "culture_summary") || "",
278
    moreCultureSummary: localizeField(locale, job, "culture_special") || "",
279
  };
280
};
281
282
function convertSliderIdToJob(
283
  formSliderArray: { id: string }[],
284
  id: string | undefined,
285
): number | null {
286
  if (id === undefined) {
287
    return null;
288
  }
289
  return formSliderArray.map((item): string => item.id).indexOf(id) + 1;
290
}
291
292
const updateJobWithValues = (
293
  job: Job,
294
  locale: "en" | "fr",
295
  {
296
    teamSize,
297
    physicalEnv,
298
    technology,
299
    amenities,
300
    envDescription,
301
    culturePace,
302
    management,
303
    experimental,
304
    facing,
305
    collaborativeness,
306
    cultureSummary,
307
    moreCultureSummary,
308
  }: JobWorkEnvValues,
309
): Job => {
310
  const physFeatures = mapToObjectTrans(
311
    physEnvOptions,
312
    identity,
313
    (option): boolean => physicalEnv.includes(option),
314
  );
315
  const techFeatures = mapToObjectTrans(
316
    techOptions,
317
    identity,
318
    (option): boolean => technology.includes(option),
319
  );
320
  const amenityFeatures = mapToObjectTrans(
321
    amenitiesOptions,
322
    identity,
323
    (option): boolean => amenities.includes(option),
324
  );
325
  const workEnvFeatures = {
326
    ...physFeatures,
327
    ...techFeatures,
328
    ...amenityFeatures,
329
  };
330
  return {
331
    ...job,
332
    team_size: teamSize || null,
333
    fast_vs_steady: convertSliderIdToJob(culturePaceList, culturePace),
334
    horizontal_vs_vertical: convertSliderIdToJob(managementList, management),
335
    experimental_vs_ongoing: convertSliderIdToJob(
336
      experimentalList,
337
      experimental,
338
    ),
339
    citizen_facing_vs_back_office: convertSliderIdToJob(facingList, facing),
340
    collaborative_vs_independent: convertSliderIdToJob(
341
      collaborativenessList,
342
      collaborativeness,
343
    ),
344
    work_env_features: workEnvFeatures,
345
    work_env_description: {
346
      ...job.work_env_description,
347
      [locale]: envDescription || null,
348
    },
349
    culture_summary: {
350
      ...job.culture_summary,
351
      [locale]: cultureSummary || null,
352
    },
353
    culture_special: {
354
      ...job.culture_special,
355
      [locale]: moreCultureSummary || null,
356
    },
357
  };
358
};
359
360
const renderRadioWithContext = (
361
  intl: IntlShape,
362
  touched: FormikTouched<JobWorkEnvValues>,
363
  errors: FormikErrors<JobWorkEnvValues>,
364
  values: JobWorkEnvValues,
365
  fieldName: string,
366
  label: string,
367
  sliderList: {
368
    id: string;
369
    title: MessageDescriptor;
370
    subtext: MessageDescriptor;
371
  }[],
372
): React.ReactElement => {
373
  return (
374
    <div className="job-builder-culture-block" data-c-grid-item="base(1of1)">
375
      <div data-c-grid="gutter">
376
        <RadioGroup
377
          id={fieldName}
378
          label={label}
379
          required
380
          touched={touched[fieldName]}
381
          error={errors[fieldName]}
382
          value={values[fieldName]}
383
          grid="base(1of1) tl(1of3)"
384
        >
385
          {sliderList.map(
386
            ({ id, title }): React.ReactElement => {
387
              return (
388
                <FastField
389
                  key={id}
390
                  name={fieldName}
391
                  component={RadioInput}
392
                  id={id}
393
                  label={intl.formatMessage(title)}
394
                  value={id}
395
                  trigger
396
                  required
397
                />
398
              );
399
            },
400
          )}
401
        </RadioGroup>
402
        <ContextBlock
403
          className="job-builder-context-block"
404
          grid="base(1of1) tl(2of3)"
405
        >
406
          {sliderList.map(
407
            ({ id, title, subtext }): React.ReactElement => {
408
              return (
409
                <ContextBlockItem
410
                  key={id}
411
                  contextId={id}
412
                  title={intl.formatMessage(title)}
413
                  subtext={intl.formatMessage(subtext)}
414
                  className="job-builder-context-item"
415
                  active={values[fieldName] === id}
416
                />
417
              );
418
            },
419
          )}
420
        </ContextBlock>
421
      </div>
422
    </div>
423
  );
424
};
425
426
interface JobWorkEnvProps {
427
  // Optional Job to prepopulate form values from.
428
  job: Job | null;
429
  // A boolean that gives you the state of the request for the job data.
430
  jobIsComplete: boolean;
431
  // Submit function that runs after successful validation.
432
  // It must return the submitted job, if successful.
433
  handleSubmit: (values: Job) => Promise<Job>;
434
  // The function to run when user clicks Prev Page
435
  handleReturn: () => void;
436
  // Function to run when modal cancel is clicked.
437
  handleModalCancel: () => void;
438
  // Function to run when modal confirm is clicked.
439
  handleModalConfirm: () => void;
440
  handleSkipToReview: () => Promise<void>;
441
}
442
443
const JobWorkEnv = ({
444
  job,
445
  handleSubmit,
446
  handleReturn,
447
  handleModalCancel,
448
  handleModalConfirm,
449
  jobIsComplete,
450
  handleSkipToReview,
451
}: JobWorkEnvProps): React.ReactElement => {
452
  const intl = useIntl();
453
  const locale = getLocale(intl.locale);
454
  const [isModalVisible, setIsModalVisible] = useState(false);
455
456
  const initialValues: JobWorkEnvValues = job
457
    ? jobToValues(job, locale)
458
    : {
459
        teamSize: "",
460
        physicalEnv: [],
461
        technology: [],
462
        amenities: [],
463
        culturePace: undefined,
464
        management: undefined,
465
        experimental: undefined,
466
        facing: undefined,
467
        collaborativeness: undefined,
468
        envDescription: "",
469
        cultureSummary: "",
470
        moreCultureSummary: "",
471
      };
472
473
  const phyEnvData: { value: string; label: string }[] = phyEnvDescriptions(
474
    intl,
475
  );
476
  const techData: { value: string; label: string }[] = techDescriptions(intl);
477
  const amenitiesData: {
478
    value: string;
479
    label: string;
480
  }[] = amenitiesDescriptions(intl);
481
482
  const modalParentRef = useRef<HTMLDivElement>(null);
483
  const workEnvSchema = Yup.object().shape({
484
    teamSize: Yup.number()
485
      .min(1, intl.formatMessage(validationMessages.required))
486
      .required(intl.formatMessage(validationMessages.required)),
487
    physicalEnv: Yup.array().of(Yup.string()),
488
    technology: Yup.array().of(Yup.string()),
489
    amenities: Yup.array().of(Yup.string()),
490
    envDescription: Yup.string(),
491
    culturePace: Yup.string()
492
      .oneOf(culturePaceList.map((item): string => item.id))
493
      .required(intl.formatMessage(validationMessages.checkboxRequired)),
494
    management: Yup.string()
495
      .oneOf(managementList.map((item): string => item.id))
496
      .required(intl.formatMessage(validationMessages.checkboxRequired)),
497
    experimental: Yup.string()
498
      .oneOf(experimentalList.map((item): string => item.id))
499
      .required(intl.formatMessage(validationMessages.checkboxRequired)),
500
    facing: Yup.string()
501
      .oneOf(facingList.map((item): string => item.id))
502
      .required(intl.formatMessage(validationMessages.checkboxRequired)),
503
    collaborativeness: Yup.string()
504
      .oneOf(collaborativenessList.map((item): string => item.id))
505
      .required(intl.formatMessage(validationMessages.checkboxRequired)),
506
  });
507
508
  /** Compiles and returns all the active radio buttons corresponding context box values within the culture section  */
509
  const buildCultureSummary = (values: JobWorkEnvValues): string => {
510
    const pace = culturePaceList.find(
511
      ({ id }): boolean => id === values.culturePace,
512
    );
513
    const management = managementList.find(
514
      ({ id }): boolean => id === values.management,
515
    );
516
    const experimental = experimentalList.find(
517
      ({ id }): boolean => id === values.experimental,
518
    );
519
    const facing = facingList.find(({ id }): boolean => id === values.facing);
520
    const collaborativeness = collaborativenessList.find(
521
      ({ id }): boolean => id === values.collaborativeness,
522
    );
523
524
    const cultureSummary: string = [
525
      pace,
526
      management,
527
      experimental,
528
      facing,
529
      collaborativeness,
530
    ]
531
      .filter(notEmpty)
532
      .map((item): string => intl.formatMessage(item.subtext))
533
      .join(" ");
534
    return cultureSummary;
535
  };
536
537
  const updateValuesAndReturn = (values: JobWorkEnvValues): void => {
538
    nprogress.start();
539
    // If custom summary textbox is length is zero, set cultureSummary to generated text
540
    const cultureSummary =
541
      values.cultureSummary.length === 0
542
        ? buildCultureSummary(values)
543
        : values.cultureSummary;
544
    const formValues: JobWorkEnvValues = { ...values, cultureSummary };
545
    const oldJob = job || emptyJob();
546
    const updatedJob = updateJobWithValues(oldJob, locale, formValues);
547
    handleSubmit(updatedJob).then((): void => {
548
      nprogress.done();
549
      handleReturn();
550
    });
551
  };
552
553
  return (
554
    <div
555
      data-c-container="form"
556
      data-c-padding="top(triple) bottom(triple)"
557
      ref={modalParentRef}
558
    >
559
      <h3
560
        data-c-font-size="h3"
561
        data-c-font-weight="bold"
562
        data-c-margin="bottom(double)"
563
      >
564
        <FormattedMessage
565
          id="jobBuilder.workEnv.title"
566
          defaultMessage="Work Environment"
567
          description="Header of job poster builder work environment step."
568
        />
569
      </h3>
570
      <p>
571
        <FormattedMessage
572
          id="jobBuilder.workEnv.stepDescription"
573
          defaultMessage={`Applicants care a lot about the team they'll be working with and the physical workspace as well. Sharing information about these things help applicants determine if they'll be a good fit, and can reduce the number of "wishful thinking" applications that slow down the screening process.`}
574
          description="Description of job poster builder work environment step."
575
        />
576
      </p>
577
      <div data-c-grid-item="base(1of1)">
578
        <h4 data-c-font-size="h4" data-c-margin="top(triple) bottom(normal)">
579
          <FormattedMessage
580
            id="jobBuilder.workEnv.ourWorkEnv"
581
            defaultMessage="Our Work Environment"
582
            description="Section 1 of Job Poster Builder Work Environment Step"
583
          />
584
        </h4>
585
        <p data-c-margin="bottom(normal)">
586
          {intl.formatMessage(formMessages.ourWorkEnvDesc)}
587
        </p>
588
      </div>
589
590
      <Formik
591
        enableReinitialize
592
        initialValues={initialValues}
593
        validationSchema={workEnvSchema}
594
        onSubmit={(values, { setSubmitting }): void => {
595
          // If custom summary textbox is length is zero, set cultureSummary to generated text
596
          const cultureSummary =
597
            values.cultureSummary.length === 0
598
              ? buildCultureSummary(values)
599
              : values.cultureSummary;
600
          const formValues: JobWorkEnvValues = { ...values, cultureSummary };
601
          const oldJob = job || emptyJob();
602
          const updatedJob = updateJobWithValues(oldJob, locale, formValues);
603
604
          nprogress.start();
605
          handleSubmit(updatedJob)
606
            .then((): void => {
607
              nprogress.done();
608
              setIsModalVisible(true);
609
            })
610
            .finally((): void => {
611
              setSubmitting(false);
612
            });
613
        }}
614
      >
615
        {({ errors, touched, isSubmitting, values }): React.ReactElement => (
616
          <>
617
            <Form id="form" data-c-margin="bottom(normal)">
618
              <FastField
619
                id="teamSize"
620
                type="number"
621
                name="teamSize"
622
                component={NumberInput}
623
                required
624
                min={1}
625
                grid="tl(1of2)"
626
                label={intl.formatMessage(formMessages.teamSizeLabel)}
627
                placeholder={intl.formatMessage(
628
                  formMessages.teamSizePlaceholder,
629
                )}
630
              />
631
              <div data-c-grid-item="base(1of1)">
632
                <CheckboxGroupField
633
                  id="physicalEnv"
634
                  groupLabel={intl.formatMessage(formMessages.physicalEnvLabel)}
635
                  name="physicalEnv"
636
                  allBoxes={phyEnvData}
637
                  grid="base(1of2)"
638
                />
639
              </div>
640
              <div data-c-grid-item="base(1of1)">
641
                <CheckboxGroupField
642
                  id="technology"
643
                  groupLabel={intl.formatMessage(formMessages.technologyLabel)}
644
                  name="technology"
645
                  allBoxes={techData}
646
                  grid="base(1of2)"
647
                />
648
              </div>
649
              <div data-c-grid-item="base(1of1)">
650
                <CheckboxGroupField
651
                  id="amenities"
652
                  groupLabel={intl.formatMessage(formMessages.amenitiesLabel)}
653
                  name="amenities"
654
                  allBoxes={amenitiesData}
655
                  grid="base(1of2)"
656
                />
657
              </div>
658
              <p
659
                data-c-margin="bottom(normal) top(normal)"
660
                data-c-font-weight="bold"
661
              >
662
                {intl.formatMessage(formMessages.moreOnWorkEnv)}
663
              </p>
664
              <p data-c-margin="bottom(normal)">
665
                {intl.formatMessage(formMessages.thisIsOptional)}
666
              </p>
667
              <p data-c-margin="bottom(normal)">
668
                {intl.formatMessage(formMessages.moreOnWorkEnvSubtext)}
669
              </p>
670
              <FastField
671
                type="textarea"
672
                id="environment_description"
673
                name="envDescription"
674
                label={intl.formatMessage(formMessages.moreOnWorkEnvLabel)}
675
                placeholder={intl.formatMessage(
676
                  formMessages.moreOnWorkEnvPlaceholder,
677
                )}
678
                component={TextAreaInput}
679
                grid="base(1of2)"
680
              />
681
              <div data-c-grid-item="base(1of1)">
682
                <h4
683
                  data-c-font-size="h4"
684
                  data-c-margin="top(double) bottom(normal)"
685
                >
686
                  {intl.formatMessage(formMessages.culture)}
687
                </h4>
688
                <p data-c-margin="bottom(normal)">
689
                  <FormattedMessage
690
                    id="jobBuilder.workEnv.cultureSubtext1"
691
                    defaultMessage="Now let applicants know more about the personality of your team and the type of work that you usually do."
692
                    description="Subtext 1 displayed of the our culture section."
693
                  />
694
                </p>
695
                <p data-c-margin="bottom(normal)">
696
                  {intl.formatMessage(formMessages.cultureSubtext2)}
697
                </p>
698
              </div>
699
              {renderRadioWithContext(
700
                intl,
701
                touched,
702
                errors,
703
                values,
704
                "culturePace",
705
                intl.formatMessage(formMessages.fastPacedSteadyLabel),
706
                culturePaceList,
707
              )}
708
              {renderRadioWithContext(
709
                intl,
710
                touched,
711
                errors,
712
                values,
713
                "management",
714
                intl.formatMessage(formMessages.managementLabel),
715
                managementList,
716
              )}
717
              {renderRadioWithContext(
718
                intl,
719
                touched,
720
                errors,
721
                values,
722
                "experimental",
723
                intl.formatMessage(formMessages.experimentalLabel),
724
                experimentalList,
725
              )}
726
              {renderRadioWithContext(
727
                intl,
728
                touched,
729
                errors,
730
                values,
731
                "facing",
732
                intl.formatMessage(formMessages.facingLabel),
733
                facingList,
734
              )}
735
              {renderRadioWithContext(
736
                intl,
737
                touched,
738
                errors,
739
                values,
740
                "collaborativeness",
741
                intl.formatMessage(formMessages.collaborativeLabel),
742
                collaborativenessList,
743
              )}
744
              <div data-c-grid-item="base(1of1)">
745
                <p
746
                  data-c-margin="bottom(normal) top(normal)"
747
                  data-c-font-weight="bold"
748
                >
749
                  {intl.formatMessage(formMessages.cultureSummary)}
750
                </p>
751
                <p data-c-margin="bottom(normal)">
752
                  {intl.formatMessage(formMessages.cultureSummarySubtext)}
753
                </p>
754
                <ContextBlockItem subtext={buildCultureSummary(values)} />
755
                <div
756
                  data-c-alignment="base(centre) tl(right)"
757
                  data-c-margin="top(normal)"
758
                >
759
                  <CopyToClipboardButton
760
                    actionText={
761
                      <FormattedMessage
762
                        id="button.copyToClipboard"
763
                        defaultMessage="Copy to Clipboard"
764
                        description="Button to copy text to clipboard."
765
                      />
766
                    }
767
                    postActionText={
768
                      <FormattedMessage
769
                        id="button.copied"
770
                        defaultMessage="Copied!"
771
                        description="Confirmation for Button to copy text to clipboard."
772
                      />
773
                    }
774
                    textToCopy={buildCultureSummary(values)}
775
                  />
776
                </div>
777
              </div>
778
              <FastField
779
                type="textarea"
780
                id="custom_culture_summary"
781
                name="cultureSummary"
782
                label={intl.formatMessage(
783
                  formMessages.customCultureSummaryLabel,
784
                )}
785
                placeholder={intl.formatMessage(
786
                  formMessages.customCultureSummaryPlaceholder,
787
                )}
788
                component={TextAreaInput}
789
                grid="base(1of1)"
790
              />
791
              <p data-c-margin="bottom(normal)" data-c-font-weight="bold">
792
                {intl.formatMessage(formMessages.specialWorkCulture)}
793
              </p>
794
              <p data-c-margin="bottom(normal)">
795
                {intl.formatMessage(formMessages.thisIsOptional)}
796
              </p>
797
              <p data-c-margin="bottom(normal)">
798
                {intl.formatMessage(formMessages.specialWorkCultureSubtext)}
799
              </p>
800
              <FastField
801
                type="textarea"
802
                id="more_culture_summary"
803
                name="moreCultureSummary"
804
                label={intl.formatMessage(formMessages.specialWorkCultureLabel)}
805
                placeholder={intl.formatMessage(
806
                  formMessages.textAreaPlaceholder1,
807
                )}
808
                component={TextAreaInput}
809
                grid="base(1of1)"
810
              />
811
              <div data-c-grid="gutter" data-c-grid-item="base(1of1)">
812
                <div data-c-grid-item="base(1of1)">
813
                  <hr data-c-margin="top(normal) bottom(normal)" />
814
                </div>
815
                <div
816
                  data-c-alignment="base(centre) tp(left)"
817
                  data-c-grid-item="tp(1of2)"
818
                >
819
                  <button
820
                    data-c-button="outline(c2)"
821
                    data-c-radius="rounded"
822
                    type="button"
823
                    disabled={isSubmitting}
824
                    onClick={(): void => {
825
                      updateValuesAndReturn(values);
826
                    }}
827
                  >
828
                    <FormattedMessage
829
                      id="jobBuilder.workEnv.saveAndReturnButtonLabel"
830
                      defaultMessage="Save & Return to Job Details"
831
                      description="Label for Save & Return button on Work Environment form."
832
                    />
833
                  </button>
834
                </div>
835
                <div
836
                  data-c-alignment="base(centre) tp(right)"
837
                  data-c-grid-item="tp(1of2)"
838
                >
839
                  <button
840
                    data-c-button="solid(c1)"
841
                    data-c-radius="rounded"
842
                    type="submit"
843
                    disabled={isSubmitting}
844
                  >
845
                    <FormattedMessage
846
                      id="jobBuilder.workEnv.submitButtonLabel"
847
                      defaultMessage="Save & Preview"
848
                      description="Label for work environment submit button."
849
                    />
850
                  </button>
851
                </div>
852
              </div>
853
            </Form>
854
            <JobWorkEnvModal
855
              modalConfirm={(): void => {
856
                setIsModalVisible(false);
857
                handleModalConfirm();
858
              }}
859
              modalCancel={(): void => {
860
                setIsModalVisible(false);
861
                handleModalCancel();
862
              }}
863
              isVisible={isModalVisible}
864
              parentElement={modalParentRef.current}
865
              values={values}
866
              cultureSummary={
867
                values.cultureSummary || buildCultureSummary(values)
868
              }
869
              jobIsComplete={jobIsComplete}
870
              handleSkipToReview={(): void => {
871
                handleSkipToReview().finally((): void => {
872
                  setIsModalVisible(false);
873
                });
874
              }}
875
            />
876
          </>
877
        )}
878
      </Formik>
879
    </div>
880
  );
881
};
882
883
export default JobWorkEnv;
884