'use client' import { Suspense, use } from 'react' import Link from 'next/link' import type { Route } from 'next' 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 { Separator } from '@/components/ui/separator' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { FileViewer } from '@/components/shared/file-viewer' import { FileUpload } from '@/components/shared/file-upload' import { ProjectLogoWithUrl } from '@/components/shared/project-logo-with-url' import { UserAvatar } from '@/components/shared/user-avatar' import { EvaluationSummaryCard } from '@/components/admin/evaluation-summary-card' import { AnimatedCard } from '@/components/shared/animated-container' import { ArrowLeft, Edit, AlertCircle, Users, FileText, Calendar, CheckCircle2, XCircle, Circle, Clock, BarChart3, ThumbsUp, ThumbsDown, MapPin, Waves, GraduationCap, Heart, Crown, UserPlus, } from 'lucide-react' import { formatDate, formatDateOnly } from '@/lib/utils' interface PageProps { params: Promise<{ id: string }> } // Status badge colors const statusColors: Record = { SUBMITTED: 'secondary', ELIGIBLE: 'default', ASSIGNED: 'default', SEMIFINALIST: 'default', FINALIST: 'default', REJECTED: 'destructive', } // Evaluation status colors const evalStatusColors: Record = { NOT_STARTED: 'outline', DRAFT: 'secondary', SUBMITTED: 'default', LOCKED: 'default', } function ProjectDetailContent({ projectId }: { projectId: string }) { // Fetch project + assignments + stats in a single combined query const { data: fullDetail, isLoading } = trpc.project.getFullDetail.useQuery({ id: projectId, }) const project = fullDetail?.project const assignments = fullDetail?.assignments const stats = fullDetail?.stats // Fetch files (flat list for backward compatibility) const { data: files } = trpc.file.listByProject.useQuery({ projectId }) // Fetch file requirements from the pipeline's intake stage const { data: requirementsData } = trpc.file.getProjectRequirements.useQuery( { projectId }, { enabled: !!project } ) // Fetch available stages for upload selector (if project has a programId) const { data: programData } = trpc.program.get.useQuery( { id: project?.programId || '' }, { enabled: !!project?.programId } ) const availableStages = (programData?.stages as Array<{ id: string; name: string }>) || [] const utils = trpc.useUtils() if (isLoading) { return } if (!project) { return (

Project Not Found

) } return (
{/* Header */}
{project.programId ? ( {programData?.name ?? 'Program'} ) : ( No program )}

{project.title}

{(project.status ?? 'SUBMITTED').replace('_', ' ')}
{project.teamName && (

{project.teamName}

)}
{/* Stats Grid */} {stats && (
Average Score
{stats.averageGlobalScore?.toFixed(1) || '-'}

Range: {stats.minScore || '-'} - {stats.maxScore || '-'}

Recommendations
{stats.yesPercentage?.toFixed(0) || 0}%

{stats.yesVotes} yes / {stats.noVotes} no

)} {/* Project Info */}
Project Information
{/* Category & Ocean Issue badges */}
{project.competitionCategory && ( {project.competitionCategory === 'STARTUP' ? 'Start-up' : 'Business Concept'} )} {project.oceanIssue && ( {project.oceanIssue.replace(/_/g, ' ')} )} {project.wantsMentorship && ( Wants Mentorship )}
{project.description && (

Description

{project.description}

)} {/* Location & Institution */}
{(project.country || project.geographicZone) && (

Location

{project.geographicZone || project.country}

)} {project.institution && (

Institution

{project.institution}

)} {project.foundedAt && (

Founded

{formatDateOnly(project.foundedAt)}

)}
{/* Submission URLs */} {(project.phase1SubmissionUrl || project.phase2SubmissionUrl) && (

Submission Links

{project.phase1SubmissionUrl && ( )} {project.phase2SubmissionUrl && ( )}
)} {/* AI-Assigned Expertise Tags */} {project.projectTags && project.projectTags.length > 0 && (

Expertise Tags

{project.projectTags.map((pt) => ( {pt.tag.name} {pt.confidence < 1 && ( {Math.round(pt.confidence * 100)}% )} ))}
)} {/* Simple Tags (legacy) */} {project.tags && project.tags.length > 0 && (

Tags

{project.tags.map((tag) => ( {tag} ))}
)} {/* Internal Info */} {(project.internalComments || project.applicationStatus || project.referralSource) && (

Internal Notes

{project.applicationStatus && (

Application Status

{project.applicationStatus}

)} {project.referralSource && (

Referral Source

{project.referralSource}

)}
{project.internalComments && (

Comments

{project.internalComments}

)}
)}
Created:{' '} {formatDateOnly(project.createdAt)}
Updated:{' '} {formatDateOnly(project.updatedAt)}
{/* Team Members Section */} {project.teamMembers && project.teamMembers.length > 0 && (
Team Members ({project.teamMembers.length})
{project.teamMembers.map((member: { id: string; role: string; title: string | null; user: { id: string; name: string | null; email: string; avatarUrl?: string | null } }) => (
{member.role === 'LEAD' ? (
) : ( )}

{member.user.name || 'Unnamed'}

{member.role === 'LEAD' ? 'Lead' : member.role === 'ADVISOR' ? 'Advisor' : 'Member'}

{member.user.email}

{member.title && (

{member.title}

)}
))}
)} {/* Mentor Assignment Section */} {project.wantsMentorship && (
Mentor Assignment
{!project.mentorAssignment && ( )}
{project.mentorAssignment ? (

{project.mentorAssignment.mentor.name || 'Unnamed'}

{project.mentorAssignment.mentor.email}

{project.mentorAssignment.method.replace('_', ' ')}
) : (

No mentor assigned yet. The applicant has requested mentorship support.

)}
)} {/* Files Section */}
Files
Project documents and materials
{/* Required Documents from Pipeline Intake Stage */} {requirementsData && requirementsData.requirements.length > 0 && ( <>

Required Documents

{requirementsData.requirements.map((req, idx) => { const isFulfilled = req.fulfilled return (
{isFulfilled ? ( ) : ( )}

{req.name}

{req.isRequired && ( Required )}
{req.description && ( {req.description} )} {req.maxSizeMB && ( Max {req.maxSizeMB}MB )}
{isFulfilled && req.fulfilledFile && (

{req.fulfilledFile.fileName}

)}
{!isFulfilled && ( Missing )}
) })}
)} {/* Additional Documents Upload */}

{requirementsData && requirementsData.requirements.length > 0 ? 'Additional Documents' : 'Upload New Files'}

({ id: s.id, name: s.name }))} onUploadComplete={() => { utils.file.listByProject.invalidate({ projectId }) utils.file.getProjectRequirements.invalidate({ projectId }) }} />
{/* All Files list */} {files && files.length > 0 && ( <>

All Files

({ id: f.id, fileName: f.fileName, fileType: f.fileType, mimeType: f.mimeType, size: f.size, bucket: f.bucket, objectKey: f.objectKey, }))} />
)}
{/* Assignments Section */} {assignments && assignments.length > 0 && (
Jury Assignments
{assignments.filter((a) => a.evaluation?.status === 'SUBMITTED') .length}{' '} of {assignments.length} evaluations completed
Juror Expertise Status Score Decision {assignments.map((assignment) => (

{assignment.user.name || 'Unnamed'}

{assignment.user.email}

{assignment.user.expertiseTags?.slice(0, 2).map((tag) => ( {tag} ))} {(assignment.user.expertiseTags?.length || 0) > 2 && ( +{(assignment.user.expertiseTags?.length || 0) - 2} )}
{(assignment.evaluation?.status || 'NOT_STARTED').replace( '_', ' ' )} {assignment.evaluation?.globalScore !== null && assignment.evaluation?.globalScore !== undefined ? ( {assignment.evaluation.globalScore}/10 ) : ( - )} {assignment.evaluation?.binaryDecision !== null && assignment.evaluation?.binaryDecision !== undefined ? ( assignment.evaluation.binaryDecision ? (
Yes
) : (
No
) ) : ( - )}
))}
)} {/* AI Evaluation Summary */} {assignments && assignments.length > 0 && stats && stats.totalEvaluations > 0 && ( )}
) } function ProjectDetailSkeleton() { return (
{[1, 2, 3, 4].map((i) => ( ))}
) } export default function ProjectDetailPage({ params }: PageProps) { const { id } = use(params) return ( }> ) }