Admin UI audit round 2: fix 28 display bugs across 23 files
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m51s
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m51s
HIGH fixes (broken features / wrong data): - H1: Fix roundAssignments → projectRoundStates in project router (7 occurrences) - H2: Fix deliberation results panel blank table (wrong field names) - H3: Fix deliberation participant names blank (wrong data path) - H4: Fix awards "Evaluated" stat duplicating "Eligible" count - H5: Fix cross-round comparison enabled at 1 round (backend requires 2) - H6: Fix setState during render anti-pattern (6 occurrences) - H7: Fix round detail jury member count always showing 0 - H8: Remove 4 invalid status values from observer dashboard filter - H9: Fix filtering progress bar always showing 100% MEDIUM fixes (misleading display): - M1: Filter special-award rounds from competition timeline - M2: Exclude special-award rounds from distinct project count - M3: Fix MENTORING pipeline node hardcoded "0 mentored" - M4: Fix DELIB_LOCKED badge using red for success state - M5: Add status label maps to deliberation session detail - M6: Humanize deliberation category + tie-break method displays - M8: Rename setStageId → setRoundId, "Select Stage" → "Select Round" - M9: Add missing INVITED/ACTIVE/SUSPENDED to members status labels - M10: Add ROUND_DRAFT/ACTIVE/CLOSED/ARCHIVED to StatusBadge - M11: Fix unsent messages showing "Scheduled" instead of "Draft" - M12: Rename misleading totalEvaluations → totalAssignments - M13: Rename "Stage" column to "Program" in projects page LOW fixes (cosmetic / edge-case): - L1: Use unfiltered rounds array for active round detection - L2: Use all rounds length for new round sort order - L3: Filter special-award rounds from header count - L4: Fix single-underscore replace in award status badges - L5: Fix score bucket boundary gaps (4.99 dropped between buckets) - L6: Title-case LIVE_FINAL pipeline metric status - L7: Fix roundType.replace only replacing first underscore - L8: Remove duplicate severity sort in smart-actions component Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { trpc } from '@/lib/trpc/client'
|
||||
import {
|
||||
@@ -71,9 +71,11 @@ function ReportsOverview() {
|
||||
// Project reporting scope (default: latest program, all rounds)
|
||||
const [selectedValue, setSelectedValue] = useState<string | null>(null)
|
||||
|
||||
if (programs?.length && !selectedValue) {
|
||||
setSelectedValue(`all:${programs[0].id}`)
|
||||
}
|
||||
useEffect(() => {
|
||||
if (programs?.length && !selectedValue) {
|
||||
setSelectedValue(`all:${programs[0].id}`)
|
||||
}
|
||||
}, [programs, selectedValue])
|
||||
|
||||
const scopeInput = parseSelection(selectedValue)
|
||||
const hasScope = !!scopeInput.roundId || !!scopeInput.programId
|
||||
@@ -109,7 +111,7 @@ function ReportsOverview() {
|
||||
const activeRounds = dashStats?.activeRoundCount ?? rounds.filter((r: { status: string }) => r.status === 'ROUND_ACTIVE').length
|
||||
const jurorCount = dashStats?.jurorCount ?? 0
|
||||
const submittedEvaluations = dashStats?.submittedEvaluations ?? 0
|
||||
const totalEvaluations = dashStats?.totalEvaluations ?? 0
|
||||
const totalAssignments = dashStats?.totalAssignments ?? 0
|
||||
const completionRate = dashStats?.completionRate ?? 0
|
||||
|
||||
return (
|
||||
@@ -177,7 +179,7 @@ function ReportsOverview() {
|
||||
<p className="text-sm font-medium text-muted-foreground">Evaluations</p>
|
||||
<p className="text-2xl font-bold mt-1">{submittedEvaluations}</p>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
{totalEvaluations > 0
|
||||
{totalAssignments > 0
|
||||
? `${completionRate}% completion rate`
|
||||
: 'No assignments yet'}
|
||||
</p>
|
||||
@@ -417,9 +419,11 @@ function StageAnalytics() {
|
||||
) || []
|
||||
|
||||
// Set default selected stage
|
||||
if (rounds.length && !selectedValue) {
|
||||
setSelectedValue(rounds[0].id)
|
||||
}
|
||||
useEffect(() => {
|
||||
if (rounds.length && !selectedValue) {
|
||||
setSelectedValue(rounds[0].id)
|
||||
}
|
||||
}, [rounds.length, selectedValue])
|
||||
|
||||
const queryInput = parseSelection(selectedValue)
|
||||
const hasSelection = !!queryInput.roundId || !!queryInput.programId
|
||||
@@ -701,9 +705,11 @@ function JurorConsistencyTab() {
|
||||
((p.stages ?? []) as Array<{ id: string; name: string }>).map((s: { id: string; name: string }) => ({ id: s.id, name: s.name, programId: p.id, programName: `${p.year} Edition` }))
|
||||
) || []
|
||||
|
||||
if (stages.length && !selectedValue) {
|
||||
setSelectedValue(stages[0].id)
|
||||
}
|
||||
useEffect(() => {
|
||||
if (stages.length && !selectedValue) {
|
||||
setSelectedValue(stages[0].id)
|
||||
}
|
||||
}, [stages.length, selectedValue])
|
||||
|
||||
const queryInput = parseSelection(selectedValue)
|
||||
const hasSelection = !!queryInput.roundId || !!queryInput.programId
|
||||
@@ -773,9 +779,11 @@ function DiversityTab() {
|
||||
((p.stages ?? []) as Array<{ id: string; name: string }>).map((s: { id: string; name: string }) => ({ id: s.id, name: s.name, programId: p.id, programName: `${p.year} Edition` }))
|
||||
) || []
|
||||
|
||||
if (stages.length && !selectedValue) {
|
||||
setSelectedValue(stages[0].id)
|
||||
}
|
||||
useEffect(() => {
|
||||
if (stages.length && !selectedValue) {
|
||||
setSelectedValue(stages[0].id)
|
||||
}
|
||||
}, [stages.length, selectedValue])
|
||||
|
||||
const queryInput = parseSelection(selectedValue)
|
||||
const hasSelection = !!queryInput.roundId || !!queryInput.programId
|
||||
@@ -846,7 +854,7 @@ function RoundPipelineTab() {
|
||||
const { data: comparison, isLoading: comparisonLoading } =
|
||||
trpc.analytics.getCrossRoundComparison.useQuery(
|
||||
{ roundIds },
|
||||
{ enabled: roundIds.length >= 1 }
|
||||
{ enabled: roundIds.length >= 2 }
|
||||
)
|
||||
|
||||
if (isLoading || comparisonLoading) {
|
||||
@@ -929,9 +937,11 @@ export default function ReportsPage() {
|
||||
((p.stages ?? []) as Array<{ id: string; name: string }>).map((s: { id: string; name: string }) => ({ id: s.id, name: s.name, programName: `${p.year} Edition` }))
|
||||
) || []
|
||||
|
||||
if (pdfStages.length && !pdfStageId) {
|
||||
setPdfStageId(pdfStages[0].id)
|
||||
}
|
||||
useEffect(() => {
|
||||
if (pdfStages.length && !pdfStageId) {
|
||||
setPdfStageId(pdfStages[0].id)
|
||||
}
|
||||
}, [pdfStages.length, pdfStageId])
|
||||
|
||||
const selectedPdfStage = pdfStages.find((r) => r.id === pdfStageId)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user