Passed
Push — feature/connect-application-st... ( 3c62e3...cf7200 )
by Tristan
09:55
created

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

Complexity

Total Complexity 10
Complexity/F 0

Size

Lines of Code 244
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 10
eloc 198
c 0
b 0
f 0
dl 0
loc 244
rs 10
mnd 10
bc 10
fnc 0
bpm 0
cpm 0
noi 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
        </>
125
      ) : (
126
        <div data-c-alignment="base(centre)">
127
          <Icon
128
            icon="fa fa-spinner fa-spin"
129
            accessibleText={intl.formatMessage(messages.loadingIcon)}
130
            sematicIcon
131
          />
132
        </div>
133
      )}
134
      <div data-c-grid="gutter">
135
        <div data-c-grid-item="base(1of1)">
136
          <hr data-c-margin="top(normal) bottom(normal)" />
137
        </div>
138
        <div
139
          data-c-alignment="base(centre) tp(left)"
140
          data-c-grid-item="tp(1of2)"
141
        >
142
          <a href={hrJobSummary(locale, jobId)} title="">
143
            <FormattedMessage
144
              id="jobReviewHr.summaryLink"
145
              defaultMessage="Return to Summary"
146
              description="Text for the Return to Summary link."
147
            />
148
          </a>
149
        </div>
150
      </div>
151
    </div>
152
  );
153
};
154
155
const JobReviewHrDataFetcher: React.FC<{ jobId: number }> = ({ jobId }) => {
156
  const dispatch = useDispatch();
157
158
  // Request and select the job
159
  useEffect(() => {
160
    dispatch(fetchJob(jobId));
161
  }, [dispatch, jobId]);
162
  const job = useSelector((state: RootState) => getJob(state, { jobId }));
163
164
  // Request and select the job tasks
165
  useEffect(() => {
166
    dispatch(fetchJobTasks(jobId));
167
  }, [dispatch, jobId]);
168
  const tasks = useSelector((state: RootState) =>
169
    getTasksByJob(state, { jobId }),
170
  );
171
172
  // Request and select job criteria
173
  useEffect(() => {
174
    dispatch(fetchCriteria(jobId));
175
  }, [dispatch, jobId]);
176
  const criteria = useSelector((state: RootState) =>
177
    getCriteriaByJob(state, { jobId }),
178
  );
179
180
  // Load all skills
181
  useEffect(() => {
182
    dispatch(fetchSkills());
183
  }, [dispatch]);
184
  const skills = useSelector(getSkills);
185
186
  // Load all departments
187
  useEffect(() => {
188
    dispatch(fetchDepartments());
189
  }, [dispatch]);
190
  const departments = useSelector(getDepartments);
191
192
  // Load manager after Job has loaded
193
  // eslint-disable-next-line camelcase
194
  const managerId = job?.manager_id;
195
  useEffect(() => {
196
    if (managerId) {
197
      dispatch(fetchManager(managerId));
198
    }
199
  }, [dispatch, managerId]);
200
  const manager = useSelector((state: RootState) =>
201
    managerId ? getManagerById(state, { managerId }) : null,
202
  );
203
204
  // Load user after manager has loaded
205
  // eslint-disable-next-line camelcase
206
  const userId = manager?.user_id;
207
  useEffect(() => {
208
    if (userId) {
209
      dispatch(fetchUser(userId));
210
    }
211
  }, [dispatch, userId]);
212
  const user = useSelector((state: RootState) =>
213
    userId ? getUserById(state, { userId }) : null,
214
  );
215
216
  return (
217
    <JobReviewHrPage
218
      jobId={jobId}
219
      job={job}
220
      manager={manager}
221
      user={user}
222
      keyTasks={tasks}
223
      criteria={criteria}
224
      skills={skills}
225
      departments={departments}
226
    />
227
  );
228
};
229
230
export default JobReviewHrDataFetcher;
231
232
const container = document.getElementById("job-review-hr");
233
if (container !== null) {
234
  if ("jobId" in container.dataset) {
235
    const jobId = Number(container.dataset.jobId as string);
236
    ReactDOM.render(
237
      <RootContainer>
238
        <JobReviewHrDataFetcher jobId={jobId} />
239
      </RootContainer>,
240
      container,
241
    );
242
  }
243
}
244