Hacker admissions emails and Tito duplicate check fix#516
Merged
michelleyeoh merged 15 commits intomainfrom May 5, 2026
Merged
Hacker admissions emails and Tito duplicate check fix#516michelleyeoh merged 15 commits intomainfrom
michelleyeoh merged 15 commits intomainfrom
Conversation
When a pre-fetched existingInvitationsMap is provided (email→url): - If the email is already in the map, return the cached URL immediately without hitting the Tito API at all. - Otherwise, create normally.
There was a problem hiding this comment.
Pull request overview
Adds hacker admissions emailing (single + bulk) into the admin invites workflow while also reducing Tito duplicate-check latency during bulk sends.
Changes:
- Introduces hacker admission invite types (accept/waitlist_accept/waitlist/reject) and corresponding single/bulk invite responses.
- Consolidates the admin invites UI into a unified
InvitePanel(single + bulk) shared across hackers/judges/mentors/volunteers. - Optimizes Tito duplicate handling by prefetching existing RSVP invitations into an email→URL map and reusing URLs when possible.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| app/_types/emails.ts | Adds hacker admission types, labels, and response/result types used across UI + server actions. |
| app/(pages)/admin/invites/page.tsx | Updates invites page to include Hackers tab and use the consolidated InvitePanel. |
| app/(pages)/admin/_components/InvitePanel/InvitePanel.tsx | New shared panel for single/bulk invite flows across roles (with Tito config fetching). |
| app/(pages)/admin/_components/InvitePanel/SingleInviteForm.tsx | New unified single-invite form including hacker admission decision handling. |
| app/(pages)/admin/_components/InvitePanel/BulkInviteForm.tsx | New unified bulk-invite form including hacker CSV Type column + result downloads. |
| app/(pages)/admin/_utils/generateInviteResultsCSV.ts | Adds optional admission Type column support for results export. |
| app/(pages)/admin/_utils/generateInviteFailuresCSV.ts | Adds optional Type column in failures export to enable re-upload for retries. |
| app/(api)/_actions/emails/sendSingleHackerInvite.ts | Implements server action for single hacker admissions emails (email-only vs Tito+Hub). |
| app/(api)/_actions/emails/sendBulkHackerInvites.ts | Implements server action for bulk hacker admissions emails using custom CSV parser. |
| app/(api)/_actions/emails/parseHackerAdmissionsCSV.ts | Adds CSV parsing/validation for hacker admissions (Type column). |
| app/(api)/_actions/emails/processBulkInvites.ts | Allows swapping the default CSV parser with a custom parser per bulk flow. |
| app/(api)/api/admissions/hackers/route.ts | Adds an authenticated admissions API endpoint for batch sending hacker emails. |
| app/(api)/_actions/tito/getAllRsvpInvitations.ts | New helper to prefetch all RSVP invitations for duplicate short-circuiting. |
| app/(api)/_actions/tito/getOrCreateTitoInvitation.ts | Extends Tito invite creation to accept a prefetched invitation map for faster duplicate handling. |
| app/(api)/_actions/emails/sendBulkMentorOrVolunteerInvites.ts | Uses prefetched Tito invitations map to reduce duplicate-check latency. |
| app/(api)/_actions/emails/transporter.ts | Makes Nodemailer transporter lazily initialized and exports DEFAULT_SENDER for guards. |
| app/(api)/_actions/emails/emailTemplates/2026HackerInviteTemplate.ts | Adds 2026 hacker acceptance email template. |
| app/(api)/_actions/emails/emailTemplates/2026HackerWaitlistAcceptTemplate.ts | Adds 2026 hacker waitlist-accept template. |
| app/(api)/_actions/emails/emailTemplates/2026HackerWaitlistTemplate.ts | Adds 2026 hacker waitlist template. |
| app/(api)/_actions/emails/emailTemplates/2026HackerRejectionTemplate.ts | Adds 2026 hacker rejection template. |
| Deleted legacy judge/mentor/volunteer invite form components | Removes now-redundant per-role invite forms replaced by InvitePanel. |
Comments suppressed due to low confidence (2)
app/(pages)/admin/_components/InvitePanel/InvitePanel.tsx:59
- When
rolechanges to a Tito-required role, the effect starts fetching RSVP lists/releases butloadingisn't set back totrue. This can renderSingleInviteForm/BulkInviteFormwith emptyrsvpLists/releasesbriefly and allow interaction before data is loaded. Consider settingsetLoading(true)at the start of the effect (whenneedsTito(role)), and optionally clearingloadError/data when switching roles.
app/(api)/_actions/tito/getOrCreateTitoInvitation.ts:56 - The comment says duplicate recovery is only for the single-invite path (no pre-fetched map), but the recovery logic runs even when
existingInvitationsMapis provided (it triggers on any duplicate error). Either update the comment to match the behavior, or gate the recovery behind!existingInvitationsMapif the intent is to avoid per-email lookups in bulk sends.
// Duplicate recovery for single-invite path (no pre-fetched map)
if (!titoResponse.ok && isDuplicateTicketError(titoResponse.error)) {
console.warn(`[Tito] Duplicate detected for ${email}, attempting recovery`);
const existingRes = await getRsvpInvitationByEmail(rsvpListSlug, email);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Member
Author
|
@michelleyeoh ready for merge now |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #515, #502