Passed
Push — dev ( 3b97fe...ebdab1 )
by Tristan
04:28 queued 11s
created

resources/assets/js/components/Application/MyFit/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
mnd 3
bc 3
fnc 0
dl 0
loc 151
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 { 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
        (value) => countNumberOfWords(value) <= ANSWER_WORD_LIMIT,
68
      )
69
      .required(intl.formatMessage(validationMessages.required)),
70
  });
71
72
  return (
73
    <Formik
74
      innerRef={formRef}
75
      initialValues={initialValues}
76
      validationSchema={validationSchema}
77
      onSubmit={async (values, { setSubmitting, resetForm }) => {
78
        const newjobApplicationAnswer = updateAnswerWithValues(
79
          jobApplicationAnswer,
80
          values,
81
        );
82
83
        await handleSubmit(newjobApplicationAnswer)
84
          .then(() => {
85
            resetForm();
86
            setSubmitting(false);
87
          })
88
          .catch(() => {
89
            setSubmitting(false);
90
          });
91
      }}
92
    >
93
      {({ dirty, isSubmitting }): React.ReactElement => (
94
        <Form>
95
          <div key={question.id}>
96
            <p
97
              data-c-margin="top(3) bottom(1)"
98
              data-c-font-weight="bold"
99
              data-c-color="c2"
100
            >
101
              <FormattedMessage
102
                id="application.myfit.question"
103
                defaultMessage="Question {index}:"
104
                description="Label for the question on the My Fit step."
105
                values={{
106
                  index: index + 1,
107
                }}
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.myfit.questionLabel"
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