Passed
Push — task/ci-test-actions ( 48435f...69d712 )
by Tristan
04:29
created

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

Complexity

Total Complexity 3
Complexity/F 0

Size

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