diff --git a/src/components/admin/round/ranking-dashboard.tsx b/src/components/admin/round/ranking-dashboard.tsx index fb9ec2b..f379afa 100644 --- a/src/components/admin/round/ranking-dashboard.tsx +++ b/src/components/admin/round/ranking-dashboard.tsx @@ -310,6 +310,7 @@ export function RankingDashboard({ competitionId: _competitionId, roundId }: Ran const { data: evalScores } = trpc.ranking.roundEvaluationScores.useQuery( { roundId }, + { refetchInterval: 30_000 }, ) const { data: evalForm } = trpc.evaluation.getStageForm.useQuery( @@ -464,9 +465,12 @@ export function RankingDashboard({ competitionId: _competitionId, roundId }: Ran } }, [snapshot, evalScores]) - // ─── Re-sort on toggle flip (after init) ───────────────────────────────── + // ─── Re-sort when toggle flips OR scores refetch (after init) ──────────── // Only resorts when no server-side manual reorder is pinned for the snapshot; // persisted manual reorders always win regardless of the score being used. + // The 30-second polling on roundEvaluationScores feeds this effect — when a + // juror submits a new evaluation, the next refetch picks it up, balanced/raw + // averages update, and the list re-sorts in place. useEffect(() => { if (!initialized.current || !snapshot || !evalScores) return const reorders = (snapshot.reordersJson as Array<{ @@ -502,10 +506,7 @@ export function RankingDashboard({ competitionId: _competitionId, roundId }: Ran STARTUP: sortedStartup.map((r) => r.projectId), BUSINESS_CONCEPT: sortedConcept.map((r) => r.projectId), }) - // Eslint disable: snapshot/evalScores are read but the resort should only - // run on toggle flip, not on every snapshot/scores refetch. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [useBalanced]) + }, [useBalanced, evalScores, snapshot]) // ─── numericCriteria from eval form ───────────────────────────────────── const numericCriteria = useMemo(() => {