Passed
Push — dev ( 05fc2a...74a584 )
by
unknown
05:49
created

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

Complexity

Total Complexity 75
Complexity/F 0

Size

Lines of Code 786
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

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