Skip to content

Feature: fix/hackathon-portal-finish to dev - #452

Merged
aamoghS merged 22 commits into
devfrom
fix/hackathon-portal-finish
Oct 2, 2026
Merged

aamoghS merged 22 commits into
devfrom
fix/hackathon-portal-finish

Conversation

@github-actions

@github-actions github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Finishes the hackathon portal end to end and drops the fake-terminal look in favour of the dashboard's house style.

Behaviour changes (decided with the owner)

  • Capacity caps acceptances, not applications. Applying never takes a seat; waves fill only what is left, and every approve path checks seats under the hackathon row lock (assertSeats). A full event still takes applications, which wait on the waitlist.
  • Teams form from acceptance, any time before +34h (was +12h to +34h).
  • Judge applications open once an event is announced.
  • Any admin can approve judges (removing one stays super-admin).

Participants

  • Teams see their judging table number on /submit.
  • Withdraw registration (pending, accepted or waitlisted; not on a team, not checked in, no project; not after the event).
  • Team create/join only offered once accepted; checked-in people get a "Submit your project" link.
  • Registration statuses read as "Under review / Accepted / Checked in" everywhere; nothing says "You're in" while an application is pending.
  • /hacklytics shows the interest form only while announced, otherwise a status line and a link.
  • Schedule times carry the day; failed loads show an error with Try again instead of an empty list.
  • Fixed: opening the registration form showed "Registration is closed." above it.

Judges and organisers

  • Add judge by email (the old Assign Judge picker could never open), plus a copyable apply link.
  • Judging can't be opened before any judge has a queue; the Judges tab links to Prepare judging, and a judge with nothing queued sees "No tables yet" instead of "All done, 0 of 0".
  • Judge applications to drafts, hidden or missing events are refused (was a 500).
  • Approve without email is labelled as such; seat-limit refusals are shown. The results email goes to checked-in participants and opens the Results tab.
  • Scanner explains it needs a check-in event and recognises passes from another hackathon.

Look

  • Hackathon list/detail/tabs, submit, judging, admin hackathons and judging, sign-in, and the auth error page now use the dashboard's styles: Oswald headings, the teal accent, one set of buttons/inputs, rounded-sm, plain sentence-case copy.
  • Removed: underscore titles ("Auth_Error", "Status_Code: 401"), "System Failure / Reboot System", "Data Evaluation Layer // SYNC ACTIVE", neon glows, gradient text, pulsing dots, rotating squares, scanlines.
  • text-text-muted was not a real utility, so "muted" text rendered at full brightness in 89 places; fixed site-wide.

Checks

Typecheck, lint, 871 tests (run in UTC like CI) and the build pass. New tests cover the acceptance cap, team window, judge rules, withdrawal (including the race) and the judging guard.

Not included: an uncommitted change to packages/db/src/schemas/events.ts (unique constraint → unique index) that was already in the working tree; it is left for its author.


Note

High Risk
Changes core registration/capacity, check-in concurrency, and admin approval flows; mistakes could over-accept participants or block legitimate organisers/judges.

Overview
Capacity and registration: maxParticipants now limits acceptances (approved/checked-in), not applications. Registration no longer increments currentParticipants or rejects “full” events; assertSeats runs inside transactions on single/batch approve, accept-wave, and check-in paths. syncCurrentParticipants and wave sizing respect remaining seats. Participants can withdrawRegistration when still pending/accepted without team, check-in, or project, with optimistic delete and seat recount.

Teams, judges, judging: Team create/join/leave opens from acceptance through +34h (removed the +12h gate). judge.setActive is any admin (remove stays super-admin); judge.create accepts email lookup; judge.register returns NOT_FOUND for missing/draft/hidden editions. toggleJudging refuses to open when the queue is empty. Team project fetch includes judging table number when promoted.

Portal / Hacklytics: Shared StatusBadge and a dashboard-aligned restyle (Oswald, accent tokens, text-[var(--text-muted)] instead of broken text-text-muted, calmer copy on errors/loading). Hacklytics funnel includes closed; interest form only while announced; registration-closed states link to the event page. Admin judging honors ?hackathonId= and surfaces toggle-judging errors.

Tests are updated/added for capacity on approve, team window, withdrawal races, judge rules, and judging guards.

Reviewed by Cursor Bugbot for commit e6bd765. Bugbot is set up for automated code reviews on this repo. Configure here.

aamoghS and others added 15 commits October 1, 2026 11:38
The hackathon pages, submit, judging and their error and loading
screens had drifted into a fake-terminal style the rest of the portal
does not use: underscored titles ("Auth_Error", "Status_Code: 401"),
"System Failure" / "Reboot System" copy, neon glows, gradient text,
pulsing dots, blur blobs inside cards, hover lifts and a second green
accent. They now use the dashboard and settings conventions: Oswald
headings, the teal accent, one set of buttons and inputs, rounded-sm,
plain sentence-case copy, and one empty-state pattern.

- Registration statuses render through a shared StatusBadge
  ("Under review", "Accepted", "Checked in") instead of raw enums.
  The detail page and registration card no longer say "Registered" or
  "You're in" while an application is still pending.
- text-text-muted is not a utility, so "muted" text rendered at full
  brightness in 89 places across the site. Now text-[var(--text-muted)].
- Hand-pasted SVG icons are lucide icons; icon-only project links have
  visible labels; external links carry rel="noopener noreferrer".
- Empty states for a filter that matches nothing and for judges with no
  open hackathons; the list page's back link no longer sends
  hackathon-only users to the members-only club page.
- The login footer's "Internal Terminal // Auth Gateway v2.1" is gone.
maxParticipants used to be claimed at application time, so the form said
"full" once N people had applied, even with most still pending, which
defeats accepting in waves. Applying now never takes a seat. A seat is
taken on acceptance: waves fill what is left, and Accept + email, single
and bulk approve check the remaining seats under the hackathon row lock
(assertSeats) and refuse rather than go over. currentParticipants counts
approved and checked-in.
Team create/join opened only 12 hours into the event. The window now
runs from acceptance up to +34h; checkAdmitted already limits who may
form a team. The +12h mark stays as the submission opening only, and
team.window reports opensAt: null.
- judge.setActive is isAdmin: every admin saw Approve, but only super
  admins could use it, so self-registered judges could stay inactive.
  Removing a judge stays super-admin.
- judge.create takes an email and finds the account, so an organiser
  can add a sponsor or walk-in judge.
- judge.register only accepts public editions that are announced or
  later. Any uuid used to pass, and a missing one hit the foreign key as
  a 500. Judge applications open while an event is announced.
- team.mySubmission returns the judging table number, and /submit shows
  it. Judges are sent to a table; the team was never told which.
- The Judges tab's Assign Judge form could never render (this edition
  had no unassigned judges). It is now Add judge: by email via
  judge.create, assigned in the same step, plus a copyable apply link.
- /submit defaults to a registration that is still active, matching the
  dropdown, and says waitlisted / not accepted in words.
- /hacklytics offered the interest form after registration opened,
  where registerInterest refuses it, and called a closed edition
  'not announced'. It now shows the form only while announced, and
  otherwise a status line with a link to the event page. closed joins
  the public funnel statuses.
- toggleJudging refuses to open judging while no judge has an unscored
  table queued; judges opened straight onto 'All done, 0 of 0'. A judge
  with an empty queue now reads 'No tables yet', and the Judges tab
  links to Prepare judging (/admin/judging?hackathonId=...).
- hackathon.withdrawRegistration removes your own registration and
  frees the seat. Refused once you are on a team, checked in, or have a
  project, since undoing those affects others.
- The results email goes to checked-in participants (it reached every
  applicant, accepted or not) and links straight to the Results tab.
- Graduation year is validated relative to the current year.
Scanlines, a cyan grid, rotating squares round the logo, floating glow
orbs and fake telemetry ("Core Operational", "REGION: ATL-08",
"Handshake Verified") are gone. The page is a short intro and a card
titled Sign in, in the portal's house style. Behaviour is unchanged.
The email error copy said link where the flow sends a code.
- A full event still takes applications (capacity caps acceptances),
  with a note that new applicants are waitlisted.
- Participants can withdraw a pending, accepted or waitlisted
  registration, with an inline confirm; checked-in participants get a
  link to submit their project.
- Team create/join only show for accepted participants, with a line
  saying why otherwise; the server already refused the rest.
- Failed loads read as errors with Try again, not as empty lists, on
  projects, teams, schedule, admin hackathons and attendees.
- Schedule times carry the day: 'Sat, Feb 27 · 2:00 PM'.
- Approve without email says so; seat-limit refusals are shown.
- The scanner explains that scans need a check-in event, and a pass
  from another hackathon says so instead of 'Event not found'.
At desktop width the intro and the card sat at opposite edges of a
6xl container. A 4xl container and a larger heading keep them together.
- updateParticipantStatus seat-checks checked_in as well as approved,
  and only promotes to checked_in from a seated status, so a check-in
  racing a waitlist change cannot seat somebody past capacity.
- withdrawRegistration carries its checks into the DELETE (not checked
  in, not on a team) and reports CONFLICT if the row changed after it
  was read. Finished or cancelled events refuse withdrawals, and the
  same caches as an organiser status change are evicted.
- toggleJudging blocks only when no queue was ever built, so judging
  can be reopened after every slot is scored.
- Opening the registration form fell through to 'Registration is
  closed.' right above the open form.
- Team members are told to leave their team before withdrawing, instead
  of getting a refusal after two clicks.
- Adding a judge refreshes the judge list even if the follow-up assign
  fails, so the new judge appears in the picker.
The admin judging page and the hackathon dashboard tabs kept the glow,
gradient-text and terminal copy the participant pages lost ("Data
Evaluation Layer // SYNC ACTIVE", "Awaiting Data Packet...", "Operations
Personnel"). They now use the portal's house style and plain words
(Results, Votes, Tied scores, Judges).

- Attendees: a failed filter or page refetch shows an inline error above
  the rows it kept, instead of passing them off as the new results.
  Status cells use StatusBadge.
- Scanner: a failed events load says so with a retry, rather than
  telling the organiser to create an event.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread sites/mainweb/app/(portal)/admin/judging/page.tsx
Comment thread packages/api/src/routers/hackathon/admin.ts

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread packages/api/src/routers/hackathon/admin.ts
Comment thread sites/mainweb/app/(portal)/submit/page.tsx Outdated
Comment thread sites/mainweb/app/(portal)/hackathons/[id]/judge/page.tsx
- updateParticipantStatus: a check-in whose seated-only WHERE matches
  nothing (concurrent waitlist or reject) now throws CONFLICT instead
  of reporting success to the desk.
- evictParticipantCaches drops the cached hackathon row, so the public
  seat count updates after accept and withdraw instead of at TTL.
- Judging page shows the toggleJudging error; Start judging refused
  for missing queues was a silent no-op.
- /submit hides Create team and Join team until the registration is
  approved or checked in, matching TeamsTab and the server check.
- Judge page says All done only when progress shows assigned work;
  loading or failed progress no longer reads as finished.
@github-actions github-actions Bot added the bug Something isn't working label Oct 1, 2026
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

Visit the preview URL for this PR (updated for commit e6bd765):

https://hacklytics2027--pr-452-wf38qmcx.web.app

(expires Fri, 09 Oct 2026 19:50:34 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: c48ba34db61581e25fe2978355160b5eefe0e83f

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0342a95. Configure here.

Comment thread sites/mainweb/app/(portal)/admin/judging/page.tsx
The toggleJudging error stayed on screen after switching events, so a
refusal for one hackathon read as a refusal for the next.
@aamoghS
aamoghS enabled auto-merge October 2, 2026 19:49
@aamoghS
aamoghS merged commit f17759d into dev Oct 2, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⤵️ pull bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant