From 68aa393559271e567505794fee61d6036aa2c880 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 1 Mar 2026 14:47:42 +0100 Subject: [PATCH] feat: show submission round file requirements on project edit page Adds a new tRPC procedure `round.getSubmissionRoundForProgram` that fetches the most recent SUBMISSION round for a given program, then displays any `requiredDocuments` from its configJson as labeled info cards above the general file upload section on the project edit page. Co-Authored-By: Claude Opus 4.6 --- .../(admin)/admin/projects/[id]/edit/page.tsx | 53 ++++++++++++++++++- src/server/routers/round.ts | 22 ++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/app/(admin)/admin/projects/[id]/edit/page.tsx b/src/app/(admin)/admin/projects/[id]/edit/page.tsx index c588c91..8c18e33 100644 --- a/src/app/(admin)/admin/projects/[id]/edit/page.tsx +++ b/src/app/(admin)/admin/projects/[id]/edit/page.tsx @@ -1,6 +1,6 @@ 'use client' -import { Suspense, use, useState, useEffect, useCallback } from 'react' +import { Suspense, use, useState, useEffect, useCallback, useMemo } from 'react' import Link from 'next/link' import { useRouter } from 'next/navigation' import { useForm } from 'react-hook-form' @@ -57,6 +57,7 @@ import { TableHeader, TableRow, } from '@/components/ui/table' +import { Separator } from '@/components/ui/separator' import { FileUpload } from '@/components/shared/file-upload' import { ProjectLogo } from '@/components/shared/project-logo' import { LogoUpload } from '@/components/shared/logo-upload' @@ -133,6 +134,27 @@ function EditProjectContent({ projectId }: { projectId: string }) { // Fetch existing tags for suggestions const { data: existingTags } = trpc.project.getTags.useQuery({}) + // Fetch submission round config to show required documents + const programId = project?.programId + const { data: submissionRound } = trpc.round.getSubmissionRoundForProgram.useQuery( + { programId: programId! }, + { enabled: !!programId } + ) + + const submissionRoundConfig = useMemo(() => { + if (!submissionRound?.configJson) return null + const config = submissionRound.configJson as Record + const docs = config.requiredDocuments as + | Array<{ name: string; required?: boolean; description?: string }> + | null + | undefined + if (!docs || docs.length === 0) return null + return { + roundName: submissionRound.name, + requiredDocuments: docs, + } + }, [submissionRound]) + // Mutations const utils = trpc.useUtils() const updateProject = trpc.project.update.useMutation({ @@ -702,7 +724,34 @@ function EditProjectContent({ projectId }: { projectId: string }) { - {files && files.length > 0 ? ( + {submissionRoundConfig && ( +
+
+

Required Documents

+

+ From {submissionRoundConfig.roundName} +

+
+
+ {submissionRoundConfig.requiredDocuments.map((doc, i) => ( +
+
+

{doc.name}

+ {doc.description && ( +

{doc.description}

+ )} + {doc.required && ( + Required + )} +
+
+ ))} +
+ +
+ )} + + {files && files.length > 0 ? ( diff --git a/src/server/routers/round.ts b/src/server/routers/round.ts index bad921b..077c6d7 100644 --- a/src/server/routers/round.ts +++ b/src/server/routers/round.ts @@ -861,4 +861,26 @@ export const roundRouter = router({ orderBy: { sortOrder: 'asc' }, }) }), + + /** + * Get the most recent SUBMISSION round config for a program. + * Used on the project edit page to show required document slots. + */ + getSubmissionRoundForProgram: adminProcedure + .input(z.object({ programId: z.string() })) + .query(async ({ ctx, input }) => { + const round = await ctx.prisma.round.findFirst({ + where: { + roundType: 'SUBMISSION', + competition: { programId: input.programId }, + }, + select: { + id: true, + name: true, + configJson: true, + }, + orderBy: { sortOrder: 'desc' }, + }) + return round ?? null + }), })