fix: show project title, team & country in ranking rows instead of truncated IDs
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled

Adds getProjectStates query to build a projectInfoMap lookup. Each row now
shows the project title, team name, and country. Also renames "Pass" label
to "Yes" to match the binary yes/no vote semantics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 11:08:30 +01:00
parent 28ae934c57
commit ba7f068b1e

View File

@@ -59,10 +59,17 @@ type RankingDashboardProps = {
roundId: string
}
type ProjectInfo = {
title: string
teamName: string | null
country: string | null
}
type SortableProjectRowProps = {
projectId: string
currentRank: number
entry: RankedProjectEntry | undefined
projectInfo: ProjectInfo | undefined
onSelect: () => void
isSelected: boolean
}
@@ -73,6 +80,7 @@ function SortableProjectRow({
projectId,
currentRank,
entry,
projectInfo,
onSelect,
isSelected,
}: SortableProjectRowProps) {
@@ -128,11 +136,17 @@ function SortableProjectRow({
</Badge>
)}
{/* Project identifier */}
{/* Project info */}
<div className="flex-1 min-w-0">
<p className="text-sm font-medium truncate">
Project {projectId.slice(-6)}
{projectInfo?.title ?? `Project${projectId.slice(-6)}`}
</p>
{projectInfo?.teamName && (
<p className="text-xs text-muted-foreground truncate">
{projectInfo.teamName}
{projectInfo.country ? ` · ${projectInfo.country}` : ''}
</p>
)}
</div>
{/* Stats */}
@@ -147,8 +161,8 @@ function SortableProjectRow({
Avg {entry.avgGlobalScore.toFixed(1)}
</span>
)}
<span title="Pass rate">
Pass {Math.round(entry.passRate * 100)}%
<span title="Yes/No vote rate">
Yes {Math.round(entry.passRate * 100)}%
</span>
<span title="Evaluator count">
{entry.evaluatorCount} juror{entry.evaluatorCount !== 1 ? 's' : ''}
@@ -197,6 +211,10 @@ export function RankingDashboard({ competitionId: _competitionId, roundId }: Ran
{ enabled: !!latestSnapshotId },
)
const { data: projectStates } = trpc.roundEngine.getProjectStates.useQuery(
{ roundId },
)
const { data: projectDetail, isLoading: detailLoading } = trpc.project.getFullDetail.useQuery(
{ id: selectedProjectId! },
{ enabled: !!selectedProjectId },
@@ -253,6 +271,20 @@ export function RankingDashboard({ competitionId: _competitionId, roundId }: Ran
return map
}, [snapshot])
// ─── projectInfoMap (O(1) lookup by projectId) ────────────────────────────
const projectInfoMap = useMemo(() => {
const map = new Map<string, ProjectInfo>()
if (!projectStates) return map
for (const ps of projectStates) {
map.set(ps.project.id, {
title: ps.project.title,
teamName: ps.project.teamName,
country: ps.project.country,
})
}
return map
}, [projectStates])
// ─── localOrder init (once, with useRef guard) ────────────────────────────
useEffect(() => {
if (!initialized.current && snapshot) {
@@ -448,6 +480,7 @@ export function RankingDashboard({ competitionId: _competitionId, roundId }: Ran
projectId={projectId}
currentRank={index + 1}
entry={rankingMap.get(projectId)}
projectInfo={projectInfoMap.get(projectId)}
onSelect={() => setSelectedProjectId(projectId)}
isSelected={selectedProjectId === projectId}
/>