From f36f68bbf9997cd4b2d179208484b458a073fd44 Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 24 Apr 2026 14:39:43 +0200 Subject: [PATCH] fix: don't mark next round as current before advancement is declared MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The applicant timeline sidebar was treating any previous round with status ROUND_CLOSED as "advanced past", which caused the Grand Finale to show "You are here" as soon as the semi-final round closed — before admins declared which teams actually advanced. Require explicit PASSED/COMPLETED project state on every prior round before marking the next one as current. A closed-but-unresolved round now correctly keeps the applicant anchored to it. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/components/applicant/competition-timeline.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/applicant/competition-timeline.tsx b/src/components/applicant/competition-timeline.tsx index a5273e6..4ab5e34 100644 --- a/src/components/applicant/competition-timeline.tsx +++ b/src/components/applicant/competition-timeline.tsx @@ -202,15 +202,16 @@ export function CompetitionTimelineSidebar() { // Is this entry after the elimination point? const isAfterElimination = eliminationIndex >= 0 && index > eliminationIndex - // Is this the current round? Either has an active project state, - // or is the first round the project hasn't passed yet (for seed data - // where project states may be missing). + // Is this the current round? Either the project has an active state + // here, or every previous round has an explicit advancement outcome + // (PASSED/COMPLETED). A closed round alone isn't enough — a round can + // close before admins declare advancement, and until they do, the + // applicant has NOT moved on to the next round. const hasActiveProjectState = !!entry.projectState && entry.projectState !== 'PASSED' && entry.projectState !== 'COMPLETED' && entry.projectState !== 'REJECTED' const isCurrent = !isAfterElimination && (hasActiveProjectState || ( !isPassed && !isRejected && !isCompleted && data.entries.slice(0, index).every((prev) => - prev.projectState === 'PASSED' || prev.projectState === 'COMPLETED' || - prev.status === 'ROUND_CLOSED' || prev.status === 'ROUND_ARCHIVED' + prev.projectState === 'PASSED' || prev.projectState === 'COMPLETED' ) && index > 0 ))