Skip to content

[0] Custom Hackathon Dashboards#475

Merged
DVidal1205 merged 9 commits into
mainfrom
blade/hackathon-pages
Jun 27, 2026
Merged

[0] Custom Hackathon Dashboards#475
DVidal1205 merged 9 commits into
mainfrom
blade/hackathon-pages

Conversation

@alexanderpaolini

@alexanderpaolini alexanderpaolini commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Custom Hackathon Dashboards

The hackathon dashboard now gets presented at /hackathon/slug. /hackathon and /hackathon/current both redirect to the current hackathon (determined by the api fetch), if one exists.

Test Plan

cc @DGoel1602 (my forge doesn't work)

his images:

image image image

Summary by CodeRabbit

  • New Features
    • Added session-gated hackathon landing and per-hackathon dashboard routes.
    • Introduced a “hackathon is running now” notice in the member area with a shortcut to the hackathon dashboard.
  • Bug Fixes
    • Improved active hackathon detection to use start/end date windows.
    • Updated countdown and upcoming events to reflect the selected hackathon, including stricter event matching and an empty-state message.
  • Refactor
    • Consolidated hackathon dashboard UI into reusable base components and simplified the main user interface to focus on the member dashboard.

@alexanderpaolini alexanderpaolini added Minor Small change - 1 reviewer required Blade Change modifies code in Blade app Database Change modifies code in the DB package labels Jun 23, 2026
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: e878c252-a310-4fd5-b120-0f64ae10209a

📥 Commits

Reviewing files that changed from the base of the PR and between b6aa22c and d53f8b2.

📒 Files selected for processing (4)
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/upcoming-events.tsx
  • apps/blade/src/app/_components/dashboard/member-dashboard/download-qr-pass.tsx
  • apps/blade/src/app/hackathon/[slug]/page.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/upcoming-events.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx

📝 Walkthrough

Walkthrough

Hackathon dashboard components were split into named base exports, explicit hackathon context now flows through dashboard pages, the current-hackathon lookup uses a date window, and member dashboards show a current-hackathon notice.

Changes

Hackathon dashboard and routing

Layer / File(s) Summary
Current-hackathon routing and validation
packages/api/src/routers/hackathon.ts, packages/api/src/routers/hackers/mutations.ts, apps/blade/src/app/hackathon/page.tsx
getCurrentHackathon now uses a start/end date window, eventCheckIn validation uses schema parsing, and the /hackathon route adds metadata plus auth-gated redirect and empty-state handling.
Shared dashboard leaf widgets
apps/blade/src/app/_components/dashboard/hackathon-dashboard/countdown.tsx, apps/blade/src/app/_components/dashboard/hackathon-dashboard/issue-dialog.tsx, apps/blade/src/app/_components/dashboard/hackathon-dashboard/upcoming-events.tsx, apps/blade/src/app/_components/dashboard/hackathon-dashboard/team-points.tsx
Countdown, issue-dialog, upcoming-events, and team-points exports are renamed to base components; countdown now uses endDate, issue-dialog becomes a client component, and upcoming-events filters by hackathonId.
Hackathon data card
apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx
BaseHackathonData now queries by hackathon.name, uses shared QR/wallet/guide buttons, and changes the status badge to a checked-in state.
Dashboard shell and delegate
apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsx, apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-dashboard.tsx
The consolidated dashboard module re-exports shared widgets, adds a registration prompt and default guide link, and HackathonDashboard now resolves an active hackathon before delegating to BaseHackathonDashboard.
Hacker dashboard data flow
apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsx, apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-data.tsx
HackerDashboard now receives explicit hackathon context, and HackerData derives its queries from that context or a fallback hackathon lookup while keeping initial server data.
Member notice and shell
apps/blade/src/app/_components/dashboard/member-dashboard/current-hackathon-notice.tsx, apps/blade/src/app/_components/dashboard/member-dashboard/member-dashboard.tsx, apps/blade/src/app/_components/user-interface.tsx
CurrentHackathonNotice is added, MemberDashboard shows it when a current hackathon exists, and UserInterface now only renders member surfaces.
BloomKnights route
apps/blade/src/app/hackathon/bloomknights/page.tsx
The BloomKnights page adds metadata, requires auth, loads the fixed hackathon and hacker, and renders inside HydrateClient with SessionNavbar before choosing BaseHackathonDashboard or HackerDashboard by check-in status.

Sequence Diagram(s)

/hackathon

sequenceDiagram
  participant Browser
  participant CurrentHackathonPage
  participant auth
  participant api.hackathon.getCurrentHackathon
  participant redirect

  Browser->>CurrentHackathonPage: GET /hackathon
  CurrentHackathonPage->>auth: auth()
  CurrentHackathonPage->>api.hackathon.getCurrentHackathon: fetch current hackathon
  api.hackathon.getCurrentHackathon-->>CurrentHackathonPage: currentHackathon or null
  alt currentHackathon exists
    CurrentHackathonPage->>redirect: /hackathon/{currentHackathon.name}
  else no current hackathon
    CurrentHackathonPage-->>Browser: render empty state
  end
Loading

Member notice

sequenceDiagram
  participant MemberDashboard
  participant api.hackathon.getCurrentHackathon
  participant CurrentHackathonNotice
  participant Browser

  MemberDashboard->>api.hackathon.getCurrentHackathon: fetch current hackathon
  api.hackathon.getCurrentHackathon-->>MemberDashboard: currentHackathon or null
  alt currentHackathon exists
    MemberDashboard->>CurrentHackathonNotice: render displayName
    CurrentHackathonNotice-->>Browser: alert and dialog
  else no current hackathon
    MemberDashboard-->>Browser: render dashboard without notice
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • KnightHacks/forge#374: Directly updates the same hackathon dashboard component surface and data flow patterns.
  • KnightHacks/forge#381: Touches the same hackathon dashboard files and nearby rendering logic that this refactor also changes.
  • KnightHacks/forge#461: Modifies the same hacker dashboard data path and related dashboard UI wiring.

Suggested labels

API, Feature, Major

Suggested reviewers

  • DVidal1205
  • cataladev
  • kwaiidev
🚥 Pre-merge checks | ✅ 6 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title is related to the PR, but it uses [0] instead of a valid issue number format like [#123]. Change the title to start with a real issue number in brackets, e.g. "[#123] Custom Hackathon Dashboards".
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No Hardcoded Secrets ✅ Passed Scans of the PR-touched dashboard/page files found no hardcoded API keys, passwords, tokens, or secrets; only benign field names/env references.
Validated Env Access ✅ Passed No raw process.env access appears in the PR-touched hackathon/dashboard/API files; the change stays within validated env imports.
No Typescript Escape Hatches ✅ Passed No any, @ts-ignore, @ts-expect-error, or postfix non-null assertions were found in the touched TS/TSX files.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch blade/hackathon-pages

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@DGoel1602 DGoel1602 left a comment

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.

The first thing is minimal but I think the second one does need some eyes

Comment thread apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsx Outdated
Comment thread apps/blade/src/app/hackathon/bloomknights/page.tsx Outdated

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsx (1)

21-54: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Remove the hardcoded leaderboard cutoff from the base component.

targetDate is fixed to October 25, 2025. On June 24, 2026, targetDate <= Date.now() is always true, so non-admin users will stay in the hidden-leaderboard branch indefinitely. This breaks the new reusable/base behavior across hackathons.

💡 Suggested fix
-export function BaseHackathonPointLeaderboard({
-  hacker,
-  hId,
-}: {
+export function BaseHackathonPointLeaderboard({
+  hacker,
+  hId,
+  hideLeaderboardAfter,
+}: {
   hacker: Awaited<ReturnType<(typeof serverCall.hackerQuery)["getHacker"]>>;
   hId: string;
+  hideLeaderboardAfter?: Date;
 }) {
@@
-  const targetDate = new Date("2025-10-25T23:00:00").getTime();
+  const targetDate = hideLeaderboardAfter?.getTime() ?? Number.POSITIVE_INFINITY;
-<BaseHackathonPointLeaderboard
-  hacker={hacker}
-  hId={hackathon.name}
-/>
+<BaseHackathonPointLeaderboard
+  hacker={hacker}
+  hId={hackathon.name}
+  hideLeaderboardAfter={hackathon.endDate}
+/>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsx`
around lines 21 - 54, The targetDate variable in the
BaseHackathonPointLeaderboard function is hardcoded to October 25, 2025, which
means once the current date passes this fixed date, the leaderboard visibility
condition will always be true for non-admin users, breaking the reusable
behavior across different hackathons. Remove the hardcoded targetDate variable
and instead pass the leaderboard cutoff date as a configurable prop to the
BaseHackathonPointLeaderboard function, or derive it from the hackathon data
that is already being passed in as the hId parameter, allowing each hackathon
instance to specify its own cutoff date.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsx`:
- Around line 35-36: Remove the type assertion using `as Record<string,
BaseHackathonClassInfo>` from the DEFAULT_CLASS_INFO variable declaration and
replace it with an explicit type annotation instead. Change the declaration to
use a colon followed by the type annotation directly on the variable (`:
Record<string, BaseHackathonClassInfo>`) rather than casting with `as`. This
ensures proper type checking without bypassing it through assertions.

In `@apps/blade/src/app/hackathon/bloomknights/page.tsx`:
- Line 41: Remove the `as string` type assertion from the hacker.status
comparison on line 41. The status field is already properly typed as a string
literal union from the database schema, so the cast is unnecessary and bypasses
TypeScript's type safety. Replace the conditional check with optional chaining
syntax (hacker?.status) instead of the current `hacker && (hacker.status as
string)` pattern to achieve a cleaner, type-safe comparison while maintaining
the same functionality.

---

Outside diff comments:
In
`@apps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsx`:
- Around line 21-54: The targetDate variable in the
BaseHackathonPointLeaderboard function is hardcoded to October 25, 2025, which
means once the current date passes this fixed date, the leaderboard visibility
condition will always be true for non-admin users, breaking the reusable
behavior across different hackathons. Remove the hardcoded targetDate variable
and instead pass the leaderboard cutoff date as a configurable prop to the
BaseHackathonPointLeaderboard function, or derive it from the hackathon data
that is already being passed in as the hId parameter, allowing each hackathon
instance to specify its own cutoff date.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 8f344a94-5ac6-48f4-820f-80ce15e98baf

📥 Commits

Reviewing files that changed from the base of the PR and between 58ad852 and a2c28bb.

📒 Files selected for processing (19)
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/countdown.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-dashboard.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/issue-dialog.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/team-points.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/upcoming-events.tsx
  • apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsx
  • apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-data.tsx
  • apps/blade/src/app/_components/dashboard/member-dashboard/current-hackathon-notice.tsx
  • apps/blade/src/app/_components/dashboard/member-dashboard/member-dashboard.tsx
  • apps/blade/src/app/_components/user-interface.tsx
  • apps/blade/src/app/hackathon/bloomknights/components/bk-hackathon-dashboard.tsx
  • apps/blade/src/app/hackathon/bloomknights/page.tsx
  • apps/blade/src/app/hackathon/current/page.tsx
  • apps/blade/src/app/hackathon/page.tsx
  • packages/api/src/routers/hackathon.ts
  • packages/api/src/routers/hackers/mutations.ts

Comment thread apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsx Outdated
Comment thread apps/blade/src/app/hackathon/bloomknights/page.tsx Outdated
@alexanderpaolini alexanderpaolini marked this pull request as ready for review June 24, 2026 02:33
@alexanderpaolini alexanderpaolini changed the title [WIP] Custom Hackathon Dashboards [0] Custom Hackathon Dashboards Jun 24, 2026
coderabbitai[bot]
coderabbitai Bot previously requested changes Jun 25, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/api/src/routers/event.ts (1)

366-428: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Build break: discordEventId and googleEventId are no longer declared.

The catch block still references discordEventId (Line 406) and googleEventId (Line 418), but both were declared only inside the now-commented provisioning blocks (former Lines 301 and 330). The compiler will fail with Cannot find name 'discordEventId' / 'googleEventId', and even if it compiled, this cleanup is now dead logic since no Discord/Google events are created here.

Drop the external-cleanup branches and keep only the DB-failure path.

🐛 Proposed fix to remove the now-invalid cleanup branches
       } catch (error) {
         logger.error(JSON.stringify(error, null, 2));
 
-        try {
-          await discord.api.delete(
-            Routes.guildScheduledEvent(
-              DISCORD.KNIGHTHACKS_GUILD,
-              discordEventId,
-            ),
-          );
-        } catch (cleanupErr) {
-          logger.error(JSON.stringify(cleanupErr, null, 2));
-        }
-
-        try {
-          await google.calendar.events.delete({
-            calendarId: input.isOperationsCalendar
-              ? EVENTS.DEV_GOOGLE_CALENDAR_ID
-              : EVENTS.GOOGLE_CALENDAR_ID,
-            eventId: googleEventId,
-          });
-        } catch (cleanupErr) {
-          logger.error(JSON.stringify(cleanupErr, null, 2));
-        }
-
         throw new TRPCError({
           message: "Failed to create event in the database",
           code: "BAD_REQUEST",
         });
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/api/src/routers/event.ts` around lines 366 - 428, The catch block in
event creation still references discordEventId and googleEventId even though
those identifiers are no longer declared in this flow. Remove the Discord and
Google cleanup branches from the error handling in the event router’s create
path, and keep only the database rollback/error logging around the
db.insert(Event) and the final TRPCError throw. Use the existing catch block in
the create-event handler to locate and simplify this dead cleanup logic.
apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx (1)

201-219: 🎯 Functional Correctness | 🟠 Major

The "View Leaderboard" button currently opens an empty dialog.

Lines 201-219 wrap the button in a Dialog component, but the necessary DialogContent (or any child content) is missing. This renders the button non-functional; clicking it opens an empty modal overlay.

If the leaderboard UI is not yet ready, remove the Dialog wrapper and use a standard button or link instead to avoid dead interactions. If the dialog content exists elsewhere, ensure it is imported and placed inside the <Dialog> tags.

// Current (broken)
<Dialog>
  <DialogTrigger asChild>
    <button>View Leaderboard</button>
  </DialogTrigger>
  {/* Missing DialogContent here */}
</Dialog>

If the feature isn't ready, simplify to:

// Fixed (temporary)
<button className="..." onClick={() => window.location.href = '/leaderboard'}>
  View Leaderboard
</button>

Otherwise, add the modal structure:

<Dialog>
  <DialogTrigger asChild>
    <button>View Leaderboard</button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>Leaderboard</DialogHeader>
    {/* Leaderboard content here */}
  </DialogContent>
</Dialog>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx`
around lines 201 - 219, The View Leaderboard control is wrapped in a Dialog
without any DialogContent, so it opens an empty modal. Update the
hackathon-dashboard component around the Dialog/DialogTrigger block by either
removing the Dialog wrapper and using a normal button/link if the leaderboard UI
is not ready, or by adding the missing DialogContent (with the leaderboard UI)
inside the Dialog so the trigger has real content to display.
🧹 Nitpick comments (1)
apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsx (1)

24-42: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Return before loading secondary data on the registration-only path.

Lines 24-27 fetch resume and past-hackathon data before the !hacker guard in Line 29. For unregistered users, those requests are unused and delay the prompt unnecessarily.

Possible fix
-  const [resume, pastHackathons] = await Promise.allSettled([
-    api.resume.getResume(),
-    api.hackathon.getPastHackathons(),
-  ]);
-
   if (!hacker) {
     return (
       <div className="flex flex-col items-center justify-center gap-y-6 text-xl font-semibold">
         <p className="w-full max-w-xl text-center text-2xl">
           Register for {hackathon.displayName} today!
@@
       </div>
     );
   }
+
+  const [resume, pastHackathons] = await Promise.allSettled([
+    api.resume.getResume(),
+    api.hackathon.getPastHackathons(),
+  ]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsx`
around lines 24 - 42, The `HackerDashboard` component is fetching secondary data
with `Promise.allSettled` before the `!hacker` registration-only branch, which
delays the registration prompt for users who don’t need that data. Move the
`api.resume.getResume()` and `api.hackathon.getPastHackathons()` loading so it
only runs after the `!hacker` early return, and keep the guard in
`HackerDashboard` as the first decision point before any unused requests are
started.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx`:
- Around line 155-167: The inline styles in hackathon-data.tsx are using invalid
raw color values like primary and secondary, which will not render as CSS
colors. Update the affected JSX in the dashboard component to use Tailwind
utility classes where possible, or replace the style values with the correct
hsl(var(--...)) theme syntax; check the elements around the Trophy icon and
surrounding containers in the hackathon dashboard markup.

In `@apps/blade/src/app/hackathon/bloomknights/page.tsx`:
- Around line 2-3: The page component in bloomknights/page.tsx is rendering
NotFoundPage directly, which leaves the response as 200 instead of a real 404.
Update the page logic to call Next.js notFound() from next/navigation at the
point where the 404 is needed, and remove the manual NotFoundPage return so
routing emits the proper Not Found status. Use the page component and
NotFoundPage references to locate the affected branch.

In `@packages/api/src/routers/event.ts`:
- Around line 277-364: Remove the large commented-out Discord/Google
provisioning experiment from the event router and keep only the live
`updateEvent`/`deleteEvent` logic. The commented blocks around the Discord
scheduled event creation and Google Calendar insert/callback cleanup should be
deleted entirely rather than left as dead code. If this work is intentionally
paused, capture the context in a TODO, issue, or ADR instead of preserving the
commented implementation in `event.ts`.
- Around line 379-380: The temporary discordId and googleId values in the event
flow are being treated like real external IDs, which will cause update/delete
calls in updateEvent and deleteEvent to hit Discord/Google APIs with invalid
identifiers. Replace the arbitrary placeholder strings in the event record with
an explicit sentinel such as "PLACEHOLDER" or null, and update the external call
sites in updateEvent and deleteEvent to guard on valid IDs before calling
discord.api or the Google Calendar client. Use the existing eventRecord
discordId/googleId checks so external requests are skipped whenever the ID is
missing or marked as a placeholder.

---

Outside diff comments:
In
`@apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx`:
- Around line 201-219: The View Leaderboard control is wrapped in a Dialog
without any DialogContent, so it opens an empty modal. Update the
hackathon-dashboard component around the Dialog/DialogTrigger block by either
removing the Dialog wrapper and using a normal button/link if the leaderboard UI
is not ready, or by adding the missing DialogContent (with the leaderboard UI)
inside the Dialog so the trigger has real content to display.

In `@packages/api/src/routers/event.ts`:
- Around line 366-428: The catch block in event creation still references
discordEventId and googleEventId even though those identifiers are no longer
declared in this flow. Remove the Discord and Google cleanup branches from the
error handling in the event router’s create path, and keep only the database
rollback/error logging around the db.insert(Event) and the final TRPCError
throw. Use the existing catch block in the create-event handler to locate and
simplify this dead cleanup logic.

---

Nitpick comments:
In
`@apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsx`:
- Around line 24-42: The `HackerDashboard` component is fetching secondary data
with `Promise.allSettled` before the `!hacker` registration-only branch, which
delays the registration prompt for users who don’t need that data. Move the
`api.resume.getResume()` and `api.hackathon.getPastHackathons()` loading so it
only runs after the `!hacker` early return, and keep the guard in
`HackerDashboard` as the first decision point before any unused requests are
started.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 6eba0fde-c616-4abd-b735-d373c45aaa05

📥 Commits

Reviewing files that changed from the base of the PR and between a2c28bb and 8c152ba.

📒 Files selected for processing (12)
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-dashboard.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/team-points.tsx
  • apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsx
  • apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-data.tsx
  • apps/blade/src/app/_components/dashboard/member-dashboard/current-hackathon-notice.tsx
  • apps/blade/src/app/_components/dashboard/member-dashboard/member-dashboard.tsx
  • apps/blade/src/app/hackathon/bloomknights/page.tsx
  • apps/blade/src/app/hackathon/page.tsx
  • packages/api/src/routers/event.ts
💤 Files with no reviewable changes (4)
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/team-points.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsx
  • apps/blade/src/app/_components/dashboard/member-dashboard/member-dashboard.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-dashboard.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/blade/src/app/_components/dashboard/member-dashboard/current-hackathon-notice.tsx
  • apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-data.tsx

Comment thread apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx Outdated
Comment on lines +2 to +3
import { redirect } from "next/navigation";

@coderabbitai coderabbitai Bot Jun 25, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n apps/blade/src/app/hackathon/bloomknights/page.tsx | sed -n '1,35p'

Repository: KnightHacks/forge

Length of output: 1425


Use notFound() instead of rendering the 404 page component directly

Line 29 currently returns <NotFoundPage />, which renders a 404 UI but keeps the HTTP response status as 200 OK. This is invalid for an App Router page.tsx and interferes with correct 404 status handling.

Replace the manual return with notFound() to ensure a proper 404 Not Found status and to integrate with Next.js routing conventions.

Fix
-import { redirect } from "next/navigation";
+import { notFound, redirect } from "next/navigation";

-    return <NotFoundPage />;
+    notFound();

See App Router docs for details on 404 semantic handling.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { redirect } from "next/navigation";
import { notFound, redirect } from "next/navigation";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/blade/src/app/hackathon/bloomknights/page.tsx` around lines 2 - 3, The
page component in bloomknights/page.tsx is rendering NotFoundPage directly,
which leaves the response as 200 instead of a real 404. Update the page logic to
call Next.js notFound() from next/navigation at the point where the 404 is
needed, and remove the manual NotFoundPage return so routing emits the proper
Not Found status. Use the page component and NotFoundPage references to locate
the affected branch.

Source: Path instructions

✅ Confirmed as addressed by @alexanderpaolini

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@alexanderpaolini The PR description image 1 shows a dark BloomKnights dashboard with “Hello, Alchemist Dhruv!”, a checked-in status card, quick action buttons for QR / Apple Wallet / Hacker’s Guide / Report an Issue, a Hack Points card showing 35, a humanity vs monstrosity progress bar, and the top of a countdown section labeled “HACKING ENDS IN.”

The PR description image 2 shows the Blade member dashboard dimmed behind a centered modal titled “BloomKnights is live,” with copy about check-in tools, points, live events, and event-specific info, plus “Stay Here” and “Open Hackathon Dashboard” buttons.

The PR description image 3 shows the Hackathon Dashboard with “Hello, Dhruv!”, a “Confirmed” status, a QR action bar, a notice that “The confirmation deadline has passed.”, a red “WITHDRAW” button, and lower actions for “View Past Hackathons” and “Download Resume.”

Thanks for resolving this. Using notFound() here is the right App Router fix because it returns a real 404 response instead of a 200 page that only looks like a 404.

For reference, the intended pattern is:

import { notFound, redirect } from "next/navigation";

if (!hackathon) {
  notFound();
}

🧠 Learnings used
Learnt from: DVidal1205
Repo: KnightHacks/forge PR: 354
File: apps/blade/src/app/admin/club/data/_components/MemberDemographics.tsx:19-35
Timestamp: 2026-02-10T19:07:03.232Z
Learning: In the KnightHacks/forge repository, apply the pattern in TSX React components: gating rendering should occur only when all required data fetches succeed. Do not render partial success when some queries fail; instead, implement a unified loading/state or error handling that surfaces a single, coherent state once all data is ready or failed. This repo-wide guideline helps ensure consistent UX when multiple data sources are involved.

If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

Comment thread packages/api/src/routers/event.ts Outdated
Comment thread packages/api/src/routers/event.ts Outdated
Comment thread apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx Outdated
Comment thread apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx Outdated
@DVidal1205

Copy link
Copy Markdown
Contributor

Addressed the requested cleanup in commit 64f5d90e:

  • Removed the base hackathon dashboard points card and leaderboard trigger so the base dashboard stays focused on hacker info, status management, and upcoming events.
  • Dropped the leftover class-info prop/type from the base dashboard API.
  • Switched the BloomKnights missing-hackathon branch to notFound() so it returns a real App Router 404 instead of rendering the 404 page with a 200.

Verified with:

  • git diff --check
  • pnpm --dir apps/blade exec prettier --check src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx src/app/_components/dashboard/hackathon-dashboard/components.tsx src/app/hackathon/bloomknights/page.tsx
  • cd apps/blade && timeout 90 pnpm exec eslint src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx src/app/_components/dashboard/hackathon-dashboard/components.tsx src/app/hackathon/bloomknights/page.tsx
  • cd apps/blade && timeout 120 pnpm exec tsc --noEmit --pretty false

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx (1)

54-78: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive status during render instead of syncing it via useEffect.

hackerStatus/hackerStatusColor are pure functions of hacker, so the useState + useEffect round-trip isn't needed. Computing them inline removes the react-hooks/set-state-in-effect suppression (the codebase discourages unjustified eslint-disable) and avoids the one-render lag where the badge shows the empty initial state before the effect runs.

♻️ Proposed refactor
-  const [hackerStatus, setHackerStatus] = useState<string | null>("");
-  const [hackerStatusColor, setHackerStatusColor] = useState<string>("");
-
   const { data: hacker, isError } = api.hackerQuery.getHacker.useQuery(
     { hackathonName: hackathon.name },
     {
       initialData: data,
     },
   );

   function getStatusName(status: StatusKey) {
     if (!status) return "";
     return HACKER_STATUS_MAP[status].name;
   }

   function getStatusColor(status: StatusKey) {
     if (!status) return "";
     return HACKER_STATUS_MAP[status].color;
   }

-  useEffect(() => {
-    // eslint-disable-next-line react-hooks/set-state-in-effect
-    setHackerStatus(getStatusName(hacker?.status));
-    setHackerStatusColor(getStatusColor(hacker?.status));
-  }, [hacker]);
+  const hackerStatus = getStatusName(hacker?.status);
+  const hackerStatusColor = getStatusColor(hacker?.status);

Note: drop the now-unused useState/useEffect imports after applying this.

As per coding guidelines: "Do not bypass type or lint errors with any, broad casts, eslint-disable, or ignored promises unless justified."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx`
around lines 54 - 78, The `hackathon-data.tsx` component is deriving
`hackerStatus` and `hackerStatusColor` through `useState` plus `useEffect`, but
both values are pure functions of `hacker`. Move this logic into the render path
by computing the status name/color directly from `hacker?.status` (using
`getStatusName` and `getStatusColor`), remove the state/effect pair and the
`react-hooks/set-state-in-effect` suppression, and drop any now-unused
`useState`/`useEffect` imports.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx`:
- Around line 54-78: The `hackathon-data.tsx` component is deriving
`hackerStatus` and `hackerStatusColor` through `useState` plus `useEffect`, but
both values are pure functions of `hacker`. Move this logic into the render path
by computing the status name/color directly from `hacker?.status` (using
`getStatusName` and `getStatusColor`), remove the state/effect pair and the
`react-hooks/set-state-in-effect` suppression, and drop any now-unused
`useState`/`useEffect` imports.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: a2fe0ccc-4bd0-429f-a0b1-c3a27cf6cf82

📥 Commits

Reviewing files that changed from the base of the PR and between 8c152ba and 64f5d90.

📒 Files selected for processing (10)
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-dashboard.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/team-points.tsx
  • apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsx
  • apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-data.tsx
  • apps/blade/src/app/_components/dashboard/member-dashboard/current-hackathon-notice.tsx
  • apps/blade/src/app/hackathon/bloomknights/page.tsx
  • apps/blade/src/app/hackathon/page.tsx
💤 Files with no reviewable changes (4)
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/team-points.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-dashboard.tsx
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/blade/src/app/_components/dashboard/member-dashboard/current-hackathon-notice.tsx
  • apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsx
  • apps/blade/src/app/hackathon/bloomknights/page.tsx
  • apps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-data.tsx
  • apps/blade/src/app/hackathon/page.tsx

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx (1)

69-96: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore status derivation from hacker.status.

This badge now always renders Checked-in with the success icon, so members on the base dashboard path will see the wrong state (for example, confirmed-but-not-checked-in users). That breaks the status-management flow this PR is adding. Please derive the label/color/icon from hacker.status instead of hardcoding HACKER_STATUS_MAP.checkedin.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx`
around lines 69 - 96, The status badge is hardcoded to the checked-in state, so
it no longer reflects the actual hacker state. Update the status rendering in
the dashboard component to derive the label, color, and icon from hacker.status
instead of HACKER_STATUS_MAP.checkedin, using the existing status mapping logic
in hackathon-data.tsx so the badge matches each hacker’s real status.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx`:
- Around line 69-96: The status badge is hardcoded to the checked-in state, so
it no longer reflects the actual hacker state. Update the status rendering in
the dashboard component to derive the label, color, and icon from hacker.status
instead of HACKER_STATUS_MAP.checkedin, using the existing status mapping logic
in hackathon-data.tsx so the badge matches each hacker’s real status.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 5717a7dc-abd9-4492-8e9a-7fe93f38b9bf

📥 Commits

Reviewing files that changed from the base of the PR and between 64f5d90 and b6aa22c.

📒 Files selected for processing (1)
  • apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx

@DGoel1602 DGoel1602 left a comment

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.

Lgtm type beat

@DVidal1205 DVidal1205 left a comment

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.

lettuce guacamole tomato meat

@DVidal1205 DVidal1205 added this pull request to the merge queue Jun 27, 2026
Merged via the queue into main with commit 53d49b0 Jun 27, 2026
11 checks passed
@DVidal1205 DVidal1205 deleted the blade/hackathon-pages branch June 27, 2026 04:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Blade Change modifies code in Blade app Database Change modifies code in the DB package Minor Small change - 1 reviewer required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants