'use client' import { Suspense, use } from 'react' import Link from 'next/link' import { useRouter } from 'next/navigation' import { trpc } from '@/lib/trpc/client' import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { Skeleton } from '@/components/ui/skeleton' import { Progress } from '@/components/ui/progress' import { Separator } from '@/components/ui/separator' import { ArrowLeft, Edit, Users, FileText, Calendar, CheckCircle2, Clock, AlertCircle, Archive, Play, Pause, BarChart3, Upload, } from 'lucide-react' import { format, formatDistanceToNow, isPast, isFuture } from 'date-fns' interface PageProps { params: Promise<{ id: string }> } function RoundDetailContent({ roundId }: { roundId: string }) { const router = useRouter() const { data: round, isLoading } = trpc.round.get.useQuery({ id: roundId }) const { data: progress } = trpc.round.getProgress.useQuery({ id: roundId }) const utils = trpc.useUtils() const updateStatus = trpc.round.updateStatus.useMutation({ onSuccess: () => { utils.round.get.invalidate({ id: roundId }) }, }) if (isLoading) { return } if (!round) { return (

Round Not Found

) } const now = new Date() const isVotingOpen = round.status === 'ACTIVE' && round.votingStartAt && round.votingEndAt && new Date(round.votingStartAt) <= now && new Date(round.votingEndAt) >= now const getStatusBadge = () => { if (round.status === 'ACTIVE' && isVotingOpen) { return ( Voting Open ) } switch (round.status) { case 'DRAFT': return Draft case 'ACTIVE': return ( Active ) case 'CLOSED': return Closed case 'ARCHIVED': return ( Archived ) default: return {round.status} } } return (
{/* Header */}
{round.program.name}

{round.name}

{getStatusBadge()}
{round.status === 'DRAFT' && ( )} {round.status === 'ACTIVE' && ( )}
{/* Stats Grid */}
Projects
{round._count.projects}
Assignments
{round._count.assignments}
Required Reviews
{round.requiredReviews}

per project

Completion
{progress?.completionPercentage || 0}%

{progress?.completedAssignments || 0} of {progress?.totalAssignments || 0}

{/* Progress */} {progress && progress.totalAssignments > 0 && ( Evaluation Progress
Overall Completion {progress.completionPercentage}%
{Object.entries(progress.evaluationsByStatus).map(([status, count]) => (

{count}

{status.toLowerCase().replace('_', ' ')}

))}
)} {/* Voting Window */} Voting Window

Start Date

{round.votingStartAt ? (

{format(new Date(round.votingStartAt), 'PPP')}

{format(new Date(round.votingStartAt), 'p')}

) : (

Not set

)}

End Date

{round.votingEndAt ? (

{format(new Date(round.votingEndAt), 'PPP')}

{format(new Date(round.votingEndAt), 'p')}

{isFuture(new Date(round.votingEndAt)) && (

Ends {formatDistanceToNow(new Date(round.votingEndAt), { addSuffix: true })}

)}
) : (

Not set

)}
{/* Voting status */} {round.votingStartAt && round.votingEndAt && (
{isVotingOpen ? (
Voting is currently open
) : isFuture(new Date(round.votingStartAt)) ? (
Voting opens {formatDistanceToNow(new Date(round.votingStartAt), { addSuffix: true })}
) : (
Voting period has ended
)}
)}
{/* Quick Actions */} Quick Actions
) } function RoundDetailSkeleton() { return (
{[1, 2, 3, 4].map((i) => ( ))}
) } export default function RoundDetailPage({ params }: PageProps) { const { id } = use(params) return ( }> ) }