Conversation
…nto participating-page Merge into main
…nto participating-page Merge into main
|
@Michaelkingsdev is attempting to deploy a commit to the Threadflow Team on Vercel. A member of the Team first needs to authorize it. |
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughReplaces a placeholder with a client-side SubmissionsPage and supporting components that normalize and deduplicate session-provided hackathon submissions, provide a sortable table UI, selection with a BoundlessSheet detail drawer, status badges, loading/empty states, and related types/UI primitives. Changes
Sequence DiagramsequenceDiagram
participant User
participant SubmissionsPage
participant Session (profile)
participant Table
participant BoundlessSheet
User->>SubmissionsPage: Navigate to /me/hackathons/submissions
SubmissionsPage->>Session (profile): Read hackathon submissions from session.user.profile
Session (profile)-->>SubmissionsPage: Return submissions array
SubmissionsPage->>SubmissionsPage: Normalize & dedupe -> SubmissionRow[]
SubmissionsPage->>Table: Render rows with sortField/sortDir
Table-->>User: Display sortable rows
User->>Table: Click column header
Table->>SubmissionsPage: Update sort state
SubmissionsPage->>Table: Re-render sorted rows
User->>Table: Click submission row
Table->>SubmissionsPage: Set selected submission
SubmissionsPage->>BoundlessSheet: Open sheet with submission
BoundlessSheet-->>User: Show detailed submission metadata
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
app/me/layout.tsx (1)
32-46: Harden source normalization before merge/dedupe.Line 38 assumes both sources are iterable arrays. If one path is truthy but non-array, this throws. Also, mixed numeric/string IDs can bypass dedupe. Normalize both inputs with
Array.isArrayand coerce dedupe keys.♻️ Proposed hardening
- const fromUser = - (profile as any)?.user?.hackathonSubmissionsAsParticipant || []; + const fromUserRaw = + (profile as any)?.user?.hackathonSubmissionsAsParticipant; + const fromUser = Array.isArray(fromUserRaw) ? fromUserRaw : []; @@ - const fromProfile = - (profile as any)?.hackathonSubmissionsAsParticipant || []; + const fromProfileRaw = + (profile as any)?.hackathonSubmissionsAsParticipant; + const fromProfile = Array.isArray(fromProfileRaw) ? fromProfileRaw : []; @@ - const seen = new Set<string>(); + const seen = new Set<string>(); return merged.filter((s: any) => { - const id = s?.id || s?._id; - if (!id || seen.has(id)) return false; - seen.add(id); + const rawId = s?.id ?? s?._id; + const id = rawId != null ? String(rawId) : ''; + if (!id || seen.has(id)) return false; + seen.add(id); return true; }).length;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/layout.tsx` around lines 32 - 46, Normalize and guard both sources before merging/dedupe: ensure (profile as any)?.user?.hackathonSubmissionsAsParticipant and (profile as any)?.hackathonSubmissionsAsParticipant are treated as arrays (use Array.isArray and default to [] for fromUser and fromProfile), build merged from those safe arrays, and coerce dedupe keys to a consistent string form (e.g. compute idKey = String(s?.id ?? s?._id ?? '') and skip empty keys) when using seen/set to filter unique entries in the merged array; update references to fromUser, fromProfile, merged, and seen accordingly.app/me/hackathons/submissions/submission-components.tsx (1)
28-50: ModeldisqualificationReasoninSubmissionRowinstead of casting toany.The current cast at Line 345/351 bypasses type safety in a core UI path. Add the field to
SubmissionRowand remove the casts.🧩 Proposed type-safe update
export type SubmissionRow = { id: string; @@ comments?: number | any[]; + disqualificationReason?: string; hackathon?: { @@ - {(submission.status || '').toLowerCase() === 'disqualified' && - (submission as any).disqualificationReason && ( + {(submission.status || '').toLowerCase() === 'disqualified' && + submission.disqualificationReason && ( <div className='rounded-xl border border-red-500/30 bg-red-500/10 p-4'> @@ - {(submission as any).disqualificationReason} + {submission.disqualificationReason} </p> </div> )}Also applies to: 344-352
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/submission-components.tsx` around lines 28 - 50, SubmissionRow is missing a typed disqualificationReason field and the code currently casts to any; add a strongly-typed field to SubmissionRow (e.g. disqualificationReason?: string | null or a small object type like { reason: string; details?: string } depending on backend shape) and then remove the casts to any where disqualificationReason is read (the places that currently cast at the submission usage sites). Update any code that expects the cast to instead use the new typed field (SubmissionRow.disqualificationReason) and adjust null/undefined checks accordingly to restore type safety.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/me/hackathons/submissions/page.tsx`:
- Around line 219-266: Headers with onClick handlers (e.g., the <th> elements
using thClass and calling handleSort('projectName') and rendering SortIcon) must
be made keyboard-accessible: move the click interaction into a focusable
<button> inside each <th> (keep existing classes on the <th> for layout), remove
onClick from the <th>, and call handleSort from the button’s onClick/onKey
handlers; set aria-sort on the <th> based on sortField and sortDir (e.g.,
"ascending", "descending" or "none") so assistive tech can read the current
state; ensure the button has an accessible label (visible text plus the existing
SortIcon) and apply the same change for the other sortable columns ('hackathon',
'status', 'submittedAt', 'rank') so SortIcon, sortField and sortDir logic
remains intact.
In `@app/me/hackathons/submissions/submission-components.tsx`:
- Around line 382-402: The row currently routes all auxiliary clicks and any
non-left mouse button into handleClick and only supports Enter for keyboard
activation; update the click/key handling so right-clicks don't open the drawer
and Space activates the button. In handleClick (and the onAuxClick usage) only
treat middle-click (e.button === 1) or Ctrl/Cmd modifiers as "open in new tab",
and only treat left-click (e.button === 0) as activation that calls onClick;
ensure onAuxClick checks e.button === 1 before delegating to handleClick or call
a separate onAuxClick that only handles middle-click. For keyboard, change the
onKeyDown handler to call onClick() for both 'Enter' and ' ' (Space), and call
e.preventDefault() for Space to prevent page scrolling. Reference: handleClick,
onAuxClick, onKeyDown, role='button', tabIndex.
---
Nitpick comments:
In `@app/me/hackathons/submissions/submission-components.tsx`:
- Around line 28-50: SubmissionRow is missing a typed disqualificationReason
field and the code currently casts to any; add a strongly-typed field to
SubmissionRow (e.g. disqualificationReason?: string | null or a small object
type like { reason: string; details?: string } depending on backend shape) and
then remove the casts to any where disqualificationReason is read (the places
that currently cast at the submission usage sites). Update any code that expects
the cast to instead use the new typed field
(SubmissionRow.disqualificationReason) and adjust null/undefined checks
accordingly to restore type safety.
In `@app/me/layout.tsx`:
- Around line 32-46: Normalize and guard both sources before merging/dedupe:
ensure (profile as any)?.user?.hackathonSubmissionsAsParticipant and (profile as
any)?.hackathonSubmissionsAsParticipant are treated as arrays (use Array.isArray
and default to [] for fromUser and fromProfile), build merged from those safe
arrays, and coerce dedupe keys to a consistent string form (e.g. compute idKey =
String(s?.id ?? s?._id ?? '') and skip empty keys) when using seen/set to filter
unique entries in the merged array; update references to fromUser, fromProfile,
merged, and seen accordingly.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (6)
app/me/hackathons/submissions/page.tsxapp/me/hackathons/submissions/submission-components.tsxapp/me/layout.tsxcomponents/app-sidebar.tsxcomponents/profile/PublicEarningsTab.tsxdocs/project-detail-redesign.md
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
app/me/hackathons/submissions/submission-components.tsx (1)
383-387:⚠️ Potential issue | 🟠 MajorCmd/Ctrl+click on row does not follow the new-tab behavior requirement.
Middle-click is handled, but Ctrl/Cmd + left-click currently falls through to opening the drawer.
🖱️ Suggested interaction fix
const handleLeftClick = (e: React.MouseEvent) => { // Left click only if (e.button !== 0) return; + if (e.metaKey || e.ctrlKey) { + e.preventDefault(); + window.open(viewUrl, '_blank', 'noopener,noreferrer'); + return; + } onClick(); };Also applies to: 389-394
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/submission-components.tsx` around lines 383 - 387, The left-click handler (handleLeftClick) currently only ignores non-left buttons but still runs on Ctrl/Cmd+click; update handleLeftClick to also early-return when e.ctrlKey or e.metaKey (and optionally e.shiftKey if desired), so Ctrl/Cmd+Click falls through to browser default (open in new tab) instead of calling onClick; apply the same fix to the similar handler around the other click handling block (the other left-click handler in this file) so both respect modifier keys.
🧹 Nitpick comments (4)
app/me/hackathons/submissions/page.tsx (2)
26-26: Use const-arrow export with explicit return type for the page component.This file uses a function declaration for the exported component; project TSX guideline prefers const-arrow + explicit type.
♻️ Suggested change
-export default function SubmissionsPage() { +const SubmissionsPage = (): JSX.Element => { const router = useRouter(); const { user, isLoading } = useAuthStatus(); @@ -} +}; + +export default SubmissionsPage;As per coding guidelines, "Prefer const arrow functions with explicit type annotations over function declarations".
Also applies to: 369-369
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/page.tsx` at line 26, Replace the function declaration export default function SubmissionsPage() with a const-arrow export using an explicit React/Next.js component return type (e.g., const SubmissionsPage: React.FC or NextPage) and export default that const; update the other occurrence referenced (the same SubmissionsPage at the other location) to the same pattern so both use a const arrow with explicit type annotation.
37-47: Reduceanyin submission normalization to keep type guarantees.Lines 39/43/46/58 rely on
any, which weakens safety in a critical data-mapping path. If Trustless Work profile/submission types are available, this mapping should be typed end-to-end.As per coding guidelines, "Use provided Types from Trustless Work documentation when applicable".
Also applies to: 58-74
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/page.tsx` around lines 37 - 47, The submission normalization uses unsafe any types in the useMemo block (variables profile, fromUser, fromProfile) and weakens guarantees for rawSubmissions/SubmissionRow; replace the any usages with the appropriate Trustless Work types (e.g., ProfileType, HackathonSubmissionType or whatever the SDK/definitions export), update the local variables fromUser and fromProfile to be typed arrays of that submission type, and adjust the mapping logic (the normalization found around the map block that produces SubmissionRow between lines ~58-74) to accept and return strongly typed fields so rawSubmissions: SubmissionRow[] is produced end-to-end with proper type checks via the exported types rather than any.app/me/hackathons/submissions/submission-components.tsx (2)
29-51: Type drift:disqualificationReasonis read viaanybut missing fromSubmissionRow.This model mismatch forces unsafe casts and can hide typos/runtime bugs.
♻️ Suggested change
export type SubmissionRow = { id: string; projectName: string; @@ votes?: number | any[]; comments?: number | any[]; + disqualificationReason?: string; hackathon?: { @@ - {(submission.status || '').toLowerCase() === 'disqualified' && - (submission as any).disqualificationReason && ( + {(submission.status || '').toLowerCase() === 'disqualified' && + submission.disqualificationReason && ( <div className='rounded-xl border border-red-500/30 bg-red-500/10 p-4'> @@ - <p className='text-sm text-red-300'> - {(submission as any).disqualificationReason} - </p> + <p className='text-sm text-red-300'> + {submission.disqualificationReason} + </p> </div> )}As per coding guidelines, "Use provided Types from Trustless Work documentation when applicable".
Also applies to: 345-353
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/submission-components.tsx` around lines 29 - 51, The SubmissionRow type is missing the disqualificationReason field which is currently being read as any elsewhere; update the SubmissionRow type declaration to include disqualificationReason?: any (or a more specific union such as string | null | any[] if you know the shape) so callers no longer need unsafe casts; make the same addition to the equivalent submission DTO/type definitions referenced later (the other SubmissionRow-like declarations around the file, e.g., the block noted at lines 345-353) and run TypeScript type checks to remove the unsafe any casts.
55-58: Align exported TSX functions with const-arrow + explicit type style.This file’s exported functions/components are function declarations; project TSX style prefers typed const-arrow exports.
As per coding guidelines, "Prefer const arrow functions with explicit type annotations over function declarations".
Also applies to: 101-102, 114-122, 132-136, 360-368
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/submission-components.tsx` around lines 55 - 58, Convert the exported function declarations to typed const-arrow exports: replace the function declaration for getStatusConfig with a const getStatusConfig: (status: string) => { label: string; className: string } = (status) => { ... } and do the same for the other exported functions/components referenced (the ones around lines 101-102, 114-122, 132-136, 360-368), ensuring each has an explicit parameter and return type annotation and uses a const-arrow form instead of the function keyword so they conform to the project's TSX style.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/me/hackathons/submissions/page.tsx`:
- Line 28: The page is calling useAuthStatus(), which triggers getMe() on mount;
remove this hook usage and rely on session-only data to avoid the extra request:
delete or replace the line using useAuthStatus() (const { user, isLoading } =
useAuthStatus()) and instead use the existing session (session?.user and
session.status) from the component (e.g., via useSession or the session prop
already present), and update the getMe() trigger logic so it no longer runs when
userProfile is null on initial render (adjust the condition that references
session, 'user' in session, userProfile, and profileLoading or require a
distinct “needsFetch” flag). Ensure references to user and isLoading are
replaced with session?.user and session.status so getMe() is never implicitly
called by useAuthStatus().
In `@app/me/hackathons/submissions/submission-components.tsx`:
- Around line 309-313: The anchors directly bind user-supplied
submission.videoUrl and link.url — validate and sanitize these before use: parse
the value (e.g., new URL(...) or URL constructor) and allow only safe schemes
such as http and https (optionally mailto if intended); if parsing fails or the
scheme is not allowed, do not set the unsafe value on href (use a safe fallback
like '#' or omit href and/or disable the anchor). Apply this check where
submission.videoUrl and link.url are used in submission-components.tsx so clicks
cannot execute javascript: or other unsafe schemes.
- Around line 441-448: The anchor for opening a submission (the <a ...
className='text-zinc-500 opacity-0 ... group-hover:opacity-100' ...
aria-label={`Open ${submission.projectName} in new tab`}> element) is
keyboard-focusable while hidden; add keyboard handling so it is removed from the
tab order when visually hidden and becomes focusable when visible. Implement a
small local state (e.g., isHoverOrFocus) in the component and set
tabIndex={isHoverOrFocus ? 0 : -1} and aria-hidden={!isHoverOrFocus} on that
anchor, toggling isHoverOrFocus on onMouseEnter/onMouseLeave and onFocus/onBlur
(or onKeyDown if needed) so keyboard users cannot tab to the icon when opacity-0
but can once it becomes visible.
---
Duplicate comments:
In `@app/me/hackathons/submissions/submission-components.tsx`:
- Around line 383-387: The left-click handler (handleLeftClick) currently only
ignores non-left buttons but still runs on Ctrl/Cmd+click; update
handleLeftClick to also early-return when e.ctrlKey or e.metaKey (and optionally
e.shiftKey if desired), so Ctrl/Cmd+Click falls through to browser default (open
in new tab) instead of calling onClick; apply the same fix to the similar
handler around the other click handling block (the other left-click handler in
this file) so both respect modifier keys.
---
Nitpick comments:
In `@app/me/hackathons/submissions/page.tsx`:
- Line 26: Replace the function declaration export default function
SubmissionsPage() with a const-arrow export using an explicit React/Next.js
component return type (e.g., const SubmissionsPage: React.FC or NextPage) and
export default that const; update the other occurrence referenced (the same
SubmissionsPage at the other location) to the same pattern so both use a const
arrow with explicit type annotation.
- Around line 37-47: The submission normalization uses unsafe any types in the
useMemo block (variables profile, fromUser, fromProfile) and weakens guarantees
for rawSubmissions/SubmissionRow; replace the any usages with the appropriate
Trustless Work types (e.g., ProfileType, HackathonSubmissionType or whatever the
SDK/definitions export), update the local variables fromUser and fromProfile to
be typed arrays of that submission type, and adjust the mapping logic (the
normalization found around the map block that produces SubmissionRow between
lines ~58-74) to accept and return strongly typed fields so rawSubmissions:
SubmissionRow[] is produced end-to-end with proper type checks via the exported
types rather than any.
In `@app/me/hackathons/submissions/submission-components.tsx`:
- Around line 29-51: The SubmissionRow type is missing the
disqualificationReason field which is currently being read as any elsewhere;
update the SubmissionRow type declaration to include disqualificationReason?:
any (or a more specific union such as string | null | any[] if you know the
shape) so callers no longer need unsafe casts; make the same addition to the
equivalent submission DTO/type definitions referenced later (the other
SubmissionRow-like declarations around the file, e.g., the block noted at lines
345-353) and run TypeScript type checks to remove the unsafe any casts.
- Around line 55-58: Convert the exported function declarations to typed
const-arrow exports: replace the function declaration for getStatusConfig with a
const getStatusConfig: (status: string) => { label: string; className: string }
= (status) => { ... } and do the same for the other exported
functions/components referenced (the ones around lines 101-102, 114-122,
132-136, 360-368), ensuring each has an explicit parameter and return type
annotation and uses a const-arrow form instead of the function keyword so they
conform to the project's TSX style.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
app/me/hackathons/submissions/page.tsxapp/me/hackathons/submissions/submission-components.tsx
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
app/me/hackathons/submissions/submission-components.tsx (1)
404-415:⚠️ Potential issue | 🟠 MajorRestore Cmd/Ctrl+click behavior for row interactions.
Line 404 currently treats all primary clicks as drawer-open, so Cmd/Ctrl+left-click no longer opens a new tab.
🔧 Suggested fix
const handleLeftClick = (e: React.MouseEvent) => { - // Left click only if (e.button !== 0) return; + // Cmd/Ctrl + left click -> open in new tab + if (e.metaKey || e.ctrlKey) { + e.stopPropagation(); + window.open(viewUrl, '_blank', 'noopener,noreferrer'); + return; + } onClick(); };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/submission-components.tsx` around lines 404 - 415, The left-click handler handleLeftClick currently treats any primary click as a normal click and calls onClick(), which breaks Cmd/Ctrl+click new-tab behavior; update handleLeftClick to detect modifier keys (e.metaKey or e.ctrlKey) and if pressed, prevent the normal drawer open and instead open viewUrl in a new tab (window.open with '_blank' and 'noopener,noreferrer'), otherwise call onClick(); keep the existing handleAuxClick behavior for middle clicks and ensure you call e.stopPropagation() when opening a new tab to avoid triggering onClick.
🧹 Nitpick comments (3)
app/me/hackathons/submissions/submission-components.tsx (2)
45-67: Make disqualification metadata type-safe instead of usingas any.Lines 366-373 rely on
(submission as any).disqualificationReason, which bypasses type safety and can hide shape regressions.🧩 Suggested typing cleanup
export type SubmissionRow = { id: string; projectName: string; @@ - votes?: number | any[]; - comments?: number | any[]; + votes?: number | Array<unknown>; + comments?: number | Array<unknown>; + disqualificationReason?: string; hackathon?: { @@ - {(submission.status || '').toLowerCase() === 'disqualified' && - (submission as any).disqualificationReason && ( + {(submission.status || '').toLowerCase() === 'disqualified' && + submission.disqualificationReason && ( <div className='rounded-xl border border-red-500/30 bg-red-500/10 p-4'> @@ - {(submission as any).disqualificationReason} + {submission.disqualificationReason} </p> </div> )}Also applies to: 365-373
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/submission-components.tsx` around lines 45 - 67, The code is using (submission as any).disqualificationReason which bypasses type checking; add a proper disqualification shape to the SubmissionRow type (e.g., disqualification?: { reason?: string; disqualifiedBy?: string; at?: string } or a named Disqualification interface) and update all usages (replace (submission as any).disqualificationReason with submission.disqualification?.reason or submission.disqualificationReason if you choose a flat field) so the compiler enforces the shape and remove the unsafe `as any` casts; ensure any components/functions referencing disqualification fields use the new typed property names (SubmissionRow and the component reading disqualification).
24-35: Extract inline JSX callbacks to named handlers withhandle*prefix and convert exported functions to const arrow syntax.This file has two convention violations:
Function declarations: All exported utilities and components use
export functionsyntax. Per repo conventions for.tsxfiles, these should beconst arrowfunctions with explicit type annotations (e.g.,const getSafeUrl = (urlString?: string): string | undefined => {...}).Inline event handlers: Anonymous inline callbacks (lines 202, 435–436, 468–470) lack named handlers. These should be extracted to named functions prefixed with
handle*(e.g.,const handleMouseEnter = () => setIsHoverOrFocus(true)).Affected lines: 24–35, 71–75, 117–126, 130–138, 148–152, 202–203, 380–388, 435–436, 468–470.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/submission-components.tsx` around lines 24 - 35, Change exported function declarations to const arrow exports with explicit type annotations (e.g., replace "export function getSafeUrl(...)" with "export const getSafeUrl = (urlString?: string): string | undefined => { ... }"). Also extract all inline JSX callbacks into named handler functions prefixed with "handle" (for the inline callbacks at the noted locations create handlers such as handleMouseEnter, handleMouseLeave, handleClick, handleFocus, handleBlur as appropriate) and replace the inline arrow callbacks in the JSX with those handler references; ensure handlers reference the same state setters (e.g., setIsHoverOrFocus) and are defined in the same component scope so TypeScript types remain correct.app/me/hackathons/submissions/page.tsx (1)
26-26: Convert component to const arrow function with explicit return type annotation.The function declaration should be converted to
const SubmissionsPage: React.FC<void> = () => { ... }per the**/*.{ts,tsx}guideline to prefer const arrow functions with explicit type annotations over function declarations.Additionally, the inline callback at line 349 (
onAddClick={() => router.push('/hackathons')}) should be extracted as a named handler (e.g.,const handleExploreClick = () => { ... }) to follow the handle* naming convention for event handlers.Note: The callbacks at lines 237, 255, 273, 291, 309, and 330 correctly use the
handleSortandhandleRowClickhandlers and do not require changes.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/page.tsx` at line 26, Convert the SubmissionsPage function declaration into a const arrow component with an explicit type annotation (replace `export default function SubmissionsPage()` with `const SubmissionsPage: React.FC<void> = () => { ... }` and export it as default), and extract the inline callback passed to onAddClick (currently `() => router.push('/hackathons')`) into a named handler such as `const handleExploreClick = () => { router.push('/hackathons') }` and pass `handleExploreClick` to onAddClick; keep existing handlers like handleSort and handleRowClick unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/me/hackathons/submissions/page.tsx`:
- Around line 187-191: The "Under Review" count uses a raw string check that
misses the "under review" variant; inside the rawSubmissions.filter callback
normalize s.status (e.g., lowercase and collapse spaces/underscores/dashes to a
single normalized token) before comparing, then test the normalized value
against "under_review" and "submitted" so both "under review", "under_review",
"under-review", etc. are counted consistently.
---
Duplicate comments:
In `@app/me/hackathons/submissions/submission-components.tsx`:
- Around line 404-415: The left-click handler handleLeftClick currently treats
any primary click as a normal click and calls onClick(), which breaks
Cmd/Ctrl+click new-tab behavior; update handleLeftClick to detect modifier keys
(e.metaKey or e.ctrlKey) and if pressed, prevent the normal drawer open and
instead open viewUrl in a new tab (window.open with '_blank' and
'noopener,noreferrer'), otherwise call onClick(); keep the existing
handleAuxClick behavior for middle clicks and ensure you call
e.stopPropagation() when opening a new tab to avoid triggering onClick.
---
Nitpick comments:
In `@app/me/hackathons/submissions/page.tsx`:
- Line 26: Convert the SubmissionsPage function declaration into a const arrow
component with an explicit type annotation (replace `export default function
SubmissionsPage()` with `const SubmissionsPage: React.FC<void> = () => { ... }`
and export it as default), and extract the inline callback passed to onAddClick
(currently `() => router.push('/hackathons')`) into a named handler such as
`const handleExploreClick = () => { router.push('/hackathons') }` and pass
`handleExploreClick` to onAddClick; keep existing handlers like handleSort and
handleRowClick unchanged.
In `@app/me/hackathons/submissions/submission-components.tsx`:
- Around line 45-67: The code is using (submission as
any).disqualificationReason which bypasses type checking; add a proper
disqualification shape to the SubmissionRow type (e.g., disqualification?: {
reason?: string; disqualifiedBy?: string; at?: string } or a named
Disqualification interface) and update all usages (replace (submission as
any).disqualificationReason with submission.disqualification?.reason or
submission.disqualificationReason if you choose a flat field) so the compiler
enforces the shape and remove the unsafe `as any` casts; ensure any
components/functions referencing disqualification fields use the new typed
property names (SubmissionRow and the component reading disqualification).
- Around line 24-35: Change exported function declarations to const arrow
exports with explicit type annotations (e.g., replace "export function
getSafeUrl(...)" with "export const getSafeUrl = (urlString?: string): string |
undefined => { ... }"). Also extract all inline JSX callbacks into named handler
functions prefixed with "handle" (for the inline callbacks at the noted
locations create handlers such as handleMouseEnter, handleMouseLeave,
handleClick, handleFocus, handleBlur as appropriate) and replace the inline
arrow callbacks in the JSX with those handler references; ensure handlers
reference the same state setters (e.g., setIsHoverOrFocus) and are defined in
the same component scope so TypeScript types remain correct.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
app/me/hackathons/submissions/page.tsxapp/me/hackathons/submissions/submission-components.tsx
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/me/hackathons/submissions/page.tsx (1)
26-59: Convert to arrow function and replaceanycasts with proper types.The component uses a function declaration (line 26) and relies on multiple
anycasts (lines 38, 43, 46, 58, 79–80), which weakens type safety in the session/profile data mapping path. Convert to a const arrow function with explicit types per TSX guidelines.♻️ Proposed refactor
-export default function SubmissionsPage() { +type SessionSubmission = { + id?: string; + _id?: string; + projectName?: string; + title?: string; + name?: string; + description?: string; + introduction?: string; + logo?: string; + videoUrl?: string; + category?: string; + links?: Array<{ type: string; url: string }>; + status?: string; + rank?: number | null; + submittedAt?: string; + submissionDate?: string; + createdAt?: string; + votes?: number | any[]; + comments?: number | any[]; + hackathon?: SubmissionRow['hackathon']; + disqualificationReason?: string; +}; + +const SubmissionsPage = (): JSX.Element => { const router = useRouter(); const { data: session, status } = useSession(); @@ - const sessionUser = session?.user as any; + const sessionUser = session?.user as { + profile?: { + user?: { hackathonSubmissionsAsParticipant?: SessionSubmission[] }; + hackathonSubmissionsAsParticipant?: SessionSubmission[]; + }; + } | undefined; @@ - const fromUser: any[] = + const fromUser: SessionSubmission[] = profile?.user?.hackathonSubmissionsAsParticipant || []; @@ - const fromProfile: any[] = profile?.hackathonSubmissionsAsParticipant || []; + const fromProfile: SessionSubmission[] = + profile?.hackathonSubmissionsAsParticipant || []; @@ - return deduped.map((s: any) => ({ + return deduped.map((s): SubmissionRow => ({ id: s.id || s._id || '', @@ -} +}; + +export default SubmissionsPage;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/page.tsx` around lines 26 - 59, The component is declared as a function and uses many any casts in the session/profile mapping; change to a typed arrow component (e.g., declare const SubmissionsPage: React.FC = () => { ...) and replace the any usages with explicit types: use the session type for session (e.g., Session from next-auth), a Profile type for profile (or an inline interface matching profile.hackathonSubmissionsAsParticipant), and SubmissionRow[] for fromUser/fromProfile/rawSubmissions; update variables sessionUser, profile, fromUser, fromProfile, merged, deduped and the rawSubmissions useMemo signature to use these concrete types so you can remove all any casts while preserving the existing logic in rawSubmissions and keep setSelectedSubmission, sheetOpen, sortField, sortDir unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/me/hackathons/submissions/page.tsx`:
- Around line 189-192: Normalize status to collapse spaces, dashes and
underscores by updating the replacement applied to s.status (the st computation)
so multiple underscores are also collapsed; change the regex used when creating
st (currently replacing /[\s\-]+/g) to include underscores (e.g., include _ in
the character class) so inputs like under__review normalize to under_review and
the comparison against 'under_review' and 'submitted' remains correct.
---
Nitpick comments:
In `@app/me/hackathons/submissions/page.tsx`:
- Around line 26-59: The component is declared as a function and uses many any
casts in the session/profile mapping; change to a typed arrow component (e.g.,
declare const SubmissionsPage: React.FC = () => { ...) and replace the any
usages with explicit types: use the session type for session (e.g., Session from
next-auth), a Profile type for profile (or an inline interface matching
profile.hackathonSubmissionsAsParticipant), and SubmissionRow[] for
fromUser/fromProfile/rawSubmissions; update variables sessionUser, profile,
fromUser, fromProfile, merged, deduped and the rawSubmissions useMemo signature
to use these concrete types so you can remove all any casts while preserving the
existing logic in rawSubmissions and keep setSelectedSubmission, sheetOpen,
sortField, sortDir unchanged.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
app/me/hackathons/submissions/page.tsx
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
app/me/hackathons/submissions/page.tsx (2)
38-47: Replaceany-based session parsing with typed profile/submission models.This path is the core data contract for the page;
anyhere removes compile-time guarantees and makes shape drift easy to miss.As per coding guidelines
**/*.{ts,tsx}: Use provided Types from Trustless Work documentation when applicable.Also applies to: 58-74
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/page.tsx` around lines 38 - 47, The current parsing uses any for sessionUser/profile/submissions (sessionUser, profile, fromUser, fromProfile, hackathonSubmissionsAsParticipant) which loses type-safety; replace these any types with the canonical types from the Trustless Work typings (e.g., import and use the exported SessionUser, UserProfile and HackathonSubmission types or their equivalent), update the session extraction to cast session?.user to SessionUser, type profile as UserProfile, and type both fromUser and fromProfile as HackathonSubmission[] (or the provided submission list type), then narrow null checks accordingly so the rest of the code uses typed properties instead of any.
26-26: Prefer a typed const arrow component export for TSX consistency.Consider switching from a function declaration to a typed const arrow component to align with the project’s TSX convention.
As per coding guidelines
**/*.{ts,tsx}: Prefer const arrow functions with explicit type annotations over function declarations.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/hackathons/submissions/page.tsx` at line 26, Replace the function declaration export default function SubmissionsPage() with a typed const arrow component: declare const SubmissionsPage with an explicit React function component type (e.g., React.FC or React.FunctionComponent) and assign an arrow function, then export default SubmissionsPage; ensure you import the React type (import React from 'react' or import type { FC } from 'react') and update any internal references to the SubmissionsPage symbol accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/me/hackathons/submissions/page.tsx`:
- Around line 96-98: In the sort comparator that assigns aVal and bVal from
a.submittedAt and b.submittedAt, guard against invalid dates by parsing the
timestamp (e.g., Date.parse or new Date(...).getTime()) and if the result is NaN
use a safe fallback (0 or -Infinity) so comparisons remain deterministic; update
the assignments for aVal and bVal (the places referencing a.submittedAt and
b.submittedAt) to validate Number.isFinite(parsed) or !Number.isNaN(parsed)
before using the value and otherwise assign the chosen fallback.
- Line 4: The import of motion and AnimatePresence from 'framer-motion' in
app/me/hackathons/submissions/page.tsx requires adding framer-motion to the
project dependencies; update package.json to include "framer-motion" (choose
dependencies if used at runtime in the client bundle or devDependencies if
appropriate), pick a compatible version, run your package manager
(npm/yarn/pnpm) to install so the lockfile is updated, and commit the updated
package.json and lockfile to avoid build/runtime failures when importing
motion/AnimatePresence.
---
Nitpick comments:
In `@app/me/hackathons/submissions/page.tsx`:
- Around line 38-47: The current parsing uses any for
sessionUser/profile/submissions (sessionUser, profile, fromUser, fromProfile,
hackathonSubmissionsAsParticipant) which loses type-safety; replace these any
types with the canonical types from the Trustless Work typings (e.g., import and
use the exported SessionUser, UserProfile and HackathonSubmission types or their
equivalent), update the session extraction to cast session?.user to SessionUser,
type profile as UserProfile, and type both fromUser and fromProfile as
HackathonSubmission[] (or the provided submission list type), then narrow null
checks accordingly so the rest of the code uses typed properties instead of any.
- Line 26: Replace the function declaration export default function
SubmissionsPage() with a typed const arrow component: declare const
SubmissionsPage with an explicit React function component type (e.g., React.FC
or React.FunctionComponent) and assign an arrow function, then export default
SubmissionsPage; ensure you import the React type (import React from 'react' or
import type { FC } from 'react') and update any internal references to the
SubmissionsPage symbol accordingly.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
app/me/hackathons/submissions/page.tsx
Closes #395
feat: Implement Unified Hackathon Submissions Dashboard
Summary
This PR replaces the
/coming-soonstub at/me/hackathons/submissionswith a fully functional submissions dashboard.The page provides users with complete visibility into the lifecycle of their hackathon submissions. All data is sourced directly from the existing
user.profilesession, introducing zero new API requests.Key Features
Submissions Table
Status Badges
StatusBadgecomponentSubmission Details Drawer
size="xl") opens on row clickSidebar Integration
AppSidebarEmpty State
EmptyStatecomponent/hackathonsTechnical Notes
useAuthStatus()user.profile.user.hackathonSubmissionsAsParticipantuser.profile.hackathonSubmissionsAsParticipantsubmission-components.tsxVideo Proof
Summary by CodeRabbit
New Features
UI
Documentation
Style