Skip to content

Commit 407b72e

Browse files
committed
Merge branch 'main' of https://github.com/uwblueprint/website-bp-be into INTW26-reviewer-authorization
2 parents e2147e7 + 3ce3feb commit 407b72e

File tree

7 files changed

+97
-6
lines changed

7 files changed

+97
-6
lines changed

backend/typescript/graphql/resolvers/reviewPageResolvers.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ApplicationDTO } from "../../types";
1+
import { ApplicationDTO, ReviewedApplicantsDTO } from "../../types";
22
import ReviewPageService from "../../services/implementations/reviewPageService";
33
import { getErrorMessage } from "../../utilities/errorUtils";
44

@@ -16,6 +16,18 @@ const reviewPageResolvers = {
1616
throw new Error(getErrorMessage(error));
1717
}
1818
},
19+
getReviewedApplicantsByUserId: async (
20+
_parent: undefined,
21+
args: { userId: number },
22+
): Promise<ReviewedApplicantsDTO[]> => {
23+
try {
24+
return await reviewPageService.getReviewedApplicantsByUserId(
25+
args.userId,
26+
);
27+
} catch (error) {
28+
throw new Error(getErrorMessage(error));
29+
}
30+
},
1931
},
2032
};
2133

backend/typescript/graphql/types/reviewPageType.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,16 @@ const reviewPageType = gql`
2525
timestamp: Int
2626
}
2727
28+
type ReviewedApplicantsDTO {
29+
applicantRecordId: String!
30+
reviewStatus: String!
31+
applicantFirstName: String!
32+
applicantLastName: String!
33+
}
34+
2835
extend type Query {
2936
reviewApplicantPage(applicantRecordId: String!): ApplicationDTO!
37+
getReviewedApplicantsByUserId(userId: Int!): [ReviewedApplicantsDTO!]!
3038
}
3139
`;
3240

backend/typescript/models/reviewedApplicantRecord.model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,10 @@ export default class ReviewedApplicantRecord extends Model {
5959

6060
@BelongsTo(() => User, { foreignKey: "reviewerId", targetKey: "id" })
6161
user?: NonAttribute<User>;
62+
63+
@BelongsTo(() => ApplicantRecord, {
64+
foreignKey: "applicantRecordId",
65+
targetKey: "id",
66+
})
67+
applicantRecord?: NonAttribute<ApplicantRecord>;
6268
}

backend/typescript/models/user.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default class User extends Model {
3939

4040
@HasMany(() => ReviewedApplicantRecord, {
4141
foreignKey: "reviewerId",
42-
as: "user",
42+
sourceKey: "id",
4343
})
4444
reviewedApplicantRecords?: NonAttribute<ReviewedApplicantRecord[]>;
4545
}

backend/typescript/services/implementations/reviewPageService.ts

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import { ApplicationDTO } from "../../types";
1+
import { ApplicationDTO, ReviewedApplicantsDTO } from "../../types";
22
import IReviewPageService from "../interfaces/IReviewPageService";
33
import { getErrorMessage } from "../../utilities/errorUtils";
44
import logger from "../../utilities/logger";
55
import ApplicantRecord from "../../models/applicantRecord.model";
6+
import type ReviewedApplicantRecord from "../../models/reviewedApplicantRecord.model";
67
import Applicant from "../../models/applicant.model";
8+
import User from "../../models/user.model";
79

810
const Logger = logger(__filename);
911

10-
function toDTO(model: Applicant): ApplicationDTO {
12+
function toApplicationDTO(model: Applicant): ApplicationDTO {
13+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
1114
const firstChoice = model.applicantRecords!.find((ar) => ar.choice === 1);
1215
const secondChoice = model.applicantRecords!.find((ar) => ar.choice === 2);
1316

@@ -36,6 +39,18 @@ function toDTO(model: Applicant): ApplicationDTO {
3639
};
3740
}
3841

42+
function toReviewedApplicantRecordDTO(
43+
model: ReviewedApplicantRecord,
44+
): ReviewedApplicantsDTO {
45+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
46+
return {
47+
applicantRecordId: model.applicantRecordId,
48+
reviewStatus: model.status,
49+
applicantFirstName: model.applicantRecord!.applicant!.firstName,
50+
applicantLastName: model.applicantRecord!.applicant!.lastName,
51+
};
52+
}
53+
3954
class ReviewPageService implements IReviewPageService {
4055
/* eslint-disable class-methods-use-this */
4156
async getReviewPage(applicantRecordId: string): Promise<ApplicationDTO> {
@@ -60,7 +75,42 @@ class ReviewPageService implements IReviewPageService {
6075
});
6176
if (!applicant) throw new Error(`Database integrity has been violated`);
6277

63-
return toDTO(applicant);
78+
return toApplicationDTO(applicant);
79+
} catch (error: unknown) {
80+
Logger.error(`Failed to fetch. Reason = ${getErrorMessage(error)}`);
81+
throw error;
82+
}
83+
}
84+
85+
async getReviewedApplicantsByUserId(
86+
userId: number,
87+
): Promise<ReviewedApplicantsDTO[]> {
88+
try {
89+
const user: User | null = await User.findOne({
90+
where: { id: userId },
91+
attributes: { exclude: ["createdAt", "updatedAt"] },
92+
include: [
93+
{
94+
attributes: { exclude: ["createdAt", "updatedAt"] },
95+
association: "reviewedApplicantRecords",
96+
include: [
97+
{
98+
attributes: { exclude: ["createdAt", "updatedAt"] },
99+
association: "applicantRecord",
100+
include: [
101+
{
102+
attributes: { exclude: ["createdAt", "updatedAt"] },
103+
association: "applicant",
104+
},
105+
],
106+
},
107+
],
108+
},
109+
],
110+
});
111+
if (!user) throw new Error(`No user with ${userId} found.`);
112+
if (!user.reviewedApplicantRecords) return [];
113+
return user.reviewedApplicantRecords.map(toReviewedApplicantRecordDTO);
64114
} catch (error: unknown) {
65115
Logger.error(`Failed to fetch. Reason = ${getErrorMessage(error)}`);
66116
throw error;
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
import { ApplicationDTO } from "../../types";
1+
import { ApplicationDTO, ReviewedApplicantsDTO } from "../../types";
22

33
interface IReviewPageService {
44
/**
55
* Fetch data from the Applicant and ApplicantRecord table to return an ApplicationDTO object
66
* @Param applicantRecordId the id of the applicant record that the viewer is interested in
77
*/
88
getReviewPage(applicantRecordId: string): Promise<ApplicationDTO>;
9+
10+
/**
11+
* Fetches information about all the applicants assigned to a user to review
12+
* @param userId the id of the user that the viewer is interested in
13+
*/
14+
getReviewedApplicantsByUserId(
15+
userId: number,
16+
): Promise<ReviewedApplicantsDTO[]>;
917
}
1018

1119
export default IReviewPageService;

backend/typescript/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,13 @@ export type ReviewDashboardSidePanelDTO = {
239239
reviewDetails: ReviewDetails[];
240240
};
241241

242+
export type ReviewedApplicantsDTO = {
243+
applicantRecordId: string;
244+
reviewStatus: ReviewStatus;
245+
applicantFirstName: string;
246+
applicantLastName: string;
247+
};
248+
242249
export type AdminCommentDTO = {
243250
id: string;
244251
userId: number;

0 commit comments

Comments
 (0)