Passed
Push — dev ( 8c2015...701428 )
by Yonathan
05:05 queued 10s
created

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

Complexity

Total Complexity 10
Complexity/F 0

Size

Lines of Code 242
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

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