AI category-aware evaluation: per-round config, file parsing, shortlist, advance flow

- Per-juror cap mode (HARD/SOFT/NONE) in add-member dialog and members table
- Jury invite flow: create user + add to group + send invitation from dialog
- Per-round config: notifyOnAdvance, aiParseFiles, startupAdvanceCount, conceptAdvanceCount
- Moved notify-on-advance from competition-level to per-round setting
- AI filtering: round-tagged files with newest-first sorting, optional file content extraction
- File content extractor service (pdf-parse for PDF, utf-8 for text files)
- AI shortlist runs independently per category (STARTUP / BUSINESS_CONCEPT)
- generateAIRecommendations tRPC endpoint with per-round config integration
- AI recommendations UI: trigger button, confirmation dialog, per-category results display
- Category-aware advance dialog: select/deselect projects by category with target caps
- STAGE_ACTIVE bug fix in assignment router

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 10:09:52 +01:00
parent 93f4ad4b31
commit 80c9e35971
21 changed files with 1886 additions and 1381 deletions

View File

@@ -36,6 +36,7 @@ interface JuryMember {
email: string
}
maxAssignmentsOverride: number | null
capModeOverride: string | null
preferredStartupRatio: number | null
}
@@ -82,13 +83,14 @@ export function JuryMembersTable({ juryGroupId, members }: JuryMembersTableProps
<TableHead>Email</TableHead>
<TableHead className="hidden md:table-cell">Role</TableHead>
<TableHead className="hidden sm:table-cell">Max Assignments</TableHead>
<TableHead className="hidden lg:table-cell">Cap Mode</TableHead>
<TableHead>Actions</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{members.length === 0 ? (
<TableRow>
<TableCell colSpan={5} className="text-center text-muted-foreground">
<TableCell colSpan={6} className="text-center text-muted-foreground">
No members yet. Add members to get started.
</TableCell>
</TableRow>
@@ -109,6 +111,15 @@ export function JuryMembersTable({ juryGroupId, members }: JuryMembersTableProps
<TableCell className="hidden sm:table-cell">
{member.maxAssignmentsOverride ?? '—'}
</TableCell>
<TableCell className="hidden lg:table-cell">
{member.capModeOverride ? (
<Badge variant="outline" className="text-[10px]">
{member.capModeOverride}
</Badge>
) : (
<span className="text-muted-foreground text-xs">Group default</span>
)}
</TableCell>
<TableCell>
<Button
variant="ghost"