Passed
Push — task/applicant-profile-api ( bae4f4 )
by Yonathan
05:49
created

JobWorkEnv.tsx ➔ convertSliderIdFromJob   A

Complexity

Conditions 2

Size

Total Lines 11
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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