Skip to content

Ints26 reassign reviewer - #76

Open
joc31yn wants to merge 14 commits into
mainfrom
INTS26-reassign-reviewer
Open

Ints26 reassign reviewer#76
joc31yn wants to merge 14 commits into
mainfrom
INTS26-reassign-reviewer

Conversation

@joc31yn

@joc31yn joc31yn commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Notion ticket link

Reassign Reviewer on Dashboard Feature

Implementation description

  • Added getUsersByPosition query to fetch all users with the same position as the applicant record, used to populate the reassign reviewer dropdown
  • Added reassignReviewer mutation that atomically deletes the existing reviewedApplicantRecord for the old reviewer and creates a new one for the new reviewer using a Sequelize transaction
  • Modified createReviewedApplicantRecord and deleteReviewedApplicantRecordByPk service functions to accept an optional Sequelize transaction parameter
  • Added frontend API client methods getUsersByPosition and reassignReviewer to ReviewPageAPIClient

Steps to test

  1. Navigate to the review dashboard and click on a reviewer's name in the table
  2. In the dialogue, search for and select a new reviewer, then click "Update"
  3. Verify that the dashboard refreshes with the updated reviewer

What should reviewers focus on?

  • The Sequelize transaction in reassignReviewer ensure if either the delete or create fails, both operations are rolled back correctly
  • The optional transaction parameter added to createReviewedApplicantRecord and deleteReviewedApplicantRecordByPk doesn't break existing callers
  • Auth middleware is set to admin only for both new endpoints

Checklist

  • My PR name is descriptive and in imperative tense
  • My commit messages are descriptive and in imperative tense. My commits are atomic and trivial commits are squashed or fixup'd into non-trivial commits
  • I have run the appropriate linter(s)
  • I have requested a review from the PL, as well as other devs who have background knowledge on this PR or who will be building on top of this PR

@joc31yn
joc31yn requested a review from mxc-maggiechen July 19, 2026 02:53
Comment on lines +252 to +281
async reassignReviewer(
applicantRecordId: string,
oldReviewerId: string,
newReviewerId: string,
): Promise<ReviewedApplicantRecordDTO> {
const transaction = await sequelize.transaction();
try {
await this.deleteReviewedApplicantRecordByPk(
applicantRecordId,
oldReviewerId,
transaction,
);
const newRecord = await this.createReviewedApplicantRecord(
{
applicantRecordId,
reviewerId: newReviewerId,
status: "TODO",
},
transaction,
);
await transaction.commit();
return newRecord;
} catch (error: unknown) {
await transaction.rollback();
Logger.error(
`Failed to reassign reviewer. Reason = ${getErrorMessage(error)}`,
);
throw error;
}
}

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.

this looks correct, let's not create a new service function though, we can just call these service functions in the GraphQL mutation: backend/typescript/graphql/resolvers/reviewedApplicantRecordResolvers.ts

I think the goal is to keep service functions as atomic to the table and reusable as possible. If we need joins from multiple tables, thats what our composite service files are for. But if we need to just call different service functions, we can just do it from the query/mutation.

Comment on lines +122 to +132
users.map(async (user) => {
let firebaseUser: firebaseAdmin.auth.UserRecord;
try {
firebaseUser = await firebaseAdmin.auth().getUser(user.auth_id);
} catch (error) {
Logger.error(
`user with authId ${user.auth_id} could not be fetched from Firebase`,
);
throw error;
}

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 dont think we need to fetch email from firebase, it should be recorded in users table, i think just your initial .findAll shoudl be fine. We also have a toUserDTO helper function that casts the sequelize type to our internal typescript DTO type

boxShadow: "none",
opacity: 1,
width: "310px",
width: width,

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.

nice, this is a lot better for a common dialgoue component 😄

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.

why did you need to edit this file? if its not necessary for this PR, lets revert it to keep this PR well scoped 😄

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

remerged with main, but when a reviewer is reassigned i wanted to trigger dashboard to reload so added refetch. Not sure if there's another preferred way without needing to edit this file?

Comment thread frontend/pages/admin/review/index.tsx Outdated
Comment on lines +82 to +84
const handleSortingChange = (
updater: SortingState | ((old: SortingState) => SortingState),
) => {

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 this change is within the scope of the PR either, lets revert it to keep this PR simple!

Comment thread frontend/pages/admin/review/index.tsx Outdated
Comment on lines +60 to +73
const columns = useMemo(
() =>
createReviewDashboardColumns({
onReviewerClick: (row, reviewer) => {
setReassignmentTarget({
applicantRecordId: row.applicantRecordId,
position: row.position,
reviewerId: reviewer.id,
reviewerName: `${reviewer.firstName} ${reviewer.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 think there might be a cleaner way to add a callback per cell? i haven't used tanstack before either, i just asked cursor for a bit and it cooked up this: #85

let me know your thoughts! if you think its good, we can merge that change into your branch

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.

2 participants