Add observer project detail page with files, evaluations & reviews
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m59s

New page at /observer/projects/[projectId] showing project info,
documents grouped by round requirements, and jury evaluations with
click-through to full review details. Dashboard table rows now link
to project detail. Also cleans up redundant programName prefixes
and fixes chart edge cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt
2026-02-20 18:39:53 +01:00
parent f1062f4805
commit 03c59c188e
9 changed files with 1236 additions and 57 deletions

View File

@@ -657,7 +657,7 @@ function CrossStageTab() {
className="cursor-pointer text-sm py-1.5 px-3"
onClick={() => toggleRound(stage.id)}
>
{stage.programName} - {stage.name}
{stage.name}
</Badge>
)
})}
@@ -740,7 +740,7 @@ function JurorConsistencyTab() {
))}
{stages.map((stage) => (
<SelectItem key={stage.id} value={stage.id}>
{stage.programName} - {stage.name}
{stage.name}
</SelectItem>
))}
</SelectContent>
@@ -814,7 +814,7 @@ function DiversityTab() {
))}
{stages.map((stage) => (
<SelectItem key={stage.id} value={stage.id}>
{stage.programName} - {stage.name}
{stage.name}
</SelectItem>
))}
</SelectContent>
@@ -992,7 +992,7 @@ export default function ReportsPage() {
<SelectContent>
{pdfStages.map((stage) => (
<SelectItem key={stage.id} value={stage.id}>
{stage.programName} - {stage.name}
{stage.name}
</SelectItem>
))}
</SelectContent>

View File

@@ -0,0 +1,15 @@
import type { Metadata } from 'next'
import { ObserverProjectDetail } from '@/components/observer/observer-project-detail'
export const metadata: Metadata = { title: 'Project Detail' }
export const dynamic = 'force-dynamic'
export default async function ObserverProjectDetailPage({
params,
}: {
params: Promise<{ projectId: string }>
}) {
const { projectId } = await params
return <ObserverProjectDetail projectId={projectId} />
}

View File

@@ -508,9 +508,9 @@ function CrossStageTab() {
size="sm"
pressed={selectedRoundIds.includes(stage.id)}
onPressedChange={() => toggleRound(stage.id)}
aria-label={`${stage.programName} - ${stage.name}`}
aria-label={stage.name}
>
{stage.programName} - {stage.name}
{stage.name}
</Toggle>
))}
</div>
@@ -644,7 +644,7 @@ export default function ObserverReportsPage() {
))}
{stages.map((stage) => (
<SelectItem key={stage.id} value={stage.id}>
{stage.programName} - {stage.name}{stage.roundType ? ` (${ROUND_TYPE_LABELS[stage.roundType] || stage.roundType})` : ''}
{stage.name}{stage.roundType ? ` (${ROUND_TYPE_LABELS[stage.roundType] || stage.roundType})` : ''}
</SelectItem>
))}
</SelectContent>