Files
MOPC-Portal/src/components/jury/multi-window-doc-viewer.tsx
Matt c7488b3e07
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m45s
fix: save roundId on admin file upload and group assignments by round
The admin upload flow accepted roundId but never wrote it to the
ProjectFile record, causing all admin-uploaded files to appear under
"General". Fixed the create call, the listByProject filter, and the
listByProjectForStage grouping to also use the direct roundId field.

Jury assignments on the project detail page are now grouped by round
with per-round completion counts instead of a flat list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:20:48 -04:00

127 lines
4.1 KiB
TypeScript

'use client'
import { trpc } from '@/lib/trpc/client'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Skeleton } from '@/components/ui/skeleton'
import { FileText } from 'lucide-react'
import { FileViewer } from '@/components/shared/file-viewer'
interface MultiWindowDocViewerProps {
roundId: string
projectId: string
}
export function MultiWindowDocViewer({ roundId, projectId }: MultiWindowDocViewerProps) {
const { data: files, isLoading } = trpc.file.listByProject.useQuery(
{ projectId },
{ enabled: !!projectId }
)
if (isLoading) {
return (
<Card>
<CardHeader>
<Skeleton className="h-6 w-48" />
</CardHeader>
<CardContent>
<Skeleton className="h-64" />
</CardContent>
</Card>
)
}
if (!files || files.length === 0) {
return (
<Card>
<CardHeader>
<CardTitle>Documents</CardTitle>
<CardDescription>Project files and submissions</CardDescription>
</CardHeader>
<CardContent className="text-center py-8">
<FileText className="h-12 w-12 text-muted-foreground/50 mx-auto mb-3" />
<p className="text-sm text-muted-foreground">No files uploaded</p>
</CardContent>
</Card>
)
}
// Group files by round name for the grouped view
const groupMap: Record<string, {
roundId: string | null
roundName: string
sortOrder: number
files: typeof files
}> = {}
for (const file of files) {
const rId = file.requirement?.round?.id ?? (file as any).roundId ?? null
const roundName = file.requirement?.round?.name ?? (rId ? 'Round Files' : 'General')
const sortOrder = file.requirement?.round?.sortOrder ?? 999
if (!groupMap[roundName]) {
groupMap[roundName] = { roundId: rId, roundName, sortOrder, files: [] }
}
groupMap[roundName].files.push(file)
}
const groupedFiles = Object.values(groupMap)
// If only one group, use flat view
if (groupedFiles.length === 1) {
const mappedFiles = files.map((f) => ({
id: f.id,
fileType: (f.fileType ?? 'OTHER') as 'EXEC_SUMMARY' | 'PRESENTATION' | 'VIDEO' | 'OTHER' | 'BUSINESS_PLAN' | 'VIDEO_PITCH' | 'SUPPORTING_DOC',
fileName: f.fileName,
mimeType: f.mimeType,
size: f.size,
bucket: f.bucket,
objectKey: f.objectKey,
version: f.version ?? undefined,
requirementId: f.requirementId,
requirement: f.requirement ? {
id: f.requirement.id,
name: f.requirement.name,
description: f.requirement.description,
isRequired: f.requirement.isRequired,
} : undefined,
pageCount: (f as any).pageCount ?? undefined,
textPreview: (f as any).textPreview ?? undefined,
detectedLang: (f as any).detectedLang ?? undefined,
langConfidence: (f as any).langConfidence ?? undefined,
analyzedAt: (f as any).analyzedAt ?? undefined,
}))
return <FileViewer files={mappedFiles} />
}
// Multiple groups — use grouped view
const mappedGroups = groupedFiles.map((g) => ({
roundId: g.roundId,
roundName: g.roundName,
sortOrder: g.sortOrder,
files: g.files.map((f) => ({
id: f.id,
fileType: (f.fileType ?? 'OTHER') as 'EXEC_SUMMARY' | 'PRESENTATION' | 'VIDEO' | 'OTHER' | 'BUSINESS_PLAN' | 'VIDEO_PITCH' | 'SUPPORTING_DOC',
fileName: f.fileName,
mimeType: f.mimeType,
size: f.size,
bucket: f.bucket,
objectKey: f.objectKey,
version: f.version ?? undefined,
requirementId: f.requirementId,
requirement: f.requirement ? {
id: f.requirement.id,
name: f.requirement.name,
description: f.requirement.description,
isRequired: f.requirement.isRequired,
} : undefined,
pageCount: (f as any).pageCount ?? undefined,
textPreview: (f as any).textPreview ?? undefined,
detectedLang: (f as any).detectedLang ?? undefined,
langConfidence: (f as any).langConfidence ?? undefined,
analyzedAt: (f as any).analyzedAt ?? undefined,
})),
}))
return <FileViewer groupedFiles={mappedGroups} />
}