Passed
Push — task/hr-job-review ( 40ed2c...671c4c )
by Yonathan
11:15 queued 12s
created

resources/assets/js/components/CommentForm.tsx   A

Complexity

Total Complexity 5
Complexity/F 0

Size

Lines of Code 217
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 5
eloc 165
mnd 5
bc 5
fnc 0
dl 0
loc 217
rs 10
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
1
/* eslint-disable @typescript-eslint/camelcase, camelcase */
2
import * as React from "react";
3
import { connect } from "react-redux";
4
import { Formik, Form, Field } from "formik";
5
import * as Yup from "yup";
6
import { useIntl, defineMessages, FormattedMessage } from "react-intl";
7
import { validationMessages } from "./Form/Messages";
8
import { CommentTypeId } from "../models/lookupConstants";
9
import TextInput from "./Form/TextInput";
10
import SelectInput from "./Form/SelectInput";
11
import { Comment } from "../models/types";
12
import { DispatchType } from "../configureStore";
13
import { createComment } from "../store/Job/jobActions";
14
import { emptyComment } from "../models/jobUtil";
15
16
const formMessages = defineMessages({
17
  commentLabel: {
18
    id: "commentForm.comment.label",
19
    defaultMessage: "Add a Comment",
20
    description: "The label displayed for the comment input field.",
21
  },
22
  commentPlaceholder: {
23
    id: "commentForm.comment.placeholder",
24
    defaultMessage: "eg. Enter your question, recommendation, etc.",
25
    description: "The placeholder displayed for the comment input field.",
26
  },
27
  commentTypeLabel: {
28
    id: "commentForm.commentType.label",
29
    defaultMessage: "Type of Comment",
30
    description: "The label displayed for the comment type select box.",
31
  },
32
  commentTypeNullSelection: {
33
    id: "commentForm.commentType.nullSelection",
34
    defaultMessage: "Select a comment type...",
35
    description: "Comment type from list of comment types",
36
  },
37
});
38
39
export const commentTypeMessages = defineMessages({
40
  question: {
41
    id: "commentType.question",
42
    defaultMessage: "Question",
43
    description: "Comment type from list of comment types",
44
  },
45
  recommendation: {
46
    id: "commentType.recommendation",
47
    defaultMessage: "Recommendation",
48
    description: "Comment type from list of comment types",
49
  },
50
  requiredAction: {
51
    id: "commentType.requiredAction",
52
    defaultMessage: "Required Action",
53
    description: "Comment type from list of comment types",
54
  },
55
  comment: {
56
    id: "commentType.comment",
57
    defaultMessage: "Comment",
58
    description: "Comment type from list of comment types",
59
  },
60
});
61
62
interface CommentFormProps {
63
  jobId: number;
64
  isHrAdviser: boolean;
65
  location: string;
66
  handleCreateComment: (jobId: number, newComment: Comment) => Promise<Comment>;
67
}
68
69
interface CommentFormValues {
70
  comment: string;
71
  commentType: number | null;
72
}
73
74
const CommentForm: React.FunctionComponent<CommentFormProps> = ({
75
  isHrAdviser,
76
  handleCreateComment,
77
  jobId,
78
  location,
79
}: CommentFormProps): React.ReactElement => {
80
  const intl = useIntl();
81
  const initialValues: CommentFormValues = {
82
    comment: "",
83
    commentType: 0 || null,
84
  };
85
86
  const hrCommentSchema = Yup.object().shape({
87
    comment: Yup.string().required(
88
      intl.formatMessage(validationMessages.required),
89
    ),
90
    commentType: Yup.number()
91
      .oneOf(
92
        Object.values(CommentTypeId),
93
        intl.formatMessage(validationMessages.invalidSelection),
94
      )
95
      .required(intl.formatMessage(validationMessages.required)),
96
  });
97
98
  const managerCommentSchema = Yup.object().shape({
99
    comment: Yup.string().required(
100
      intl.formatMessage(validationMessages.required),
101
    ),
102
  });
103
104
  return (
105
    <section>
106
      <Formik
107
        initialValues={initialValues}
108
        validationSchema={isHrAdviser ? hrCommentSchema : managerCommentSchema}
109
        onSubmit={(values, { setSubmitting, resetForm }): void => {
110
          const newComment: Comment = {
111
            ...emptyComment(),
112
            location,
113
            comment: values.comment,
114
            type_id: isHrAdviser ? Number(values.commentType) : null,
115
          };
116
          handleCreateComment(jobId, newComment)
117
            .then(() => {
118
              setSubmitting(false);
119
              resetForm();
120
            })
121
            .catch(() => {
122
              setSubmitting(false);
123
            });
124
        }}
125
        render={({ isSubmitting }): React.ReactElement => (
126
          <Form data-c-grid="gutter(all, 1)">
127
            <Field
128
              id="comment_form_input"
129
              type="text"
130
              name="comment"
131
              component={TextInput}
132
              required
133
              grid="tl(2of3)"
134
              label={intl.formatMessage(formMessages.commentLabel)}
135
              placeholder={intl.formatMessage(formMessages.commentPlaceholder)}
136
            />
137
            {isHrAdviser && (
138
              <Field
139
                id="comment_form_type"
140
                name="commentType"
141
                component={SelectInput}
142
                required
143
                grid="tl(1of3)"
144
                label={intl.formatMessage(formMessages.commentTypeLabel)}
145
                options={[
146
                  {
147
                    value: "",
148
                    label: intl.formatMessage(
149
                      formMessages.commentTypeNullSelection,
150
                    ),
151
                  },
152
                  {
153
                    value: CommentTypeId.question,
154
                    label: intl.formatMessage(commentTypeMessages.question),
155
                  },
156
                  {
157
                    value: CommentTypeId.recommendation,
158
                    label: intl.formatMessage(
159
                      commentTypeMessages.recommendation,
160
                    ),
161
                  },
162
                  {
163
                    value: CommentTypeId.requiredAction,
164
                    label: intl.formatMessage(
165
                      commentTypeMessages.requiredAction,
166
                    ),
167
                  },
168
                ]}
169
              />
170
            )}
171
            <div
172
              data-c-grid-item={isHrAdviser ? "base(1of1)" : "tl(1of3)"}
173
              data-c-align="base(center) tl(right)"
174
              style={
175
                isHrAdviser ? {} : { display: "flex", alignItems: "center" }
176
              }
177
            >
178
              <button
179
                type="submit"
180
                disabled={isSubmitting}
181
                data-c-button="solid(c1)"
182
                data-c-radius="rounded"
183
              >
184
                <FormattedMessage
185
                  id="commentForm.submitButton.label"
186
                  defaultMessage="Submit Comment"
187
                  description="The text displayed on the submit button in the comment form."
188
                />
189
              </button>
190
            </div>
191
          </Form>
192
        )}
193
      />
194
    </section>
195
  );
196
};
197
198
const mapDispatchToProps = (
199
  dispatch: DispatchType,
200
): {
201
  handleCreateComment: (jobId: number, newComment: Comment) => Promise<Comment>;
202
} => ({
203
  handleCreateComment: async (
204
    jobId: number,
205
    newComment: Comment,
206
  ): Promise<Comment> => {
207
    const result = await dispatch(createComment(jobId, newComment));
208
    if (!result.error) {
209
      const resultComment = await result.payload;
210
      return resultComment;
211
    }
212
    return Promise.reject(result.payload);
213
  },
214
});
215
216
export default connect(() => ({}), mapDispatchToProps)(CommentForm);
217