Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit ee9dc30

Browse files
committed
fix: issue #523
1 parent 61e9fcd commit ee9dc30

File tree

4 files changed

+184
-0
lines changed

4 files changed

+184
-0
lines changed

src/constants/index.js

+13
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,19 @@ export const POSITION_STATUS = {
4848
CANCELLED: "cancelled",
4949
};
5050

51+
/**
52+
* Interview related constants
53+
*/
54+
export const INTERVIEW_STATUS = {
55+
SCHEDULING: "Scheduling",
56+
SCHEDULED: "Scheduled",
57+
REQUESTEDFORRESCHEDULE: "Requested for reschedule",
58+
RESCHEDULED: "Rescheduled",
59+
COMPLETED: "Completed",
60+
CANCELLED: "Cancelled",
61+
EXPIRED: "Expired",
62+
};
63+
5164
/**
5265
* Mapping between position status "server value" and human readable value
5366
*/

src/root.component.jsx

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import InputSkills from "./routes/CreateNewTeam/pages/InputSkills";
1919
import InputJobDescription from "./routes/CreateNewTeam/pages/InputJobDescription";
2020
import SelectRole from "./routes/CreateNewTeam/pages/SelectRole";
2121
import CreateTaasPayment from "./routes/CreateNewTeam/pages/CreateTaasPayment";
22+
import SchedulingPage from "./routes/SchedulingPage";
2223
import ReduxToastr from "react-redux-toastr";
2324
import store from "./store";
2425
import "./styles/main.vendor.scss";
@@ -50,6 +51,7 @@ export default function Root() {
5051
<InputSkills path="skills/*" />
5152
<SelectRole path="role/*" />
5253
</CreateNewTeam>
54+
<SchedulingPage path="/taas/interview/:interviewId" />
5355
</Router>
5456

5557
{/* Global config for Toastr popups */}

src/routes/SchedulingPage/index.jsx

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* Scheduling Page
3+
*
4+
* Allows users to set up bookings for an interview in Nylas
5+
*/
6+
import React, { useEffect, useState } from "react";
7+
import { getAuthUserProfile } from "@topcoder/micro-frontends-navbar-app";
8+
import _ from "lodash";
9+
import Page from "components/Page";
10+
import LoadingIndicator from "components/LoadingIndicator";
11+
import PageHeader from "components/PageHeader";
12+
import { getInterview } from "services/scheduler";
13+
import { INTERVIEW_STATUS } from "constants";
14+
import withAuthentication from "../../hoc/withAuthentication";
15+
16+
const SchedulingPage = ({ interviewId }) => {
17+
const [schedulingPageUrl, setSchedulingPageUrl] = useState(null);
18+
const [errorMessage, setErrorMessage] = useState(null);
19+
20+
// if there are some candidates to review, then show "To Review" tab by default
21+
useEffect(() => {
22+
getAuthUserProfile()
23+
.then((res) => {
24+
return {
25+
firstName: res.firstName,
26+
lastName: res.lastName,
27+
email: res.email,
28+
};
29+
})
30+
.then((profile) => {
31+
getInterview(interviewId)
32+
.then(({ data }) => {
33+
if (
34+
data.status === INTERVIEW_STATUS.SCHEDULED ||
35+
data.status === INTERVIEW_STATUS.RESCHEDULED
36+
) {
37+
setSchedulingPageUrl(
38+
`https://schedule.nylas.com/${data.nylasPageSlug}?email=${
39+
profile.email
40+
}&name=${encodeURI(
41+
profile.firstName + " " + profile.lastName
42+
)}&prefilled_readonly=true`
43+
);
44+
} else {
45+
setErrorMessage("No interviews scheduled");
46+
}
47+
})
48+
.catch((err) => {
49+
setErrorMessage(err);
50+
});
51+
});
52+
}, [interviewId]);
53+
54+
return (
55+
<Page title="Schedule Interview">
56+
{!schedulingPageUrl ? (
57+
<LoadingIndicator error={errorMessage} />
58+
) : (
59+
<>
60+
<PageHeader title="Schedule Interview" />
61+
<iframe
62+
title="Nylas Scheduling Page"
63+
src={schedulingPageUrl}
64+
width="1020"
65+
height="900"
66+
/>
67+
</>
68+
)}
69+
</Page>
70+
);
71+
};
72+
73+
export default withAuthentication(SchedulingPage);

src/services/scheduler.js

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/* global process */
2+
3+
/**
4+
* Scheduler Service
5+
*/
6+
import { axiosInstance as axiosWrapper } from "./requestInterceptor";
7+
import axios from "axios";
8+
import jwt from "jsonwebtoken";
9+
import config from "../../config";
10+
11+
/**
12+
* Initializes the Scheduler
13+
* @param {Object} profile the logged in user and candidate profile
14+
*/
15+
export function initializeScheduler(profile) {
16+
return axiosWrapper.post(
17+
`${config.INTERVIEW_SCHEDULER_URL}/authorize`,
18+
profile
19+
);
20+
}
21+
22+
/**
23+
* Gets the scheduling page url
24+
* @param {Object} page The scheduling page
25+
* @param {Object} profile The customer and candidate details
26+
* @returns Promise
27+
*/
28+
export function scheduleInterview(page, profile) {
29+
return axiosWrapper.post(`${config.INTERVIEW_SCHEDULER_URL}/interview`, {
30+
schedulingPage: page,
31+
...profile,
32+
});
33+
}
34+
35+
/**
36+
* Returns the interview page url for the given interview
37+
* @param {String} interviewId The interview id
38+
* @returns Promise
39+
*/
40+
export function getInterview(interviewId) {
41+
return axiosWrapper.get(`${config.API.V5}/getInterview/${interviewId}`);
42+
}
43+
44+
/**
45+
* Updates a scheduling page
46+
* @param {Number} pageId The scheduling page id
47+
* @param {Object} page The scheduling page
48+
* @param {String} editToken The auth token
49+
* @returns Promise
50+
*/
51+
export function editSchedulingPage(pageId, page, editToken) {
52+
return axios.put(`${config.NYLAS_API_URL}/manage/pages/${pageId}`, page, {
53+
headers: {
54+
Authorization: `Bearer ${editToken}`,
55+
},
56+
});
57+
}
58+
59+
/**
60+
* Redirects to Nylas Hosted Auth
61+
*/
62+
export function redirectToNylasHostedAuth(
63+
pageId,
64+
pageEditToken,
65+
candidateId,
66+
path
67+
) {
68+
const clientId = process.env.NYLAS_CLIENT_ID;
69+
const redirectUri = `${config.INTERVIEW_SCHEDULER_URL}/oauth/callback`;
70+
const responseType = "code";
71+
const scopes = "calendar";
72+
const state = jwt.sign(
73+
{
74+
pageId,
75+
candidateId,
76+
pageEditToken,
77+
path,
78+
},
79+
"secret"
80+
);
81+
window.location.href = `https://api.nylas.com/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=${responseType}&scopes=${scopes}&state=${state}`;
82+
}
83+
84+
/**
85+
* Fetch the scheduling page details
86+
* @param {Number} pageId The scheduling page id
87+
* @param {String} editToken The auth token
88+
* @returns Promise
89+
*/
90+
export function fetchLatestSchedule(pageId, editToken) {
91+
return axios.get(`${config.NYLAS_API_URL}/manage/pages/${pageId}`, {
92+
headers: {
93+
Authorization: `Bearer ${editToken}`,
94+
},
95+
});
96+
}

0 commit comments

Comments
 (0)