-
Notifications
You must be signed in to change notification settings - Fork 77
Open
Labels
Beta-Campaigndifficulty: mediumenhancementNew feature or requestNew feature or requestfrontendgood first issueGood for newcomersGood for newcomershelp wantedExtra attention is neededExtra attention is needed
Description
Judging Timeline Enforcement
Objective
Enforce the active judging window by disabling all scoring interactions outside of the defined judgingStart–judgingEnd period, so judges can never accidentally submit or modify scores when the phase is closed. This closes a critical gap where the judging UI remains fully interactive regardless of whether the judging phase is actually open, creating the risk of out-of-window score submissions that could compromise the integrity of hackathon results.
Technical Implementation
Target Route
app/organization/[id]/hackathons/[hackathonId]/judging
Target Components
JudgingResultsTable.tsxJudgingCriteriaList.tsx
Hook — useHackathonStatus()
- Use
useHackathonStatus()as the single source of truth for all timeline-based evaluations - Extend this hook if needed to derive and return an
isJudgingActiveboolean — computed from whetherDate.now()falls within thejudgingStartandjudgingEndwindow - The boolean should be reactive — components consuming it must automatically reflect state changes as time progresses, without requiring a manual refresh or page reload
- Centralizing this logic in the hook prevents duplicated
Date.now()comparisons scattered acrossJudgingResultsTableandJudgingCriteriaList
Enforcement Logic
- In both
JudgingResultsTable.tsxandJudgingCriteriaList.tsx, wrap all scoring inputs and the "Grade" button in a conditional check againstisJudgingActive - If
isJudgingActiveisfalse, all scoring interactions must be disabled — not hidden, but explicitly non-interactive so judges understand the inputs exist but are currently locked - The disable state must be applied at the component level using the
disabledprop on inputs and buttons so the browser enforces non-interactivity natively - Any submission or save action tied to scoring must also be blocked at the function level as a secondary guard, in case a disabled input is bypassed via devtools
Alert — Alert Component
- Render the
Alertcomponent from@/components/ui/alertat the top of the judging dashboard wheneverisJudgingActiveisfalse - The alert must clearly communicate one of two states:
- The judging phase has not yet started — optionally surfacing when it will begin
- The judging phase has already ended — optionally surfacing when it closed
- The alert must be non-dismissible while the window is closed — judges must not be able to hide it and forget that scoring is unavailable
- When
isJudgingActiveistrue, the alert must not be rendered at all — its absence implicitly confirms that scoring is open
Logic & Enforcement
- The time comparison must account for timezone consistency — ensure both
Date.now()and thejudgingStart/judgingEndvalues are evaluated in the same timezone context to avoid off-by-one errors around window boundaries - The enforcement must be reactive — if a judge has the dashboard open as the judging window opens or closes, the UI should reflect the new state without requiring a page refresh
⚠️ Caution
This is a production environment — not a sandbox.
- Code must be performant, accessible, and clean
- No dummy data — all enforcement logic must operate on real
judgingStartandjudgingEndvalues from the hackathon data source - AI-generated code will be scrutinized; poorly structured or "hallucinated" code will result in immediate issue closure
- Follow the existing design system: shadcn/ui, Tailwind, Framer Motion
Testing & Verification
Automated Tests
npm run lint # Ensure code quality
npm run build # Verify no breaking changes in routing or typesManual Verification
- Set
judgingStartto a future timestamp — confirm all score inputs and the "Grade" button are disabled in bothJudgingResultsTableandJudgingCriteriaList, and theAlertis visible with a "not yet started" message - Set
judgingEndto a past timestamp — confirm all score inputs and the "Grade" button are disabled and theAlertis visible with a "phase ended" message - Set both timestamps to bracket the current time — confirm score inputs and the "Grade" button are enabled and the
Alertis not rendered - Leave the dashboard open across a judging window boundary — confirm the UI updates reactively via
useHackathonStatus()without a page refresh - Attempt to submit a score while the window is closed via devtools or form manipulation — confirm the action is blocked at the function level, not just the UI
- Verify the
Alertis non-dismissible and cannot be hidden while the judging window is closed - Confirm
isJudgingActiveis correctly derived inuseHackathonStatus()and both components consume it from the hook rather than computing it independently - Confirm timezone consistency — test with
judgingStart/judgingEndvalues near DST boundaries or across timezone offsets - Provide video evidence
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Beta-Campaigndifficulty: mediumenhancementNew feature or requestNew feature or requestfrontendgood first issueGood for newcomersGood for newcomershelp wantedExtra attention is neededExtra attention is needed