Skip to content
17 changes: 16 additions & 1 deletion backend/typescript/graphql/resolvers/reviewDashboardResolvers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import ReviewDashboardService from "../../services/implementations/reviewDashboardService";
import { ReviewDashboardRowDTO } from "../../types";
import {
ReviewDashboardRowDTO,
ReviewDashboardSidePanelDTO,
} from "../../types";
import { getErrorMessage } from "../../utilities/errorUtils";

const reviewDashboardService = new ReviewDashboardService();
Expand All @@ -19,6 +22,18 @@ const reviewDashboardResolvers = {
throw new Error(getErrorMessage(error));
}
},
reviewDashboardSidePanel: async (
_parent: undefined,
args: { applicantId: string },
): Promise<ReviewDashboardSidePanelDTO> => {
try {
return await reviewDashboardService.getReviewDashboardSidePanel(
args.applicantId,
);
} catch (error) {
throw new Error(getErrorMessage(error));
}
},
},
};

Expand Down
28 changes: 28 additions & 0 deletions backend/typescript/graphql/types/reviewDashboardType.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { gql } from "apollo-server-express";
import { ApplicationStatus, PositionTitle, ReviewerDTO } from "../../types";

Check warning on line 2 in backend/typescript/graphql/types/reviewDashboardType.ts

View workflow job for this annotation

GitHub Actions / run-lint

'ReviewerDTO' is defined but never used

Check warning on line 2 in backend/typescript/graphql/types/reviewDashboardType.ts

View workflow job for this annotation

GitHub Actions / run-lint

'PositionTitle' is defined but never used

Check warning on line 2 in backend/typescript/graphql/types/reviewDashboardType.ts

View workflow job for this annotation

GitHub Actions / run-lint

'ApplicationStatus' is defined but never used

const reviewDashboardType = gql`
type ReviewerDTO {
Expand All @@ -18,11 +18,39 @@
totalScore: Int
}

type Review {
passionFSG: Int
teamPlayer: Int
desireToLearn: Int
skill: Int
skillCategory: String
comments: String
}

type ReviewDetails {
reviewerFirstName: String!
reviewerLastName: String!
review: Review!
}

type ReviewDashboardSidePanelDTO {
firstName: String!
lastName: String!
positionTitle: String!
program: String!
resumeUrl: String!
applicationStatus: String!
skillCategory: String
reviewDetails: [ReviewDetails!]!
}

extend type Query {
reviewDashboard(
pageNumber: Int!
resultsPerPage: Int!
): [ReviewDashboardRowDTO!]!

reviewDashboardSidePanel(applicantId: String!): ReviewDashboardSidePanelDTO!
}
`;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { PositionTitle, ReviewDashboardRowDTO } from "../../types";
import {
PositionTitle,
ReviewDashboardRowDTO,
ReviewDashboardSidePanelDTO,
} from "../../types";
import IReviewDashboardService from "../interfaces/IReviewDashboardService";
import { getErrorMessage } from "../../utilities/errorUtils";
import logger from "../../utilities/logger";
Expand All @@ -22,6 +26,26 @@ function toDTO(model: ApplicantRecord): ReviewDashboardRowDTO {
};
}

function toSidePanelDTO(model: ApplicantRecord): ReviewDashboardSidePanelDTO {
const reviewDetails =
model.reviewedApplicantRecords?.map((reviewRecord) => ({
reviewerFirstName: reviewRecord.user?.first_name || "",
reviewerLastName: reviewRecord.user?.last_name || "",
review: reviewRecord.review,
})) || [];

return {
firstName: model.applicant!.firstName,
lastName: model.applicant!.lastName,
positionTitle: model.position as PositionTitle,
program: model.applicant!.program,
resumeUrl: model.applicant!.resumeUrl,
applicationStatus: model.status,
skillCategory: model.skillCategory,
reviewDetails,
};
}

class ReviewDashboardService implements IReviewDashboardService {
/* eslint-disable class-methods-use-this */
async getReviewDashboard(
Expand Down Expand Up @@ -72,6 +96,47 @@ class ReviewDashboardService implements IReviewDashboardService {
throw error;
}
}

async getReviewDashboardSidePanel(
applicantId: string,
): Promise<ReviewDashboardSidePanelDTO> {
try {
const applicantRecord: ApplicantRecord | null =
await ApplicantRecord.findOne({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥹 looks familiar

where: { applicantId },
attributes: { exclude: ["createdAt", "updatedAt"] },
include: [
{
attributes: { exclude: ["createdAt", "updatedAt"] },
association: "reviewedApplicantRecords",
include: [
{
attributes: { exclude: ["createdAt", "updatedAt"] },
association: "user",
},
],
},
{
attributes: { exclude: ["createdAt", "updatedAt"] },
association: "applicant",
},
],
});

if (!applicantRecord || !applicantRecord.applicant) {
throw new Error(`Applicant with ID ${applicantId} not found`);
}

return toSidePanelDTO(applicantRecord);
} catch (error: unknown) {
Logger.error(
`Failed to get review dashboard side panel for applicant ${applicantId}. Reason = ${getErrorMessage(
error,
)}`,
);
throw error;
}
}
}

export default ReviewDashboardService;
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { ReviewDashboardRowDTO } from "../../types";
import {
ReviewDashboardRowDTO,
ReviewDashboardSidePanelDTO,
} from "../../types";

interface IReviewDashboardService {
/**
Expand All @@ -10,6 +13,14 @@ interface IReviewDashboardService {
page: number,
resultsPerPage: number,
): Promise<ReviewDashboardRowDTO[]>;

/**
* Fetch data that can fill out the review dashboard side panel for an applicant
* @Param applicantId the ID of the applicant
*/
getReviewDashboardSidePanel(
applicantId: string,
): Promise<ReviewDashboardSidePanelDTO>;
}

export default IReviewDashboardService;
18 changes: 18 additions & 0 deletions backend/typescript/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ export type Review = {
desireToLearn?: number;
skill?: number;
skillCategory?: SkillCategory;
comments?: string;
};

export type ReviewedApplicantRecordDTO = {
Expand All @@ -208,6 +209,23 @@ export type ReviewedApplicantRecordDTO = {
reviewerHasConflict: boolean;
};

export type ReviewDetails = {
reviewerFirstName: string;
reviewerLastName: string;
review: Review;
};

export type ReviewDashboardSidePanelDTO = {
firstName: string;
lastName: string;
positionTitle: PositionTitle;
program: string;
resumeUrl: string;
applicationStatus: ApplicationStatus;
skillCategory: SkillCategory | null;
reviewDetails: ReviewDetails[];
};

export type AdminCommentDTO = {
id: string;
userId: number;
Expand Down
Loading