Passed
Push — dev ( 244fa7...6a4715 )
by Yonathan
04:54 queued 12s
created

resources/assets/js/components/HRPortal/JobReviewHrPage.tsx   A

Complexity

Total Complexity 12
Complexity/F 0

Size

Lines of Code 252
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 12
eloc 206
mnd 12
bc 12
fnc 0
dl 0
loc 252
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
rs 10
1
import React, { useEffect, useCallback } from "react";
2
import { useIntl, FormattedMessage, defineMessages } from "react-intl";
3
import { useDispatch, useSelector } from "react-redux";
4
import ReactDOM from "react-dom";
5
import RootContainer from "../RootContainer";
6
import {
7
  Job,
8
  JobPosterKeyTask,
9
  Criteria,
10
  Skill,
11
  Manager,
12
  Department,
13
  User,
14
  Comment,
15
  Classification,
16
} from "../../models/types";
17
import { hrJobSummary } from "../../helpers/routes";
18
import { RootState } from "../../store/store";
19
import {
20
  getJob,
21
  getTasksByJob,
22
  getCriteriaByJob,
23
} from "../../store/Job/jobSelector";
24
import { getSkills } from "../../store/Skill/skillSelector";
25
import {
26
  fetchJob,
27
  fetchJobTasks,
28
  fetchCriteria,
29
} from "../../store/Job/jobActions";
30
import { getDepartments as fetchDepartments } from "../../store/Department/deptActions";
31
import { getDepartments } from "../../store/Department/deptSelector";
32
import { getManagerById } from "../../store/Manager/managerSelector";
33
import { fetchManager } from "../../store/Manager/managerActions";
34
import { JobReviewDisplay } from "../JobBuilder/Review/JobReview";
35
import { fetchSkills } from "../../store/Skill/skillActions";
36
import Icon from "../Icon";
37
import ActivityFeed from "../ActivityFeed";
38
import { jobReviewLocations } from "../../models/localizedConstants";
39
import { LocationId } from "../../models/lookupConstants";
40
import { localizeField } from "../../helpers/localize";
41
import { getUserById } from "../../store/User/userSelector";
42
import { fetchUser } from "../../store/User/userActions";
43
import { hasKey } from "../../helpers/queries";
44
import { useLoadClassifications } from "../../hooks/classificationHooks";
45
import { DispatchType } from "../../configureStore";
46
47
interface JobReviewHrPageProps {
48
  jobId: number;
49
  job: Job | null;
50
  skills: Skill[];
51
  keyTasks: JobPosterKeyTask[];
52
  criteria: Criteria[];
53
  departments: Department[];
54
  manager: Manager | null;
55
  user: User | null;
56
}
57
58
const messages = defineMessages({
59
  loadingIcon: {
60
    id: "jobReviewHr.loadingIconText",
61
    defaultMessage: "Data is loading...",
62
    description: "Accessible text for the loading icon",
63
  },
64
});
65
66
const JobReviewHrPage: React.FunctionComponent<JobReviewHrPageProps> = ({
67
  jobId,
68
  job,
69
  skills,
70
  keyTasks,
71
  criteria,
72
  departments,
73
  manager,
74
  user,
75
}): React.ReactElement => {
76
  const intl = useIntl();
77
  const { locale } = intl;
78
  const dispatch = useDispatch<DispatchType>();
79
  if (locale !== "en" && locale !== "fr") {
80
    throw new Error("Unexpected locale");
81
  }
82
  const filterComments = useCallback(
83
    (comment: Comment): boolean => hasKey(jobReviewLocations, comment.location),
84
    [],
85
  );
86
  const { classifications } = useLoadClassifications(dispatch);
87
  const classificationKey: string =
88
    classifications.find(
89
      (item: Classification) => item.id === job?.classification_id,
90
    )?.key || "";
91
  return (
92
    <div data-c-container="form" data-c-padding="top(triple) bottom(triple)">
93
      {job !== null ? (
94
        <>
95
          <h3
96
            data-c-font-size="h3"
97
            data-c-font-weight="bold"
98
            data-c-margin="bottom(normal)"
99
          >
100
            <FormattedMessage
101
              id="jobReviewHr.reviewYourPoster"
102
              defaultMessage="Review Your Job Poster for:"
103
              description="Title for Review Job Poster section."
104
            />{" "}
105
            <span data-c-colour="c2">
106
              {localizeField(locale, job, "title")}
107
            </span>
108
          </h3>
109
          <p data-c-margin="bottom(double)">
110
            <FormattedMessage
111
              id="jobReviewHr.headsUp"
112
              defaultMessage="Just a heads up! We've rearranged some of your information to help you understand how an applicant will see it once published."
113
              description="Description under primary title of review section"
114
            />
115
          </p>
116
          <ActivityFeed
117
            jobId={job.id}
118
            isHrAdvisor
119
            generalLocation={LocationId.jobGeneric}
120
            locationMessages={jobReviewLocations}
121
            filterComments={filterComments}
122
          />
123
          <JobReviewDisplay
124
            job={job}
125
            classificationKey={classificationKey}
126
            manager={manager}
127
            user={user}
128
            tasks={keyTasks}
129
            criteria={criteria}
130
            skills={skills}
131
            departments={departments}
132
            hideBuilderLinks
133
          />
134
          <div data-c-grid="gutter">
135
            <div
136
              data-c-alignment="base(centre) tp(left)"
137
              data-c-grid-item="tp(1of2)"
138
              data-c-margin="top(normal) bottom(normal)"
139
            >
140
              <a href={hrJobSummary(locale, jobId)} title="">
141
                <FormattedMessage
142
                  id="jobReviewHr.summaryLink"
143
                  defaultMessage="Return to Summary"
144
                  description="Text for the Return to Summary link."
145
                />
146
              </a>
147
            </div>
148
          </div>
149
        </>
150
      ) : (
151
        <div data-c-alignment="base(centre)">
152
          <Icon
153
            icon="fa fa-spinner fa-spin"
154
            accessibleText={intl.formatMessage(messages.loadingIcon)}
155
            sematicIcon
156
          />
157
        </div>
158
      )}
159
    </div>
160
  );
161
};
162
163
const JobReviewHrDataFetcher: React.FC<{ jobId: number }> = ({ jobId }) => {
164
  const dispatch = useDispatch();
165
166
  // Request and select the job
167
  useEffect(() => {
168
    dispatch(fetchJob(jobId));
169
  }, [dispatch, jobId]);
170
  const job = useSelector((state: RootState) => getJob(state, { jobId }));
171
172
  // Request and select the job tasks
173
  useEffect(() => {
174
    dispatch(fetchJobTasks(jobId));
175
  }, [dispatch, jobId]);
176
  const tasks = useSelector((state: RootState) =>
177
    getTasksByJob(state, { jobId }),
178
  );
179
180
  // Request and select job criteria
181
  useEffect(() => {
182
    dispatch(fetchCriteria(jobId));
183
  }, [dispatch, jobId]);
184
  const criteria = useSelector((state: RootState) =>
185
    getCriteriaByJob(state, { jobId }),
186
  );
187
188
  // Load all skills
189
  useEffect(() => {
190
    dispatch(fetchSkills());
191
  }, [dispatch]);
192
  const skills = useSelector(getSkills);
193
194
  // Load all departments
195
  useEffect(() => {
196
    dispatch(fetchDepartments());
197
  }, [dispatch]);
198
  const departments = useSelector(getDepartments);
199
200
  // Load manager after Job has loaded
201
  // eslint-disable-next-line camelcase
202
  const managerId = job?.manager_id;
203
  useEffect(() => {
204
    if (managerId) {
205
      dispatch(fetchManager(managerId));
206
    }
207
  }, [dispatch, managerId]);
208
  const manager = useSelector((state: RootState) =>
209
    managerId ? getManagerById(state, { managerId }) : null,
210
  );
211
212
  // Load user after manager has loaded
213
  // eslint-disable-next-line camelcase
214
  const userId = manager?.user_id;
215
  useEffect(() => {
216
    if (userId) {
217
      dispatch(fetchUser(userId));
218
    }
219
  }, [dispatch, userId]);
220
  const user = useSelector((state: RootState) =>
221
    userId ? getUserById(state, { userId }) : null,
222
  );
223
224
  return (
225
    <JobReviewHrPage
226
      jobId={jobId}
227
      job={job}
228
      manager={manager}
229
      user={user}
230
      keyTasks={tasks}
231
      criteria={criteria}
232
      skills={skills}
233
      departments={departments}
234
    />
235
  );
236
};
237
238
export default JobReviewHrDataFetcher;
239
240
const container = document.getElementById("job-review-hr");
241
if (container !== null) {
242
  if ("jobId" in container.dataset) {
243
    const jobId = Number(container.dataset.jobId as string);
244
    ReactDOM.render(
245
      <RootContainer>
246
        <JobReviewHrDataFetcher jobId={jobId} />
247
      </RootContainer>,
248
      container,
249
    );
250
  }
251
}
252