'use client'; import { use, useState } from 'react'; import { useRouter } from 'next/navigation'; import Link from 'next/link'; import { trpc } from '@/lib/trpc/client'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Checkbox } from '@/components/ui/checkbox'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; import { ArrowLeft, Plus } from 'lucide-react'; import { toast } from 'sonner'; import type { Route } from 'next'; export default function DeliberationListPage({ params: paramsPromise }: { params: Promise<{ competitionId: string }>; }) { const params = use(paramsPromise); const router = useRouter(); const utils = trpc.useUtils(); const [createDialogOpen, setCreateDialogOpen] = useState(false); const [selectedJuryGroupId, setSelectedJuryGroupId] = useState(''); const [formData, setFormData] = useState({ roundId: '', category: 'STARTUP' as 'STARTUP' | 'BUSINESS_CONCEPT', mode: 'SINGLE_WINNER_VOTE' as 'SINGLE_WINNER_VOTE' | 'FULL_RANKING', tieBreakMethod: 'TIE_RUNOFF' as 'TIE_RUNOFF' | 'TIE_ADMIN_DECIDES' | 'SCORE_FALLBACK', showCollectiveRankings: false, showPriorJuryData: false, participantUserIds: [] as string[] }); const { data: sessions = [], isLoading } = trpc.deliberation.listSessions.useQuery( { competitionId: params.competitionId }, { enabled: !!params.competitionId } ); // Get rounds for this competition const { data: competition } = trpc.competition.getById.useQuery( { id: params.competitionId }, { enabled: !!params.competitionId } ); const rounds = competition?.rounds || []; // Jury groups & members for participant selection const { data: juryGroups = [] } = trpc.juryGroup.list.useQuery( { competitionId: params.competitionId }, { enabled: !!params.competitionId } ); const { data: selectedJuryGroup } = trpc.juryGroup.getById.useQuery( { id: selectedJuryGroupId }, { enabled: !!selectedJuryGroupId } ); const juryMembers = selectedJuryGroup?.members ?? []; const createSessionMutation = trpc.deliberation.createSession.useMutation({ onSuccess: (data) => { utils.deliberation.listSessions.invalidate({ competitionId: params.competitionId }); toast.success('Deliberation session created'); setCreateDialogOpen(false); router.push( `/admin/competitions/${params.competitionId}/deliberation/${data.id}` as Route ); }, onError: (err) => { toast.error(err.message); } }); const handleCreateSession = () => { if (!formData.roundId) { toast.error('Please select a round'); return; } if (formData.participantUserIds.length === 0) { toast.error('Please select at least one participant'); return; } createSessionMutation.mutate({ competitionId: params.competitionId, roundId: formData.roundId, category: formData.category, mode: formData.mode, tieBreakMethod: formData.tieBreakMethod, showCollectiveRankings: formData.showCollectiveRankings, showPriorJuryData: formData.showPriorJuryData, participantUserIds: formData.participantUserIds }); }; const getStatusBadge = (status: string) => { const variants: Record = { DELIB_OPEN: 'outline', DELIB_VOTING: 'default', DELIB_TALLYING: 'secondary', DELIB_LOCKED: 'destructive' }; return {status}; }; if (isLoading) { return (
{[1, 2, 3].map((i) => ( ))}
); } return (

Deliberation Sessions

Manage final jury deliberations and winner selection

{sessions?.map((session: any) => (
{session.round?.name} - {session.category} {session.mode === 'SINGLE_WINNER_VOTE' ? 'Single Winner Vote' : 'Full Ranking'}
{getStatusBadge(session.status)}
{session.participants?.length || 0} participants Tie break: {session.tieBreakMethod}
))}
{sessions?.length === 0 && (

No deliberation sessions yet

)} {/* Create Session Dialog */} Create Deliberation Session Set up a new deliberation session for final winner selection
{/* Participant Selection */}
{juryMembers.length > 0 && (
{juryMembers.map((member: any) => (
{ setFormData({ ...formData, participantUserIds: checked ? [...formData.participantUserIds, member.user.id] : formData.participantUserIds.filter((id: string) => id !== member.user.id), }); }} />
))}
)}
setFormData({ ...formData, showCollectiveRankings: checked as boolean }) } />
setFormData({ ...formData, showPriorJuryData: checked as boolean }) } />
); }