AI-powered assignment generation with enriched data and streaming UI
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m19s

- Add aiPreview mutation with full project/juror data (bios, descriptions,
  documents, categories, ocean issues, countries, team sizes)
- Increase AI description limit from 300 to 2000 chars for richer context
- Update GPT system prompt to use all available data fields
- Add mode toggle (AI default / Algorithm fallback) in assignment preview
- Lift AI mutation to parent page for background generation persistence
- Show visual indicator on page while AI generates (spinner + progress card)
- Toast notification with "Review" action when AI completes
- Staggered reveal animation for assignment results (streaming feel)
- Fix assignment balance with dynamic penalty (25pts per existing assignment)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt
2026-02-17 14:45:57 +01:00
parent a7b6031f4d
commit 6743119c4d
7 changed files with 640 additions and 73 deletions

View File

@@ -21,7 +21,7 @@ import type {
// ─── Description Limits ──────────────────────────────────────────────────────
export const DESCRIPTION_LIMITS = {
ASSIGNMENT: 300,
ASSIGNMENT: 2000,
FILTERING: 500,
ELIGIBILITY: 400,
MENTOR: 350,
@@ -46,6 +46,8 @@ export interface AnonymizedJuror {
expertiseTags: string[]
currentAssignmentCount: number
maxAssignments: number | null
bio?: string | null
country?: string | null
}
export interface AnonymizedProject {
@@ -54,6 +56,12 @@ export interface AnonymizedProject {
description: string | null
tags: Array<{ name: string; confidence: number }>
teamName: string | null
category?: string | null
oceanIssue?: string | null
country?: string | null
institution?: string | null
teamSize?: number
fileTypes?: string[]
}
export interface JurorMapping {
@@ -200,6 +208,8 @@ interface JurorInput {
name?: string | null
email: string
expertiseTags: string[]
bio?: string | null
country?: string | null
maxAssignments?: number | null
_count?: {
assignments: number
@@ -213,6 +223,12 @@ interface ProjectInput {
tags: string[]
tagConfidences?: Array<{ name: string; confidence: number }>
teamName?: string | null
competitionCategory?: string | null
oceanIssue?: string | null
country?: string | null
institution?: string | null
teamSize?: number
fileTypes?: string[]
}
/**
@@ -238,6 +254,8 @@ export function anonymizeForAI(
expertiseTags: juror.expertiseTags,
currentAssignmentCount: juror._count?.assignments ?? 0,
maxAssignments: juror.maxAssignments ?? null,
bio: juror.bio ? truncateAndSanitize(juror.bio, 500) : null,
country: juror.country ?? null,
}
})
@@ -260,6 +278,12 @@ export function anonymizeForAI(
? project.tagConfidences
: project.tags.map((t) => ({ name: t, confidence: 1.0 })),
teamName: project.teamName ? `Team ${index + 1}` : null,
category: project.competitionCategory ?? null,
oceanIssue: project.oceanIssue ?? null,
country: project.country ?? null,
institution: project.institution ? sanitizeText(project.institution) : null,
teamSize: project.teamSize,
fileTypes: project.fileTypes,
}
}
)