diff --git a/src/app/(admin)/admin/projects/[id]/page.tsx b/src/app/(admin)/admin/projects/[id]/page.tsx index d43e0a3..0e0cf64 100644 --- a/src/app/(admin)/admin/projects/[id]/page.tsx +++ b/src/app/(admin)/admin/projects/[id]/page.tsx @@ -845,9 +845,10 @@ function ProjectDetailContent({ projectId }: { projectId: string }) { } : null, })) for (const f of files) { - const roundId = f.requirement?.roundId ?? null - const roundName = f.requirement?.round?.name ?? 'General' - const sortOrder = f.requirement?.round?.sortOrder ?? -1 + const roundId = f.requirement?.roundId ?? f.roundId ?? null + const matchedRound = roundId ? competitionRounds.find((r: any) => r.id === roundId) : null + const roundName = f.requirement?.round?.name ?? matchedRound?.name ?? 'General' + const sortOrder = f.requirement?.round?.sortOrder ?? matchedRound?.sortOrder ?? -1 const key = roundId ?? '_general' if (!groups.has(key)) { groups.set(key, { roundId, roundName, sortOrder, files: [] }) @@ -864,141 +865,172 @@ function ProjectDetailContent({ projectId }: { projectId: string }) { - {/* Assignments Section */} - {assignments && assignments.length > 0 && ( - - - -
-
- -
- -
- Jury Assignments -
- - {assignments.filter((a) => a.evaluation?.status === 'SUBMITTED') - .length}{' '} - of {assignments.length} evaluations completed - + {/* Assignments Section — grouped by round */} + {assignments && assignments.length > 0 && (() => { + // Group assignments by round + const roundGroups = new Map() + for (const a of assignments) { + const rId = a.round?.id ?? '_unknown' + const rName = a.round?.name ?? 'Unknown Round' + if (!roundGroups.has(rId)) { + roundGroups.set(rId, { roundId: rId, roundName: rName, assignments: [] }) + } + roundGroups.get(rId)!.assignments.push(a) + } + const groups = Array.from(roundGroups.values()) + + return ( + + + +
+
+ +
+ +
+ Jury Assignments +
+ + {assignments.filter((a) => a.evaluation?.status === 'SUBMITTED') + .length}{' '} + of {assignments.length} evaluations completed across {groups.length} round{groups.length !== 1 ? 's' : ''} + +
+
- -
- - - - - - Juror - Expertise - Status - Score - Decision - - - - - {assignments.map((assignment) => ( - { - if (assignment.evaluation?.status === 'SUBMITTED') { - setSelectedEvalAssignment(assignment) - } - }} - > - -
- -
-

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

-

- {assignment.user.email} -

-
-
-
- -
- {assignment.user.expertiseTags?.slice(0, 2).map((tag) => ( - - {tag} - + + + {groups.map((group) => { + const submitted = group.assignments.filter((a) => a.evaluation?.status === 'SUBMITTED').length + return ( +
+
+

{group.roundName}

+ + {submitted} of {group.assignments.length} completed + +
+
+ + + Juror + Expertise + Status + Score + Decision + + + + + {group.assignments.map((assignment) => ( + { + if (assignment.evaluation?.status === 'SUBMITTED') { + setSelectedEvalAssignment(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 +
+ ) + ) : ( + - + )} +
+ + {assignment.evaluation?.status === 'SUBMITTED' && ( + + )} + +
))} - {(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 -
- ) - ) : ( - - - )} -
- - {assignment.evaluation?.status === 'SUBMITTED' && ( - - )} - - - ))} -
-
-
- - - )} + + +
+ ) + })} + +
+
+ ) + })()} {/* Evaluation Detail Sheet */} = {} for (const file of files) { - const roundName = file.requirement?.round?.name ?? 'General' - const rId = file.requirement?.round?.id ?? null + 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: [] } diff --git a/src/server/routers/file.ts b/src/server/routers/file.ts index 34a1ea2..6d5f7fb 100644 --- a/src/server/routers/file.ts +++ b/src/server/routers/file.ts @@ -206,6 +206,7 @@ export const fileRouter = router({ const file = await ctx.prisma.projectFile.create({ data: { projectId: input.projectId, + roundId: input.roundId ?? null, fileType: input.fileType, fileName: input.fileName, mimeType: input.mimeType, @@ -341,7 +342,10 @@ export const fileRouter = router({ const where: Record = { projectId: input.projectId } if (input.roundId) { - where.requirement = { roundId: input.roundId } + where.OR = [ + { requirement: { roundId: input.roundId } }, + { roundId: input.roundId, requirementId: null }, + ] } return ctx.prisma.projectFile.findMany({ @@ -429,7 +433,8 @@ export const fileRouter = router({ projectId: input.projectId, OR: [ { requirement: { roundId: { in: eligibleRoundIds } } }, - { requirementId: null }, + { roundId: { in: eligibleRoundIds }, requirementId: null }, + { roundId: null, requirementId: null }, ], }, include: { @@ -454,7 +459,8 @@ export const fileRouter = router({ files: typeof files }> = [] - const generalFiles = files.filter((f) => !f.requirementId) + // Files with no round association at all go to General + const generalFiles = files.filter((f) => !f.requirementId && !f.roundId) if (generalFiles.length > 0) { grouped.push({ roundId: null, @@ -465,7 +471,9 @@ export const fileRouter = router({ } for (const round of eligibleRounds) { - const roundFiles = files.filter((f) => f.requirement?.roundId === round.id) + const roundFiles = files.filter( + (f) => f.requirement?.roundId === round.id || (!f.requirementId && f.roundId === round.id) + ) if (roundFiles.length > 0) { grouped.push({ roundId: round.id,