import type { Metadata } from 'next' import { Suspense } from 'react' import { auth } from '@/lib/auth' import { prisma } from '@/lib/prisma' export const metadata: Metadata = { title: 'Observer Dashboard' } export const dynamic = 'force-dynamic' import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Progress } from '@/components/ui/progress' import { Skeleton } from '@/components/ui/skeleton' import { FolderKanban, ClipboardList, Users, CheckCircle2, Eye, BarChart3, } from 'lucide-react' import { cn, formatDateOnly } from '@/lib/utils' async function ObserverDashboardContent() { const [ programCount, activeRoundCount, projectCount, jurorCount, evaluationStats, recentRounds, evaluationScores, ] = await Promise.all([ prisma.program.count(), prisma.round.count({ where: { status: 'ACTIVE' } }), prisma.project.count(), prisma.user.count({ where: { role: 'JURY_MEMBER', status: 'ACTIVE' } }), prisma.evaluation.groupBy({ by: ['status'], _count: true, }), prisma.round.findMany({ orderBy: { createdAt: 'desc' }, take: 5, include: { program: { select: { name: true, year: true } }, _count: { select: { projects: true, assignments: true, }, }, assignments: { select: { evaluation: { select: { status: true } }, }, }, }, }), prisma.evaluation.findMany({ where: { status: 'SUBMITTED', globalScore: { not: null } }, select: { globalScore: true }, }), ]) const submittedCount = evaluationStats.find((e) => e.status === 'SUBMITTED')?._count || 0 const draftCount = evaluationStats.find((e) => e.status === 'DRAFT')?._count || 0 const totalEvaluations = submittedCount + draftCount const completionRate = totalEvaluations > 0 ? (submittedCount / totalEvaluations) * 100 : 0 // Score distribution computation const scores = evaluationScores.map(e => e.globalScore!).filter(s => s != null) const buckets = [ { label: '9-10', min: 9, max: 10, color: 'bg-green-500' }, { label: '7-8', min: 7, max: 8.99, color: 'bg-emerald-400' }, { label: '5-6', min: 5, max: 6.99, color: 'bg-amber-400' }, { label: '3-4', min: 3, max: 4.99, color: 'bg-orange-400' }, { label: '1-2', min: 1, max: 2.99, color: 'bg-red-400' }, ] const maxCount = Math.max(...buckets.map(b => scores.filter(s => s >= b.min && s <= b.max).length), 1) const scoreDistribution = buckets.map(b => { const count = scores.filter(s => s >= b.min && s <= b.max).length return { ...b, count, percentage: (count / maxCount) * 100 } }) return ( <> {/* Observer Notice */}

Observer Mode

Read-Only

You have read-only access to view platform statistics and reports.

{/* Stats Grid */}
Programs
{programCount}

{activeRoundCount} active round{activeRoundCount !== 1 ? 's' : ''}

Projects
{projectCount}

Across all rounds

Jury Members
{jurorCount}

Active members

Evaluations
{submittedCount}

{completionRate.toFixed(0)}% completion rate

{/* Recent Rounds */} Recent Rounds Overview of the latest voting rounds {recentRounds.length === 0 ? (

No rounds created yet

) : (
{recentRounds.map((round) => (

{round.name}

{round.status}

{round.program.year} Edition

{round._count.projects} projects

{round._count.assignments} assignments

))}
)}
{/* Score Distribution */} Score Distribution Distribution of global scores across all evaluations {scoreDistribution.length === 0 ? (

No completed evaluations yet

) : (
{scoreDistribution.map((bucket) => (
{bucket.label}
{bucket.count}
))}
)} {/* Jury Completion by Round */} Jury Completion by Round Evaluation completion rate per round {recentRounds.length === 0 ? (

No rounds available

) : (
{recentRounds.map((round) => { const submittedInRound = round.assignments.filter(a => a.evaluation?.status === 'SUBMITTED').length const totalAssignments = round.assignments.length const percent = totalAssignments > 0 ? Math.round((submittedInRound / totalAssignments) * 100) : 0 return (
{round.name} {round.status}
{percent}%

{submittedInRound} of {totalAssignments} evaluations submitted

) })}
)}
) } function DashboardSkeleton() { return ( <>
{[...Array(4)].map((_, i) => ( ))}
{[...Array(3)].map((_, i) => ( ))}
) } export default async function ObserverDashboardPage() { const session = await auth() return (
{/* Header */}

Dashboard

Welcome, {session?.user?.name || 'Observer'}

{/* Content */} }>
) }