Passed
Push — feature/application-skill-info... ( 9c1770...3584f9 )
by Chris
05:42 queued 15s
created

resources/assets/js/components/Application/MyFit/Question.tsx   A

Complexity

Total Complexity 3
Complexity/F 0

Size

Lines of Code 153
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 3
eloc 119
mnd 3
bc 3
fnc 0
dl 0
loc 153
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
rs 10
1
/* eslint-disable @typescript-eslint/camelcase */
2
import * as React from "react";
3
import { Formik, Form, FastField } from "formik";
4
import * as Yup from "yup";
5
import { useIntl, FormattedMessage, defineMessages } from "react-intl";
6
import { JobPosterQuestion, JobApplicationAnswer } from "../../../models/types";
7
import { getLocale, localizeField } from "../../../helpers/localize";
8
import { validationMessages } from "../../Form/Messages";
9
import { countNumberOfWords } from "../../WordCounter/helpers";
10
import TextAreaInput from "../../Form/TextAreaInput";
11
12
const saveButtonMessages = defineMessages({
13
  save: {
14
    id: "application.myfit.saveAnswerButton.default",
15
    defaultMessage: "Save Answer",
16
    description: "Default message displayed on save answer button.",
17
  },
18
  saved: {
19
    id: "application.myfit.saveAnswerButton.saved",
20
    defaultMessage: "Saved",
21
    description: "Message displayed on button when data is saved.",
22
  },
23
});
24
25
interface QuestionProps {
26
  jobApplicationAnswer: JobApplicationAnswer;
27
  formRef: any;
28
  index: number;
29
  question: JobPosterQuestion;
30
  handleSubmit: (data: JobApplicationAnswer) => Promise<void>;
31
}
32
33
export interface QuestionValues {
34
  answer: string;
35
}
36
37
const answerToValues = ({ answer }: JobApplicationAnswer): QuestionValues => ({
38
  answer: answer ?? "",
39
});
40
41
const updateAnswerWithValues = (
42
  applicationAnswer: JobApplicationAnswer,
43
  { answer }: QuestionValues,
44
): JobApplicationAnswer => ({
45
  ...applicationAnswer,
46
  answer,
47
});
48
49
const Question: React.FunctionComponent<QuestionProps> = ({
50
  jobApplicationAnswer,
51
  formRef,
52
  index,
53
  question,
54
  handleSubmit,
55
}) => {
56
  const intl = useIntl();
57
  const locale = getLocale(intl.locale);
58
  const ANSWER_WORD_LIMIT = 250;
59
60
  const initialValues: QuestionValues = answerToValues(jobApplicationAnswer);
61
62
  const validationSchema = Yup.object({
63
    answer: Yup.string()
64
      .test(
65
        "wordCount",
66
        intl.formatMessage(validationMessages.overMaxWords, {
67
          numberOfWords: ANSWER_WORD_LIMIT,
68
        }),
69
        (value) => countNumberOfWords(value) <= ANSWER_WORD_LIMIT,
70
      )
71
      .required(intl.formatMessage(validationMessages.required)),
72
  });
73
74
  return (
75
    <Formik
76
      innerRef={formRef}
77
      initialValues={initialValues}
78
      validationSchema={validationSchema}
79
      onSubmit={async (values, { setSubmitting, resetForm }) => {
80
        const newjobApplicationAnswer = updateAnswerWithValues(
81
          jobApplicationAnswer,
82
          values,
83
        );
84
85
        await handleSubmit(newjobApplicationAnswer)
86
          .then(() => {
87
            resetForm();
88
            setSubmitting(false);
89
          })
90
          .catch(() => {
91
            setSubmitting(false);
92
          });
93
      }}
94
    >
95
      {({ dirty, isSubmitting }): React.ReactElement => (
96
        <Form>
97
          <div key={question.id}>
98
            <p
99
              data-c-margin="top(3) bottom(1)"
100
              data-c-font-weight="bold"
101
              data-c-color="c2"
102
            >
103
              <FormattedMessage
104
                id="application.myfit.question"
105
                defaultMessage="Question {index}:"
106
                description="Label for the question on the My Fit step."
107
                values={{
108
                  index: index + 1,
109
                }}
110
              />{" "}
111
              {localizeField(locale, question, "question")}
112
            </p>
113
            <FastField
114
              id={`answer-${question.id}`}
115
              name="answer"
116
              component={TextAreaInput}
117
              required
118
              label={
119
                <FormattedMessage
120
                  id="application.myfit.questionLabel"
121
                  defaultMessage="My Answer to Question {index}"
122
                  description="Label before the users answer on the My Fit step."
123
                  values={{
124
                    index: index + 1,
125
                  }}
126
                />
127
              }
128
              wordLimit={ANSWER_WORD_LIMIT}
129
            />
130
            <div data-c-align="base(center) tl(right)">
131
              <button
132
                id={`save-button-${question.id}`}
133
                data-c-button="solid(c1)"
134
                data-c-radius="rounded"
135
                disabled={!dirty || isSubmitting}
136
                type="submit"
137
              >
138
                <span>
139
                  {dirty
140
                    ? intl.formatMessage(saveButtonMessages.save)
141
                    : intl.formatMessage(saveButtonMessages.saved)}
142
                </span>
143
              </button>
144
            </div>
145
          </div>
146
        </Form>
147
      )}
148
    </Formik>
149
  );
150
};
151
152
export default Question;
153