Skip to content

Comments

Judging dashboard#384

Merged
Benjtalkshow merged 112 commits intoboundlessfi:mainfrom
Benjtalkshow:judging-dashboard
Feb 16, 2026
Merged

Judging dashboard#384
Benjtalkshow merged 112 commits intoboundlessfi:mainfrom
Benjtalkshow:judging-dashboard

Conversation

@Benjtalkshow
Copy link
Collaborator

@Benjtalkshow Benjtalkshow commented Feb 16, 2026

Summary by CodeRabbit

  • New Features

    • Aggregated judging summaries and winners surfaced; dashboard metrics prefer aggregated data
    • Criteria breakdown visualization and per-criterion scoring view added
    • Submissions workflow now threads current judge context so review/disqualify actions record the acting judge
  • UI/UX Improvements

    • Judging status badges (Pending, Incomplete, Disagreement) and improved EmptyState across pages
    • Tooltips for scoring discrepancies/outliers; judges labeled “Judge N”
    • Tab navigation gains horizontal scrolling; announcement image dialog spacing tweaked
  • Bug Fixes

    • Improved error messaging and graceful fallbacks for missing or partial score data

@vercel
Copy link

vercel bot commented Feb 16, 2026

@Benjtalkshow is attempting to deploy a commit to the Threadflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Feb 16, 2026

Warning

Rate limit exceeded

@Benjtalkshow has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 0 minutes and 42 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Wires aggregated judging results and summaries from the API into the UI, adds criteria-aware components and per-judge scoring flows, threads currentUserId/hackathon through submissions flows, updates request shapes to include judgeId, and enhances tooltips and error handling across judging and submissions components.

Changes

Cohort / File(s) Summary
Judging API & Types
lib/api/hackathons/judging.ts
Introduced AggregatedJudgingResults, expanded JudgingResult with per-judge stats, criteriaBreakdown, range/variance, progress/status flags, rank; updated getJudgingResults/getJudgingWinners response handling to accept aggregated payloads.
Submission Request Types
lib/api/hackathons.ts
Added judgeId: string to ReviewSubmissionRequest, DisqualifySubmissionRequest, and BulkActionRequest payloads.
Judging Page
app/(landing)/organizations/[id]/hackathons/[hackathonId]/judging/page.tsx
Added state for aggregated summaries (judgingSummary, winnersSummary), prefer API metrics when available, show EmptyState for multiple no-data scenarios, and pass new criteria prop to JudgingResultsTable.
Results Table & Criteria UI
components/organization/hackathons/judging/JudgingResultsTable.tsx, components/organization/hackathons/judging/AggregatedCriteriaBreakdown.tsx, components/organization/hackathons/judging/JudgingCriteriaList.tsx
JudgingResultsTable now accepts criteria?: JudgingCriterion[], renders Pending/Incomplete/Disagreement badges, supports expanded AggregatedCriteriaBreakdown; added AggregatedCriteriaBreakdown component and replaced inline empty-state with EmptyState.
Individual Scores
components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx
Added initialScores? prop and new JudgeScore shape, always attempts detailed criteria fetch with fallback to initialScores, added tooltips for discrepancy/outlier badges, and improved per-criterion rendering and total-score handling.
Submissions — Page & Management
app/(landing)/organizations/[id]/hackathons/[hackathonId]/submissions/page.tsx, components/organization/hackathons/submissions/SubmissionsManagement.tsx
Client-side fetch of currentUserId and hackathon; SubmissionsManagement now accepts currentUserId and hackathon, and includes judgeId in review/disqualify/bulk action payloads.
Submissions List
components/organization/hackathons/submissions/SubmissionsList.tsx
Added optional hackathon?: Hackathon prop, deadline-aware isBeforeDeadline gating for actions, support for grid/table views, and disqualification state handling.
UX / Error Handling / Misc
components/organization/cards/GradeSubmissionModal/useScoreForm.ts, components/hackathons/hackathonNavTabs.tsx, components/ui/shadcn-io/announcement-editor/index.tsx
Improved API error messaging in grading flow, replaced scrolling container with ScrollArea/ScrollBar for tabs, minor spacing/styling tweaks in announcement editor.
Other wiring
app/(landing)/.../judging/page.tsx, components/.../JudgingResultsTable.tsx
Multiple call sites updated to provide criteria and initialScores props to judging subcomponents.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Page as Judging Page
    participant API as Judging API
    participant Table as JudgingResultsTable
    participant Criteria as AggregatedCriteriaBreakdown
    participant Scores as IndividualScoresBreakdown

    User->>Page: Open judging page
    Page->>API: GET /judging/results & /judging/winners
    API-->>Page: AggregatedJudgingResults (results, summaries, metadata)

    Page->>Table: render(results[], criteria[])
    loop per result
        Table->>Table: render row, status badges
        alt has criteriaBreakdown
            Table->>Criteria: pass criteriaBreakdown + criteria
            Criteria-->>Table: render ranges & averages
        end
        alt has individualScores
            Table->>Scores: pass initialScores
            Scores->>API: GET detailed per-judge criteria (if needed)
            API-->>Scores: detailed scores
            Scores-->>Table: render per-judge breakdown with tooltips
        end
    end

    Table-->>User: display aggregated metrics, rows, and expanded details
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly Related PRs

  • Judging dashboard #382 — Overlapping judging API/type changes and UI updates (getJudgingResults/getJudgingWinners, JudgingResultsTable, IndividualScoresBreakdown).
  • Fix hackathon #375 — Related submissions management changes and judgeId wiring for review/disqualify/bulk actions.

Suggested Reviewers

  • 0xdevcollins

Poem

🐇 I hopped into the judging hall,
With bars and averages standing tall,
Judges, scores, and tiny charts,
Criteria sing and split apart,
I nibble bytes and cheer the call.

🚥 Pre-merge checks | ✅ 2 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Judging dashboard' is vague and does not clearly convey the specific changes made. While the PR does involve judging-related components and functionality, the title lacks specificity about what aspects of the judging dashboard were modified or added. Consider using a more descriptive title that specifies the main change, such as 'Add aggregated judging results and criteria breakdown to judging dashboard' or 'Enhance judging dashboard with aggregated metrics and status indicators'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

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

⚠️ Outside diff range comments (5)
components/organization/hackathons/submissions/SubmissionsManagement.tsx (1)

124-144: ⚠️ Potential issue | 🔴 Critical

handleBulkAction doesn't guard on currentUserId, unlike handleReview and handleDisqualify.

handleReview (Line 101) and handleDisqualify (Line 110) both early-return when currentUserId is falsy, but handleBulkAction only checks organizationId, hackathonId, and selectedIds. This means bulk actions can fire with judgeId: '' (Line 138), which is likely invalid on the backend.

🐛 Proposed fix
   const handleBulkAction = async (
     action: 'SHORTLISTED' | 'SUBMITTED' | 'DISQUALIFIED',
     reason?: string
   ) => {
-    if (!organizationId || !hackathonId || selectedIds.length === 0) return;
+    if (!organizationId || !hackathonId || !currentUserId || selectedIds.length === 0) return;

     if (action === 'DISQUALIFIED' && !reason) {
       setShowBulkDisqualifyDialog(true);
       return;
     }

     await performBulkAction(organizationId, hackathonId, {
       submissionIds: selectedIds,
       action,
-      judgeId: currentUserId || '',
+      judgeId: currentUserId,
       reason,
     });
components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx (2)

78-81: ⚠️ Potential issue | 🟠 Major

avgTotalScore will be NaN when using initialScores fallback.

initialScores objects have a score field, not totalScore. So s.totalScore is undefined, making the sum NaN. This silently breaks the discrepancy detection at Lines 113 and 135, though it doesn't crash.

🐛 Proposed fix
   const avgTotalScore =
     scores.length > 0
-      ? scores.reduce((sum, s) => sum + s.totalScore, 0) / scores.length
+      ? scores.reduce((sum, s) => sum + (s.totalScore ?? s.score ?? 0), 0) / scores.length
       : 0;

40-69: ⚠️ Potential issue | 🟠 Major

initialScores in the dependency array may cause re-fetch loops.

If the parent component doesn't memoize the initialScores array (e.g., via useMemo), a new array reference is created on each render, causing this useEffect to re-fire indefinitely and spam the API.

Consider removing initialScores from the dependency array (it's only used as a fallback, not as a trigger) or ensuring the parent memoizes it.

lib/api/hackathons/judging.ts (1)

440-450: ⚠️ Potential issue | 🟠 Major

Unsafe fallback: casting {} as GetJudgingResultsResponse when res.data is nullish.

Line 449 falls through to (res.data || {}) as GetJudgingResultsResponse. If res.data is nullish, consumers get {} typed as having .success, .data.results, etc., which will crash on access. The same pattern exists in getJudgingWinners at Line 525.

🛡️ Proposed fix — return a well-typed empty response
-  return (res.data || {}) as GetJudgingResultsResponse;
+  return {
+    success: false,
+    message: 'Unexpected response format',
+    data: undefined,
+  } as unknown as GetJudgingResultsResponse;

Or better yet, throw an error to surface the issue early:

-  return (res.data || {}) as GetJudgingResultsResponse;
+  throw new Error('Unexpected response format from judging results API');
app/(landing)/organizations/[id]/hackathons/[hackathonId]/judging/page.tsx (1)

132-151: 🛠️ Refactor suggestion | 🟠 Major

currentUserId local variable shadows the state variable of the same name (line 63).

Line 134 declares const currentUserId which shadows the state variable from useState<string | null>(null) on line 63. This works today but is fragile — any future code in this callback referencing currentUserId will get the local, not the state. Rename the local to disambiguate.

Suggested fix
-    const currentUserId = session?.user?.id;
-    if (currentUserId && finalMembers.length > 0) {
+    const sessionUserId = session?.user?.id;
+    if (sessionUserId && finalMembers.length > 0) {
       const me = finalMembers.find(
-        (m: any) => m.userId === currentUserId || m.id === currentUserId
+        (m: any) => m.userId === sessionUserId || m.id === sessionUserId
       );
       setCurrentUserRole(me?.role || null);
 
       const isJudge = judges.some(
-        (j: any) => j.userId === currentUserId || j.id === currentUserId
+        (j: any) => j.userId === sessionUserId || j.id === sessionUserId
       );
       setIsCurrentUserJudge(isJudge);
     }
 
-    if (currentUserId) {
-      setCurrentUserId(currentUserId);
+    if (sessionUserId) {
+      setCurrentUserId(sessionUserId);
     }
🤖 Fix all issues with AI agents
In `@app/`(landing)/organizations/[id]/hackathons/[hackathonId]/judging/page.tsx:
- Line 160: Remove the development `console.log('Judging Results Structure
Verification:', res)` from the Judging page component; locate the logging call
that prints the `res` response in the rendering or data-fetching logic (the
console.log that includes "Judging Results Structure Verification") and delete
it, or replace it with a proper server-side or debug-only logger if you need
persisted/filtered diagnostic output ( gated by an environment/debug flag ).

In `@components/hackathons/hackathonNavTabs.tsx`:
- Line 1: The file imports unused React hooks useState and useEffect; remove
these unused imports from the import line (replace "import { useState, useEffect
} from 'react';" with a plain React import or remove entirely if not needed) so
that the component no longer includes unused symbols and ESLint/compiler
warnings go away; locate the import statement at the top of
components/hackathons/hackathonNavTabs.tsx and update it to only import what the
file actually uses.

In
`@components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx`:
- Line 34: The scores state is typed as any[] which hides a mismatch: API items
use totalScore while initialScores use score, causing avgTotalScore and the
discrepancy checks to break; update the scores typing to a discriminated union
or a proper interface (e.g., ScoreApi { totalScore: number; ... } | ScoreInitial
{ score: number; ... }) and normalize data when calling setScores — either map
the API response into the internal shape expected by avgTotalScore (convert
totalScore -> score or vice versa) or when falling back to initialScores, map
its items to match the API shape used by avgTotalScore and discrepancy detection
(references: scores, setScores, initialScores, avgTotalScore).

In `@components/organization/hackathons/judging/AggregatedCriteriaBreakdown.tsx`:
- Around line 25-34: The component AggregatedCriteriaBreakdown currently assumes
numeric fields (variance, averageScore, min, max) are non-null and calls
.toFixed(), which can throw if the API returns null/undefined; update the
rendering logic in AggregatedCriteriaBreakdown (and any helpers like
getScoreColor usage points) to coerce these values to safe numbers before
formatting (e.g., use nullish coalescing or Number(...) with a default like 0)
and only call .toFixed() on the safe fallback value, applying the same defensive
checks for variance, averageScore, min and max wherever they are formatted.

In `@components/organization/hackathons/judging/JudgingResultsTable.tsx`:
- Around line 190-191: In JudgingResultsTable (the JSX that renders the judge
counts), the expression "{result.judgeCount} / {result.expectedJudgeCount ||
totalJudges || '?'}" incorrectly treats an expectedJudgeCount of 0 as falsy;
change the fallback chain to use the nullish coalescing operator so it becomes
"{result.judgeCount} / {result.expectedJudgeCount ?? totalJudges ?? '?'}"
(referencing result.judgeCount, result.expectedJudgeCount and totalJudges) to
preserve zero values while still falling back when expectedJudgeCount is null or
undefined.
- Line 106: The rank display currently uses the falsy check "result.rank ||
index + 1" which treats a valid numeric rank 0 as missing; update the fallback
to use nullish coalescing so only null/undefined fall back: replace the
expression in JudgingResultsTable (the span rendering result.rank) with
"result.rank ?? index + 1" ensuring result.rank (from the result object) remains
typed as number and preserves 0 correctly.
🧹 Nitpick comments (11)
components/ui/shadcn-io/announcement-editor/index.tsx (1)

366-387: Inconsistent styling across sibling dialogs.

The mb-2 on the Image URL label (line 366) and text-background on the Image Insert button (line 387) aren't applied to the structurally identical Link and Embed dialogs:

  • Labels: Link Text (line 308), URL (line 320), and Embed URL (line 412) all lack mb-2.
  • Insert buttons: Link Insert (line 341) and Embed Insert (line 433) use text-white instead of text-background.

If these are intentional fixes, apply them consistently to all three dialogs.

♻️ Suggested diff for consistency
-                <Label htmlFor='link-text' className='text-white'>
+                <Label htmlFor='link-text' className='mb-2 text-white'>
-                <Label htmlFor='link-url' className='text-white'>
+                <Label htmlFor='link-url' className='mb-2 text-white'>
-                <Label htmlFor='embed-url' className='text-white'>
+                <Label htmlFor='embed-url' className='mb-2 text-white'>
-                  className='bg-primary hover:bg-primary/90 text-white'
+                  className='bg-primary hover:bg-primary/90 text-background'

(Apply to Insert buttons on lines 341 and 433.)

components/hackathons/hackathonNavTabs.tsx (2)

16-20: Prefer const arrow function with explicit type annotation.

As per coding guidelines, "Prefer const arrow functions with explicit type annotations over function declarations."

Proposed fix
-export function HackathonNavTabs({
-  tabs,
-  activeTab,
-  onTabChange,
-}: HackathonNavTabsProps) {
+export const HackathonNavTabs: React.FC<HackathonNavTabsProps> = ({
+  tabs,
+  activeTab,
+  onTabChange,
+}) => {

36-36: Use clsx (or cn) for conditional classes instead of a ternary in a template literal.

This improves readability and aligns with the project convention. As per coding guidelines, "For conditional classes, prefer clsx or similar helper functions over ternary operators in JSX."

Proposed fix (using clsx)
-                  className={`relative px-4 py-4 text-sm font-medium whitespace-nowrap transition-colors duration-200 ${isActive ? 'text-[`#a7f950`]' : 'text-gray-400 hover:text-white'} `}
+                  className={clsx(
+                    'relative px-4 py-4 text-sm font-medium whitespace-nowrap transition-colors duration-200',
+                    isActive ? 'text-[`#a7f950`]' : 'text-gray-400 hover:text-white',
+                  )}

And add the import:

+import clsx from 'clsx';
components/organization/hackathons/judging/AggregatedCriteriaBreakdown.tsx (1)

101-118: Visual layering: average bar renders on top of range bar — is this intentional?

Both the range bar (gray, Lines 103-109) and the average marker (colored, Lines 111-117) are absolutely positioned children. The average bar uses width from 0, meaning it overlays the range bar from the left edge rather than being a point marker at the average position. If the intent is to show a filled bar up to the average and a separate range indicator, this works. If the intent is a narrow marker at the average point, you'd need a thin element positioned at left: averageScore * 10% instead.

app/(landing)/organizations/[id]/hackathons/[hackathonId]/submissions/page.tsx (1)

34-49: Consider separating fetchHackathonDetails into its own useEffect.

fetchHackathonDetails is embedded inside the same useEffect as fetchSubmissions, but they serve different purposes and have different lifecycles. The hackathon details likely only need fetching once, whereas submissions may be re-fetched (via refresh). Extracting it to a dedicated effect improves clarity and avoids re-fetching hackathon details if fetchSubmissions changes identity.

components/organization/hackathons/submissions/SubmissionsList.tsx (1)

182-184: Use cn() for conditional classes instead of template literal ternaries.

Lines 184 and 500 use template literal ternaries for conditional class names. The project already imports cn in other components, and the coding guidelines require clsx or similar helpers over ternary operators in JSX.

♻️ Example for Line 184
- className={`group hover:border-primary/50 relative cursor-pointer overflow-hidden border-gray-800/50 bg-gray-900/20 transition-all hover:bg-gray-900/40 ${selectedIds?.includes(subData.id) ? 'border-primary/50 bg-primary/5' : ''}`}
+ className={cn(
+   'group hover:border-primary/50 relative cursor-pointer overflow-hidden border-gray-800/50 bg-gray-900/20 transition-all hover:bg-gray-900/40',
+   selectedIds?.includes(subData.id) && 'border-primary/50 bg-primary/5'
+ )}

Apply the same pattern to Line 500. As per coding guidelines, "For conditional classes, prefer clsx or similar helper functions over ternary operators in JSX".

lib/api/hackathons/judging.ts (1)

430-450: Duplicated dual-format response handling between getJudgingResults and getJudgingWinners.

Both functions share the same pattern: check for 'results' in res.data, wrap in success response or fall through. Consider extracting this into a shared helper to reduce duplication.

♻️ Suggested helper
const normalizeAggregatedResponse = (
  resData: AggregatedJudgingResults | ApiResponse<AggregatedJudgingResults> | undefined,
  fallbackMessage: string
): GetJudgingResultsResponse => {
  if (resData && 'results' in resData) {
    return {
      success: true,
      data: resData as AggregatedJudgingResults,
      message: fallbackMessage,
    } as GetJudgingResultsResponse;
  }
  if (resData && 'success' in resData) {
    return resData as GetJudgingResultsResponse;
  }
  throw new Error('Unexpected response format');
};

Also applies to: 507-526

components/organization/hackathons/judging/JudgingResultsTable.tsx (2)

4-4: Consolidate imports from the same module.

JudgingResult (line 4) and JudgingCriterion (line 23) are both imported from @/lib/api/hackathons/judging. Merge them into a single import statement.

Suggested fix
-import { JudgingResult } from '@/lib/api/hackathons/judging';
+import { JudgingResult, JudgingCriterion } from '@/lib/api/hackathons/judging';
 ...
 import AggregatedCriteriaBreakdown from './AggregatedCriteriaBreakdown';
-import { JudgingCriterion } from '@/lib/api/hackathons/judging';

Also applies to: 22-23


49-54: Rename toggleRow to handleToggleRow to follow the event handler naming convention.

As per coding guidelines, "Event handlers should start with 'handle' prefix (e.g., handleClick, handleSubmit)".

app/(landing)/organizations/[id]/hackathons/[hackathonId]/judging/page.tsx (2)

168-170: Avoid as any cast — type the API response properly or use optional chaining.

If the response type doesn't include message on the failure path, consider extending the type or using a type guard rather than casting to any.


197-199: Fire-and-forget calls are intentional but worth a brief comment.

fetchJudges() and fetchResults() run in parallel without await, meaning isLoading (set to false in the finally block) only reflects submissions/criteria completion. This is fine since judges and results have their own loading states, but a brief inline comment would help future readers understand this is deliberate.

Copy link

@coderabbitai coderabbitai bot left a comment

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)
app/(landing)/organizations/[id]/hackathons/[hackathonId]/judging/page.tsx (1)

300-303: ⚠️ Potential issue | 🟡 Minor

fetchResults() is called twice on success.

handleSuccess calls fetchData() (which internally fires fetchResults() on line 198) and then calls fetchResults() again on line 302. This results in a redundant network request every time a judge submits scores.

🐛 Proposed fix
 const handleSuccess = () => {
   fetchData();
-  fetchResults(); // Refresh results to update metrics/table
 };

Since fetchData already triggers fetchResults() internally, the explicit call is unnecessary.

🤖 Fix all issues with AI agents
In
`@components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx`:
- Line 97: The useEffect inside the IndividualScoresBreakdown component
currently includes initialScores in its dependency array which can trigger
unnecessary re-fetches when the parent recreates that array; remove
initialScores from the dependency array (keep [organizationId, hackathonId,
participantId]) and treat initialScores only as a fallback inside the effect, or
if you prefer value-based tracking, replace the dependency with a stable
signature (e.g., a JSON.stringify(initialScores) or a memoized/stableRef) so the
effect only reruns on meaningful changes; update the useEffect associated with
loading individual scores accordingly.
- Around line 64-66: res.data is an array of IndividualJudgeScore[] but
setScores expects JudgeScore[] which requires a totalScore; map res.data before
calling setScores (or change the state type) by computing totalScore from each
IndividualJudgeScore's criteriaScores (e.g., sum or average of
criteriaScores[].score) and produce the JudgeScore shape, then call
setScores(mappedArray); update any uses of JudgeScore (references at lines where
totalScore is accessed) if you choose to change the state type instead.
🧹 Nitpick comments (7)
components/hackathons/hackathonNavTabs.tsx (2)

15-15: Prefer const arrow function with explicit type annotation.

As per coding guidelines, prefer const arrow functions with explicit type annotations over function declarations.

♻️ Proposed fix
-export function HackathonNavTabs({
+export const HackathonNavTabs: React.FC<HackathonNavTabsProps> = ({
   tabs,
   activeTab,
   onTabChange,
-}: HackathonNavTabsProps) {
+}) => {

(Add import React from 'react' or use the return type inline if preferred.)


35-35: Use clsx (or cn) for conditional classes instead of a ternary in the template literal.

As per coding guidelines: "For conditional classes, prefer clsx or similar helper functions over ternary operators in JSX."

♻️ Proposed fix
+import { cn } from '@/lib/utils'; // or clsx
 ...
-                  className={`relative px-4 py-4 text-sm font-medium whitespace-nowrap transition-colors duration-200 ${isActive ? 'text-[`#a7f950`]' : 'text-gray-400 hover:text-white'} `}
+                  className={cn(
+                    'relative px-4 py-4 text-sm font-medium whitespace-nowrap transition-colors duration-200',
+                    isActive ? 'text-[`#a7f950`]' : 'text-gray-400 hover:text-white'
+                  )}
components/organization/hackathons/judging/AggregatedCriteriaBreakdown.tsx (1)

29-34: getScoreColor is duplicated across components.

This identical helper exists in both AggregatedCriteriaBreakdown (here) and IndividualScoresBreakdown (line 111). Consider extracting it into a shared utility (e.g., in lib/utils.ts or a judging-specific utils file) to keep things DRY.

components/organization/hackathons/judging/JudgingResultsTable.tsx (1)

49-54: Event handler naming convention: toggleRowhandleToggleRow.

Per coding guidelines, event handlers should use the handle prefix. As per coding guidelines, "Event handlers should start with 'handle' prefix (e.g., handleClick, handleSubmit)".

♻️ Proposed rename
-  const toggleRow = (id: string) => {
+  const handleToggleRow = (id: string) => {
     setExpandedRows(prev => ({
       ...prev,
       [id]: !prev[id],
     }));
   };

And update the usage on line 101:

-                  onClick={() => toggleRow(result.submissionId)}
+                  onClick={() => handleToggleRow(result.submissionId)}
app/(landing)/organizations/[id]/hackathons/[hackathonId]/judging/page.tsx (1)

36-36: Page component uses function declaration instead of const arrow function.

The coding guidelines prefer const arrow functions with explicit type annotations. This is a common Next.js pattern though, so flagging as optional.

As per coding guidelines, "Prefer const arrow functions with explicit type annotations over function declarations".

components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx (2)

65-76: Duplicated initialScores normalization logic.

The same mapping from initialScores to JudgeScore[] appears in both the else if branch (lines 70-76) and the catch block (lines 83-89). Extract it to avoid drift.

♻️ Proposed refactor
   useEffect(() => {
+    const normalizeInitialScores = (): JudgeScore[] | null => {
+      if (!initialScores) return null;
+      return initialScores.map(s => ({
+        judgeId: s.judgeId,
+        judgeName: s.judgeName,
+        totalScore: s.score,
+        score: s.score,
+      }));
+    };
+
     const fetchScores = async () => {
       setIsLoading(true);
       try {
         const res = await getSubmissionScores(
           organizationId,
           hackathonId,
           participantId
         );
         if (res.success && Array.isArray(res.data)) {
           setScores(res.data);
-        } else if (initialScores) {
-          const normalizedScores: JudgeScore[] = initialScores.map(s => ({
-            judgeId: s.judgeId,
-            judgeName: s.judgeName,
-            totalScore: s.score,
-            score: s.score,
-          }));
-          setScores(normalizedScores);
+        } else {
+          const fallback = normalizeInitialScores();
+          if (fallback) setScores(fallback);
         }
       } catch (err) {
         console.error('Failed to fetch individual scores:', err);
-        if (initialScores) {
-          const normalizedScores: JudgeScore[] = initialScores.map(s => ({
-            judgeId: s.judgeId,
-            judgeName: s.judgeName,
-            totalScore: s.score,
-            score: s.score,
-          }));
-          setScores(normalizedScores);
-        }
+        const fallback = normalizeInitialScores();
+        if (fallback) setScores(fallback);
       } finally {
         setIsLoading(false);
       }
     };

Also applies to: 78-90


240-240: Avoid any type for criteria scores.

score.criteriaScores is already typed in the JudgeScore interface (lines 34-39), so the (c: any, idx: number) annotation is unnecessary and weakens type safety.

♻️ Proposed fix
-                            {score.criteriaScores.map((c: any, idx: number) => (
+                            {score.criteriaScores.map((c, idx) => (

Copy link

@coderabbitai coderabbitai bot left a comment

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)
components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx (1)

250-286: ⚠️ Potential issue | 🟡 Minor

"Criteria Breakdown" label renders even when there are no criteria.

The <label> at Line 252 is always shown inside the expanded section, while the criteria grid is conditionally rendered only when score.criteriaScores?.length > 0. For scores originating from the initialScores fallback (which never has criteriaScores), the user sees a heading with nothing beneath it.

🔧 Proposed fix — wrap both the label and the grid in the same conditional
-                     <div>
-                      <label className='mb-2 block text-[10px] font-bold text-gray-400 uppercase'>
-                        Criteria Breakdown
-                      </label>
-                      {score.criteriaScores &&
-                        score.criteriaScores.length > 0 && (
+                     {score.criteriaScores && score.criteriaScores.length > 0 && (
+                      <div>
+                        <label className='mb-2 block text-[10px] font-bold text-gray-400 uppercase'>
+                          Criteria Breakdown
+                        </label>
                          <div className='grid grid-cols-1 gap-x-6 gap-y-3 md:grid-cols-2'>
                            ...
                          </div>
-                        )}
-                    </div>
+                      </div>
+                     )}
🤖 Fix all issues with AI agents
In
`@components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx`:
- Around line 268-276: The progress-bar width in IndividualScoresBreakdown uses
`c.score * 10` which assumes a 0–10 scale and lets values >10 produce >100%
widths; change the calculation to normalise and clamp the score against a max
(preferably criteria metadata, otherwise a default like 10) before computing
percentage, e.g. compute a maxScore (from criteria metadata or default 10),
clamp c.score to [0, maxScore] and set width = (clampedScore / maxScore) * 100%;
update the JSX where `style={{ width: `${c.score * 10}%` }}` is set and ensure
`getScoreColor(c.score)` either receives the clamped/normalized value or is
adapted accordingly.
- Around line 255-283: score.criteriaScores.map is using the array index as the
React key and `c: any`, which loses typing and can cause reconciliation bugs;
change the map callback to use the existing unique identifier (`criterionId`) as
the key (e.g., key={c.criterionId}) and replace the any with the proper type for
the item (use the CriteriaScore type/interface from the surrounding types or
props) in the map signature (e.g., (c: CriteriaScore, idx: number) => ...) and
optionally guard/fallback if criterionId can be missing.
🧹 Nitpick comments (3)
components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx (3)

84-107: Extract duplicate initialScores normalization into a helper.

The normalization of initialScores into JudgeScore[] is duplicated verbatim in the success-fallback path (Lines 87–92) and the catch-fallback path (Lines 100–105). Extract it to a small helper to keep the effect body DRY.

♻️ Proposed refactor

Define once above or inside the effect:

+ const normalizeInitial = (
+   initial: NonNullable<typeof initialScores>
+ ): JudgeScore[] =>
+   initial.map(s => ({
+     judgeId: s.judgeId,
+     judgeName: s.judgeName,
+     totalScore: s.score,
+     score: s.score,
+   }));

Then replace both blocks:

        } else if (initialScores) {
-          const normalizedScores: JudgeScore[] = initialScores.map(s => ({
-            judgeId: s.judgeId,
-            judgeName: s.judgeName,
-            totalScore: s.score,
-            score: s.score,
-          }));
-          setScores(normalizedScores);
+          setScores(normalizeInitial(initialScores));
        }
      } catch (err) {
        console.error('Failed to fetch individual scores:', err);
        if (initialScores) {
-          const normalizedScores: JudgeScore[] = initialScores.map(s => ({
-            judgeId: s.judgeId,
-            judgeName: s.judgeName,
-            totalScore: s.score,
-            score: s.score,
-          }));
-          setScores(normalizedScores);
+          setScores(normalizeInitial(initialScores));
        }

68-82: Use the imported IndividualJudgeScore type instead of any.

IndividualJudgeScore is imported at Line 6 but never used — the mapping at Line 68 casts item to any, losing all type safety on the API response shape. The same applies to c: any at Line 75. Using the real types lets the compiler catch field renames or shape drift.

♻️ Proposed fix
-          const mappedScores: JudgeScore[] = res.data.map((item: any) => ({
+          const mappedScores: JudgeScore[] = res.data.map((item: IndividualJudgeScore) => ({
             judgeId: item.judgeId,
             judgeName: item.judgeName,
             totalScore:
               item.totalScore ??
-              item.criteriaScores?.reduce(
-                (sum: number, c: any) => sum + (c.score || 0),
+              item.criteriaScores?.reduce(
+                (sum, c) => sum + (c.score || 0),
                 0
               ) ??
               0,

If IndividualJudgeScore doesn't have a totalScore field, that's a signal the mapping logic needs adjustment rather than being papered over with any.


117-122: Event handler naming: prefer handle prefix.

Per the project's coding guidelines, event handlers should start with handle (e.g., handleToggleExpand). toggleExpand reads more like a utility than a handler.

As per coding guidelines, "Event handlers should start with 'handle' prefix (e.g., handleClick, handleSubmit)".

Comment on lines 268 to 276
<div className='h-1.5 w-full overflow-hidden rounded-full bg-gray-800'>
<div
className={cn(
'h-full transition-all',
getScoreColor(c.score)
)}
style={{ width: `${c.score * 10}%` }}
/>
</div>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Progress bar width assumes a 0–10 scoring scale with no clamp.

c.score * 10 produces a percentage, so a score of 12 would yield 120%. The parent's overflow-hidden clips the visual overflow, but the bar silently becomes "full" for any score above 10, hiding real data. Clamp or normalise to make intent explicit and future-proof against different max scores.

🔧 Proposed fix
-                                   style={{ width: `${c.score * 10}%` }}
+                                   style={{ width: `${Math.min(c.score * 10, 100)}%` }}

Ideally the max score would come from criteria metadata rather than being hard-coded to 10.

🤖 Prompt for AI Agents
In
`@components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx`
around lines 268 - 276, The progress-bar width in IndividualScoresBreakdown uses
`c.score * 10` which assumes a 0–10 scale and lets values >10 produce >100%
widths; change the calculation to normalise and clamp the score against a max
(preferably criteria metadata, otherwise a default like 10) before computing
percentage, e.g. compute a maxScore (from criteria metadata or default 10),
clamp c.score to [0, maxScore] and set width = (clampedScore / maxScore) * 100%;
update the JSX where `style={{ width: `${c.score * 10}%` }}` is set and ensure
`getScoreColor(c.score)` either receives the clamped/normalized value or is
adapted accordingly.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx`:
- Around line 84-107: Extract the duplicated initialScores normalization into a
helper function (e.g., normalizeInitialScores) and use it in both branches;
specifically, create a function above the effect that accepts initialScores and
returns JudgeScore[] by mapping each s to { judgeId: s.judgeId, judgeName:
s.judgeName, totalScore: s.score, score: s.score }, then replace the two inline
map blocks in the effect with setScores(normalizeInitialScores(initialScores)).
Ensure the helper is used in both the successful-else branch and the catch
fallback so setScores is only called with the normalized result.
🧹 Nitpick comments (4)
components/organization/cards/JudgingParticipant/IndividualScoresBreakdown.tsx (4)

28-40: Local JudgeScore shadows the API-layer type of the same name.

lib/api/hackathons/judging.ts (and lib/api/hackathons.ts) both export a JudgeScore interface with a completely different shape (nested judge object, weightedScore, scores: CriterionScore[], etc.). Naming the local interface identically will confuse anyone navigating between these files. Consider renaming to something like MappedJudgeScore or JudgeScoreSummary.


68-82: any types in the mapping callback defeat the purpose of the local JudgeScore interface.

item: any (Line 68) and c: any (Line 75) drop all type safety. Since the API returns IndividualJudgeScore[] (already imported), use that as the parameter type — or type res.data explicitly — so the compiler catches field-name mismatches.

♻️ Suggested fix
-          const mappedScores: JudgeScore[] = res.data.map((item: any) => ({
+          const mappedScores: JudgeScore[] = res.data.map((item: IndividualJudgeScore) => ({
             judgeId: item.judgeId,
             judgeName: item.judgeName,
             totalScore:
               item.totalScore ??
               item.criteriaScores?.reduce(
-                (sum: number, c: any) => sum + (c.score || 0),
+                (sum: number, c: { score?: number }) => sum + (c.score || 0),
                 0
               ) ??
               0,

117-122: Rename toggleExpandhandleToggleExpand to match the naming convention.

♻️ Suggested fix
- const toggleExpand = (judgeId: string) => {
+ const handleToggleExpand = (judgeId: string) => {

And update the call site on Line 195:

- onClick={() => toggleExpand(score.judgeId)}
+ onClick={() => handleToggleExpand(score.judgeId)}

As per coding guidelines, "Event handlers should start with 'handle' prefix (e.g., handleClick, handleSubmit)".


224-228: Defensive score display with fallback chain — minor note.

The typeof score.totalScore === 'number' guard is redundant given that JudgeScore.totalScore is typed as number (not optional). It's harmless but adds cognitive noise; if the type is trusted, score.totalScore.toFixed(1) suffices.

@Benjtalkshow Benjtalkshow merged commit 45ba02d into boundlessfi:main Feb 16, 2026
5 of 8 checks passed
Benjtalkshow added a commit that referenced this pull request Feb 19, 2026
* Judging dashboard (#382)

* fix: modify api.ts

* fix: remove google auth buttom

* fix: fixes responsive fixes on organization

* fix: minor fixes

* fix: modify create organization

* fix: modify create organization

* fix: fix organization permission

* fix: merge into main

* feat: hackathon overview page

* feat: hackathon overview page

* feat: implement participant overview

* feat: implement participant overview

* feat: implement resources tab

* feat: implement the submission tab

* feat: implement comment tab

* fix: implement provider for hackathon

* fix: implement provider for hackathon

* fix: minor fixes

* fix: hackathon banner

* fix: hackathon banner

* fix: fix organization page

* fix: fix organization page

* fix: use transform

* fix: add tagline

* fix: add tagline

* fix: minor fixes

* fix: minor fixes

* fix: fix timeline and prizes

* fix: correct timeline events

* fix: implement registration deadline policy

* fix: implement registration deadline policy

* feat: implement leave hackathon

* feat: implement leave hackathon

* fix: delete hackathon

* fix: implement invite participants

* fix: implement participant profile viewing

* feat: fetch participants team

* fix: redesign hackathon banner

* fix: fix hackthon card

* fix: fix search bar in blog page

* fix: fix search bar in blog page

* fix: fix search bar in blog page

* fix: fix error in fetching team posts

* feat: implement create team, get my team

* feat: implement create team, get my team

* feat: implement hackathon project submission flow

* feat: implement voting for submission

* fix: team formation updates

* fix: implement team invitation

* feat: hackathon submissions bulk actions, ranking and ui refinements

* fix: implement empty state for hackathons page

* feat: Implement  submission visibility and explore submissions

* feat: Implement winners tab for hackathon winners display

* feat: implement hackathon analytics

* fix: fix coderabbit corrections

* fix: fix coderabbit corrections

* fix: fix coderabbit corrections

* fix: fix organization settings data persistence, hackathondrafts and population

* feat: fix user profile

* feat: Implemented the participant-facing and hackathon organizers announcement features

* feat: Implement judging dashboard and detailed breakdowns

* feat: Implement judging dashboard and detailed breakdowns

* fix: fix coderabbit corrections

* Refactor/updated the timeline tab (#383)

* feat: enhance hackathon timeline management and publishing flow

- Updated HackathonPublishedModal to utilize new publish response structure.
- Refactored TimelineSection to display additional timeline details including judging start/end and winner announcement dates.
- Introduced DateTimeInput component for better date and time selection.
- Added FieldLabel component for improved form labeling with tooltips.
- Created timelineConstants for standardized tooltips and timezone options.
- Modified timelineSchema to include new fields for judging start, end, and winner announcement dates with validation.
- Enhanced TimelineSettingsTab to support new timeline fields and improved user experience with time inputs.
- Updated use-hackathon-publish hook to handle new publish response format and manage state accordingly.
- Adjusted use-hackathons hook to ensure proper handling of publish responses.
- Updated API interfaces and utility functions to accommodate new timeline structure.
- Improved validation logic for hackathon steps to ensure all necessary dates are set correctly.
- Enhanced timeline calculation logic to reflect new judging and announcement phases.

* chore: update markdown-it to version 14.1.1 and remove framer-motion dependency

* refactor: clean up ReviewTab and HackathonPublishedModal components, improve DateTimeInput logic, and update timeline constants

* refactor: update timeline calculation logic to ensure phases are only created with non-zero duration and add endDate to HackathonTimeline interface

* Judging dashboard (#384)

* fix: modify api.ts

* fix: remove google auth buttom

* fix: fixes responsive fixes on organization

* fix: minor fixes

* fix: modify create organization

* fix: modify create organization

* fix: fix organization permission

* fix: merge into main

* feat: hackathon overview page

* feat: hackathon overview page

* feat: implement participant overview

* feat: implement participant overview

* feat: implement resources tab

* feat: implement the submission tab

* feat: implement comment tab

* fix: implement provider for hackathon

* fix: implement provider for hackathon

* fix: minor fixes

* fix: hackathon banner

* fix: hackathon banner

* fix: fix organization page

* fix: fix organization page

* fix: use transform

* fix: add tagline

* fix: add tagline

* fix: minor fixes

* fix: minor fixes

* fix: fix timeline and prizes

* fix: correct timeline events

* fix: implement registration deadline policy

* fix: implement registration deadline policy

* feat: implement leave hackathon

* feat: implement leave hackathon

* fix: delete hackathon

* fix: implement invite participants

* fix: implement participant profile viewing

* feat: fetch participants team

* fix: redesign hackathon banner

* fix: fix hackthon card

* fix: fix search bar in blog page

* fix: fix search bar in blog page

* fix: fix search bar in blog page

* fix: fix error in fetching team posts

* feat: implement create team, get my team

* feat: implement create team, get my team

* feat: implement hackathon project submission flow

* feat: implement voting for submission

* fix: team formation updates

* fix: implement team invitation

* feat: hackathon submissions bulk actions, ranking and ui refinements

* fix: implement empty state for hackathons page

* feat: Implement  submission visibility and explore submissions

* feat: Implement winners tab for hackathon winners display

* feat: implement hackathon analytics

* fix: fix coderabbit corrections

* fix: fix coderabbit corrections

* fix: fix coderabbit corrections

* fix: fix organization settings data persistence, hackathondrafts and population

* feat: fix user profile

* feat: Implemented the participant-facing and hackathon organizers announcement features

* feat: Implement judging dashboard and detailed breakdowns

* feat: Implement judging dashboard and detailed breakdowns

* fix: fix coderabbit corrections

* fix: submission management ux refinements

* fix: submission management ux refinements

* fix: submission management ux refinements

* fix: submission management ux refinements

* fix: submission management ux refinements

* feat: implement organizer override functionality for judging scores a… (#385)

* feat: implement organizer override functionality for judging scores and enhance judging UI

* fix: update response handling in score submission and enhance submissions list styling

* fix: update eslint dependencies to latest versions for improved linting

* fix: update ajv and json-schema-traverse dependencies in package-lock.json

* fix: update

* fix: update security audit level to high in pre-push checks

* fix: update eslint dependencies and ensure security audit fails on error

---------

Co-authored-by: Collins Ikechukwu <collinschristroa@gmail.com>
0xdevcollins added a commit that referenced this pull request Feb 21, 2026
* Judging dashboard (#382)

* fix: modify api.ts

* fix: remove google auth buttom

* fix: fixes responsive fixes on organization

* fix: minor fixes

* fix: modify create organization

* fix: modify create organization

* fix: fix organization permission

* fix: merge into main

* feat: hackathon overview page

* feat: hackathon overview page

* feat: implement participant overview

* feat: implement participant overview

* feat: implement resources tab

* feat: implement the submission tab

* feat: implement comment tab

* fix: implement provider for hackathon

* fix: implement provider for hackathon

* fix: minor fixes

* fix: hackathon banner

* fix: hackathon banner

* fix: fix organization page

* fix: fix organization page

* fix: use transform

* fix: add tagline

* fix: add tagline

* fix: minor fixes

* fix: minor fixes

* fix: fix timeline and prizes

* fix: correct timeline events

* fix: implement registration deadline policy

* fix: implement registration deadline policy

* feat: implement leave hackathon

* feat: implement leave hackathon

* fix: delete hackathon

* fix: implement invite participants

* fix: implement participant profile viewing

* feat: fetch participants team

* fix: redesign hackathon banner

* fix: fix hackthon card

* fix: fix search bar in blog page

* fix: fix search bar in blog page

* fix: fix search bar in blog page

* fix: fix error in fetching team posts

* feat: implement create team, get my team

* feat: implement create team, get my team

* feat: implement hackathon project submission flow

* feat: implement voting for submission

* fix: team formation updates

* fix: implement team invitation

* feat: hackathon submissions bulk actions, ranking and ui refinements

* fix: implement empty state for hackathons page

* feat: Implement  submission visibility and explore submissions

* feat: Implement winners tab for hackathon winners display

* feat: implement hackathon analytics

* fix: fix coderabbit corrections

* fix: fix coderabbit corrections

* fix: fix coderabbit corrections

* fix: fix organization settings data persistence, hackathondrafts and population

* feat: fix user profile

* feat: Implemented the participant-facing and hackathon organizers announcement features

* feat: Implement judging dashboard and detailed breakdowns

* feat: Implement judging dashboard and detailed breakdowns

* fix: fix coderabbit corrections

* Refactor/updated the timeline tab (#383)

* feat: enhance hackathon timeline management and publishing flow

- Updated HackathonPublishedModal to utilize new publish response structure.
- Refactored TimelineSection to display additional timeline details including judging start/end and winner announcement dates.
- Introduced DateTimeInput component for better date and time selection.
- Added FieldLabel component for improved form labeling with tooltips.
- Created timelineConstants for standardized tooltips and timezone options.
- Modified timelineSchema to include new fields for judging start, end, and winner announcement dates with validation.
- Enhanced TimelineSettingsTab to support new timeline fields and improved user experience with time inputs.
- Updated use-hackathon-publish hook to handle new publish response format and manage state accordingly.
- Adjusted use-hackathons hook to ensure proper handling of publish responses.
- Updated API interfaces and utility functions to accommodate new timeline structure.
- Improved validation logic for hackathon steps to ensure all necessary dates are set correctly.
- Enhanced timeline calculation logic to reflect new judging and announcement phases.

* chore: update markdown-it to version 14.1.1 and remove framer-motion dependency

* refactor: clean up ReviewTab and HackathonPublishedModal components, improve DateTimeInput logic, and update timeline constants

* refactor: update timeline calculation logic to ensure phases are only created with non-zero duration and add endDate to HackathonTimeline interface

* Judging dashboard (#384)

* fix: modify api.ts

* fix: remove google auth buttom

* fix: fixes responsive fixes on organization

* fix: minor fixes

* fix: modify create organization

* fix: modify create organization

* fix: fix organization permission

* fix: merge into main

* feat: hackathon overview page

* feat: hackathon overview page

* feat: implement participant overview

* feat: implement participant overview

* feat: implement resources tab

* feat: implement the submission tab

* feat: implement comment tab

* fix: implement provider for hackathon

* fix: implement provider for hackathon

* fix: minor fixes

* fix: hackathon banner

* fix: hackathon banner

* fix: fix organization page

* fix: fix organization page

* fix: use transform

* fix: add tagline

* fix: add tagline

* fix: minor fixes

* fix: minor fixes

* fix: fix timeline and prizes

* fix: correct timeline events

* fix: implement registration deadline policy

* fix: implement registration deadline policy

* feat: implement leave hackathon

* feat: implement leave hackathon

* fix: delete hackathon

* fix: implement invite participants

* fix: implement participant profile viewing

* feat: fetch participants team

* fix: redesign hackathon banner

* fix: fix hackthon card

* fix: fix search bar in blog page

* fix: fix search bar in blog page

* fix: fix search bar in blog page

* fix: fix error in fetching team posts

* feat: implement create team, get my team

* feat: implement create team, get my team

* feat: implement hackathon project submission flow

* feat: implement voting for submission

* fix: team formation updates

* fix: implement team invitation

* feat: hackathon submissions bulk actions, ranking and ui refinements

* fix: implement empty state for hackathons page

* feat: Implement  submission visibility and explore submissions

* feat: Implement winners tab for hackathon winners display

* feat: implement hackathon analytics

* fix: fix coderabbit corrections

* fix: fix coderabbit corrections

* fix: fix coderabbit corrections

* fix: fix organization settings data persistence, hackathondrafts and population

* feat: fix user profile

* feat: Implemented the participant-facing and hackathon organizers announcement features

* feat: Implement judging dashboard and detailed breakdowns

* feat: Implement judging dashboard and detailed breakdowns

* fix: fix coderabbit corrections

* fix: submission management ux refinements

* fix: submission management ux refinements

* fix: submission management ux refinements

* fix: submission management ux refinements

* fix: submission management ux refinements

* feat: implement organizer override functionality for judging scores a… (#385)

* feat: implement organizer override functionality for judging scores and enhance judging UI

* fix: update response handling in score submission and enhance submissions list styling

* fix: update eslint dependencies to latest versions for improved linting

* fix: update ajv and json-schema-traverse dependencies in package-lock.json

* fix: update

* fix: update security audit level to high in pre-push checks

* fix: update eslint dependencies and ensure security audit fails on error

* refactor: Dynamically determine Stellar network and centralize wallet utility functions, including explorer URLs and API key handling.

---------

Co-authored-by: Nnaji Benjamin <60315147+Benjtalkshow@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant