Passed
Push — dev ( b477e5...9dd4e3 )
by
unknown
04:01
created

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

Complexity

Total Complexity 3
Complexity/F 0

Size

Lines of Code 151
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 3
eloc 118
c 0
b 0
f 0
dl 0
loc 151
rs 10
mnd 3
bc 3
fnc 0
bpm 0
cpm 0
noi 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
      innerRef={formRef}
79
      initialValues={initialValues}
80
      validationSchema={validationSchema}
81
      onSubmit={async (values, { setSubmitting, resetForm }) => {
82
        const newjobApplicationAnswer = updateAnswerWithValues(
83
          jobApplicationAnswer,
84
          values,
85
        );
86
87
        await handleSubmit(newjobApplicationAnswer)
88
          .then(() => {
89
            resetForm();
90
            setSubmitting(false);
91
          })
92
          .catch(() => {
93
            setSubmitting(false);
94
          });
95
      }}
96
    >
97
      {({ dirty, isSubmitting }): React.ReactElement => (
98
        <Form>
99
          <AlertWhenUnsaved />
100
          <div key={question.id}>
101
            <p
102
              data-c-margin="top(3) bottom(1)"
103
              data-c-font-weight="bold"
104
              data-c-color="c2"
105
            >
106
              {intl.formatMessage(fitMessages.questionLabel, {
107
                index: index + 1,
108
              })}{" "}
109
              {localizeField(locale, question, "question")}
110
            </p>
111
            <FastField
112
              id={`answer-${question.id}`}
113
              name="answer"
114
              component={TextAreaInput}
115
              required
116
              label={
117
                <FormattedMessage
118
                  id="application.fit.answerLabel"
119
                  defaultMessage="My Answer to Question {index}"
120
                  description="Label before the users answer on the My Fit step."
121
                  values={{
122
                    index: index + 1,
123
                  }}
124
                />
125
              }
126
              wordLimit={ANSWER_WORD_LIMIT}
127
            />
128
            <div data-c-align="base(center) tl(right)">
129
              <button
130
                id={`save-button-${question.id}`}
131
                data-c-button="solid(c1)"
132
                data-c-radius="rounded"
133
                disabled={!dirty || isSubmitting}
134
                type="submit"
135
              >
136
                <span>
137
                  {dirty
138
                    ? intl.formatMessage(saveButtonMessages.save)
139
                    : intl.formatMessage(saveButtonMessages.saved)}
140
                </span>
141
              </button>
142
            </div>
143
          </div>
144
        </Form>
145
      )}
146
    </Formik>
147
  );
148
};
149
150
export default Question;
151