'use client'
import { Suspense, useState } from 'react'
import Link from 'next/link'
import { trpc } from '@/lib/trpc/client'
import { toast } from 'sonner'
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 {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog'
import {
Plus,
MoreHorizontal,
Eye,
Edit,
Users,
FileText,
Calendar,
CheckCircle2,
Clock,
Archive,
Trash2,
Loader2,
} from 'lucide-react'
import { format, isPast, isFuture } from 'date-fns'
function RoundsContent() {
const { data: programs, isLoading } = trpc.program.list.useQuery({
includeRounds: true,
})
if (isLoading) {
return
}
if (!programs || programs.length === 0) {
return (
No Programs Found
Create a program first to start managing rounds
)
}
return (
{programs.map((program) => (
{program.name}
{program.year} - {program.status}
{program.rounds && program.rounds.length > 0 ? (
Round
Status
Voting Window
Projects
Assignments
Actions
{program.rounds.map((round) => (
))}
) : (
)}
))}
)
}
function RoundRow({ round }: { round: any }) {
const utils = trpc.useUtils()
const [showDeleteDialog, setShowDeleteDialog] = useState(false)
const updateStatus = trpc.round.updateStatus.useMutation({
onSuccess: () => {
utils.program.list.invalidate()
},
})
const deleteRound = trpc.round.delete.useMutation({
onSuccess: () => {
toast.success('Round deleted successfully')
utils.program.list.invalidate()
},
onError: (error) => {
toast.error(error.message || 'Failed to delete round')
},
})
const getStatusBadge = () => {
const now = new Date()
const isVotingOpen =
round.status === 'ACTIVE' &&
round.votingStartAt &&
round.votingEndAt &&
new Date(round.votingStartAt) <= now &&
new Date(round.votingEndAt) >= now
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}
}
}
const getVotingWindow = () => {
if (!round.votingStartAt || !round.votingEndAt) {
return Not set
}
const start = new Date(round.votingStartAt)
const end = new Date(round.votingEndAt)
const now = new Date()
if (isFuture(start)) {
return (
Opens {format(start, 'MMM d, yyyy')}
)
}
if (isPast(end)) {
return (
Ended {format(end, 'MMM d, yyyy')}
)
}
return (
Until {format(end, 'MMM d, yyyy')}
)
}
return (
{round.name}
{getStatusBadge()}
{getVotingWindow()}
{round._count?.projects || 0}
{round._count?.assignments || 0}
View Details
Edit Round
Manage Assignments
{round.status === 'DRAFT' && (
updateStatus.mutate({ id: round.id, status: 'ACTIVE' })
}
>
Activate Round
)}
{round.status === 'ACTIVE' && (
updateStatus.mutate({ id: round.id, status: 'CLOSED' })
}
>
Close Round
)}
{round.status === 'CLOSED' && (
updateStatus.mutate({ id: round.id, status: 'ARCHIVED' })
}
>
Archive Round
)}
setShowDeleteDialog(true)}
>
Delete Round
Delete Round
Are you sure you want to delete "{round.name}"? This will
permanently delete all {round._count?.projects || 0} projects,{' '}
{round._count?.assignments || 0} assignments, and all evaluations
in this round. This action cannot be undone.
Cancel
deleteRound.mutate({ id: round.id })}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{deleteRound.isPending ? (
) : null}
Delete
)
}
function RoundsListSkeleton() {
return (
{[1, 2].map((i) => (
{[1, 2, 3].map((j) => (
))}
))}
)
}
export default function RoundsPage() {
return (
{/* Header */}
Rounds
Manage selection rounds and voting periods
{/* Content */}
}>
)
}