Passed
Push — feature/azure-webapp-pipeline-... ( 5f3462...4237ea )
by Grant
04:59
created

resources/assets/js/components/Application/Experience/Experience.tsx   F

Complexity

Total Complexity 89
Complexity/F 0

Size

Lines of Code 766
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 89
eloc 649
mnd 89
bc 89
fnc 0
dl 0
loc 766
rs 1.951
bpm 0
cpm 0
noi 0
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like resources/assets/js/components/Application/Experience/Experience.tsx often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/* eslint-disable camelcase */
2
/* eslint-disable @typescript-eslint/camelcase */
3
import * as React from "react";
4
import { FormattedMessage, useIntl, defineMessages } from "react-intl";
5
import {
6
  Skill,
7
  ExperienceEducation,
8
  ExperienceWork,
9
  ExperienceCommunity,
10
  Experience,
11
  ExperiencePersonal,
12
  ExperienceAward,
13
  ExperienceSkill,
14
  Criteria,
15
} from "../../../models/types";
16
import { localizeFieldNonNull, getLocale } from "../../../helpers/localize";
17
import {
18
  SkillTypeId,
19
  CriteriaTypeId,
20
  getKeyByValue,
21
  ClassificationId,
22
} from "../../../models/lookupConstants";
23
import EducationExperienceModal, {
24
  messages as educationMessages,
25
  EducationType,
26
  EducationStatus,
27
  EducationExperienceSubmitData,
28
} from "../ExperienceModals/EducationExperienceModal";
29
30
import WorkExperienceModal, {
31
  messages as workMessages,
32
  WorkExperienceSubmitData,
33
} from "../ExperienceModals/WorkExperienceModal";
34
import CommunityExperienceModal, {
35
  messages as communityMessages,
36
  CommunityExperienceSubmitData,
37
} from "../ExperienceModals/CommunityExperienceModal";
38
import PersonalExperienceModal, {
39
  messages as personalMessages,
40
  PersonalExperienceSubmitData,
41
} from "../ExperienceModals/PersonalExperienceModal";
42
import AwardExperienceModal, {
43
  messages as awardMessages,
44
  AwardRecipientType,
45
  AwardRecognitionType,
46
  AwardExperienceSubmitData,
47
} from "../ExperienceModals/AwardExperienceModal";
48
import ExperienceEducationAccordion from "../ExperienceAccordions/ExperienceEducationAccordion";
49
import ExperienceWorkAccordion from "../ExperienceAccordions/ExperienceWorkAccordion";
50
import ExperienceCommunityAccordion from "../ExperienceAccordions/ExperienceCommunityAccordion";
51
import ExperiencePersonalAccordion from "../ExperienceAccordions/ExperiencePersonalAccordion";
52
import ExperienceAwardAccordion from "../ExperienceAccordions/ExperienceAwardAccordion";
53
import {
54
  getSkillOfCriteria,
55
  getSkillsOfExperience,
56
  getDisconnectedRequiredSkills,
57
} from "../helpers";
58
import { navigationMessages, experienceMessages } from "../applicationMessages";
59
60
const messages = defineMessages({
61
  educationTypeMissing: {
62
    id: "application.experience.educationTypeMissing",
63
    defaultMessage: "Education type not found",
64
    description: "Error message for when the education type cannot be found.",
65
  },
66
  educationStatusMissing: {
67
    id: "application.experience.educationStatusMissing",
68
    defaultMessage: "Education status not found",
69
    description: "Error message for when the education status cannot be found.",
70
  },
71
  awardRecipientMissing: {
72
    id: "application.experience.awardRecipientMissing",
73
    defaultMessage: "Award recipient not found",
74
    description: "Error message for when the award recipient cannot be found.",
75
  },
76
  awardRecognitionMissing: {
77
    id: "application.experience.awardRecognitionMissing",
78
    defaultMessage: "Award recognition not found",
79
    description:
80
      "Error message for when the award recognition cannot be found.",
81
  },
82
  errorRenderingExperience: {
83
    id: "application.experience.errorRenderingExperience",
84
    defaultMessage: "Experience failed to render (experience type missing).",
85
    description: "Error message displayed when experience fails to render.",
86
  },
87
});
88
89
export type ExperienceSubmitData =
90
  | EducationExperienceSubmitData
91
  | WorkExperienceSubmitData
92
  | CommunityExperienceSubmitData
93
  | PersonalExperienceSubmitData
94
  | AwardExperienceSubmitData;
95
96
interface ExperienceProps {
97
  experiences: Experience[];
98
  educationStatuses: EducationStatus[];
99
  educationTypes: EducationType[];
100
  experienceSkills: ExperienceSkill[];
101
  criteria: Criteria[];
102
  skills: Skill[];
103
  jobId: number;
104
  jobClassificationId: number;
105
  recipientTypes: AwardRecipientType[];
106
  recognitionTypes: AwardRecognitionType[];
107
  handleSubmitExperience: (data: ExperienceSubmitData) => Promise<void>;
108
  handleDeleteExperience: (
109
    id: number,
110
    type: Experience["type"],
111
  ) => Promise<void>;
112
  handleContinue: () => void;
113
  handleQuit: () => void;
114
  handleReturn: () => void;
115
}
116
117
const MyExperience: React.FunctionComponent<ExperienceProps> = ({
118
  experiences,
119
  educationStatuses,
120
  educationTypes,
121
  experienceSkills,
122
  criteria,
123
  skills,
124
  handleSubmitExperience,
125
  handleDeleteExperience,
126
  jobId,
127
  jobClassificationId,
128
  recipientTypes,
129
  recognitionTypes,
130
  handleContinue,
131
  handleQuit,
132
  handleReturn,
133
}) => {
134
  const intl = useIntl();
135
  const locale = getLocale(intl.locale);
136
137
  const jobClassification = getKeyByValue(
138
    ClassificationId,
139
    jobClassificationId,
140
  );
141
142
  const [experienceData, setExperienceData] = React.useState<
143
    | (Experience & {
144
        savedOptionalSkills: Skill[];
145
        savedRequiredSkills: Skill[];
146
      })
147
    | null
148
  >(null);
149
150
  const [isModalVisible, setIsModalVisible] = React.useState<{
151
    id: Experience["type"] | "";
152
    visible: boolean;
153
  }>({
154
    id: "",
155
    visible: false,
156
  });
157
158
  const filteredSkills = criteria.reduce(
159
    (result, criterion): { essential: Skill[]; asset: Skill[] } => {
160
      const skillOfCriterion = getSkillOfCriteria(criterion, skills);
161
      if (skillOfCriterion) {
162
        if (criterion.criteria_type_id === CriteriaTypeId.Essential) {
163
          result.essential.push(skillOfCriterion);
164
        }
165
        if (criterion.criteria_type_id === CriteriaTypeId.Asset) {
166
          result.asset.push(skillOfCriterion);
167
        }
168
      }
169
      return result;
170
    },
171
    { essential: [], asset: [] } as { essential: Skill[]; asset: Skill[] },
172
  );
173
174
  const essentialSkills = filteredSkills.essential;
175
  const assetSkills = filteredSkills.asset;
176
177
  getDisconnectedRequiredSkills(experiences, experienceSkills, essentialSkills);
178
179
  const [
180
    disconnectedRequiredSkills,
181
    setDisconnectedRequiredSkills,
182
  ] = React.useState<Skill[]>(
183
    getDisconnectedRequiredSkills(
184
      experiences,
185
      experienceSkills,
186
      essentialSkills,
187
    ),
188
  );
189
190
  const openModal = (id: Experience["type"]): void => {
191
    setIsModalVisible({ id, visible: true });
192
  };
193
194
  const closeModal = (): void => {
195
    setDisconnectedRequiredSkills(
196
      getDisconnectedRequiredSkills(
197
        experiences,
198
        experienceSkills,
199
        essentialSkills,
200
      ),
201
    );
202
    setExperienceData(null);
203
    setIsModalVisible({ id: "", visible: false });
204
  };
205
206
  const submitExperience = (data: ExperienceSubmitData): Promise<void> =>
207
    handleSubmitExperience(data).then(closeModal);
208
209
  const editExperience = (
210
    experience: Experience,
211
    savedOptionalSkills: Skill[],
212
    savedRequiredSkills: Skill[],
213
  ): void => {
214
    setExperienceData({
215
      ...experience,
216
      savedOptionalSkills,
217
      savedRequiredSkills,
218
    });
219
    setIsModalVisible({ id: experience.type, visible: true });
220
  };
221
222
  const deleteExperience = (experience: Experience): Promise<void> =>
223
    handleDeleteExperience(experience.id, experience.type).then(closeModal);
224
225
  const softSkills = [...assetSkills, ...essentialSkills].filter(
226
    (skill) => skill.skill_type_id === SkillTypeId.Soft,
227
  );
228
229
  const modalButtons: {
230
    [key: string]: { id: Experience["type"]; title: string; icon: string };
231
  } = {
232
    education: {
233
      id: "experience_education",
234
      title: intl.formatMessage(educationMessages.modalTitle),
235
      icon: "fas fa-book",
236
    },
237
    work: {
238
      id: "experience_work",
239
      title: intl.formatMessage(workMessages.modalTitle),
240
      icon: "fas fa-briefcase",
241
    },
242
    community: {
243
      id: "experience_community",
244
      title: intl.formatMessage(communityMessages.modalTitle),
245
      icon: "fas fa-people-carry",
246
    },
247
    personal: {
248
      id: "experience_personal",
249
      title: intl.formatMessage(personalMessages.modalTitle),
250
      icon: "fas fa-mountain",
251
    },
252
    award: {
253
      id: "experience_award",
254
      title: intl.formatMessage(awardMessages.modalTitle),
255
      icon: "fas fa-trophy",
256
    },
257
  };
258
259
  const modalButton = ({ id, title, icon }): React.ReactElement => (
260
    <div key={id} data-c-grid-item="base(1of2) tp(1of3) tl(1of5)">
261
      <button
262
        className="application-experience-trigger"
263
        data-c-card
264
        data-c-background="c1(100)"
265
        data-c-radius="rounded"
266
        title={title}
267
        data-c-dialog-id={id}
268
        data-c-dialog-action="open"
269
        type="button"
270
        onClick={(): void => openModal(id)}
271
      >
272
        <i className={icon} aria-hidden="true" />
273
        <span data-c-font-size="regular" data-c-font-weight="bold">
274
          {title}
275
        </span>
276
      </button>
277
    </div>
278
  );
279
280
  const modalRoot = document.getElementById("modal-root");
281
282
  const experienceAccordion = (
283
    experience: Experience,
284
    irrelevantSkillCount: number,
285
    relevantSkills: ExperienceSkill[],
286
    handleEdit: () => void,
287
    handleDelete: () => void,
288
  ): React.ReactElement => {
289
    switch (experience.type) {
290
      case "experience_education":
291
        return (
292
          <ExperienceEducationAccordion
293
            key={`${experience.id}-${experience.type}`}
294
            areaOfStudy={experience.area_of_study}
295
            educationType={localizeFieldNonNull(
296
              locale,
297
              experience,
298
              "education_type",
299
            )}
300
            endDate={experience.end_date}
301
            handleDelete={handleDelete}
302
            handleEdit={handleEdit}
303
            institution={experience.institution}
304
            irrelevantSkillCount={irrelevantSkillCount}
305
            isActive={experience.is_active}
306
            isEducationJustification={experience.is_education_requirement}
307
            relevantSkills={relevantSkills}
308
            skills={skills}
309
            showButtons
310
            showSkillDetails
311
            startDate={experience.start_date}
312
            status={localizeFieldNonNull(
313
              locale,
314
              experience,
315
              "education_status",
316
            )}
317
            thesisTitle={experience.thesis_title}
318
          />
319
        );
320
      case "experience_work":
321
        return (
322
          <ExperienceWorkAccordion
323
            key={`${experience.id}-${experience.type}`}
324
            endDate={experience.end_date}
325
            group={experience.group}
326
            handleDelete={handleDelete}
327
            handleEdit={handleEdit}
328
            irrelevantSkillCount={irrelevantSkillCount}
329
            isActive={experience.is_active}
330
            isEducationJustification={experience.is_education_requirement}
331
            organization={experience.organization}
332
            relevantSkills={relevantSkills}
333
            skills={skills}
334
            showButtons
335
            showSkillDetails
336
            startDate={experience.start_date}
337
            title={experience.title}
338
          />
339
        );
340
      case "experience_community":
341
        return (
342
          <ExperienceCommunityAccordion
343
            key={`${experience.id}-${experience.type}`}
344
            endDate={experience.end_date}
345
            group={experience.group}
346
            handleDelete={handleDelete}
347
            handleEdit={handleEdit}
348
            irrelevantSkillCount={irrelevantSkillCount}
349
            isActive={experience.is_active}
350
            isEducationJustification={experience.is_education_requirement}
351
            project={experience.project}
352
            relevantSkills={relevantSkills}
353
            skills={skills}
354
            showButtons
355
            showSkillDetails
356
            startDate={experience.start_date}
357
            title={experience.title}
358
          />
359
        );
360
      case "experience_personal":
361
        return (
362
          <ExperiencePersonalAccordion
363
            key={`${experience.id}-${experience.type}`}
364
            description={experience.description}
365
            endDate={experience.end_date}
366
            handleDelete={handleDelete}
367
            handleEdit={handleEdit}
368
            irrelevantSkillCount={irrelevantSkillCount}
369
            isActive={experience.is_active}
370
            isEducationJustification={experience.is_education_requirement}
371
            isShareable={experience.is_shareable}
372
            relevantSkills={relevantSkills}
373
            skills={skills}
374
            showButtons
375
            showSkillDetails
376
            startDate={experience.start_date}
377
            title={experience.title}
378
          />
379
        );
380
      case "experience_award":
381
        return (
382
          <ExperienceAwardAccordion
383
            key={`${experience.id}-${experience.type}`}
384
            awardedDate={experience.awarded_date}
385
            handleDelete={handleDelete}
386
            handleEdit={handleEdit}
387
            irrelevantSkillCount={irrelevantSkillCount}
388
            isEducationJustification={experience.is_education_requirement}
389
            issuer={experience.issued_by}
390
            recipient={localizeFieldNonNull(
391
              locale,
392
              experience,
393
              "award_recipient_type",
394
            )}
395
            relevantSkills={relevantSkills}
396
            skills={skills}
397
            scope={localizeFieldNonNull(
398
              locale,
399
              experience,
400
              "award_recognition_type",
401
            )}
402
            showButtons
403
            showSkillDetails
404
            title={experience.title}
405
          />
406
        );
407
      default:
408
        return (
409
          <div
410
            data-c-background="gray(10)"
411
            data-c-radius="rounded"
412
            data-c-border="all(thin, solid, gray)"
413
            data-c-margin="top(1)"
414
            data-c-padding="all(1)"
415
          >
416
            <div data-c-align="base(center)">
417
              <p data-c-color="stop">
418
                {intl.formatMessage(messages.errorRenderingExperience)}
419
              </p>
420
            </div>
421
          </div>
422
        );
423
    }
424
  };
425
426
  return (
427
    <>
428
      <div data-c-container="medium">
429
        <h2 data-c-heading="h2" data-c-margin="top(3) bottom(1)">
430
          {intl.formatMessage(experienceMessages.heading)}
431
        </h2>
432
        <p data-c-margin="bottom(1)">
433
          <FormattedMessage
434
            id="application.experience.preamble"
435
            defaultMessage="Use the buttons below to add experiences you want to share with the manager. Experiences you have added in the past also appear below, and you can edit them to link them to skills required for this job when necessary."
436
            description="First section of text on the experience step of the Application Timeline."
437
          />
438
        </p>
439
        <div data-c-grid="gutter(all, 1)">
440
          {essentialSkills.length > 0 && (
441
            <div data-c-grid-item="tl(1of2)">
442
              <p data-c-margin="bottom(.5)">
443
                <FormattedMessage
444
                  id="application.experience.essentialSkillsListIntro"
445
                  description="Text before the list of essential skills on the experience step of the Application Timeline."
446
                  defaultMessage="This job <span>requires</span> the following skills:"
447
                  values={{
448
                    span: (chunks): React.ReactElement => (
449
                      <span data-c-font-weight="bold" data-c-color="c2">
450
                        {chunks}
451
                      </span>
452
                    ),
453
                  }}
454
                />
455
              </p>
456
              <ul data-c-margin="bottom(1)">
457
                {essentialSkills.map((skill) => (
458
                  <li key={skill.id}>
459
                    {localizeFieldNonNull(locale, skill, "name")}
460
                  </li>
461
                ))}
462
              </ul>
463
            </div>
464
          )}
465
          {assetSkills.length > 0 && (
466
            <div data-c-grid-item="tl(1of2)">
467
              <p data-c-margin="bottom(.5)">
468
                <FormattedMessage
469
                  id="application.experience.assetSkillsListIntro"
470
                  defaultMessage="These skills are beneficial, but not required:"
471
                  description="Text before the list of asset skills on the experience step of the Application Timeline."
472
                />
473
              </p>
474
              <ul data-c-margin="bottom(1)">
475
                {assetSkills.map((skill) => (
476
                  <li key={skill.id}>
477
                    {localizeFieldNonNull(locale, skill, "name")}
478
                  </li>
479
                ))}
480
              </ul>
481
            </div>
482
          )}
483
        </div>
484
        <p data-c-color="gray" data-c-margin="bottom(2)">
485
          <FormattedMessage
486
            id="application.experience.softSkillsList"
487
            defaultMessage="Don't forget, {skill} will be evaluated later in the hiring process."
488
            description="List of soft skills that will be evaluated later."
489
            values={{
490
              skill: (
491
                <>
492
                  {softSkills.map((skill, index) => {
493
                    const and = " and ";
494
                    const lastElement = index === softSkills.length - 1;
495
                    return (
496
                      <>
497
                        {lastElement && softSkills.length > 1 && and}
498
                        <span key={skill.id} data-c-font-weight="bold">
499
                          {localizeFieldNonNull(locale, skill, "name")}
500
                        </span>
501
                        {!lastElement && softSkills.length > 2 && ", "}
502
                      </>
503
                    );
504
                  })}
505
                </>
506
              ),
507
            }}
508
          />
509
        </p>
510
        {/* Experience Modal Buttons */}
511
        <div data-c-grid="gutter(all, 1)">
512
          {Object.keys(modalButtons).map((id) => modalButton(modalButtons[id]))}
513
        </div>
514
        {/* Experience Accordion List */}
515
        {experiences && experiences.length > 0 ? (
516
          <div className="experience-list" data-c-margin="top(2)">
517
            <div data-c-accordion-group>
518
              {experiences.map((experience) => {
519
                const savedOptionalSkills = getSkillsOfExperience(
520
                  experienceSkills,
521
                  experience,
522
                  assetSkills,
523
                );
524
                const savedRequiredSkills = getSkillsOfExperience(
525
                  experienceSkills,
526
                  experience,
527
                  essentialSkills,
528
                );
529
                const relevantSkills: ExperienceSkill[] =
530
                  savedRequiredSkills.map((skill) => {
531
                    const experienceSkill = experienceSkills.find(
532
                      ({ experience_id, experience_type, skill_id }) =>
533
                        experience_id === experience.experienceable_id &&
534
                        skill_id === skill.id &&
535
                        experience_type === experience.type,
536
                    );
537
                    return {
538
                      id: experienceSkill?.id ?? 0,
539
                      skill_id: experienceSkill?.skill_id ?? 0,
540
                      experience_id: experienceSkill?.experience_id ?? 0,
541
                      experience_type: experienceSkill?.experience_type ?? "",
542
                      justification: experienceSkill?.justification ?? "",
543
                      created_at: experienceSkill?.created_at ?? new Date(),
544
                      updated_at: experienceSkill?.updated_at ?? new Date(),
545
                    };
546
                  }) ?? [];
547
548
                // Number of skills attached to Experience but are not part of the jobs skill criteria.
549
                const irrelevantSkillCount =
550
                  experienceSkills.filter(
551
                    (experienceSkill) =>
552
                      experienceSkill.experience_id === experience.id &&
553
                      experienceSkill.experience_type === experience.type,
554
                  ).length -
555
                  (savedOptionalSkills.length + savedRequiredSkills.length);
556
557
                return experienceAccordion(
558
                  experience,
559
                  irrelevantSkillCount,
560
                  relevantSkills,
561
                  () =>
562
                    editExperience(
563
                      experience,
564
                      savedOptionalSkills,
565
                      savedRequiredSkills,
566
                    ),
567
                  () => deleteExperience(experience),
568
                );
569
              })}
570
            </div>
571
          </div>
572
        ) : (
573
          <div
574
            data-c-background="gray(10)"
575
            data-c-radius="rounded"
576
            data-c-border="all(thin, solid, gray)"
577
            data-c-margin="top(2)"
578
            data-c-padding="all(1)"
579
          >
580
            <div data-c-align="base(center)">
581
              <p data-c-color="gray">
582
                <FormattedMessage
583
                  id="application.experience.noExperiences"
584
                  defaultMessage="Looks like you don't have any experience added yet. Use the buttons above to add experience. Don't forget that experience will always be saved to your profile so that you can use it on future applications!"
585
                  description="Message displayed when application has no experiences."
586
                />
587
              </p>
588
            </div>
589
          </div>
590
        )}
591
        {disconnectedRequiredSkills && disconnectedRequiredSkills.length > 0 && (
592
          <p data-c-color="stop" data-c-margin="top(2)">
593
            <FormattedMessage
594
              id="application.experience.unconnectedSkills"
595
              defaultMessage="The following required skill(s) are not connected to your experience:"
596
              description="Message showing list of required skills that are not connected to a experience."
597
            />{" "}
598
            {disconnectedRequiredSkills.map((skill) => (
599
              <>
600
                <span
601
                  data-c-tag="stop"
602
                  data-c-radius="pill"
603
                  data-c-font-size="small"
604
                >
605
                  {localizeFieldNonNull(locale, skill, "name")}
606
                </span>{" "}
607
              </>
608
            ))}
609
          </p>
610
        )}
611
      </div>
612
      <div data-c-container="medium" data-c-padding="tb(2)">
613
        <hr data-c-hr="thin(c1)" data-c-margin="bottom(2)" />
614
        <div data-c-grid="gutter">
615
          <div
616
            data-c-alignment="base(centre) tp(left)"
617
            data-c-grid-item="tp(1of2)"
618
          >
619
            <button
620
              data-c-button="outline(c2)"
621
              data-c-radius="rounded"
622
              type="button"
623
              onClick={(): void => handleReturn()}
624
            >
625
              {intl.formatMessage(navigationMessages.return)}
626
            </button>
627
          </div>
628
          <div
629
            data-c-alignment="base(centre) tp(right)"
630
            data-c-grid-item="tp(1of2)"
631
          >
632
            <button
633
              data-c-button="outline(c2)"
634
              data-c-radius="rounded"
635
              type="button"
636
              onClick={(): void => handleQuit()}
637
            >
638
              {intl.formatMessage(navigationMessages.quit)}
639
            </button>
640
            <button
641
              data-c-button="solid(c1)"
642
              data-c-radius="rounded"
643
              data-c-margin="left(1)"
644
              type="button"
645
              onClick={(): void => handleContinue()}
646
            >
647
              {intl.formatMessage(navigationMessages.continue)}
648
            </button>
649
          </div>
650
        </div>
651
      </div>
652
653
      <div data-c-dialog-overlay={isModalVisible.visible ? "active" : ""} />
654
      <EducationExperienceModal
655
        educationStatuses={educationStatuses}
656
        educationTypes={educationTypes}
657
        experienceEducation={experienceData as ExperienceEducation}
658
        experienceableId={experienceData?.experienceable_id ?? 0}
659
        experienceableType={
660
          experienceData?.experienceable_type ?? "application"
661
        }
662
        jobId={jobId}
663
        jobClassification={jobClassification}
664
        modalId={modalButtons.education.id}
665
        onModalCancel={closeModal}
666
        onModalConfirm={submitExperience}
667
        optionalSkills={assetSkills}
668
        parentElement={modalRoot}
669
        requiredSkills={essentialSkills}
670
        savedOptionalSkills={experienceData?.savedOptionalSkills ?? []}
671
        savedRequiredSkills={experienceData?.savedRequiredSkills ?? []}
672
        visible={
673
          isModalVisible.visible &&
674
          isModalVisible.id === modalButtons.education.id
675
        }
676
      />
677
      <WorkExperienceModal
678
        experienceWork={experienceData as ExperienceWork}
679
        experienceableId={experienceData?.experienceable_id ?? 0}
680
        experienceableType={
681
          experienceData?.experienceable_type ?? "application"
682
        }
683
        jobId={jobId}
684
        jobClassification={jobClassification}
685
        modalId={modalButtons.work.id}
686
        onModalCancel={closeModal}
687
        onModalConfirm={submitExperience}
688
        optionalSkills={assetSkills}
689
        parentElement={modalRoot}
690
        requiredSkills={essentialSkills}
691
        savedOptionalSkills={experienceData?.savedOptionalSkills ?? []}
692
        savedRequiredSkills={experienceData?.savedRequiredSkills ?? []}
693
        visible={
694
          isModalVisible.visible && isModalVisible.id === modalButtons.work.id
695
        }
696
      />
697
      <CommunityExperienceModal
698
        experienceCommunity={experienceData as ExperienceCommunity}
699
        experienceableId={experienceData?.experienceable_id ?? 0}
700
        experienceableType={
701
          experienceData?.experienceable_type ?? "application"
702
        }
703
        jobId={jobId}
704
        jobClassification={jobClassification}
705
        modalId={modalButtons.community.id}
706
        onModalCancel={closeModal}
707
        onModalConfirm={submitExperience}
708
        optionalSkills={assetSkills}
709
        parentElement={modalRoot}
710
        requiredSkills={essentialSkills}
711
        savedOptionalSkills={experienceData?.savedOptionalSkills ?? []}
712
        savedRequiredSkills={experienceData?.savedRequiredSkills ?? []}
713
        visible={
714
          isModalVisible.visible &&
715
          isModalVisible.id === modalButtons.community.id
716
        }
717
      />
718
      <PersonalExperienceModal
719
        experiencePersonal={experienceData as ExperiencePersonal}
720
        experienceableId={experienceData?.experienceable_id ?? 0}
721
        experienceableType={
722
          experienceData?.experienceable_type ?? "application"
723
        }
724
        jobId={jobId}
725
        jobClassification={jobClassification}
726
        modalId={modalButtons.personal.id}
727
        onModalCancel={closeModal}
728
        onModalConfirm={submitExperience}
729
        optionalSkills={assetSkills}
730
        parentElement={modalRoot}
731
        requiredSkills={essentialSkills}
732
        savedOptionalSkills={experienceData?.savedOptionalSkills ?? []}
733
        savedRequiredSkills={experienceData?.savedRequiredSkills ?? []}
734
        visible={
735
          isModalVisible.visible &&
736
          isModalVisible.id === modalButtons.personal.id
737
        }
738
      />
739
      <AwardExperienceModal
740
        experienceAward={experienceData as ExperienceAward}
741
        experienceableId={experienceData?.experienceable_id ?? 0}
742
        experienceableType={
743
          experienceData?.experienceable_type ?? "application"
744
        }
745
        jobId={jobId}
746
        jobClassification={jobClassification}
747
        modalId={modalButtons.award.id}
748
        onModalCancel={closeModal}
749
        onModalConfirm={submitExperience}
750
        optionalSkills={assetSkills}
751
        parentElement={modalRoot}
752
        recipientTypes={recipientTypes}
753
        recognitionTypes={recognitionTypes}
754
        requiredSkills={essentialSkills}
755
        savedOptionalSkills={experienceData?.savedOptionalSkills ?? []}
756
        savedRequiredSkills={experienceData?.savedRequiredSkills ?? []}
757
        visible={
758
          isModalVisible.visible && isModalVisible.id === modalButtons.award.id
759
        }
760
      />
761
    </>
762
  );
763
};
764
765
export default MyExperience;
766