feat: group observer project files by round
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m15s

Files on the observer project detail page are now grouped by round
(e.g., "Application Intake", "Semi-Finals Document Submission") instead
of shown in a flat list. Uses FileViewer's existing groupedFiles prop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 16:24:33 +01:00
parent 0390d05727
commit a8b8643936
2 changed files with 64 additions and 35 deletions

View File

@@ -929,10 +929,33 @@ export function ObserverProjectDetail({ projectId }: { projectId: string }) {
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
{project.files && project.files.length > 0 ? ( {project.files && project.files.length > 0 ? (() => {
// Group files by round
type FileItem = (typeof project.files)[number]
const roundMap = new Map<string, { roundId: string | null; roundName: string; sortOrder: number; files: FileItem[] }>()
for (const f of project.files) {
const key = (f as any).roundId ?? '__none__'
if (!roundMap.has(key)) {
const round = (f as any).round as { id: string; name: string; sortOrder: number } | null
roundMap.set(key, {
roundId: round?.id ?? null,
roundName: round?.name ?? 'Other Files',
sortOrder: round?.sortOrder ?? 999,
files: [],
})
}
roundMap.get(key)!.files.push(f)
}
const groups = Array.from(roundMap.values()).sort((a, b) => a.sortOrder - b.sortOrder)
return (
<FileViewer <FileViewer
projectId={projectId} projectId={projectId}
files={project.files.map((f) => ({ groupedFiles={groups.map((g) => ({
roundId: g.roundId,
roundName: g.roundName,
sortOrder: g.sortOrder,
files: g.files.map((f) => ({
id: f.id, id: f.id,
fileName: f.fileName, fileName: f.fileName,
fileType: f.fileType as fileType: f.fileType as
@@ -961,9 +984,11 @@ export function ObserverProjectDetail({ projectId }: { projectId: string }) {
isRequired: f.requirement.isRequired, isRequired: f.requirement.isRequired,
} }
: null, : null,
})),
}))} }))}
/> />
) : ( )
})() : (
<div className="flex flex-col items-center justify-center py-8 text-center"> <div className="flex flex-col items-center justify-center py-8 text-center">
<FileText className="h-12 w-12 text-muted-foreground/50" /> <FileText className="h-12 w-12 text-muted-foreground/50" />
<p className="mt-2 text-sm text-muted-foreground"> <p className="mt-2 text-sm text-muted-foreground">

View File

@@ -1378,9 +1378,12 @@ export const analyticsRouter = router({
id: true, fileName: true, fileType: true, mimeType: true, size: true, id: true, fileName: true, fileType: true, mimeType: true, size: true,
bucket: true, objectKey: true, pageCount: true, textPreview: true, bucket: true, objectKey: true, pageCount: true, textPreview: true,
detectedLang: true, langConfidence: true, analyzedAt: true, detectedLang: true, langConfidence: true, analyzedAt: true,
roundId: true,
round: { select: { id: true, name: true, roundType: true, sortOrder: true } },
requirementId: true, requirementId: true,
requirement: { select: { id: true, name: true, description: true, isRequired: true } }, requirement: { select: { id: true, name: true, description: true, isRequired: true } },
}, },
orderBy: [{ round: { sortOrder: 'asc' } }, { createdAt: 'asc' }],
}, },
teamMembers: { teamMembers: {
include: { include: {
@@ -1526,6 +1529,7 @@ export const analyticsRouter = router({
return { return {
project: { project: {
...projectRaw, ...projectRaw,
files: projectRaw.files,
projectTags, projectTags,
teamMembers: teamMembersWithAvatars, teamMembers: teamMembersWithAvatars,
}, },