Passed
Push — task/applicant-classification-... ( a73fc7...ae016f )
by Yonathan
04:35
created

resources/assets/js/components/JobBuilder/JobBuilderRoot.tsx   A

Complexity

Total Complexity 5
Complexity/F 0

Size

Lines of Code 230
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 5
eloc 182
mnd 5
bc 5
fnc 0
dl 0
loc 230
rs 10
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
1
/* eslint-disable @typescript-eslint/explicit-function-return-type */
2
import React, { useEffect } from "react";
3
import ReactDOM from "react-dom";
4
import { Routes } from "universal-router";
5
import { defineMessages, useIntl, IntlShape } from "react-intl";
6
import { useSelector } from "react-redux";
7
import { useRouter, RouterResult } from "../../helpers/router";
8
import JobIntroPage from "./Intro/JobIntroPage";
9
import RootContainer from "../RootContainer";
10
import JobDetailsPage from "./Details/JobDetailsPage";
11
import JobWorkEnvPage from "./WorkEnv/JobWorkEnvPage";
12
import JobImpactPage from "./Impact/JobImpactPage";
13
import JobTasksPage from "./Tasks/JobTasksPage";
14
import JobSkillsPage from "./Skills/JobSkillsPage";
15
import JobReviewPage from "./Review/JobReviewPage";
16
import ScrollToTop from "../ScrollToTop";
17
import RedirectPage from "./RedirectToLastIncompleteStep";
18
import { RootState } from "../../store/store";
19
import { getSelectedJob } from "../../store/Job/jobSelector";
20
import { Job } from "../../models/types";
21
import { managerJobSummary } from "../../helpers/routes";
22
import { getLocale, localizeField } from "../../helpers/localize";
23
import { messages } from "../HRPortal/JobIndexHrPage";
24
25
const titles = defineMessages({
26
  rootTitle: {
27
    id: "jobBuilder.root.documentTitle",
28
    defaultMessage: "Job Builder",
29
    description: "The document's title shown in browser's title bar or tab.",
30
  },
31
  introTitle: {
32
    id: "jobBuilder.intro.documentTitle",
33
    defaultMessage: "Job Builder: Intro",
34
    description: "The document's title shown in browser's title bar or tab.",
35
  },
36
  detailsTitle: {
37
    id: "jobBuilder.details.documentTitle",
38
    defaultMessage: "Job Builder: Details",
39
    description: "The document's title shown in browser's title bar or tab.",
40
  },
41
  workEnvTitle: {
42
    id: "jobBuilder.workEnv.documentTitle",
43
    defaultMessage: "Job Builder: Work Environment",
44
    description: "The document's title shown in browser's title bar or tab.",
45
  },
46
  impactTitle: {
47
    id: "jobBuilder.impact.documentTitle",
48
    defaultMessage: "Job Builder: Impact",
49
    description: "The document's title shown in browser's title bar or tab.",
50
  },
51
  tasksTitle: {
52
    id: "jobBuilder.tasks.documentTitle",
53
    defaultMessage: "Job Builder: Tasks",
54
    description: "The document's title shown in browser's title bar or tab.",
55
  },
56
  skillsTitle: {
57
    id: "jobBuilder.skills.documentTitle",
58
    defaultMessage: "Job Builder: Skills",
59
    description: "The document's title shown in browser's title bar or tab.",
60
  },
61
  reviewTitle: {
62
    id: "jobBuilder.review.documentTitle",
63
    defaultMessage: "Job Builder: Review",
64
    description: "The document's title shown in browser's title bar or tab.",
65
  },
66
});
67
68
const routes: Routes<{}, RouterResult> = [
69
  {
70
    path: "/:locale/manager/jobs",
71
    children: [
72
      {
73
        path: "/builder",
74
        action: () => ({
75
          title: titles.introTitle,
76
          component: <JobIntroPage jobId={null} />,
77
        }),
78
      },
79
      {
80
        path: "/:id/builder",
81
        children: [
82
          {
83
            path: "",
84
            action: ({ params }) => ({
85
              title: titles.rootTitle,
86
              component: <RedirectPage jobId={Number(params.id)} />,
87
            }),
88
          },
89
          {
90
            path: "/intro",
91
            action: ({ params }) => ({
92
              title: titles.introTitle,
93
              component: <JobIntroPage jobId={Number(params.id)} />,
94
            }),
95
          },
96
          {
97
            path: "/details",
98
            action: ({ params }) => ({
99
              title: titles.detailsTitle,
100
              component: <JobDetailsPage jobId={Number(params.id)} />,
101
            }),
102
          },
103
          {
104
            path: "/environment",
105
            action: ({ params }) => ({
106
              title: titles.workEnvTitle,
107
              component: <JobWorkEnvPage jobId={Number(params.id)} />,
108
            }),
109
          },
110
          {
111
            path: "/impact",
112
            action: ({ params }) => ({
113
              title: titles.impactTitle,
114
              component: <JobImpactPage jobId={Number(params.id)} />,
115
            }),
116
          },
117
          {
118
            path: "/tasks",
119
            action: ({ params }) => ({
120
              title: titles.tasksTitle,
121
              component: <JobTasksPage jobId={Number(params.id)} />,
122
            }),
123
          },
124
          {
125
            path: "/skills",
126
            action: ({ params }) => ({
127
              title: titles.skillsTitle,
128
              component: <JobSkillsPage jobId={Number(params.id)} />,
129
            }),
130
          },
131
          {
132
            path: "/review",
133
            action: ({ params }) => ({
134
              title: titles.reviewTitle,
135
              component: <JobReviewPage jobId={Number(params.id)} />,
136
            }),
137
          },
138
        ],
139
      },
140
    ],
141
  },
142
];
143
144
const useJobBreadcrumbs = (intl: IntlShape) => {
145
  const locale = getLocale(intl.locale);
146
  const job = useSelector((state: RootState) => getSelectedJob(state));
147
  const jobBreadcrumbId = "job-title-breadcrumb";
148
149
  const addJobBreadcrumb = (jobBreadcrumb: Job): void => {
150
    const breadcrumbs: HTMLOListElement | null = document.querySelector(
151
      "#jpb-breadcrumbs",
152
    );
153
    const breadcrumb: HTMLLIElement = document.createElement("li");
154
    const anchor = document.createElement("a");
155
    const icon = document.createElement("i");
156
157
    anchor.id = jobBreadcrumbId;
158
    anchor.href = managerJobSummary(locale, jobBreadcrumb.id);
159
    anchor.innerText =
160
      localizeField(locale, jobBreadcrumb, "title") ||
161
      `{ ${intl.formatMessage(messages.titleMissing)} }`;
162
163
    icon.classList.add("fas");
164
    icon.classList.add("fa-caret-right");
165
    breadcrumb.appendChild(anchor);
166
    breadcrumb.appendChild(icon);
167
168
    if (breadcrumbs) {
169
      const lastBreadcrumb = breadcrumbs.lastElementChild;
170
      breadcrumbs.insertBefore(breadcrumb, lastBreadcrumb);
171
    }
172
  };
173
174
  const jobBreadcrumb: HTMLAnchorElement | null = document.querySelector(
175
    `#${jobBreadcrumbId}`,
176
  );
177
178
  useEffect(() => {
179
    if (job) {
180
      if (jobBreadcrumb) {
181
        jobBreadcrumb.href = managerJobSummary(locale, job.id);
182
        jobBreadcrumb.innerText =
183
          localizeField(locale, job, "title") ||
184
          `{ ${intl.formatMessage(messages.titleMissing)} }`;
185
      } else {
186
        addJobBreadcrumb(job);
187
      }
188
    }
189
  }, [
190
    job,
191
    jobBreadcrumb,
192
    locale,
193
    messages,
194
    managerJobSummary,
195
    addJobBreadcrumb,
196
  ]);
197
};
198
199
const Route: React.FunctionComponent = () => {
200
  const intl = useIntl();
201
  const match = useRouter(routes, intl);
202
  const tracker: HTMLElement | null = document.getElementById(
203
    "job-builder-root",
204
  );
205
206
  // Dynamically update the breadcrumbs on step changes
207
  useJobBreadcrumbs(intl);
208
209
  const trackerOffsetTop: number = tracker ? tracker.offsetTop : 0;
210
211
  return (
212
    <ScrollToTop offsetTop={trackerOffsetTop} scrollBehaviorAuto>
213
      {match}
214
    </ScrollToTop>
215
  );
216
};
217
218
const JobBuilderRoot: React.FunctionComponent | null = () => {
219
  return (
220
    <RootContainer>
221
      <Route />
222
    </RootContainer>
223
  );
224
};
225
226
if (document.getElementById("job-builder-root")) {
227
  const root = document.getElementById("job-builder-root");
228
  ReactDOM.render(<JobBuilderRoot />, root);
229
}
230