Applicant saveFileMetadata and deleteFile mutations now log
APPLICANT_UPLOAD_FILE and APPLICANT_DELETE_FILE to the audit trail,
matching the admin file router's existing audit coverage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add getSemiFinalistStats query with per-category/per-award breakdown
- Add sendAccountReminders mutation with invite token generation and dedup
- Add SemiFinalistTracker dashboard widget with progress bars and remind buttons
- Add ACCOUNT_REMINDER email template
- Extend project search to match team member name/email (7 locations)
- Fix Passed count deduplication: count distinct projects, not round-state rows
- Fix role switcher: visible pills above user section, auto-refresh session on mount
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add attachProjectLogoUrls utility mirroring avatar URL pattern. Pipe
project.list and analytics.getAllProjects through logo URL resolver so
ProjectLogo components receive presigned URLs. Add logos to observer
projects table and mobile cards.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix round-specific document uploads (submittedAt no longer blocks uploads),
add view/download buttons for existing files, enforce active-round-only for
uploads/deletes. Harden auth layout and set-password page. Filter applicant
portal rounds by award track membership.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Custom body support for advancement/rejection notification emails, evaluation
config toggle fix, user actions improvements, round finalization with reorder
support, project detail page enhancements, award pool duplicate prevention.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add notifiedAt field to AwardEligibility. notifyEligibleProjects now
skips already-notified entries and stamps notifiedAt after sending,
so re-clicking "Notify Pool" only emails newly added projects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- getNavFlags/getMyEvaluations: return empty when project has no round
states instead of dropping the filter (prevented phantom eval rounds)
- getUpcomingDeadlines: detect isInAwardTrack from ProjectRoundState
join instead of pre-filtered deadline rounds
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Projects in SEPARATE_POOL awards now only see their award rounds (not main
pool rounds) across all applicant queries: openRounds, deadlines, document
completeness, nav flags, and evaluations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The email was implying projects had won the award. Updated banner, subject,
and body copy to clarify they are being considered, not awarded.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add drag-and-drop round reordering on award detail Rounds tab (dnd-kit)
- Replace "Open Voting" with "Assign to First Round" for SEPARATE_POOL awards
- Add reorderAwardRounds mutation (two-phase transaction for unique constraint)
- Add assignToFirstRound mutation (re-runnable, moves/creates ProjectRoundState)
- Extend applicant timeline to show award-specific rounds for SEPARATE_POOL projects
- Hide irrelevant main competition rounds when project is in award track
- Prefix award round labels with award name in timeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add admin settings: learning_hub_external, learning_hub_external_url, support_email
- Jury/Mentor nav respects external Learning Hub URL (opens in new tab)
- RoleNav supports external nav items with ExternalLink icon
- Applicant header shows Help button with configurable support email
- Settings update mutation now upserts (creates on first use)
- Shared inferSettingCategory for consistent category assignment
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Award "Notify Pool" dialog now uses EmailPreviewDialog with live preview
- Button shows eligible project count: "Notify Pool (38)"
- Finalization tab email section has "Preview" buttons for both
advancement and rejection messages
- EmailPreviewDialog supports previewOnly mode (close button, no send)
- Backend: previewAwardSelectionEmail, previewFinalizationAdvancementEmail,
previewFinalizationRejectionEmail queries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- processRoundClose now applies reordersJson drag-reorder overrides
when building the evaluation pass set (was ignoring admin reorders)
- Finalization tab groups proposed outcomes by category (Startup/Concept)
with per-group pass/reject/total counts
- Added category filter dropdown alongside the existing outcome filter
- Removed legacy "Advance Top N" button and dialog from ranking page
(replaced by the finalization workflow)
- Fix project edit status defaultValue showing empty placeholder
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- processRoundClose EVALUATION uses ranking scores + advanceMode config
(threshold vs count) to auto-set proposedOutcome instead of defaulting all to PASSED
- Advancement emails generate invite tokens for passwordless users with
"Create Your Account" CTA; rejection emails have no link
- Finalization UI shows account stats (invite vs dashboard link counts)
- Fixed getFinalizationSummary ranking query (was using non-existent rankingsJson)
- New award pool notification system: getAwardSelectionNotificationTemplate email,
notifyEligibleProjects mutation with invite token generation,
"Notify Pool" button on award detail page with custom message dialog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add scoreWeight and passRateWeight (0-10) to evaluation config for
configurable composite score formula. When ranking criteria text is
empty, triggerAutoRank uses pure formula ranking (no LLM calls).
When criteria text is present, AI-assisted ranking runs as before.
- Add FORMULA to RankingMode enum with migration
- Extract fetchCategoryProjects helper, add formulaRank service
- Update computeCompositeScore to accept configurable weights
- Add score/pass-rate weight sliders to ranking dashboard UI
- Mode-aware button labels (Calculator/formula vs Sparkles/AI)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create snapshot with status RUNNING before AI call starts
- Update to COMPLETED/FAILED when done
- Dashboard derives rankingInProgress from server snapshot status
- All admins see the spinner, not just the one who triggered it
- Poll snapshots every 3s so progress updates appear quickly
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Sort all ranked projects by compositeScore descending so highest-rated
projects always appear first (instead of relying on AI's inconsistent rank order)
- Deduplicate AI ranking response (AI sometimes returns same project multiple times)
- Deduplicate ranking entries and reorder IDs on dashboard load as defensive measure
- Show advancement cutoff line only once (precompute last advancing index)
- Override badge only shown when admin has actually drag-reordered (not on fresh rankings)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a round is reopened (ROUND_CLOSED → ROUND_ACTIVE), the old
windowCloseAt was still in the past, causing jury submissions to fail
with "Voting window has closed" even though the round status was active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AI ranking now includes ALL projects (never filters/excludes any)
- Updated system prompt: filter criteria inform priority, not exclusion
- Dynamic maxTokens scaling for large project pools (80 tokens/project)
- Fallback: projects AI omits are appended sorted by composite score
- Override badge uses snapshotOrder state (synced with localOrder in same
useEffect) instead of rankingMap.originalIndex to prevent stale-render
mismatch where all items incorrectly showed as overridden
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backfilled 166 evaluations' binaryDecision from criterionScoresJson on production DB
- Fixed roundEvaluationScores and ai-ranking to look in EvaluationForm.criteriaJson
instead of round.configJson for the boolean "Move to the Next Stage?" criterion
- Added advanceMode (count/threshold) toggle to round config Advancement Targets
- Added "Assign to Jurors" button on Unassigned Projects section and Projects tab bulk bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add criteriaWeights to EvaluationConfig for per-criterion weight assignment (0-10)
- Rewrite ai-ranking service: fetch eval form criteria, compute per-criterion averages,
z-score normalize juror scores to correct grading bias, send weighted criteria to AI
- Update AI prompts with criteria_definitions and per-project criteria_scores
- compositeScore uses weighted criteria when configured, falls back to globalScore
- Add collapsible ranking config section to dashboard (criteria text + weight sliders)
- Move rankingCriteria textarea from eval config tab to ranking dashboard
- Store criteriaWeights in ranking snapshot parsedRulesJson for audit
- Enhance projectScores CSV export with per-criterion averages, category, country
- Add Export CSV button to ranking dashboard header
- Add threshold-based advancement mode (decimal score threshold, e.g. 6.5)
alongside existing top-N mode in advance dialog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add adminEditEvaluation mutation and getJurorEvaluations query
- Create shared EvaluationEditSheet component with inline feedback editing
- Add Evaluations tab to member detail page (grouped by round)
- Make jury group member names clickable (link to member detail)
- Replace inline EvaluationDetailSheet on project page with shared component
- Fix project status transition validation (skip when status unchanged)
- Fix frontend to not send status when unchanged on project edit
- Ranking dashboard improvements and boolean decision converter fixes
- Backfill script updates for binary decisions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add nationality/institution fields to User model with migration
- Applicant onboarding wizard (name, photo, nationality, country, institution, bio, project logo, preferences)
- Project logo upload from applicant context with team membership verification
- APPLICANT redirects in set-password, onboarding, and auth layout
- Mask evaluation round names as "Evaluation Round 1/2/..." for applicants
- Extend inviteTeamMember with nationality/country/institution/sendInvite fields
- Admin getApplicants query with search/filter/pagination
- Admin bulkInviteApplicants mutation with token generation and emails
- Applicants tab on Members page with bulk select and floating invite bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a new tRPC procedure `round.getSubmissionRoundForProgram` that
fetches the most recent SUBMISSION round for a given program, then
displays any `requiredDocuments` from its configJson as labeled info
cards above the general file upload section on the project edit page.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ProjectStatesTable local search now covers country, institution, competitionCategory, geographicZone
- project-pool.ts DB search extended to institution, country, geographicZone, team member names
- AwardShortlist eligibility table gains a search input filtering by title, team, country, institution, category
- IndividualAssignmentsTable project filter extended to include country and institution
- Add "Generate AI Tags" dropdown item per row in ProjectStatesTable using tag.tagProject mutation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add optional roundId field to project.create mutation input schema
- After project creation, update project.roundId FK and create a
ProjectRoundState record (state: PENDING) when roundId is supplied
- Pass selectedRoundId from the new-project form to createProject.mutate()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds competitionCategory, oceanIssue, institution, geographicZone,
wantsMentorship, and foundedAt to the tRPC update mutation input schema
and the admin project edit form UI (with CountrySelect + Switch).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added AI_RANKING_COMPLETE and AI_RANKING_FAILED to NotificationTypes const
- Added BarChart3 / AlertTriangle icons in NotificationIcons
- Added normal / high priorities in NotificationPriorities
- parseRankingCriteria: parse natural-language criteria, returns ParsedRankingRule[]
- executeRanking: fetch+rank both categories, persist CONFIRMED RankingSnapshot
- quickRank: parse+execute in one step, persist QUICK RankingSnapshot
- listSnapshots: list snapshots for a round ordered by createdAt desc
- getSnapshot: fetch full snapshot by ID with NOT_FOUND guard
- All procedures use adminProcedure (SUPER_ADMIN, PROGRAM_ADMIN only)
- Casts to Prisma.InputJsonValue via unknown to satisfy strict TS
- Update listByStage query to include evaluation form criteriaJson and criterionScoresJson
- Add Advance column to individual assignments table showing YES/NO badge per submitted evaluation
- Create AdvancementSummaryCard component showing yes/no/pending vote counts with stacked bar
- Wire AdvancementSummaryCard into the EVALUATION round overview tab
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add getMyProgress juryProcedure query to evaluationRouter: fetches all
assignments for the current juror in a round, tallies completed/total,
advance yes/no counts, per-project numeric scores and averages
- Create JurorProgressDashboard client component with progress bar, advance
badge summary, and collapsible per-submission score table
- Wire dashboard into jury round page, gated by configJson.showJurorProgressDashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a new 'advance' criterion type representing "should this project advance to the next round?". Only one advance criterion is allowed per form (button disabled once added). No weight, no condition fields, always required. Also updates the upsertForm Zod schema to accept the new type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add roles UserRole[] to User model with migration + backfill from existing role column
- Update auth JWT/session to propagate roles array with [role] fallback for stale tokens
- Update tRPC hasRole() middleware and add userHasRole() helper for inline role checks
- Update ~15 router inline checks and ~13 DB queries to use roles array
- Add updateRoles admin mutation with SUPER_ADMIN guard and priority-based primary role
- Add role switcher UI in admin sidebar and role-nav for multi-role users
- Remove redundant stats cards from round detail, add window dates to header banner
- Merge Members section into JuryProgressTable with inline cap editor and remove buttons
- Reorder round detail assignments tab: Progress > Score Dist > Assignments > Coverage > Jury Group
- Make score distribution fill full vertical height, reassignment history always open
- Add per-juror progress bars to admin dashboard ActiveRoundPanel for EVALUATION rounds
- Fix evaluation submit bug: use isSubmitting state instead of startMutation.isPending
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: getProjectRoundStates now includes assignment counts and submitted
evaluation counts per project. Frontend: new Reviews column shows X/Y
(submitted/total) with green highlight when all reviews are complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add mail/transfer/reshuffle/redistribute icons to each juror row in Members card
- New redistributeJurorAssignments procedure: reassign all pending projects without dropping juror from group
- New DROPOUT_REASSIGNED email template with project names, deadline, and dropped juror context
- Update reassignDroppedJuror to send per-juror DROPOUT_REASSIGNED emails instead of generic BATCH_ASSIGNED
- Transfer dialog now shows all candidates with "Already assigned" / "At cap" labels instead of hiding them
- SQL script for prod DB insertion of new notification setting without seeding
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add COI_REASSIGNED and MANUAL_REASSIGNED notification types with distinct
email templates, icons, and priorities
- COI declaration dialog now shows a confirmation step warning that the
project will be reassigned before submitting
- reassignAfterCOI now checks historical assignments (all rounds, audit logs)
to never assign the same project to a juror twice, and prefers jurors with
incomplete evaluations over those who have finished all their work
- Admin transfer (transferAssignments) sends per-juror MANUAL_REASSIGNED
notifications with actual project names instead of generic batch emails
- docker-entrypoint syncs notification settings on every deploy via upsert
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rewrite ctaButton to use td-background pattern (works in all clients
including Outlook, Gmail, Yahoo, Apple Mail) instead of VML/conditional
comments that broke link clicking in Outlook desktop
- Add plaintext fallback URL below every CTA button so users always have
a working link even if the button fails
- Add getBaseUrl() and ensureAbsoluteUrl() helpers in email.ts to
guarantee all email links are absolute https:// URLs
- Apply ensureAbsoluteUrl safety net in sendStyledNotificationEmail and
sendNotificationEmail so relative paths can never reach email templates
- Standardize all NEXTAUTH_URL fallbacks to https://portal.monaco-opc.com
(was inconsistently http://localhost:3000 or https://monaco-opc.com)
- Fix legacy notification.ts: wrong argument order in
sendJuryInvitationEmail (URL was passed as name parameter)
- Fix legacy notification.ts: missing NEXTAUTH_URL fallback for
evaluation reminder URL construction
- Change tooltip styling from red bg to white bg with black text
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>