[0] Custom Hackathon Dashboards#475
Conversation
📝 WalkthroughWalkthroughThis PR splits hackathon dashboard rendering into named base components, threads explicit hackathon context through dashboard and route pages, updates current-hackathon selection to a date window, adds a current-hackathon notice on member dashboards, changes the top-level user interface to member-only rendering, and removes the old leaderboard surface. ChangesHackathon dashboard and routing
Sequence Diagram(s)
|
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Title check | The title is relevant, but it does not follow the required issue-number format because it uses [0] instead of [#123]. |
Change the title to start with a real issue key like "[#123] Custom Hackathon Dashboards" and keep it under 72 characters. |
|
| Docstring Coverage | 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. | |
| Validated Env Access | process.env.NODE_ENV is used in packages/consts/src/util.ts and apps/guild/src/trpc/react.tsx, outside env.ts/config files. |
Move those reads into src/env.ts (or a config file) and import a validated flag/boolean instead of reading process.env directly. |
✅ Passed checks (5 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 | Scanned the modified hackathon/dashboard source; found no API-key/password/token literals. Only benign URLs/messages were present. |
| No Typescript Escape Hatches | ✅ Passed | No any, @ts-ignore, @ts-expect-error, or non-null assertions were found in the changed files; the code uses optional chaining and typed params instead. |
✨ 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.
Comment @coderabbitai help to get the list of available commands.
DGoel1602
left a comment
There was a problem hiding this comment.
The first thing is minimal but I think the second one does need some eyes
There was a problem hiding this comment.
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 winRemove the hardcoded leaderboard cutoff from the base component.
targetDateis 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
📒 Files selected for processing (19)
apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/countdown.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-dashboard.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/issue-dialog.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/team-points.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/upcoming-events.tsxapps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsxapps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-data.tsxapps/blade/src/app/_components/dashboard/member-dashboard/current-hackathon-notice.tsxapps/blade/src/app/_components/dashboard/member-dashboard/member-dashboard.tsxapps/blade/src/app/_components/user-interface.tsxapps/blade/src/app/hackathon/bloomknights/components/bk-hackathon-dashboard.tsxapps/blade/src/app/hackathon/bloomknights/page.tsxapps/blade/src/app/hackathon/current/page.tsxapps/blade/src/app/hackathon/page.tsxpackages/api/src/routers/hackathon.tspackages/api/src/routers/hackers/mutations.ts
There was a problem hiding this comment.
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 winBuild break:
discordEventIdandgoogleEventIdare no longer declared.The catch block still references
discordEventId(Line 406) andgoogleEventId(Line 418), but both were declared only inside the now-commented provisioning blocks (former Lines 301 and 330). The compiler will fail withCannot 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 | 🟠 MajorThe "View Leaderboard" button currently opens an empty dialog.
Lines 201-219 wrap the button in a
Dialogcomponent, but the necessaryDialogContent(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
Dialogwrapper 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 winReturn before loading secondary data on the registration-only path.
Lines 24-27 fetch resume and past-hackathon data before the
!hackerguard 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
📒 Files selected for processing (12)
apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-dashboard.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/team-points.tsxapps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsxapps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-data.tsxapps/blade/src/app/_components/dashboard/member-dashboard/current-hackathon-notice.tsxapps/blade/src/app/_components/dashboard/member-dashboard/member-dashboard.tsxapps/blade/src/app/hackathon/bloomknights/page.tsxapps/blade/src/app/hackathon/page.tsxpackages/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
| import { redirect } from "next/navigation"; | ||
|
|
There was a problem hiding this comment.
🎯 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.
| 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
There was a problem hiding this comment.
@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!
8c152ba to
8f7eb2c
Compare
| className="w-full rounded-lg py-2 text-sm font-semibold transition-all hover:shadow-md sm:py-2.5" | ||
| style={{ | ||
| backgroundColor: `${teamColor}20`, | ||
| color: teamColor, | ||
| backgroundColor: `primary`, | ||
| color: "secondary", | ||
| }} | ||
| onMouseEnter={(e) => { | ||
| e.currentTarget.style.backgroundColor = `${teamColor}33`; | ||
| e.currentTarget.style.backgroundColor = `primary`; | ||
| }} | ||
| onMouseLeave={(e) => { | ||
| e.currentTarget.style.backgroundColor = `${teamColor}20`; | ||
| e.currentTarget.style.backgroundColor = `primary`; | ||
| }} | ||
| > | ||
| View Leaderboard | ||
| </button> | ||
| </DialogTrigger> | ||
| <DialogContent> | ||
| <DialogHeader> | ||
| <DialogTitle>Leaderboard</DialogTitle> | ||
| </DialogHeader> | ||
| <PointLeaderboard | ||
| hacker={hacker} | ||
| hId={hackathonData?.name ?? ""} | ||
| /> | ||
| </DialogContent> | ||
| </Dialog> |
There was a problem hiding this comment.
let's nuke the leaderboard trigger along with the content, base dash won't need a leaderboard
| textShadow: `0 0 10px primary`, | ||
| }} | ||
| > | ||
| {hacker?.points || 0} |
There was a problem hiding this comment.
we also don't rlly need this big point section in base dash, since points are dependent on the hack at hand
base is ideally:
- hacker info
- hacker status management
- upcoming events
base can remove anything concerning classes, points, leaderboards, etc
|
Addressed the requested cleanup in commit
Verified with:
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsx (1)
54-78: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDerive status during render instead of syncing it via
useEffect.
hackerStatus/hackerStatusColorare pure functions ofhacker, so theuseState+useEffectround-trip isn't needed. Computing them inline removes thereact-hooks/set-state-in-effectsuppression (the codebase discourages unjustifiedeslint-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/useEffectimports 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
📒 Files selected for processing (10)
apps/blade/src/app/_components/dashboard/hackathon-dashboard/components.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-dashboard.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/hackathon-data.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/point-leaderboard.tsxapps/blade/src/app/_components/dashboard/hackathon-dashboard/team-points.tsxapps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-dashboard.tsxapps/blade/src/app/_components/dashboard/hacker-dashboard/hacker-data.tsxapps/blade/src/app/_components/dashboard/member-dashboard/current-hackathon-notice.tsxapps/blade/src/app/hackathon/bloomknights/page.tsxapps/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
Custom Hackathon Dashboards
The hackathon dashboard now gets presented at
/hackathon/slug./hackathonand/hackathon/currentboth redirect to the current hackathon (determined by the api fetch), if one exists.Test Plan
cc @DGoel1602 (my forge doesn't work)
his images:
Summary by CodeRabbit
New Features
Bug Fixes