Auto-assign projects to first round, auto-filter on close, pipeline UX consolidation

- New projects (admin create, CSV import, public form) auto-assign to program's
  first round (by sortOrder) when no round is specified
- Closing a FILTERING round auto-starts filtering job (configurable via
  autoFilterOnClose setting, defaults to true)
- Add SUBMISSION_RECEIVED notification type for confirming submissions
- Replace separate List/Pipeline toggle with integrated pipeline view below
  the sortable round list
- Add autoFilterOnClose toggle to filtering round type settings UI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-12 15:06:11 +01:00
parent 2a5fa463b3
commit 7b85fd9602
11 changed files with 204 additions and 101 deletions

View File

@@ -8,6 +8,7 @@ import {
notifyProjectTeam,
NotificationTypes,
} from '../services/in-app-notification'
import { getFirstRoundForProgram } from '@/server/utils/round-helpers'
import { normalizeCountryToCode } from '@/lib/countries'
import { logAudit } from '../utils/audit'
import { sendInvitationEmail } from '@/lib/email'
@@ -459,10 +460,19 @@ export const projectRouter = router({
: undefined
const { project, membersToInvite } = await ctx.prisma.$transaction(async (tx) => {
// Auto-assign to first round if no roundId provided
let resolvedRoundId = input.roundId || null
if (!resolvedRoundId) {
const firstRound = await getFirstRoundForProgram(tx, resolvedProgramId)
if (firstRound) {
resolvedRoundId = firstRound.id
}
}
const created = await tx.project.create({
data: {
programId: resolvedProgramId,
roundId: input.roundId || null,
roundId: resolvedRoundId,
title: input.title,
teamName: input.teamName,
description: input.description,
@@ -882,6 +892,15 @@ export const projectRouter = router({
}
}
// Auto-assign to first round if no roundId provided
let resolvedImportRoundId = input.roundId || null
if (!resolvedImportRoundId) {
const firstRound = await getFirstRoundForProgram(ctx.prisma, input.programId)
if (firstRound) {
resolvedImportRoundId = firstRound.id
}
}
// Create projects in a transaction
const result = await ctx.prisma.$transaction(async (tx) => {
// Create all projects with roundId and programId
@@ -890,7 +909,7 @@ export const projectRouter = router({
return {
...rest,
programId: input.programId,
roundId: input.roundId!,
roundId: resolvedImportRoundId,
status: 'SUBMITTED' as const,
metadataJson: metadataJson as Prisma.InputJsonValue ?? undefined,
}