Passed
Push — task/improve-find-skills-modal... ( a8f9dc...78ae76 )
by Tristan
05:43
created

resources/assets/js/components/ApplicantProfile/Experience/AwardExperienceProfileModal.tsx   A

Complexity

Total Complexity 5
Complexity/F 0

Size

Lines of Code 159
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 5
eloc 126
c 0
b 0
f 0
dl 0
loc 159
rs 10
mnd 5
bc 5
fnc 0
bpm 0
cpm 0
noi 0
1
import React, { FunctionComponent } from "react";
2
import { Formik, Form } from "formik";
3
import { useIntl } from "react-intl";
4
import * as Yup from "yup";
5
import {
6
  dataToFormSkills,
7
  formSkillsToData,
8
  ProfileSkillSubform,
9
  SkillFormValues,
10
  validationShape as skillValidationShape,
11
} from "./ProfileSkillSubform";
12
import { Skill, ExperienceAward, ExperienceSkill } from "../../../models/types";
13
import { ExperienceSubmitData } from "./ProfileExperienceCommon";
14
import {
15
  ExperienceModalHeader,
16
  ExperienceDetailsIntro,
17
  ExperienceModalFooter,
18
} from "../../Application/ExperienceModals/ExperienceModalCommon";
19
import Modal from "../../Modal";
20
import {
21
  AwardDetailsSubform,
22
  awardValidationShape,
23
  messages,
24
  experienceToDetails,
25
  newExperienceAward,
26
  detailsToExperience,
27
  AwardDetailsFormValues,
28
  FormAwardRecipientType,
29
  FormAwardRecognitionType,
30
} from "../../Application/ExperienceModals/AwardExperienceModal";
31
import { getId } from "../../../helpers/queries";
32
33
type AwardExperienceFormValues = SkillFormValues & AwardDetailsFormValues;
34
35
const dataToFormValues = (
36
  data: ExperienceSubmitData<ExperienceAward>,
37
  allSkills: Skill[],
38
  creatingNew: boolean,
39
): AwardExperienceFormValues => {
40
  return {
41
    ...experienceToDetails(data.experience, creatingNew),
42
    ...dataToFormSkills(data, allSkills),
43
  };
44
};
45
46
const formValuesToData = (
47
  formValues: AwardExperienceFormValues,
48
  originalExperience: ExperienceAward,
49
): ExperienceSubmitData<ExperienceAward> => {
50
  return {
51
    experience: detailsToExperience(formValues, originalExperience),
52
    savedSkills: formSkillsToData(formValues),
53
  };
54
};
55
56
interface ProfileAwardModalProps {
57
  modalId: string;
58
  experienceAward: ExperienceAward | null;
59
  recipientTypes: FormAwardRecipientType[];
60
  recognitionTypes: FormAwardRecognitionType[];
61
  experienceableId: number;
62
  experienceableType: ExperienceAward["experienceable_type"];
63
  userSkills: Skill[];
64
  experienceSkills: ExperienceSkill[];
65
  parentElement: Element | null;
66
  visible: boolean;
67
  onModalCancel: () => void;
68
  onModalConfirm: (
69
    data: ExperienceSubmitData<ExperienceAward>,
70
  ) => Promise<void>;
71
}
72
73
export const ProfileAwardModal: FunctionComponent<ProfileAwardModalProps> = ({
74
  modalId,
75
  experienceAward,
76
  recipientTypes,
77
  recognitionTypes,
78
  experienceableId,
79
  experienceableType,
80
  userSkills,
81
  experienceSkills,
82
  parentElement,
83
  visible,
84
  onModalCancel,
85
  onModalConfirm,
86
}) => {
87
  const intl = useIntl();
88
89
  const originalExperience =
90
    experienceAward ?? newExperienceAward(experienceableId, experienceableType);
91
92
  const relevantExperienceSkills = experienceSkills.filter(
93
    (expSkill) =>
94
      expSkill.experience_id === experienceAward?.id &&
95
      expSkill.experience_type === "experience_award",
96
  );
97
98
  const validationSchema = Yup.object().shape({
99
    ...awardValidationShape(intl),
100
    ...skillValidationShape(intl, userSkills.map(getId)),
101
  });
102
103
  const initialFormValues = dataToFormValues(
104
    {
105
      experience: originalExperience,
106
      savedSkills: relevantExperienceSkills.map((expSkill) => ({
107
        skillId: expSkill.skill_id,
108
        justification: expSkill.justification ?? "",
109
      })),
110
    },
111
    userSkills,
112
    experienceAward === null,
113
  );
114
115
  return (
116
    <Modal
117
      id={modalId}
118
      parentElement={parentElement}
119
      visible={visible}
120
      onModalCancel={onModalCancel}
121
      onModalConfirm={onModalCancel}
122
      className="application-experience-dialog"
123
    >
124
      <ExperienceModalHeader
125
        title={intl.formatMessage(messages.modalTitle)}
126
        iconClass="fa-trophy"
127
      />
128
      <Formik
129
        enableReinitialize
130
        initialValues={initialFormValues}
131
        onSubmit={async (values, actions): Promise<void> => {
132
          await onModalConfirm(formValuesToData(values, originalExperience));
133
          actions.setSubmitting(false);
134
          actions.resetForm();
135
        }}
136
        validationSchema={validationSchema}
137
      >
138
        {(formikProps): React.ReactElement => (
139
          <Form>
140
            <Modal.Body>
141
              <ExperienceDetailsIntro
142
                description={intl.formatMessage(messages.modalDescription)}
143
              />
144
              <AwardDetailsSubform
145
                recipientTypes={recipientTypes}
146
                recognitionTypes={recognitionTypes}
147
              />
148
              <ProfileSkillSubform keyPrefix="award" skills={userSkills} />
149
            </Modal.Body>
150
            <ExperienceModalFooter buttonsDisabled={formikProps.isSubmitting} />
151
          </Form>
152
        )}
153
      </Formik>
154
    </Modal>
155
  );
156
};
157
158
export default ProfileAwardModal;
159