Passed
Push — feature/timeline-myfit-step ( 9bf1bb...99b565 )
by Yonathan
04:17
created

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

Complexity

Total Complexity 8
Complexity/F 0

Size

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