'use client' import { useState } from 'react' import { useParams, useSearchParams } from 'next/navigation' import Link from 'next/link' import { trpc } from '@/lib/trpc/client' import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Textarea } from '@/components/ui/textarea' import { Badge } from '@/components/ui/badge' import { Skeleton } from '@/components/ui/skeleton' import { ArrowLeft, BarChart3, MessageSquare, Send, Loader2, Lock, User, } from 'lucide-react' import { toast } from 'sonner' import { formatDate, cn, getInitials } from '@/lib/utils' export default function DiscussionPage() { const params = useParams() const searchParams = useSearchParams() const projectId = params.id as string const roundId = searchParams.get('roundId') || '' const [commentText, setCommentText] = useState('') const utils = trpc.useUtils() // Fetch peer summary const { data: peerSummary, isLoading: loadingSummary } = trpc.evaluation.getPeerSummary.useQuery( { projectId, roundId }, { enabled: !!roundId } ) // Fetch discussion thread const { data: discussion, isLoading: loadingDiscussion } = trpc.evaluation.getDiscussion.useQuery( { projectId, roundId }, { enabled: !!roundId } ) // Add comment mutation const addCommentMutation = trpc.evaluation.addComment.useMutation({ onSuccess: () => { utils.evaluation.getDiscussion.invalidate({ projectId, roundId }) toast.success('Comment added') setCommentText('') }, onError: (e) => toast.error(e.message), }) const handleSubmitComment = () => { if (!commentText.trim()) { toast.error('Please enter a comment') return } addCommentMutation.mutate({ projectId, roundId, content: commentText.trim(), }) } const isLoading = loadingSummary || loadingDiscussion if (!roundId) { return (

No round specified

Please access the discussion from your assignments page.

) } if (isLoading) { return } // Parse peer summary data const summary = peerSummary as Record | undefined const averageScore = summary ? Number(summary.averageScore || 0) : 0 const scoreRange = summary?.scoreRange as { min: number; max: number } | undefined const evaluationCount = summary ? Number(summary.evaluationCount || 0) : 0 const individualScores = (summary?.scores || summary?.individualScores) as | Array | undefined // Parse discussion data const discussionData = discussion as Record | undefined const comments = (discussionData?.comments || []) as Array<{ id: string user: { id: string; name: string | null; email: string } content: string createdAt: string }> const discussionStatus = String(discussionData?.status || 'OPEN') const isClosed = discussionStatus === 'CLOSED' const closedAt = discussionData?.closedAt as string | undefined const closedBy = discussionData?.closedBy as Record | undefined return (
{/* Header */}

Project Discussion

Peer review discussion and anonymized score summary

{/* Peer Summary Card */} Peer Summary Anonymized scoring overview across all evaluations {/* Stats row */}

{averageScore.toFixed(1)}

Average Score

{scoreRange ? `${scoreRange.min.toFixed(1)} - ${scoreRange.max.toFixed(1)}` : '--'}

Score Range

{evaluationCount}

Evaluations

{/* Anonymized score bars */} {individualScores && individualScores.length > 0 && (

Anonymized Individual Scores

{individualScores.map((score, i) => { const maxPossible = scoreRange?.max || 10 const height = maxPossible > 0 ? Math.max((score / maxPossible) * 100, 4) : 4 return (
{score.toFixed(1)}
= averageScore ? 'bg-primary/60' : 'bg-muted-foreground/30' )} style={{ height: `${height}%` }} /> #{i + 1}
) })}
)} {/* Discussion Section */}
Discussion {isClosed && ( Closed {closedAt && ( - {formatDate(closedAt)} )} )}
{isClosed ? 'This discussion has been closed.' : 'Share your thoughts with fellow jurors about this project.'}
{/* Comments */} {comments.length > 0 ? (
{comments.map((comment) => (
{/* Avatar */}
{comment.user?.name ? getInitials(comment.user.name) : }
{/* Content */}
{comment.user?.name || 'Anonymous Juror'} {formatDate(comment.createdAt)}

{comment.content}

))}
) : (

No comments yet. Be the first to start the discussion.

)} {/* Comment input */} {!isClosed ? (