2026-01-30 13:41:32 +01:00
|
|
|
import { z } from 'zod'
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
import { router, observerProcedure } from '../trpc'
|
2026-02-13 23:45:21 +01:00
|
|
|
import { normalizeCountryToCode } from '@/lib/countries'
|
2026-01-30 13:41:32 +01:00
|
|
|
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
const editionOrStageInput = z.object({
|
|
|
|
|
stageId: z.string().optional(),
|
2026-02-11 13:20:52 +01:00
|
|
|
programId: z.string().optional(),
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
}).refine(data => data.stageId || data.programId, {
|
|
|
|
|
message: 'Either stageId or programId is required',
|
2026-02-11 13:20:52 +01:00
|
|
|
})
|
|
|
|
|
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
function projectWhere(input: { stageId?: string; programId?: string }) {
|
|
|
|
|
if (input.stageId) return { assignments: { some: { stageId: input.stageId } } }
|
2026-02-11 13:20:52 +01:00
|
|
|
return { programId: input.programId! }
|
|
|
|
|
}
|
|
|
|
|
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
function assignmentWhere(input: { stageId?: string; programId?: string }) {
|
|
|
|
|
if (input.stageId) return { stageId: input.stageId }
|
|
|
|
|
return { stage: { track: { pipeline: { programId: input.programId! } } } }
|
2026-02-11 13:20:52 +01:00
|
|
|
}
|
|
|
|
|
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
function evalWhere(input: { stageId?: string; programId?: string }, extra: Record<string, unknown> = {}) {
|
|
|
|
|
const base = input.stageId
|
|
|
|
|
? { assignment: { stageId: input.stageId } }
|
|
|
|
|
: { assignment: { stage: { track: { pipeline: { programId: input.programId! } } } } }
|
2026-02-11 13:20:52 +01:00
|
|
|
return { ...base, ...extra }
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-30 13:41:32 +01:00
|
|
|
export const analyticsRouter = router({
|
|
|
|
|
/**
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
* Get score distribution (histogram data)
|
2026-01-30 13:41:32 +01:00
|
|
|
*/
|
Implement 10 platform features: evaluation UX, admin tools, AI summaries, applicant portal
Batch 1 - Quick Wins:
- F1: Evaluation progress indicator with touch tracking in sticky status bar
- F2: Export filtering results as CSV with dynamic AI column flattening
- F3: Observer access to analytics dashboards (8 procedures changed to observerProcedure)
Batch 2 - Jury Experience:
- F4: Countdown timer component with urgency colors + email reminder service with cron endpoint
- F5: Conflict of interest declaration system (dialog, admin management, review workflow)
Batch 3 - Admin & AI Enhancements:
- F6: Bulk status update UI with selection checkboxes, floating toolbar, status history recording
- F7: AI-powered evaluation summary with anonymized data, OpenAI integration, scoring patterns
- F8: Smart assignment improvements (geo diversity penalty, round familiarity bonus, COI blocking)
Batch 4 - Form Flexibility & Applicant Portal:
- F9: Evaluation form flexibility (text, boolean, section_header types, conditional visibility)
- F10: Applicant portal (status timeline, per-round documents, mentor messaging)
Schema: 5 new models (ReminderLog, ConflictOfInterest, EvaluationSummary, ProjectStatusHistory, MentorMessage), ProjectFile extended with roundId + isLate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:58:27 +01:00
|
|
|
getScoreDistribution: observerProcedure
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
.input(editionOrStageInput)
|
2026-01-30 13:41:32 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
const evaluations = await ctx.prisma.evaluation.findMany({
|
2026-02-11 13:20:52 +01:00
|
|
|
where: evalWhere(input, { status: 'SUBMITTED' }),
|
2026-01-30 13:41:32 +01:00
|
|
|
select: {
|
|
|
|
|
criterionScoresJson: true,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Extract all scores and calculate distribution
|
|
|
|
|
const allScores: number[] = []
|
|
|
|
|
evaluations.forEach((evaluation) => {
|
|
|
|
|
const scores = evaluation.criterionScoresJson as Record<string, number> | null
|
|
|
|
|
if (scores) {
|
|
|
|
|
Object.values(scores).forEach((score) => {
|
|
|
|
|
if (typeof score === 'number') {
|
|
|
|
|
allScores.push(score)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Count scores by bucket (1-10)
|
|
|
|
|
const distribution = Array.from({ length: 10 }, (_, i) => ({
|
|
|
|
|
score: i + 1,
|
|
|
|
|
count: allScores.filter((s) => Math.round(s) === i + 1).length,
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
distribution,
|
|
|
|
|
totalScores: allScores.length,
|
|
|
|
|
averageScore:
|
|
|
|
|
allScores.length > 0
|
|
|
|
|
? allScores.reduce((a, b) => a + b, 0) / allScores.length
|
|
|
|
|
: 0,
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get evaluation completion over time (timeline data)
|
|
|
|
|
*/
|
Implement 10 platform features: evaluation UX, admin tools, AI summaries, applicant portal
Batch 1 - Quick Wins:
- F1: Evaluation progress indicator with touch tracking in sticky status bar
- F2: Export filtering results as CSV with dynamic AI column flattening
- F3: Observer access to analytics dashboards (8 procedures changed to observerProcedure)
Batch 2 - Jury Experience:
- F4: Countdown timer component with urgency colors + email reminder service with cron endpoint
- F5: Conflict of interest declaration system (dialog, admin management, review workflow)
Batch 3 - Admin & AI Enhancements:
- F6: Bulk status update UI with selection checkboxes, floating toolbar, status history recording
- F7: AI-powered evaluation summary with anonymized data, OpenAI integration, scoring patterns
- F8: Smart assignment improvements (geo diversity penalty, round familiarity bonus, COI blocking)
Batch 4 - Form Flexibility & Applicant Portal:
- F9: Evaluation form flexibility (text, boolean, section_header types, conditional visibility)
- F10: Applicant portal (status timeline, per-round documents, mentor messaging)
Schema: 5 new models (ReminderLog, ConflictOfInterest, EvaluationSummary, ProjectStatusHistory, MentorMessage), ProjectFile extended with roundId + isLate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:58:27 +01:00
|
|
|
getEvaluationTimeline: observerProcedure
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
.input(editionOrStageInput)
|
2026-01-30 13:41:32 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
const evaluations = await ctx.prisma.evaluation.findMany({
|
2026-02-11 13:20:52 +01:00
|
|
|
where: evalWhere(input, { status: 'SUBMITTED' }),
|
2026-01-30 13:41:32 +01:00
|
|
|
select: {
|
|
|
|
|
submittedAt: true,
|
|
|
|
|
},
|
|
|
|
|
orderBy: { submittedAt: 'asc' },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Group by date
|
|
|
|
|
const byDate: Record<string, number> = {}
|
|
|
|
|
let cumulative = 0
|
|
|
|
|
|
|
|
|
|
evaluations.forEach((evaluation) => {
|
|
|
|
|
if (evaluation.submittedAt) {
|
|
|
|
|
const date = evaluation.submittedAt.toISOString().split('T')[0]
|
|
|
|
|
if (!byDate[date]) {
|
|
|
|
|
byDate[date] = 0
|
|
|
|
|
}
|
|
|
|
|
byDate[date]++
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Convert to cumulative timeline
|
|
|
|
|
const timeline = Object.entries(byDate)
|
|
|
|
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
|
|
|
.map(([date, count]) => {
|
|
|
|
|
cumulative += count
|
|
|
|
|
return {
|
|
|
|
|
date,
|
|
|
|
|
daily: count,
|
|
|
|
|
cumulative,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return timeline
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get juror workload distribution
|
|
|
|
|
*/
|
Implement 10 platform features: evaluation UX, admin tools, AI summaries, applicant portal
Batch 1 - Quick Wins:
- F1: Evaluation progress indicator with touch tracking in sticky status bar
- F2: Export filtering results as CSV with dynamic AI column flattening
- F3: Observer access to analytics dashboards (8 procedures changed to observerProcedure)
Batch 2 - Jury Experience:
- F4: Countdown timer component with urgency colors + email reminder service with cron endpoint
- F5: Conflict of interest declaration system (dialog, admin management, review workflow)
Batch 3 - Admin & AI Enhancements:
- F6: Bulk status update UI with selection checkboxes, floating toolbar, status history recording
- F7: AI-powered evaluation summary with anonymized data, OpenAI integration, scoring patterns
- F8: Smart assignment improvements (geo diversity penalty, round familiarity bonus, COI blocking)
Batch 4 - Form Flexibility & Applicant Portal:
- F9: Evaluation form flexibility (text, boolean, section_header types, conditional visibility)
- F10: Applicant portal (status timeline, per-round documents, mentor messaging)
Schema: 5 new models (ReminderLog, ConflictOfInterest, EvaluationSummary, ProjectStatusHistory, MentorMessage), ProjectFile extended with roundId + isLate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:58:27 +01:00
|
|
|
getJurorWorkload: observerProcedure
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
.input(editionOrStageInput)
|
2026-01-30 13:41:32 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
const assignments = await ctx.prisma.assignment.findMany({
|
2026-02-11 13:20:52 +01:00
|
|
|
where: assignmentWhere(input),
|
2026-01-30 13:41:32 +01:00
|
|
|
include: {
|
|
|
|
|
user: { select: { name: true, email: true } },
|
|
|
|
|
evaluation: {
|
|
|
|
|
select: { id: true, status: true },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Group by user
|
|
|
|
|
const byUser: Record<
|
|
|
|
|
string,
|
|
|
|
|
{ name: string; assigned: number; completed: number }
|
|
|
|
|
> = {}
|
|
|
|
|
|
|
|
|
|
assignments.forEach((assignment) => {
|
|
|
|
|
const userId = assignment.userId
|
|
|
|
|
if (!byUser[userId]) {
|
|
|
|
|
byUser[userId] = {
|
|
|
|
|
name: assignment.user.name || assignment.user.email || 'Unknown',
|
|
|
|
|
assigned: 0,
|
|
|
|
|
completed: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
byUser[userId].assigned++
|
|
|
|
|
if (assignment.evaluation?.status === 'SUBMITTED') {
|
|
|
|
|
byUser[userId].completed++
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return Object.entries(byUser)
|
|
|
|
|
.map(([id, data]) => ({
|
|
|
|
|
id,
|
|
|
|
|
...data,
|
|
|
|
|
completionRate:
|
|
|
|
|
data.assigned > 0
|
|
|
|
|
? Math.round((data.completed / data.assigned) * 100)
|
|
|
|
|
: 0,
|
|
|
|
|
}))
|
|
|
|
|
.sort((a, b) => b.assigned - a.assigned)
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get project rankings with average scores
|
|
|
|
|
*/
|
Implement 10 platform features: evaluation UX, admin tools, AI summaries, applicant portal
Batch 1 - Quick Wins:
- F1: Evaluation progress indicator with touch tracking in sticky status bar
- F2: Export filtering results as CSV with dynamic AI column flattening
- F3: Observer access to analytics dashboards (8 procedures changed to observerProcedure)
Batch 2 - Jury Experience:
- F4: Countdown timer component with urgency colors + email reminder service with cron endpoint
- F5: Conflict of interest declaration system (dialog, admin management, review workflow)
Batch 3 - Admin & AI Enhancements:
- F6: Bulk status update UI with selection checkboxes, floating toolbar, status history recording
- F7: AI-powered evaluation summary with anonymized data, OpenAI integration, scoring patterns
- F8: Smart assignment improvements (geo diversity penalty, round familiarity bonus, COI blocking)
Batch 4 - Form Flexibility & Applicant Portal:
- F9: Evaluation form flexibility (text, boolean, section_header types, conditional visibility)
- F10: Applicant portal (status timeline, per-round documents, mentor messaging)
Schema: 5 new models (ReminderLog, ConflictOfInterest, EvaluationSummary, ProjectStatusHistory, MentorMessage), ProjectFile extended with roundId + isLate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:58:27 +01:00
|
|
|
getProjectRankings: observerProcedure
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
.input(editionOrStageInput.and(z.object({ limit: z.number().optional() })))
|
2026-01-30 13:41:32 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
2026-02-04 14:15:06 +01:00
|
|
|
const projects = await ctx.prisma.project.findMany({
|
2026-02-11 13:20:52 +01:00
|
|
|
where: projectWhere(input),
|
2026-02-05 20:31:08 +01:00
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
title: true,
|
|
|
|
|
teamName: true,
|
|
|
|
|
status: true,
|
2026-02-04 14:15:06 +01:00
|
|
|
assignments: {
|
2026-02-05 20:31:08 +01:00
|
|
|
select: {
|
2026-02-04 14:15:06 +01:00
|
|
|
evaluation: {
|
|
|
|
|
select: { criterionScoresJson: true, status: true },
|
2026-01-30 13:41:32 +01:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Calculate average scores
|
2026-02-04 14:15:06 +01:00
|
|
|
const rankings = projects
|
|
|
|
|
.map((project) => {
|
2026-01-30 13:41:32 +01:00
|
|
|
const allScores: number[] = []
|
|
|
|
|
|
|
|
|
|
project.assignments.forEach((assignment) => {
|
|
|
|
|
const evaluation = assignment.evaluation
|
|
|
|
|
if (evaluation?.status === 'SUBMITTED') {
|
|
|
|
|
const scores = evaluation.criterionScoresJson as Record<
|
|
|
|
|
string,
|
|
|
|
|
number
|
|
|
|
|
> | null
|
|
|
|
|
if (scores) {
|
|
|
|
|
const scoreValues = Object.values(scores).filter(
|
|
|
|
|
(s): s is number => typeof s === 'number'
|
|
|
|
|
)
|
|
|
|
|
if (scoreValues.length > 0) {
|
|
|
|
|
const average =
|
|
|
|
|
scoreValues.reduce((a, b) => a + b, 0) / scoreValues.length
|
|
|
|
|
allScores.push(average)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const averageScore =
|
|
|
|
|
allScores.length > 0
|
|
|
|
|
? allScores.reduce((a, b) => a + b, 0) / allScores.length
|
|
|
|
|
: null
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: project.id,
|
|
|
|
|
title: project.title,
|
|
|
|
|
teamName: project.teamName,
|
2026-02-04 14:15:06 +01:00
|
|
|
status: project.status,
|
2026-01-30 13:41:32 +01:00
|
|
|
averageScore,
|
|
|
|
|
evaluationCount: allScores.length,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.filter((p) => p.averageScore !== null)
|
|
|
|
|
.sort((a, b) => (b.averageScore || 0) - (a.averageScore || 0))
|
|
|
|
|
|
|
|
|
|
return input.limit ? rankings.slice(0, input.limit) : rankings
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get status breakdown (pie chart data)
|
|
|
|
|
*/
|
Implement 10 platform features: evaluation UX, admin tools, AI summaries, applicant portal
Batch 1 - Quick Wins:
- F1: Evaluation progress indicator with touch tracking in sticky status bar
- F2: Export filtering results as CSV with dynamic AI column flattening
- F3: Observer access to analytics dashboards (8 procedures changed to observerProcedure)
Batch 2 - Jury Experience:
- F4: Countdown timer component with urgency colors + email reminder service with cron endpoint
- F5: Conflict of interest declaration system (dialog, admin management, review workflow)
Batch 3 - Admin & AI Enhancements:
- F6: Bulk status update UI with selection checkboxes, floating toolbar, status history recording
- F7: AI-powered evaluation summary with anonymized data, OpenAI integration, scoring patterns
- F8: Smart assignment improvements (geo diversity penalty, round familiarity bonus, COI blocking)
Batch 4 - Form Flexibility & Applicant Portal:
- F9: Evaluation form flexibility (text, boolean, section_header types, conditional visibility)
- F10: Applicant portal (status timeline, per-round documents, mentor messaging)
Schema: 5 new models (ReminderLog, ConflictOfInterest, EvaluationSummary, ProjectStatusHistory, MentorMessage), ProjectFile extended with roundId + isLate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:58:27 +01:00
|
|
|
getStatusBreakdown: observerProcedure
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
.input(editionOrStageInput)
|
2026-01-30 13:41:32 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
2026-02-04 14:15:06 +01:00
|
|
|
const projects = await ctx.prisma.project.groupBy({
|
2026-01-30 13:41:32 +01:00
|
|
|
by: ['status'],
|
2026-02-11 13:20:52 +01:00
|
|
|
where: projectWhere(input),
|
2026-01-30 13:41:32 +01:00
|
|
|
_count: true,
|
|
|
|
|
})
|
|
|
|
|
|
2026-02-04 14:15:06 +01:00
|
|
|
return projects.map((p) => ({
|
|
|
|
|
status: p.status,
|
|
|
|
|
count: p._count,
|
2026-01-30 13:41:32 +01:00
|
|
|
}))
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get overview stats for dashboard
|
|
|
|
|
*/
|
Implement 10 platform features: evaluation UX, admin tools, AI summaries, applicant portal
Batch 1 - Quick Wins:
- F1: Evaluation progress indicator with touch tracking in sticky status bar
- F2: Export filtering results as CSV with dynamic AI column flattening
- F3: Observer access to analytics dashboards (8 procedures changed to observerProcedure)
Batch 2 - Jury Experience:
- F4: Countdown timer component with urgency colors + email reminder service with cron endpoint
- F5: Conflict of interest declaration system (dialog, admin management, review workflow)
Batch 3 - Admin & AI Enhancements:
- F6: Bulk status update UI with selection checkboxes, floating toolbar, status history recording
- F7: AI-powered evaluation summary with anonymized data, OpenAI integration, scoring patterns
- F8: Smart assignment improvements (geo diversity penalty, round familiarity bonus, COI blocking)
Batch 4 - Form Flexibility & Applicant Portal:
- F9: Evaluation form flexibility (text, boolean, section_header types, conditional visibility)
- F10: Applicant portal (status timeline, per-round documents, mentor messaging)
Schema: 5 new models (ReminderLog, ConflictOfInterest, EvaluationSummary, ProjectStatusHistory, MentorMessage), ProjectFile extended with roundId + isLate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:58:27 +01:00
|
|
|
getOverviewStats: observerProcedure
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
.input(editionOrStageInput)
|
2026-01-30 13:41:32 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
const [
|
|
|
|
|
projectCount,
|
|
|
|
|
assignmentCount,
|
|
|
|
|
evaluationCount,
|
|
|
|
|
jurorCount,
|
|
|
|
|
statusCounts,
|
|
|
|
|
] = await Promise.all([
|
2026-02-11 13:20:52 +01:00
|
|
|
ctx.prisma.project.count({ where: projectWhere(input) }),
|
|
|
|
|
ctx.prisma.assignment.count({ where: assignmentWhere(input) }),
|
2026-01-30 13:41:32 +01:00
|
|
|
ctx.prisma.evaluation.count({
|
2026-02-11 13:20:52 +01:00
|
|
|
where: evalWhere(input, { status: 'SUBMITTED' }),
|
2026-01-30 13:41:32 +01:00
|
|
|
}),
|
|
|
|
|
ctx.prisma.assignment.groupBy({
|
|
|
|
|
by: ['userId'],
|
2026-02-11 13:20:52 +01:00
|
|
|
where: assignmentWhere(input),
|
2026-01-30 13:41:32 +01:00
|
|
|
}),
|
2026-02-04 14:15:06 +01:00
|
|
|
ctx.prisma.project.groupBy({
|
2026-01-30 13:41:32 +01:00
|
|
|
by: ['status'],
|
2026-02-11 13:20:52 +01:00
|
|
|
where: projectWhere(input),
|
2026-01-30 13:41:32 +01:00
|
|
|
_count: true,
|
|
|
|
|
}),
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
const completionRate =
|
|
|
|
|
assignmentCount > 0
|
|
|
|
|
? Math.round((evaluationCount / assignmentCount) * 100)
|
|
|
|
|
: 0
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
projectCount,
|
|
|
|
|
assignmentCount,
|
|
|
|
|
evaluationCount,
|
|
|
|
|
jurorCount: jurorCount.length,
|
|
|
|
|
completionRate,
|
|
|
|
|
statusBreakdown: statusCounts.map((s) => ({
|
|
|
|
|
status: s.status,
|
|
|
|
|
count: s._count,
|
|
|
|
|
})),
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get criteria-level score distribution
|
|
|
|
|
*/
|
Implement 10 platform features: evaluation UX, admin tools, AI summaries, applicant portal
Batch 1 - Quick Wins:
- F1: Evaluation progress indicator with touch tracking in sticky status bar
- F2: Export filtering results as CSV with dynamic AI column flattening
- F3: Observer access to analytics dashboards (8 procedures changed to observerProcedure)
Batch 2 - Jury Experience:
- F4: Countdown timer component with urgency colors + email reminder service with cron endpoint
- F5: Conflict of interest declaration system (dialog, admin management, review workflow)
Batch 3 - Admin & AI Enhancements:
- F6: Bulk status update UI with selection checkboxes, floating toolbar, status history recording
- F7: AI-powered evaluation summary with anonymized data, OpenAI integration, scoring patterns
- F8: Smart assignment improvements (geo diversity penalty, round familiarity bonus, COI blocking)
Batch 4 - Form Flexibility & Applicant Portal:
- F9: Evaluation form flexibility (text, boolean, section_header types, conditional visibility)
- F10: Applicant portal (status timeline, per-round documents, mentor messaging)
Schema: 5 new models (ReminderLog, ConflictOfInterest, EvaluationSummary, ProjectStatusHistory, MentorMessage), ProjectFile extended with roundId + isLate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:58:27 +01:00
|
|
|
getCriteriaScores: observerProcedure
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
.input(editionOrStageInput)
|
2026-01-30 13:41:32 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
const formWhere = input.stageId
|
|
|
|
|
? { stageId: input.stageId, isActive: true }
|
|
|
|
|
: { stage: { track: { pipeline: { programId: input.programId! } } }, isActive: true }
|
2026-02-11 13:20:52 +01:00
|
|
|
|
|
|
|
|
const evaluationForms = await ctx.prisma.evaluationForm.findMany({
|
|
|
|
|
where: formWhere,
|
2026-01-30 13:41:32 +01:00
|
|
|
})
|
|
|
|
|
|
2026-02-11 13:20:52 +01:00
|
|
|
if (!evaluationForms.length) {
|
2026-01-30 13:41:32 +01:00
|
|
|
return []
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-11 13:20:52 +01:00
|
|
|
const criteriaMap = new Map<string, { id: string; label: string }>()
|
|
|
|
|
evaluationForms.forEach((form) => {
|
|
|
|
|
const criteria = form.criteriaJson as Array<{ id: string; label: string }> | null
|
|
|
|
|
if (criteria) {
|
|
|
|
|
criteria.forEach((c) => {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
const key = input.stageId ? c.id : c.label
|
2026-02-11 13:20:52 +01:00
|
|
|
if (!criteriaMap.has(key)) {
|
|
|
|
|
criteriaMap.set(key, c)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
2026-01-30 13:41:32 +01:00
|
|
|
|
2026-02-11 13:20:52 +01:00
|
|
|
const criteria = Array.from(criteriaMap.values())
|
|
|
|
|
if (criteria.length === 0) {
|
2026-01-30 13:41:32 +01:00
|
|
|
return []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get all evaluations
|
|
|
|
|
const evaluations = await ctx.prisma.evaluation.findMany({
|
2026-02-11 13:20:52 +01:00
|
|
|
where: evalWhere(input, { status: 'SUBMITTED' }),
|
2026-01-30 13:41:32 +01:00
|
|
|
select: { criterionScoresJson: true },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Calculate average score per criterion
|
|
|
|
|
const criteriaScores = criteria.map((criterion) => {
|
|
|
|
|
const scores: number[] = []
|
|
|
|
|
|
|
|
|
|
evaluations.forEach((evaluation) => {
|
|
|
|
|
const criterionScoresJson = evaluation.criterionScoresJson as Record<
|
|
|
|
|
string,
|
|
|
|
|
number
|
|
|
|
|
> | null
|
|
|
|
|
if (criterionScoresJson && typeof criterionScoresJson[criterion.id] === 'number') {
|
|
|
|
|
scores.push(criterionScoresJson[criterion.id])
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: criterion.id,
|
|
|
|
|
name: criterion.label,
|
|
|
|
|
averageScore:
|
|
|
|
|
scores.length > 0
|
|
|
|
|
? scores.reduce((a, b) => a + b, 0) / scores.length
|
|
|
|
|
: 0,
|
|
|
|
|
count: scores.length,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return criteriaScores
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get geographic distribution of projects by country
|
|
|
|
|
*/
|
Implement 10 platform features: evaluation UX, admin tools, AI summaries, applicant portal
Batch 1 - Quick Wins:
- F1: Evaluation progress indicator with touch tracking in sticky status bar
- F2: Export filtering results as CSV with dynamic AI column flattening
- F3: Observer access to analytics dashboards (8 procedures changed to observerProcedure)
Batch 2 - Jury Experience:
- F4: Countdown timer component with urgency colors + email reminder service with cron endpoint
- F5: Conflict of interest declaration system (dialog, admin management, review workflow)
Batch 3 - Admin & AI Enhancements:
- F6: Bulk status update UI with selection checkboxes, floating toolbar, status history recording
- F7: AI-powered evaluation summary with anonymized data, OpenAI integration, scoring patterns
- F8: Smart assignment improvements (geo diversity penalty, round familiarity bonus, COI blocking)
Batch 4 - Form Flexibility & Applicant Portal:
- F9: Evaluation form flexibility (text, boolean, section_header types, conditional visibility)
- F10: Applicant portal (status timeline, per-round documents, mentor messaging)
Schema: 5 new models (ReminderLog, ConflictOfInterest, EvaluationSummary, ProjectStatusHistory, MentorMessage), ProjectFile extended with roundId + isLate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:58:27 +01:00
|
|
|
getGeographicDistribution: observerProcedure
|
2026-01-30 13:41:32 +01:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
programId: z.string(),
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
stageId: z.string().optional(),
|
2026-01-30 13:41:32 +01:00
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
.query(async ({ ctx, input }) => {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
const where = input.stageId
|
|
|
|
|
? { assignments: { some: { stageId: input.stageId } } }
|
2026-02-10 21:21:54 +01:00
|
|
|
: { programId: input.programId }
|
2026-01-30 13:41:32 +01:00
|
|
|
|
|
|
|
|
const distribution = await ctx.prisma.project.groupBy({
|
|
|
|
|
by: ['country'],
|
2026-02-10 21:21:54 +01:00
|
|
|
where: { ...where, country: { not: null } },
|
2026-01-30 13:41:32 +01:00
|
|
|
_count: { id: true },
|
|
|
|
|
})
|
|
|
|
|
|
2026-02-13 23:45:21 +01:00
|
|
|
// Resolve country names to ISO codes (DB may store "France" instead of "FR")
|
|
|
|
|
const codeMap = new Map<string, number>()
|
|
|
|
|
for (const d of distribution) {
|
|
|
|
|
const resolved = normalizeCountryToCode(d.country) ?? d.country ?? 'UNKNOWN'
|
|
|
|
|
codeMap.set(resolved, (codeMap.get(resolved) ?? 0) + d._count.id)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Array.from(codeMap.entries()).map(([countryCode, count]) => ({
|
|
|
|
|
countryCode,
|
|
|
|
|
count,
|
2026-01-30 13:41:32 +01:00
|
|
|
}))
|
|
|
|
|
}),
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// Advanced Analytics (F10)
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
/**
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
* Compare metrics across multiple stages
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
*/
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
getCrossStageComparison: observerProcedure
|
|
|
|
|
.input(z.object({ stageIds: z.array(z.string()).min(2) }))
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
const comparisons = await Promise.all(
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
input.stageIds.map(async (stageId) => {
|
|
|
|
|
const stage = await ctx.prisma.stage.findUniqueOrThrow({
|
|
|
|
|
where: { id: stageId },
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
select: { id: true, name: true },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const [projectCount, assignmentCount, evaluationCount] = await Promise.all([
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
ctx.prisma.project.count({
|
|
|
|
|
where: { assignments: { some: { stageId } } },
|
|
|
|
|
}),
|
|
|
|
|
ctx.prisma.assignment.count({ where: { stageId } }),
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
ctx.prisma.evaluation.count({
|
|
|
|
|
where: {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
assignment: { stageId },
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
status: 'SUBMITTED',
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
const completionRate = assignmentCount > 0
|
|
|
|
|
? Math.round((evaluationCount / assignmentCount) * 100)
|
|
|
|
|
: 0
|
|
|
|
|
|
|
|
|
|
const evaluations = await ctx.prisma.evaluation.findMany({
|
|
|
|
|
where: {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
assignment: { stageId },
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
status: 'SUBMITTED',
|
|
|
|
|
},
|
|
|
|
|
select: { globalScore: true },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const globalScores = evaluations
|
|
|
|
|
.map((e) => e.globalScore)
|
|
|
|
|
.filter((s): s is number => s !== null)
|
|
|
|
|
|
|
|
|
|
const averageScore = globalScores.length > 0
|
|
|
|
|
? globalScores.reduce((a, b) => a + b, 0) / globalScores.length
|
|
|
|
|
: null
|
|
|
|
|
|
|
|
|
|
const distribution = Array.from({ length: 10 }, (_, i) => ({
|
|
|
|
|
score: i + 1,
|
|
|
|
|
count: globalScores.filter((s) => Math.round(s) === i + 1).length,
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
return {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
stageId,
|
|
|
|
|
stageName: stage.name,
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
projectCount,
|
|
|
|
|
evaluationCount,
|
|
|
|
|
completionRate,
|
|
|
|
|
averageScore,
|
|
|
|
|
scoreDistribution: distribution,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return comparisons
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
* Get juror consistency metrics for a stage
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
*/
|
|
|
|
|
getJurorConsistency: observerProcedure
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
.input(editionOrStageInput)
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
const evaluations = await ctx.prisma.evaluation.findMany({
|
2026-02-11 13:20:52 +01:00
|
|
|
where: evalWhere(input, { status: 'SUBMITTED' }),
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
include: {
|
|
|
|
|
assignment: {
|
|
|
|
|
include: {
|
|
|
|
|
user: { select: { id: true, name: true, email: true } },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Group scores by juror
|
|
|
|
|
const jurorScores: Record<string, { name: string; email: string; scores: number[] }> = {}
|
|
|
|
|
|
|
|
|
|
evaluations.forEach((e) => {
|
|
|
|
|
const userId = e.assignment.userId
|
|
|
|
|
if (!jurorScores[userId]) {
|
|
|
|
|
jurorScores[userId] = {
|
|
|
|
|
name: e.assignment.user.name || e.assignment.user.email || 'Unknown',
|
|
|
|
|
email: e.assignment.user.email || '',
|
|
|
|
|
scores: [],
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (e.globalScore !== null) {
|
|
|
|
|
jurorScores[userId].scores.push(e.globalScore)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Calculate overall average
|
|
|
|
|
const allScores = Object.values(jurorScores).flatMap((j) => j.scores)
|
|
|
|
|
const overallAverage = allScores.length > 0
|
|
|
|
|
? allScores.reduce((a, b) => a + b, 0) / allScores.length
|
|
|
|
|
: 0
|
|
|
|
|
|
|
|
|
|
// Calculate per-juror metrics
|
|
|
|
|
const metrics = Object.entries(jurorScores).map(([userId, data]) => {
|
|
|
|
|
const avg = data.scores.length > 0
|
|
|
|
|
? data.scores.reduce((a, b) => a + b, 0) / data.scores.length
|
|
|
|
|
: 0
|
|
|
|
|
const variance = data.scores.length > 1
|
|
|
|
|
? data.scores.reduce((sum, s) => sum + Math.pow(s - avg, 2), 0) / data.scores.length
|
|
|
|
|
: 0
|
|
|
|
|
const stddev = Math.sqrt(variance)
|
|
|
|
|
const deviationFromOverall = Math.abs(avg - overallAverage)
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
userId,
|
|
|
|
|
name: data.name,
|
|
|
|
|
email: data.email,
|
|
|
|
|
evaluationCount: data.scores.length,
|
|
|
|
|
averageScore: avg,
|
|
|
|
|
stddev,
|
|
|
|
|
deviationFromOverall,
|
|
|
|
|
isOutlier: deviationFromOverall > 2, // Flag if 2+ points from mean
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
overallAverage,
|
|
|
|
|
jurors: metrics.sort((a, b) => b.deviationFromOverall - a.deviationFromOverall),
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
* Get diversity metrics for projects in a stage
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
*/
|
|
|
|
|
getDiversityMetrics: observerProcedure
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
.input(editionOrStageInput)
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
const projects = await ctx.prisma.project.findMany({
|
2026-02-11 13:20:52 +01:00
|
|
|
where: projectWhere(input),
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
select: {
|
|
|
|
|
country: true,
|
|
|
|
|
competitionCategory: true,
|
|
|
|
|
oceanIssue: true,
|
|
|
|
|
tags: true,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const total = projects.length
|
|
|
|
|
if (total === 0) {
|
|
|
|
|
return { total: 0, byCountry: [], byCategory: [], byOceanIssue: [], byTag: [] }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// By country
|
|
|
|
|
const countryCounts: Record<string, number> = {}
|
|
|
|
|
projects.forEach((p) => {
|
|
|
|
|
const key = p.country || 'Unknown'
|
|
|
|
|
countryCounts[key] = (countryCounts[key] || 0) + 1
|
|
|
|
|
})
|
|
|
|
|
const byCountry = Object.entries(countryCounts)
|
|
|
|
|
.map(([country, count]) => ({ country, count, percentage: (count / total) * 100 }))
|
|
|
|
|
.sort((a, b) => b.count - a.count)
|
|
|
|
|
|
|
|
|
|
// By competition category
|
|
|
|
|
const categoryCounts: Record<string, number> = {}
|
|
|
|
|
projects.forEach((p) => {
|
|
|
|
|
const key = p.competitionCategory || 'Uncategorized'
|
|
|
|
|
categoryCounts[key] = (categoryCounts[key] || 0) + 1
|
|
|
|
|
})
|
|
|
|
|
const byCategory = Object.entries(categoryCounts)
|
|
|
|
|
.map(([category, count]) => ({ category, count, percentage: (count / total) * 100 }))
|
|
|
|
|
.sort((a, b) => b.count - a.count)
|
|
|
|
|
|
|
|
|
|
// By ocean issue
|
|
|
|
|
const issueCounts: Record<string, number> = {}
|
|
|
|
|
projects.forEach((p) => {
|
|
|
|
|
const key = p.oceanIssue || 'Unspecified'
|
|
|
|
|
issueCounts[key] = (issueCounts[key] || 0) + 1
|
|
|
|
|
})
|
|
|
|
|
const byOceanIssue = Object.entries(issueCounts)
|
|
|
|
|
.map(([issue, count]) => ({ issue, count, percentage: (count / total) * 100 }))
|
|
|
|
|
.sort((a, b) => b.count - a.count)
|
|
|
|
|
|
|
|
|
|
// By tag
|
|
|
|
|
const tagCounts: Record<string, number> = {}
|
|
|
|
|
projects.forEach((p) => {
|
|
|
|
|
p.tags.forEach((tag) => {
|
|
|
|
|
tagCounts[tag] = (tagCounts[tag] || 0) + 1
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
const byTag = Object.entries(tagCounts)
|
|
|
|
|
.map(([tag, count]) => ({ tag, count, percentage: (count / total) * 100 }))
|
|
|
|
|
.sort((a, b) => b.count - a.count)
|
|
|
|
|
|
|
|
|
|
return { total, byCountry, byCategory, byOceanIssue, byTag }
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
* Get year-over-year stats across all stages in a program
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
*/
|
|
|
|
|
getYearOverYear: observerProcedure
|
|
|
|
|
.input(z.object({ programId: z.string() }))
|
|
|
|
|
.query(async ({ ctx, input }) => {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
const stages = await ctx.prisma.stage.findMany({
|
|
|
|
|
where: { track: { pipeline: { programId: input.programId } } },
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
select: { id: true, name: true, createdAt: true },
|
|
|
|
|
orderBy: { createdAt: 'asc' },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const stats = await Promise.all(
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
stages.map(async (stage) => {
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
const [projectCount, evaluationCount, assignmentCount] = await Promise.all([
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
ctx.prisma.project.count({
|
|
|
|
|
where: { assignments: { some: { stageId: stage.id } } },
|
|
|
|
|
}),
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
ctx.prisma.evaluation.count({
|
|
|
|
|
where: {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
assignment: { stageId: stage.id },
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
status: 'SUBMITTED',
|
|
|
|
|
},
|
|
|
|
|
}),
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
ctx.prisma.assignment.count({ where: { stageId: stage.id } }),
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
])
|
|
|
|
|
|
|
|
|
|
const completionRate = assignmentCount > 0
|
|
|
|
|
? Math.round((evaluationCount / assignmentCount) * 100)
|
|
|
|
|
: 0
|
|
|
|
|
|
|
|
|
|
const evaluations = await ctx.prisma.evaluation.findMany({
|
|
|
|
|
where: {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
assignment: { stageId: stage.id },
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
status: 'SUBMITTED',
|
|
|
|
|
},
|
|
|
|
|
select: { globalScore: true },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const scores = evaluations
|
|
|
|
|
.map((e) => e.globalScore)
|
|
|
|
|
.filter((s): s is number => s !== null)
|
|
|
|
|
|
|
|
|
|
const averageScore = scores.length > 0
|
|
|
|
|
? scores.reduce((a, b) => a + b, 0) / scores.length
|
|
|
|
|
: null
|
|
|
|
|
|
|
|
|
|
return {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
stageId: stage.id,
|
|
|
|
|
stageName: stage.name,
|
|
|
|
|
createdAt: stage.createdAt,
|
Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher
Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download
All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
|
|
|
projectCount,
|
|
|
|
|
evaluationCount,
|
|
|
|
|
completionRate,
|
|
|
|
|
averageScore,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return stats
|
|
|
|
|
}),
|
2026-02-10 23:08:00 +01:00
|
|
|
|
|
|
|
|
/**
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
* Get dashboard stats (optionally scoped to a stage)
|
2026-02-10 23:08:00 +01:00
|
|
|
*/
|
|
|
|
|
getDashboardStats: observerProcedure
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
.input(z.object({ stageId: z.string().optional() }).optional())
|
2026-02-10 23:08:00 +01:00
|
|
|
.query(async ({ ctx, input }) => {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
const stageId = input?.stageId
|
|
|
|
|
|
|
|
|
|
const projectFilter = stageId
|
|
|
|
|
? { assignments: { some: { stageId } } }
|
|
|
|
|
: {}
|
|
|
|
|
const assignmentFilter = stageId ? { stageId } : {}
|
|
|
|
|
const evalFilter = stageId
|
|
|
|
|
? { assignment: { stageId }, status: 'SUBMITTED' as const }
|
2026-02-10 23:08:00 +01:00
|
|
|
: { status: 'SUBMITTED' as const }
|
|
|
|
|
|
|
|
|
|
const [
|
|
|
|
|
programCount,
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
activeStageCount,
|
2026-02-10 23:08:00 +01:00
|
|
|
projectCount,
|
|
|
|
|
jurorCount,
|
|
|
|
|
submittedEvaluations,
|
|
|
|
|
totalAssignments,
|
|
|
|
|
evaluationScores,
|
|
|
|
|
] = await Promise.all([
|
|
|
|
|
ctx.prisma.program.count(),
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
ctx.prisma.stage.count({ where: { status: 'STAGE_ACTIVE' } }),
|
|
|
|
|
ctx.prisma.project.count({ where: projectFilter }),
|
2026-02-10 23:08:00 +01:00
|
|
|
ctx.prisma.user.count({ where: { role: 'JURY_MEMBER', status: 'ACTIVE' } }),
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
ctx.prisma.evaluation.count({ where: evalFilter }),
|
|
|
|
|
ctx.prisma.assignment.count({ where: assignmentFilter }),
|
2026-02-10 23:08:00 +01:00
|
|
|
ctx.prisma.evaluation.findMany({
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
where: { ...evalFilter, globalScore: { not: null } },
|
2026-02-10 23:08:00 +01:00
|
|
|
select: { globalScore: true },
|
|
|
|
|
}),
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
const completionRate = totalAssignments > 0
|
|
|
|
|
? Math.round((submittedEvaluations / totalAssignments) * 100)
|
|
|
|
|
: 0
|
|
|
|
|
|
|
|
|
|
const scores = evaluationScores.map((e) => e.globalScore!).filter((s) => s != null)
|
|
|
|
|
const scoreDistribution = [
|
|
|
|
|
{ label: '9-10', min: 9, max: 10 },
|
|
|
|
|
{ label: '7-8', min: 7, max: 8.99 },
|
|
|
|
|
{ label: '5-6', min: 5, max: 6.99 },
|
|
|
|
|
{ label: '3-4', min: 3, max: 4.99 },
|
|
|
|
|
{ label: '1-2', min: 1, max: 2.99 },
|
|
|
|
|
].map((b) => ({
|
|
|
|
|
label: b.label,
|
|
|
|
|
count: scores.filter((s) => s >= b.min && s <= b.max).length,
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
programCount,
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
activeStageCount,
|
2026-02-10 23:08:00 +01:00
|
|
|
projectCount,
|
|
|
|
|
jurorCount,
|
|
|
|
|
submittedEvaluations,
|
|
|
|
|
totalEvaluations: totalAssignments,
|
|
|
|
|
completionRate,
|
|
|
|
|
scoreDistribution,
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
// =========================================================================
|
|
|
|
|
// Stage-Scoped Analytics (Phase 4)
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get score distribution histogram for stage evaluations
|
|
|
|
|
*/
|
|
|
|
|
getStageScoreDistribution: observerProcedure
|
|
|
|
|
.input(z.object({ stageId: z.string() }))
|
|
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
const evaluations = await ctx.prisma.evaluation.findMany({
|
|
|
|
|
where: {
|
|
|
|
|
status: 'SUBMITTED',
|
|
|
|
|
assignment: { stageId: input.stageId },
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
globalScore: true,
|
|
|
|
|
criterionScoresJson: true,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Global score distribution (1-10 buckets)
|
|
|
|
|
const globalScores = evaluations
|
|
|
|
|
.map((e) => e.globalScore)
|
|
|
|
|
.filter((s): s is number => s !== null)
|
|
|
|
|
|
|
|
|
|
const globalDistribution = Array.from({ length: 10 }, (_, i) => ({
|
|
|
|
|
score: i + 1,
|
|
|
|
|
count: globalScores.filter((s) => Math.round(s) === i + 1).length,
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
// Per-criterion score distribution
|
|
|
|
|
const criterionScores: Record<string, number[]> = {}
|
|
|
|
|
evaluations.forEach((e) => {
|
|
|
|
|
const scores = e.criterionScoresJson as Record<string, number> | null
|
|
|
|
|
if (scores) {
|
|
|
|
|
Object.entries(scores).forEach(([key, value]) => {
|
|
|
|
|
if (typeof value === 'number') {
|
|
|
|
|
if (!criterionScores[key]) criterionScores[key] = []
|
|
|
|
|
criterionScores[key].push(value)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const criterionDistributions = Object.entries(criterionScores).map(([criterionId, scores]) => ({
|
|
|
|
|
criterionId,
|
|
|
|
|
average: scores.reduce((a, b) => a + b, 0) / scores.length,
|
|
|
|
|
count: scores.length,
|
|
|
|
|
distribution: Array.from({ length: 10 }, (_, i) => ({
|
|
|
|
|
score: i + 1,
|
|
|
|
|
count: scores.filter((s) => Math.round(s) === i + 1).length,
|
|
|
|
|
})),
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
globalDistribution,
|
|
|
|
|
totalEvaluations: evaluations.length,
|
|
|
|
|
averageGlobalScore:
|
|
|
|
|
globalScores.length > 0
|
|
|
|
|
? globalScores.reduce((a, b) => a + b, 0) / globalScores.length
|
|
|
|
|
: 0,
|
|
|
|
|
criterionDistributions,
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get per-stage completion summary for a pipeline
|
|
|
|
|
*/
|
|
|
|
|
getStageCompletionOverview: observerProcedure
|
|
|
|
|
.input(z.object({ pipelineId: z.string() }))
|
|
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
// Get all stages in the pipeline via tracks
|
|
|
|
|
const tracks = await ctx.prisma.track.findMany({
|
|
|
|
|
where: { pipelineId: input.pipelineId },
|
|
|
|
|
include: {
|
|
|
|
|
stages: {
|
|
|
|
|
orderBy: { sortOrder: 'asc' },
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
name: true,
|
|
|
|
|
stageType: true,
|
|
|
|
|
status: true,
|
|
|
|
|
sortOrder: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
orderBy: { sortOrder: 'asc' },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const stages = tracks.flatMap((t) =>
|
|
|
|
|
t.stages.map((s) => ({ ...s, trackName: t.name, trackId: t.id }))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// For each stage, get project counts, assignment coverage, evaluation completion
|
|
|
|
|
const stageOverviews = await Promise.all(
|
|
|
|
|
stages.map(async (stage) => {
|
|
|
|
|
const [
|
|
|
|
|
projectStates,
|
|
|
|
|
totalAssignments,
|
|
|
|
|
completedEvaluations,
|
|
|
|
|
distinctJurors,
|
|
|
|
|
] = await Promise.all([
|
|
|
|
|
ctx.prisma.projectStageState.groupBy({
|
|
|
|
|
by: ['state'],
|
|
|
|
|
where: { stageId: stage.id },
|
|
|
|
|
_count: true,
|
|
|
|
|
}),
|
|
|
|
|
ctx.prisma.assignment.count({
|
|
|
|
|
where: { stageId: stage.id },
|
|
|
|
|
}),
|
|
|
|
|
ctx.prisma.evaluation.count({
|
|
|
|
|
where: {
|
|
|
|
|
assignment: { stageId: stage.id },
|
|
|
|
|
status: 'SUBMITTED',
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
ctx.prisma.assignment.groupBy({
|
|
|
|
|
by: ['userId'],
|
|
|
|
|
where: { stageId: stage.id },
|
|
|
|
|
}),
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
const stateBreakdown = projectStates.map((ps) => ({
|
|
|
|
|
state: ps.state,
|
|
|
|
|
count: ps._count,
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
const totalProjects = projectStates.reduce((sum, ps) => sum + ps._count, 0)
|
|
|
|
|
const completionRate = totalAssignments > 0
|
|
|
|
|
? Math.round((completedEvaluations / totalAssignments) * 100)
|
|
|
|
|
: 0
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
stageId: stage.id,
|
|
|
|
|
stageName: stage.name,
|
|
|
|
|
stageType: stage.stageType,
|
|
|
|
|
stageStatus: stage.status,
|
|
|
|
|
trackName: stage.trackName,
|
|
|
|
|
trackId: stage.trackId,
|
|
|
|
|
sortOrder: stage.sortOrder,
|
|
|
|
|
totalProjects,
|
|
|
|
|
stateBreakdown,
|
|
|
|
|
totalAssignments,
|
|
|
|
|
completedEvaluations,
|
|
|
|
|
pendingEvaluations: totalAssignments - completedEvaluations,
|
|
|
|
|
completionRate,
|
|
|
|
|
jurorCount: distinctJurors.length,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
pipelineId: input.pipelineId,
|
|
|
|
|
stages: stageOverviews,
|
|
|
|
|
summary: {
|
|
|
|
|
totalStages: stages.length,
|
|
|
|
|
totalProjects: stageOverviews.reduce((sum, s) => sum + s.totalProjects, 0),
|
|
|
|
|
totalAssignments: stageOverviews.reduce((sum, s) => sum + s.totalAssignments, 0),
|
|
|
|
|
totalCompleted: stageOverviews.reduce((sum, s) => sum + s.completedEvaluations, 0),
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// Award Analytics (Phase 5)
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get per-award-track summary for a pipeline
|
|
|
|
|
*/
|
|
|
|
|
getAwardSummary: observerProcedure
|
|
|
|
|
.input(z.object({ pipelineId: z.string() }))
|
|
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
// Find all AWARD tracks in the pipeline
|
|
|
|
|
const awardTracks = await ctx.prisma.track.findMany({
|
|
|
|
|
where: { pipelineId: input.pipelineId, kind: 'AWARD' },
|
|
|
|
|
include: {
|
|
|
|
|
specialAward: {
|
|
|
|
|
include: {
|
|
|
|
|
winnerProject: { select: { id: true, title: true, teamName: true } },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
stages: {
|
|
|
|
|
orderBy: { sortOrder: 'asc' },
|
|
|
|
|
select: { id: true, name: true, stageType: true, status: true },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
orderBy: { sortOrder: 'asc' },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const awards = await Promise.all(
|
|
|
|
|
awardTracks.map(async (track) => {
|
|
|
|
|
const award = track.specialAward
|
|
|
|
|
|
|
|
|
|
// Count projects in this track (active PSS)
|
|
|
|
|
const projectCount = await ctx.prisma.projectStageState.count({
|
|
|
|
|
where: { trackId: track.id },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Count evaluations in this track's stages
|
|
|
|
|
const stageIds = track.stages.map((s) => s.id)
|
|
|
|
|
const [totalAssignments, completedEvals] = await Promise.all([
|
|
|
|
|
ctx.prisma.assignment.count({
|
|
|
|
|
where: { stageId: { in: stageIds } },
|
|
|
|
|
}),
|
|
|
|
|
ctx.prisma.evaluation.count({
|
|
|
|
|
where: {
|
|
|
|
|
assignment: { stageId: { in: stageIds } },
|
|
|
|
|
status: 'SUBMITTED',
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
const completionRate = totalAssignments > 0
|
|
|
|
|
? Math.round((completedEvals / totalAssignments) * 100)
|
|
|
|
|
: 0
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
trackId: track.id,
|
|
|
|
|
trackName: track.name,
|
|
|
|
|
routingMode: track.routingMode,
|
|
|
|
|
awardId: award?.id ?? null,
|
|
|
|
|
awardName: award?.name ?? track.name,
|
|
|
|
|
awardStatus: award?.status ?? null,
|
|
|
|
|
scoringMode: award?.scoringMode ?? null,
|
|
|
|
|
projectCount,
|
|
|
|
|
totalAssignments,
|
|
|
|
|
completedEvaluations: completedEvals,
|
|
|
|
|
completionRate,
|
|
|
|
|
winner: award?.winnerProject
|
|
|
|
|
? {
|
|
|
|
|
projectId: award.winnerProject.id,
|
|
|
|
|
title: award.winnerProject.title,
|
|
|
|
|
teamName: award.winnerProject.teamName,
|
|
|
|
|
overridden: award.winnerOverridden,
|
|
|
|
|
}
|
|
|
|
|
: null,
|
|
|
|
|
stages: track.stages,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return awards
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get per-project vote/score distribution for an award stage
|
|
|
|
|
*/
|
|
|
|
|
getAwardVoteDistribution: observerProcedure
|
|
|
|
|
.input(z.object({ stageId: z.string() }))
|
|
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
// Get all evaluations for this stage
|
|
|
|
|
const evaluations = await ctx.prisma.evaluation.findMany({
|
|
|
|
|
where: {
|
|
|
|
|
status: 'SUBMITTED',
|
|
|
|
|
assignment: { stageId: input.stageId },
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
globalScore: true,
|
|
|
|
|
assignment: {
|
|
|
|
|
select: {
|
|
|
|
|
projectId: true,
|
|
|
|
|
project: { select: { title: true, teamName: true } },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Also get any AwardVotes linked to the stage's track's award
|
|
|
|
|
const stage = await ctx.prisma.stage.findUnique({
|
|
|
|
|
where: { id: input.stageId },
|
|
|
|
|
select: {
|
|
|
|
|
track: {
|
|
|
|
|
select: {
|
|
|
|
|
specialAward: {
|
|
|
|
|
select: { id: true },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const awardId = stage?.track?.specialAward?.id
|
|
|
|
|
let awardVotes: Array<{ projectId: string; rank: number | null }> = []
|
|
|
|
|
if (awardId) {
|
|
|
|
|
awardVotes = await ctx.prisma.awardVote.findMany({
|
|
|
|
|
where: { awardId },
|
|
|
|
|
select: { projectId: true, rank: true },
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Group evaluation scores by project
|
|
|
|
|
const projectMap = new Map<string, {
|
|
|
|
|
title: string
|
|
|
|
|
teamName: string | null
|
|
|
|
|
scores: number[]
|
|
|
|
|
voteCount: number
|
|
|
|
|
avgRank: number | null
|
|
|
|
|
}>()
|
|
|
|
|
|
|
|
|
|
for (const ev of evaluations) {
|
|
|
|
|
const pid = ev.assignment.projectId
|
|
|
|
|
if (!projectMap.has(pid)) {
|
|
|
|
|
projectMap.set(pid, {
|
|
|
|
|
title: ev.assignment.project.title,
|
|
|
|
|
teamName: ev.assignment.project.teamName,
|
|
|
|
|
scores: [],
|
|
|
|
|
voteCount: 0,
|
|
|
|
|
avgRank: null,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
if (ev.globalScore !== null) {
|
|
|
|
|
projectMap.get(pid)!.scores.push(ev.globalScore)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Merge award votes
|
|
|
|
|
const ranksByProject = new Map<string, number[]>()
|
|
|
|
|
for (const vote of awardVotes) {
|
|
|
|
|
const entry = projectMap.get(vote.projectId)
|
|
|
|
|
if (entry) {
|
|
|
|
|
entry.voteCount++
|
|
|
|
|
}
|
|
|
|
|
if (vote.rank !== null) {
|
|
|
|
|
if (!ranksByProject.has(vote.projectId)) ranksByProject.set(vote.projectId, [])
|
|
|
|
|
ranksByProject.get(vote.projectId)!.push(vote.rank)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calculate averages
|
|
|
|
|
const results = Array.from(projectMap.entries()).map(([projectId, data]) => {
|
|
|
|
|
const avgScore = data.scores.length > 0
|
|
|
|
|
? data.scores.reduce((a, b) => a + b, 0) / data.scores.length
|
|
|
|
|
: null
|
|
|
|
|
const minScore = data.scores.length > 0 ? Math.min(...data.scores) : null
|
|
|
|
|
const maxScore = data.scores.length > 0 ? Math.max(...data.scores) : null
|
|
|
|
|
|
|
|
|
|
const ranks = ranksByProject.get(projectId)
|
|
|
|
|
const avgRank = ranks?.length
|
|
|
|
|
? ranks.reduce((a, b) => a + b, 0) / ranks.length
|
|
|
|
|
: null
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
projectId,
|
|
|
|
|
title: data.title,
|
|
|
|
|
teamName: data.teamName,
|
|
|
|
|
evaluationCount: data.scores.length,
|
|
|
|
|
voteCount: data.voteCount,
|
|
|
|
|
avgScore,
|
|
|
|
|
minScore,
|
|
|
|
|
maxScore,
|
|
|
|
|
avgRank,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Sort by avgScore descending
|
|
|
|
|
results.sort((a, b) => (b.avgScore ?? 0) - (a.avgScore ?? 0))
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
stageId: input.stageId,
|
|
|
|
|
projects: results,
|
|
|
|
|
totalEvaluations: evaluations.length,
|
|
|
|
|
totalVotes: awardVotes.length,
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
|
2026-02-10 23:08:00 +01:00
|
|
|
/**
|
|
|
|
|
* Get all projects with pagination, filtering, and search (for observer dashboard)
|
|
|
|
|
*/
|
|
|
|
|
getAllProjects: observerProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
stageId: z.string().optional(),
|
2026-02-10 23:08:00 +01:00
|
|
|
search: z.string().optional(),
|
|
|
|
|
status: z.string().optional(),
|
|
|
|
|
page: z.number().min(1).default(1),
|
|
|
|
|
perPage: z.number().min(1).max(100).default(20),
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
.query(async ({ ctx, input }) => {
|
|
|
|
|
const where: Record<string, unknown> = {}
|
|
|
|
|
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
if (input.stageId) {
|
|
|
|
|
where.assignments = { some: { stageId: input.stageId } }
|
2026-02-10 23:08:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input.status) {
|
|
|
|
|
where.status = input.status
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input.search) {
|
|
|
|
|
where.OR = [
|
|
|
|
|
{ title: { contains: input.search, mode: 'insensitive' } },
|
|
|
|
|
{ teamName: { contains: input.search, mode: 'insensitive' } },
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const [projects, total] = await Promise.all([
|
|
|
|
|
ctx.prisma.project.findMany({
|
|
|
|
|
where,
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
title: true,
|
|
|
|
|
teamName: true,
|
|
|
|
|
status: true,
|
|
|
|
|
country: true,
|
|
|
|
|
assignments: {
|
|
|
|
|
select: {
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
stageId: true,
|
|
|
|
|
stage: { select: { id: true, name: true } },
|
2026-02-10 23:08:00 +01:00
|
|
|
evaluation: {
|
|
|
|
|
select: { globalScore: true, status: true },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
orderBy: { title: 'asc' },
|
|
|
|
|
skip: (input.page - 1) * input.perPage,
|
|
|
|
|
take: input.perPage,
|
|
|
|
|
}),
|
|
|
|
|
ctx.prisma.project.count({ where }),
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
const mapped = projects.map((p) => {
|
|
|
|
|
const submitted = p.assignments
|
|
|
|
|
.map((a) => a.evaluation)
|
|
|
|
|
.filter((e) => e?.status === 'SUBMITTED')
|
|
|
|
|
const scores = submitted
|
|
|
|
|
.map((e) => e?.globalScore)
|
|
|
|
|
.filter((s): s is number => s !== null)
|
|
|
|
|
const averageScore =
|
|
|
|
|
scores.length > 0
|
|
|
|
|
? scores.reduce((a, b) => a + b, 0) / scores.length
|
|
|
|
|
: null
|
|
|
|
|
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
const firstAssignment = p.assignments[0]
|
|
|
|
|
|
2026-02-10 23:08:00 +01:00
|
|
|
return {
|
|
|
|
|
id: p.id,
|
|
|
|
|
title: p.title,
|
|
|
|
|
teamName: p.teamName,
|
|
|
|
|
status: p.status,
|
|
|
|
|
country: p.country,
|
Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.
Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.
Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).
Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.
Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.
Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
|
|
|
stageId: firstAssignment?.stage?.id ?? '',
|
|
|
|
|
stageName: firstAssignment?.stage?.name ?? '',
|
2026-02-10 23:08:00 +01:00
|
|
|
averageScore,
|
|
|
|
|
evaluationCount: submitted.length,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
projects: mapped,
|
|
|
|
|
total,
|
|
|
|
|
page: input.page,
|
|
|
|
|
perPage: input.perPage,
|
|
|
|
|
totalPages: Math.ceil(total / input.perPage),
|
|
|
|
|
}
|
|
|
|
|
}),
|
2026-01-30 13:41:32 +01:00
|
|
|
})
|