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
You have read-only access to view platform statistics and reports.
{activeRoundCount} active round{activeRoundCount !== 1 ? 's' : ''}
Across all rounds
Active members
{completionRate.toFixed(0)}% completion rate
No rounds created yet
{round.name}
{round.program.year} Edition
{round._count.projects} projects
{round._count.assignments} assignments
No completed evaluations yet
No rounds available
{submittedInRound} of {totalAssignments} evaluations submitted
Welcome, {session?.user?.name || 'Observer'}