Skip to content

[INTW26] Build queries for review homepage - #131

Merged
mxc-maggiechen merged 8 commits into
mainfrom
INTW26-review-homepage-queries
May 9, 2026
Merged

[INTW26] Build queries for review homepage#131
mxc-maggiechen merged 8 commits into
mainfrom
INTW26-review-homepage-queries

Conversation

@gavxue

@gavxue gavxue commented Apr 7, 2026

Copy link
Copy Markdown
Collaborator

Build queries for review homepage

Implementation description

  • Added two new review homepage queries
    • getInterviewedApplicantsByUserId
    • getInterviewedPairingsByUserId
  • Implemented corresponding resolver and GraphQL DTO types for both queries

Steps to test

  1. run the following sql script to seed in necessary data to the tables (replace AR_ID_1 and AR_ID_2 with two ids from your applicant_records table
INSERT INTO reviewed_applicant_records
("applicantRecordId","reviewerId",review,status,"reviewerHasConflict","createdAt","updatedAt")
VALUES
('AR_ID_1', 2, '{"notes":"manual-pr-test"}'::jsonb, 'Todo', false, NOW(), NOW()),
('AR_ID_2', 2, '{"notes":"manual-pr-test"}'::jsonb, 'In Progress', false, NOW(), NOW())
ON CONFLICT ("applicantRecordId","reviewerId") DO NOTHING;

INSERT INTO interviewed_applicant_records
(id,"applicantRecordId",status,"createdAt","updatedAt")
VALUES
('11111111-1111-4111-8111-111111111111', 'AR_ID_1', 'Need Review', NOW(), NOW()),
('22222222-2222-4222-8222-222222222222', 'AR_ID_2', 'In Progress', NOW(), NOW())
ON CONFLICT (id) DO NOTHING;

INSERT INTO interview_groups
(id,"schedulingLink",status,"createdAt","updatedAt")
VALUES
('aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa', NULL, 'Availability Pending', NOW(), NOW()),
('bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb', NULL, 'Ready to Interview', NOW(), NOW())
ON CONFLICT (id) DO NOTHING;

INSERT INTO interview_delegations
("interviewedApplicantRecordId","interviewerId","groupId","interviewHasConflict","createdAt","updatedAt")
VALUES
('11111111-1111-4111-8111-111111111111', 2, 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa', NULL, NOW(), NOW()),
('11111111-1111-4111-8111-111111111111', 1, 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa', NULL, NOW(), NOW()),
('22222222-2222-4222-8222-222222222222', 2, 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb', NULL, NOW(), NOW()),
('22222222-2222-4222-8222-222222222222', 3, 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb', NULL, NOW(), NOW())
ON CONFLICT ("interviewedApplicantRecordId","interviewerId") DO NOTHING;
  1. run the first query using userIds 1, 2, 3
query GetInterviewedApplicants {
  getInterviewedApplicantsByUserId(userId: 1) {
    applicantRecordId
    interviewStatus
    applicantFirstName
    applicantLastName
  }
}

The result should contain the applicant(s) you chose previously.

  1. run the second query using userIds 1, 2, 3
query GetInterviewedPairings {
  getInterviewedPairingsByUserId(userId: 1) {
    interviewedGroupId
    interviewGroupStatus
    groupMembers {
      id
      firstName
      lastName
      email
      role
    }
  }
}

The result should contain information about the interviewers each user is paired with.

What should reviewers focus on?

  • Users do not need to have reviewed an applicant to appear in interview-assigned results.

Checklist

@gavxue gavxue self-assigned this Apr 7, 2026
@gavxue
gavxue requested a review from mxc-maggiechen April 7, 2026 21:27
@mxc-maggiechen mxc-maggiechen self-assigned this May 7, 2026
@mxc-maggiechen mxc-maggiechen changed the title Build queries for review homepage [INTW26] Build queries for review homepage May 7, 2026

@BelongsTo(() => Applicant, "applicantId")
applicant?: NonAttribute<Applicant>;
applicant!: NonAttribute<Applicant>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These type assertions are added to better use the models and resolve errors with type checking. This is also logically correct, a model that belongs to another model should never be null/undefined

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice, finally a good usage of the non-null assertion

Comment on lines +37 to +56
const assignedDelegations = await InterviewDelegation.findAll({
where: { interviewerId: userId },
include: [
{
model: InterviewedApplicantRecord,
attributes: ["applicantRecordId", "status"],
include: [
{
model: ApplicantRecord,
include: [
{
model: Applicant,
attributes: ["firstName", "lastName"],
},
],
},
],
},
],
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was reading up on some best practices for sequelize, I think this pattern is more clear and uses types better than the existing pattern. Hoping to adopt this during the migration.

@mxc-maggiechen
mxc-maggiechen requested a review from SaqAsh May 9, 2026 04:21

@SaqAsh SaqAsh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

some small comments

attributes: ["groupId"],
});

// dedupe groupIds, although each groupId should have a unique set of interviewers, the database design does not guarantee this.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we not have a unique constraint at the DB lvl?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

i don't think so, so basically how it works is the following:

InterviewGroups and InterviewDelegation (a delegation is defined by one interviewer and applicant)

Each InterviewDelegation belongs to an InterviewGroup (interview delegation has FK groupId), but an InterviewGroup should have multiple delegations.

For example we have interview group 1.

We have interview delegation A1, which consists of person A and candidate X and belongs to interview group 1.
We have interview delegation B1, which consists of person B and candidate X and belongs to interview group 1.

Nothing here allows us to guarantee uniqueness on the interviewer...

// dedupe groupIds, although each groupId should have a unique set of interviewers, the database design does not guarantee this.
const groupIds = [...new Set(userGroupRows.map((row) => row.groupId))];
if (groupIds.length === 0) {
return [];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lets move this check above the groupIds so we have something like the following....

if (userGroupRows.length === 0){
    return [];
}
// then we find the groupIds
const groupIds - [...new Set(userGroupRows.map((rows) => row.groupId))];


@BelongsTo(() => Applicant, "applicantId")
applicant?: NonAttribute<Applicant>;
applicant!: NonAttribute<Applicant>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice, finally a good usage of the non-null assertion

@mxc-maggiechen
mxc-maggiechen merged commit f42df7d into main May 9, 2026
1 check passed
@mxc-maggiechen
mxc-maggiechen deleted the INTW26-review-homepage-queries branch May 9, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants