Passed
Push — task/final-submit-fully-functi... ( 9ad668...43edf1 )
by Tristan
03:52
created

resources/assets/js/components/AssessmentPlan/RatingGuideQuestion.tsx   A

Complexity

Total Complexity 8
Complexity/F 0

Size

Lines of Code 172
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 8
eloc 140
mnd 8
bc 8
fnc 0
dl 0
loc 172
rs 10
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
1
import React from "react";
2
import { connect } from "react-redux";
3
import { defineMessages, useIntl } from "react-intl";
4
import UpdatingInput from "../UpdatingInput";
5
import { RatingGuideQuestion as RatingGuideQuestionModel } from "../../models/types";
6
import { RootState } from "../../store/store";
7
import {
8
  ratingGuideQuestionIsEdited,
9
  ratingGuideQuestionIsUpdating,
10
  getTempRatingGuideQuestionById,
11
  getCurrentRatingGuideQuestionById,
12
  tempRatingGuideQuestionIsSaving,
13
} from "../../store/RatingGuideQuestion/ratingGuideQuestionSelectors";
14
import {
15
  editRatingGuideQuestion,
16
  updateRatingGuideQuestion,
17
  deleteRatingGuideQuestion,
18
  editTempRatingGuideQuestion,
19
  deleteTempRatingGuideQuestion,
20
  storeNewRatingGuideQuestion,
21
} from "../../store/RatingGuideQuestion/ratingGuideQuestionActions";
22
import { DispatchType } from "../../configureStore";
23
24
const messages = defineMessages({
25
  questionLabel: {
26
    id: "ratingGuideQuestion.questionLabel",
27
    defaultMessage: "Interview Question",
28
    description: "Label for the rating guide question.",
29
  },
30
  questionPlaceholder: {
31
    id: "ratingGuideQuestion.questionPlaceholder",
32
    defaultMessage: "Write your interview question here...",
33
    description: "Placeholder for the rating guide question.",
34
  },
35
});
36
37
interface RatingGuideQuestionProps {
38
  /** Question Model */
39
  question: RatingGuideQuestionModel | null;
40
  /** Whether the question is performing an asynchronous update */
41
  isUpdating: boolean;
42
  /** This questions display index on the page */
43
  questionIndex: number;
44
  /** If this is a temporary question */
45
  temp?: boolean;
46
  /** Handler function for when question is changed */
47
  editQuestion: (newQuestion: RatingGuideQuestionModel) => void;
48
  /** Handler function for when this question is deleted */
49
  removeQuestion: (id: number) => void;
50
  /** Handler function for when this question is saved */
51
  updateQuestion: (question: RatingGuideQuestionModel) => void;
52
}
53
54
const RatingGuideQuestion: React.FunctionComponent<RatingGuideQuestionProps> = ({
55
  question,
56
  questionIndex,
57
  isUpdating,
58
  temp,
59
  editQuestion,
60
  removeQuestion,
61
  updateQuestion,
62
}): React.ReactElement | null => {
63
  const intl = useIntl();
64
  if (question === null) {
65
    return null;
66
  }
67
  return (
68
    <div
69
      data-c-background="black(10)"
70
      data-c-border="bottom(thin, solid, black)"
71
      data-c-padding="top(normal) bottom(normal)"
72
    >
73
      <div data-c-grid="gutter middle">
74
        <div data-c-alignment="center" data-c-grid-item="base(1of1) tp(1of8)">
75
          <p>
76
            <strong>{questionIndex}</strong>
77
          </p>
78
        </div>
79
        <div data-c-grid-item="base(1of1) tp(6of8)">
80
          <UpdatingInput
81
            id={`ratingGuideQuestion${question.assessment_type_id}`}
82
            name="ratingGuideQuestion"
83
            label={intl.formatMessage(messages.questionLabel)}
84
            required
85
            placeholder={intl.formatMessage(messages.questionPlaceholder)}
86
            value={question.question || ""}
87
            updateDelay={temp ? null : 500}
88
            onChange={(event: React.ChangeEvent<HTMLInputElement>): void => {
89
              const newQuestion = String(event.target.value);
90
              editQuestion({
91
                ...question,
92
                question: newQuestion,
93
              });
94
            }}
95
            handleSave={(): void => {
96
              updateQuestion(question);
97
            }}
98
          />
99
        </div>
100
        <div data-c-alignment="center" data-c-grid-item="base(1of1) tp(1of8)">
101
          <button
102
            className="button-trash"
103
            type="button"
104
            onClick={(): void => {
105
              removeQuestion(question.id);
106
            }}
107
            disabled={isUpdating}
108
          >
109
            {isUpdating ? (
110
              <i className="fa fa-spinner fa-spin" />
111
            ) : (
112
              <i className="fa fa-trash" />
113
            )}
114
          </button>
115
        </div>
116
      </div>
117
    </div>
118
  );
119
};
120
121
interface RatingGuideQuestionContainerProps {
122
  ratingGuideQuestionId: number;
123
  questionIndex: number;
124
  temp?: boolean;
125
}
126
127
const mapStateToProps = (
128
  state: RootState,
129
  ownProps: RatingGuideQuestionContainerProps,
130
): {
131
  question: RatingGuideQuestionModel | null;
132
  isEdited: boolean;
133
  isUpdating: boolean;
134
} => ({
135
  question: ownProps.temp
136
    ? getTempRatingGuideQuestionById(state, ownProps.ratingGuideQuestionId)
137
    : getCurrentRatingGuideQuestionById(state, ownProps.ratingGuideQuestionId),
138
  isEdited: ratingGuideQuestionIsEdited(state, ownProps.ratingGuideQuestionId),
139
  isUpdating: ownProps.temp
140
    ? tempRatingGuideQuestionIsSaving(state, ownProps.ratingGuideQuestionId)
141
    : ratingGuideQuestionIsUpdating(state, ownProps.ratingGuideQuestionId),
142
});
143
144
const mapDispatchToProps = (dispatch: DispatchType, ownProps): any => ({
145
  editQuestion: ownProps.temp
146
    ? (ratingGuideQuestion: RatingGuideQuestionModel): void => {
147
        dispatch(editTempRatingGuideQuestion(ratingGuideQuestion));
148
      }
149
    : (ratingGuideQuestion: RatingGuideQuestionModel): void => {
150
        dispatch(editRatingGuideQuestion(ratingGuideQuestion));
151
      },
152
  updateQuestion: ownProps.temp
153
    ? (ratingGuideQuestion: RatingGuideQuestionModel): void =>
154
        dispatch(storeNewRatingGuideQuestion(ratingGuideQuestion))
155
    : (ratingGuideQuestion: RatingGuideQuestionModel): void =>
156
        dispatch(updateRatingGuideQuestion(ratingGuideQuestion)),
157
  removeQuestion: ownProps.temp
158
    ? (id: number): void => {
159
        dispatch(deleteTempRatingGuideQuestion(id));
160
      }
161
    : (ratingGuideQuestionId: number): void => {
162
        dispatch(deleteRatingGuideQuestion(ratingGuideQuestionId));
163
      },
164
});
165
166
const RatingGuideQuestionContainer = connect(
167
  mapStateToProps,
168
  mapDispatchToProps,
169
)(RatingGuideQuestion);
170
171
export default RatingGuideQuestionContainer;
172