Pool page: add bulk assign-to-round, enhance project pool UI
- Add assignAllToRound mutation to project-pool router - Rewrite pool page with round selector, bulk assignment, and better layout - Add pool navigation link to admin projects page Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -198,4 +198,84 @@ export const projectPoolRouter = router({
|
||||
roundId,
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Assign ALL unassigned projects in a program to a round (server-side, no ID limit)
|
||||
*/
|
||||
assignAllToRound: adminProcedure
|
||||
.input(
|
||||
z.object({
|
||||
programId: z.string(),
|
||||
roundId: z.string(),
|
||||
competitionCategory: z.enum(['STARTUP', 'BUSINESS_CONCEPT']).optional(),
|
||||
})
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const { programId, roundId, competitionCategory } = input
|
||||
|
||||
// Verify round exists
|
||||
await ctx.prisma.round.findUniqueOrThrow({
|
||||
where: { id: roundId },
|
||||
select: { id: true },
|
||||
})
|
||||
|
||||
// Find all unassigned projects
|
||||
const where: Record<string, unknown> = {
|
||||
programId,
|
||||
projectRoundStates: { none: {} },
|
||||
}
|
||||
if (competitionCategory) {
|
||||
where.competitionCategory = competitionCategory
|
||||
}
|
||||
|
||||
const projects = await ctx.prisma.project.findMany({
|
||||
where,
|
||||
select: { id: true },
|
||||
})
|
||||
|
||||
if (projects.length === 0) {
|
||||
return { success: true, assignedCount: 0, roundId }
|
||||
}
|
||||
|
||||
const projectIds = projects.map((p) => p.id)
|
||||
|
||||
const result = await ctx.prisma.$transaction(async (tx) => {
|
||||
await tx.projectRoundState.createMany({
|
||||
data: projectIds.map((projectId) => ({ projectId, roundId })),
|
||||
skipDuplicates: true,
|
||||
})
|
||||
|
||||
const updated = await tx.project.updateMany({
|
||||
where: { id: { in: projectIds } },
|
||||
data: { status: 'ASSIGNED' },
|
||||
})
|
||||
|
||||
await tx.projectStatusHistory.createMany({
|
||||
data: projectIds.map((projectId) => ({
|
||||
projectId,
|
||||
status: 'ASSIGNED',
|
||||
changedBy: ctx.user?.id,
|
||||
})),
|
||||
})
|
||||
|
||||
await logAudit({
|
||||
prisma: tx,
|
||||
userId: ctx.user?.id,
|
||||
action: 'BULK_ASSIGN_ALL_TO_ROUND',
|
||||
entityType: 'Project',
|
||||
detailsJson: {
|
||||
roundId,
|
||||
programId,
|
||||
competitionCategory: competitionCategory || 'ALL',
|
||||
projectCount: projectIds.length,
|
||||
},
|
||||
ipAddress: ctx.ip,
|
||||
userAgent: ctx.userAgent,
|
||||
})
|
||||
|
||||
return updated
|
||||
})
|
||||
|
||||
return { success: true, assignedCount: result.count, roundId }
|
||||
}),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user