diff --git a/src/app/(applicant)/applicant/mentor/page.tsx b/src/app/(applicant)/applicant/mentor/page.tsx index 683208d..81d1b14 100644 --- a/src/app/(applicant)/applicant/mentor/page.tsx +++ b/src/app/(applicant)/applicant/mentor/page.tsx @@ -16,6 +16,7 @@ import { Button } from '@/components/ui/button' import { Skeleton } from '@/components/ui/skeleton' import { MentorChat } from '@/components/shared/mentor-chat' import { WorkspaceFilesPanel } from '@/components/mentor/workspace-files-panel' +import { FinalDocumentsPanel } from '@/components/applicant/final-documents-panel' import { RequestChangeDialog } from './request-change-dialog' import { MessageSquare, @@ -216,6 +217,9 @@ export default function ApplicantMentorPage() { /> )} + {/* Final Documents (self-hides when not a finalist) */} + + {/* Request change dialog */} {projectId && ( + + {/* Final Documents (self-hides when not a finalist) */} + ) } diff --git a/src/components/applicant/final-documents-panel.tsx b/src/components/applicant/final-documents-panel.tsx new file mode 100644 index 0000000..fbe0902 --- /dev/null +++ b/src/components/applicant/final-documents-panel.tsx @@ -0,0 +1,59 @@ +'use client' + +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 { Badge } from '@/components/ui/badge' +import { FileCheck2, Clock, Upload, CheckCircle2, Circle } from 'lucide-react' + +type Props = + | { variant: 'team' } + | { variant: 'mentor'; projectId: string } + +export function FinalDocumentsPanel(props: Props) { + const teamQuery = trpc.applicant.getFinalDocumentStatus.useQuery(undefined, { enabled: props.variant === 'team' }) + const mentorQuery = trpc.mentor.getProjectFinalDocuments.useQuery( + { projectId: props.variant === 'mentor' ? props.projectId : '' }, + { enabled: props.variant === 'mentor' }, + ) + const status = props.variant === 'team' ? teamQuery.data : mentorQuery.data + if (!status) return null + + const fmt = new Intl.DateTimeFormat(undefined, { dateStyle: 'long', timeStyle: 'short' }) + return ( + + +
+ Final Documents + {status.allRequiredUploaded + ? Submitted + : status.deadline && ( + + Due {fmt.format(new Date(status.deadline))} + + )} +
+ + {props.variant === 'team' ? 'Your final deliverables for the Grand Finale.' : 'This team\'s final deliverables for the Grand Finale.'} + +
+ + {status.requirements.map((r) => ( +
+ + {r.uploaded ? : } + {r.name} + + {r.file?.fileName ?? 'Not yet uploaded'} +
+ ))} + {props.variant === 'team' && !status.allRequiredUploaded && ( + + )} +
+
+ ) +}