Commit Graph

153 Commits

Author SHA1 Message Date
36045bef9d fix: ranking dashboard respects threshold advancement mode
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- Header shows "Score >= X advance" instead of "Top N" in threshold mode
- Cutoff line placed after last project meeting threshold, not at fixed count
- Projects advancing determined by avg score vs threshold, not position

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:25:49 +01:00
2df9c54de2 fix: backfill binaryDecision, fix boolean criterion lookup, add assign buttons
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m9s
- 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>
2026-03-02 12:48:08 +01:00
19b58e4434 feat: weighted criteria in AI ranking, z-score normalization, threshold advancement, CSV export
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m16s
- 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>
2026-03-02 11:24:14 +01:00
c6ebd169dd feat: admin evaluation editing, ranking improvements, status transition fix
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m26s
- 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>
2026-03-02 10:46:52 +01:00
49e706f2cf feat: applicant onboarding, bulk invite, team management enhancements
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m50s
- 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>
2026-03-02 10:11:11 +01:00
9b3a9f6cbf feat: enhance project search to include all criteria, add AI tag generation button
- 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>
2026-03-01 14:42:37 +01:00
dd004baf79 feat: add View Project links to admin tables, conditionally show Awards tab
- IndividualAssignmentsTable: add View Project (new tab) as first dropdown item
- AwardShortlist: make project title a clickable link opening in new tab
- ProjectStatesTable: change View Project from same-tab Link to new-tab anchor
- Round page: Awards tab now only shown when roundAwards.length > 0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:37:45 +01:00
2f1136646e feat: ranking UI improvements - highlight advancing projects, expandable reviews, view project link
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:34:32 +01:00
f200eda692 fix: score distribution chart bars + add binaryDecision backfill script
All checks were successful
Build and Push Docker Image / build (push) Successful in 11m15s
Chart: fixed bars not rendering by using explicit h-[160px] + min-h-0 on
the bar container so percentage-based heights resolve correctly.

Script: one-off backfill copies the custom "Move to the Next Stage?" boolean
criterion value into binaryDecision for evaluations where it's null.
Run: npx tsx scripts/backfill-binary-decision.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:14:02 +01:00
ba7f068b1e fix: show project title, team & country in ranking rows instead of truncated IDs
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
Adds getProjectStates query to build a projectInfoMap lookup. Each row now
shows the project title, team name, and country. Also renames "Pass" label
to "Yes" to match the binary yes/no vote semantics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:08:30 +01:00
28ae934c57 feat: add ranking criteria textarea + auto-rank toggle to evaluation config UI
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m11s
The backend reads rankingCriteria from configJson but there was no UI field
to set it. Adds a Textarea and autoRankEnabled switch to the AI Features card
in the evaluation round config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 10:36:37 +01:00
a6f3945337 feat(02-03): add Advance Top N dialog + batch-reject to RankingDashboard
- Add pendingReorderCount ref + onMutate/onSettled to saveReorderMutation (DASH-07)
- Add advanceMutation (trpc.round.advanceProjects) with getProjectStates invalidation
- Add batchRejectMutation (trpc.roundEngine.batchTransition) using .length per MEMORY.md
- Add handleAdvance: advances top N per category, optionally batch-rejects the rest
- Add Advance Top N button in header (disabled when saveReorderMutation.isPending)
- Add Dialog with per-category N inputs, batch-reject checkbox, and count preview
- Import Dialog, Input, Label, Trophy from shadcn/lucide
2026-02-27 09:53:49 +01:00
6512e4ea2a feat(02-02): implement full RankingDashboard component
- Replace stub with complete drag-and-drop ranked project list (DASH-01, DASH-02)
- localOrder in useState with useRef init guard prevents snap-back (DASH-03)
- Per-category DndContext (STARTUP / BUSINESS_CONCEPT) with SortableProjectRow
- AI-order rows show dark-blue rank badge; admin-reordered show amber '(override)' badge
- Sheet panel lazy-loads trpc.project.getFullDetail on row click (DASH-04)
- Per-juror evaluation breakdown with score, binary decision, feedback text
- 'Run Ranking' button in header triggers triggerAutoRank mutation
- Empty categories show placeholder message (no empty drag zone)
- Zero TypeScript errors; build passes
2026-02-27 09:48:06 +01:00
8f71527353 feat(02-01): register Ranking tab in round detail page + create component stub
- Create src/components/admin/round/ranking-dashboard.tsx (stub with placeholder text)
- Import RankingDashboard in round detail page.tsx
- Add Ranking tab entry guarded by isEvaluation (uses existing BarChart3 icon)
- Add TabsContent block rendering RankingDashboard with competitionId + roundId props
2026-02-27 09:41:59 +01:00
c96f1b67a5 feat: add admin advancement summary card and advance column in assignments table
- 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>
2026-02-25 15:19:30 +01:00
79bd4dbae7 feat: add juror progress dashboard with evaluation.getMyProgress query
- 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>
2026-02-25 15:15:08 +01:00
2a61aa8e08 feat: add showJurorProgressDashboard toggle to EvaluationConfig
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:12:23 +01:00
a327962f04 feat: render advance criterion on juror evaluation page and fix related renderers
- Jury evaluate page: add prominent advance criterion block (h-14, brand-blue border) before boolean block, fix type cast to include 'advance', add advance to required-field validation
- evaluation-form.tsx: add 'advance' to CriterionType, schema, default values, progress tracking, rendering via new AdvanceCriterionField component with prominent styling
- Admin project detail: treat advance same as boolean in EvaluationDetailSheet criterion score display
- Observer project detail: treat advance same as boolean in evaluation criterion score display

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:11:24 +01:00
0edb50cd3a feat: add advance criterion type to evaluation form builder
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>
2026-02-25 15:04:58 +01:00
f3fd9eebee Multi-role members, round detail UI overhaul, dashboard jury progress, and submit bug fix
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- 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>
2026-02-24 17:44:55 +01:00
91563f3f47 Add Reviews column to Projects tab showing evaluation submission progress
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m36s
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>
2026-02-23 20:38:43 +01:00
3bc6552f47 Fix multi-click submit bug and add draft submit indicator on juror dashboard
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m24s
- Initialize slider values to midpoint so visual matches stored value
  (root cause: sliders appeared filled but criteriaValues was undefined)
- Use mutateAsync for submit to properly await and prevent double-clicks
- Add startMutation.isPending to submit button disabled state
- Add error toast in evaluation-form.tsx catch block (was silent)
- Show "Ready to submit" badge and "Review & Submit" button for drafts
  on juror dashboard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:29:13 +01:00
95d51e7de3 Add juror quick actions to Members section, redistribute button, dropout emails, and transfer duplicate detection
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- 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>
2026-02-23 16:08:46 +01:00
49e9405e01 Add COI/manual reassignment emails, confirmation dialog, and smart juror selection
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m14s
- 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>
2026-02-23 14:56:30 +01:00
c1b3a6ade3 Fix email links broken in Outlook and standardize all email URLs
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m33s
- 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>
2026-02-23 14:27:58 +01:00
f26ee3f076 Admin dashboard & round management UX overhaul
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m43s
- Extract round detail monolith (2900→600 lines) into 13 standalone components
- Add shared round/status config (round-config.ts) replacing 4 local copies
- Delete 12 legacy competition-scoped pages, merge project pool into projects page
- Add round-type-specific dashboard stat panels (submission, mentoring, live final, deliberation, summary)
- Add contextual header quick actions based on active round type
- Improve pipeline visualization: progress bars, checkmarks, chevron connectors, overflow fix
- Add config tab completion dots (green/amber/red) and inline validation warnings
- Enhance juries page with round assignments, member avatars, and cap mode badges
- Add context-aware project list (recent submissions vs active evaluations)
- Move competition settings into Manage Editions page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 17:14:00 +01:00
5a609457c2 Overhaul applicant portal: timeline, evaluations, nav, resources
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m6s
- Fix programId/competitionId bug in competition timeline
- Add applicantVisibility config to EvaluationConfigSchema (JSONB)
- Add admin UI card for controlling applicant feedback visibility
- Add 6 new tRPC procedures: getNavFlags, getMyCompetitionTimeline,
  getMyEvaluations, getUpcomingDeadlines, getDocumentCompleteness,
  and extend getMyDashboard with hasPassedIntake
- Rewrite competition timeline to show only EVALUATION + Grand Finale,
  synthesize FILTERING rejections, handle manually-created projects
- Dynamic ApplicantNav with conditional Evaluations/Mentoring/Resources
- Dashboard: conditional timeline, jury feedback card, deadlines,
  document completeness, conditional mentor tile
- New /applicant/evaluations page with anonymous jury feedback
- New /applicant/resources pages (clone of jury learning hub)
- Rename /applicant/competitions → /applicant/competition
- Remove broken /applicant/competitions/[windowId] page
- Add permission info banner to team invite dialog

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:51:17 +01:00
ee2f10e080 Add jury assignment transfer, cap redistribution, and learning hub overhaul
All checks were successful
Build and Push Docker Image / build (push) Successful in 12m19s
- Add getTransferCandidates/transferAssignments procedures for targeted
  assignment moves between jurors with TOCTOU guards and audit logging
- Add getOverCapPreview/redistributeOverCap for auto-redistributing
  assignments when a juror's cap is lowered below their current load
- Add TransferAssignmentsDialog (2-step: select projects, pick destinations)
- Extend InlineMemberCap with over-cap detection and redistribute banner
- Extend getReassignmentHistory to show ASSIGNMENT_TRANSFER and CAP_REDISTRIBUTE events
- Learning hub: replace ResourceType/CohortLevel enums with accessJson JSONB,
  add coverImageKey, resource detail pages for jury/mentor, shared renderer
- Migration: 20260221200000_learning_hub_overhaul

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 18:50:29 +01:00
f42b452899 Add Anthropic API integration, remove locale settings UI
All checks were successful
Build and Push Docker Image / build (push) Successful in 13m15s
Anthropic API:
- Add @anthropic-ai/sdk with adapter wrapping OpenAI-shaped interface
- Support Claude models (opus, sonnet, haiku) with extended thinking
- Auto-reset model on provider switch, JSON retry logic
- Add Claude model pricing to ai-usage tracker
- Update AI settings form with Anthropic provider option
- Add provider field to AIUsageLog for cross-provider cost tracking

Locale Settings Removal:
- Strip Localization tab from admin settings (mobile + desktop)
- Remove i18n settings from router and feature flags
- Remove LOCALIZATION from SettingCategory enum
- Keep franc document language detection intact

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:26:59 +01:00
161cd1684a Fix observer reports: charts, filtering, project preview, dashboard stats
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m32s
- Rewrite diversity metrics: horizontal bar charts for ocean issues and
  geographic distribution (replaces unreadable vertical/donut charts)
- Rewrite juror score heatmap: expandable table with score distribution
- Rewrite juror consistency: horizontal bar visual with juror names
- Merge filtering tabs into single screening view with per-project
  AI reasoning and expandable rows
- Add project preview dialog for juror performance table
- Fix status breakdown for evaluation rounds (Fully/Partially/Not Reviewed)
- Show active round name instead of count on observer dashboard
- Move Global tab to last position, default to first round-specific tab
- Add 4-card stats layout for evaluation with reviews/project ratio
- Fix oceanIssue field (singular) and remove non-existent aiSummary

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 10:12:21 +01:00
2e4b95f29c Add round-type-specific observer reports with dynamic tabs
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m44s
Refactor the observer reports page from a static 3-tab layout to a
dynamic tab system that adapts to each round type (INTAKE, FILTERING,
EVALUATION, SUBMISSION, MENTORING, LIVE_FINAL, DELIBERATION). Adds a
persistent Global tab for edition-wide analytics, juror score heatmap,
expandable juror assignment rows, filtering screening bar, and
deliberation results with tie detection.

- Add 5 observer proxy procedures to analytics router
- Create JurorScoreHeatmap, ExpandableJurorTable, FilteringScreeningBar
- Create 8 round-type tab components + GlobalAnalyticsTab
- Reduce reports page from 914 to ~190 lines (thin dispatcher)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:29:26 +01:00
533d8cb8e5 Replace generic stat cards with clean horizontal stats strip
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m5s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 00:26:04 +01:00
4f73ba5a0e Fix reports: status breakdown uses round states, filter boolean criteria, replace insight tiles with country chart
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m47s
- getStatusBreakdown now uses ProjectRoundState when a specific round is selected
  (fixes donut showing all "Eligible")
- Filter out boolean/section_header criteria from getCriteriaScores
  (removes "Move to the Next Stage?" from bar chart)
- Replace 6 insight tiles with Top Countries horizontal bar chart
- Add round-level state labels/colors to chart-theme

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 00:00:55 +01:00
26e8830df2 Revamp chart colors: replace bland cyan/teal with vibrant blue/indigo/amber palette + fix tooltip indicators
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:54:14 +01:00
6e697cb5d8 Extend Recently Reviewed card to match sibling heights
Some checks are pending
Build and Push Docker Image / build (push) Waiting to run
Use flex-1 on the Recently Reviewed card so it stretches to fill the
remaining vertical space in the left column, aligning its bottom with
Juror Workload and Activity Feed. Add className prop to AnimatedCard.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:49:15 +01:00
a6b6763fa4 Simplify project detail: back button, cleaner files, fix round inference
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- Replace breadcrumb with "Back to Projects" button on observer detail
- Remove submission links from observer project info
- Simplify files tab: remove redundant requirements checklist, show only
  FileViewer (observer + admin)
- Fix round history: infer earlier rounds as PASSED when later round is
  active (e.g. R2 shows Passed when project is active in R3)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:45:31 +01:00
d717040f03 Observer: fix round history, match admin project info, add AI rejection reason
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m30s
- Round history infers rejection round when ProjectRoundState lacks explicit
  REJECTED state; shows red XCircle + badge, dims unreached rounds
- Project info section now matches admin: description, location, founded,
  submission links, expertise tags, internal notes, created/updated dates
- Fetch FilteringResult for rejected projects; display AI reasoning + confidence
- Remove cross-round comparison from reports, replace with scoring/criteria insights
- Remove unused AI synthesis placeholder

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:30:14 +01:00
9f7b76b3cb Dashboard layout overhaul + fix Tremor chart colors and tooltips
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m55s
- Restructure dashboard: score distribution + recently reviewed stacked in left column,
  full-width map at bottom, activity feed in middle row
- Show all jurors in scrollable workload list (not just top 5)
- Filter recently reviewed to exclude rejected/not-reviewed projects
- Filter transition audit logs from activity feed
- Remove completion progress bar from stat tile for equal card heights
- Fix all Tremor charts: switch hex colors to named palette (cyan/teal/emerald/amber/rose)
  to fix black bar rendering
- Fix transparent chart tooltips with global CSS overrides
- Remove tilted text labels from cross-round comparison charts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:09:06 +01:00
213efdba87 Observer platform: mobile fixes, data/UX overhaul, animated nav
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m41s
- Fix dashboard default round selection to target active round instead of R1
- Move edition selector from dashboard header to hamburger menu via shared context
- Add observer-friendly status labels (Not Reviewed / Under Review / Reviewed)
- Fix pipeline completion: closed rounds show 100%, cap all rates at 100%
- Round badge on projects list shows furthest round reached
- Hide scores/evals for projects with zero evaluations
- Enhance project detail round history with pass/reject indicators from ProjectRoundState
- Remove irrelevant fields (Org Type, Budget, Duration) from project detail
- Clickable juror workload with expandable project assignments
- Humanize activity feed with icons and readable messages
- Fix jurors table: responsive card layout on mobile
- Fix criteria chart: horizontal bars for readable labels on mobile
- Animate hamburger menu open/close with CSS grid transition

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:45:56 +01:00
8125ca6567 Observer platform redesign Phase 4: migrate charts to Tremor, redesign all pages
Some checks failed
Build and Push Docker Image / build (push) Failing after 23s
- Migrate 9 chart components from Nivo to @tremor/react (BarChart, AreaChart, DonutChart, ScatterChart)
- Remove @nivo/*, @react-spring/web dependencies (45 packages removed)
- Redesign dashboard: 6 stat tiles, competition pipeline, score distribution, juror workload, activity feed
- Add new /observer/projects page with search, filters, sorting, pagination, CSV export
- Restructure reports page from 5 tabs to 3 (Progress, Jurors, Scores & Analytics) with per-tab CSV export
- Redesign project detail: breadcrumb nav, score card header, 3-tab layout (Overview/Evaluations/Files)
- Update loading skeletons to match new layouts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:45:01 +01:00
Matt
03c59c188e Add observer project detail page with files, evaluations & reviews
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m59s
New page at /observer/projects/[projectId] showing project info,
documents grouped by round requirements, and jury evaluations with
click-through to full review details. Dashboard table rows now link
to project detail. Also cleans up redundant programName prefixes
and fixes chart edge cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 18:39:53 +01:00
Matt
0607d79484 Fix observer analytics crash: guard Nivo edge cases
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m41s
- Disable enableSlices on ResponsiveLine with single data point (causes
  null reference in Nivo internal slice computation)
- Add null check for slice.points[0] in timeline tooltip
- Guard ResponsivePie from empty data array in diversity metrics
- Add fallback for scoreDistribution.distribution on both
  observer and admin reports pages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:09:43 +01:00
Matt
fbcbf895be Add defensive null guards to all chart components and analytics
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m59s
All 9 chart components now have early-return null/empty checks before
calling .map() on data props. The diversity-metrics chart guards all
nested array fields (byCountry, byCategory, byOceanIssue, byTag).
Analytics backend guards p.tags in getDiversityMetrics. This prevents
any "Cannot read properties of null (reading 'map')" crashes even if
upstream data shapes are unexpected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:42:31 +01:00
Matt
bf02684736 Fix COI audit log always saying conflict + fix boolean criteria submission
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m19s
1. COI audit log: The declareCOI mutation always logged action
   'COI_DECLARED' regardless of whether the user clicked "No Conflict"
   or "Yes, I Have a Conflict". Now uses 'COI_NO_CONFLICT' when
   hasConflict is false, showing "confirmed no conflict of interest"
   in the audit trail.

2. Evaluation submission: The requireAllCriteriaScored validation
   only accepted numeric values (typeof === 'number'), but boolean
   criteria (yes/no questions) store true/false. This caused jurors
   to get "Missing scores for criteria: criterion-xxx" errors even
   after completing all fields. Now correctly validates boolean
   criteria with typeof === 'boolean'. Also improved the error
   message to show criterion labels instead of cryptic IDs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 12:53:54 +01:00
Matt
9d945c33f9 Observer platform overhaul: Nivo charts, round-type stats, UX improvements
All checks were successful
Build and Push Docker Image / build (push) Successful in 12m29s
Phase 1: Fix 6 backend data bugs in analytics.ts (roundName filtering,
unscored projects, criteria scores, activeRoundCount scoping, email
privacy leaks in juror consistency + workload)

Phase 2-3: Migrate all 9 chart components from Recharts to Nivo
(@nivo/bar, @nivo/line, @nivo/pie, @nivo/scatterplot) with shared brand
theme, scoreGradient colors, and STATUS_COLORS map. Fixes scatter plot
outlier coloring and pie chart label visibility bugs.

Phase 4: Add round-type-aware stats (getRoundTypeStats backend +
RoundTypeStatsCards component) showing appropriate metrics per round
type (intake/filtering/evaluation/submission/mentoring/live/deliberation).

Phase 5: UX improvements — Stage→Round terminology, clickable dashboard
round links, URL-based round selection (?round=), round type indicators
in selectors, accessible Toggle-based cross-round comparison, sortable
project table columns (title/score/evaluations), brand score colors on
dashboard bar chart with aria labels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:44:38 +01:00
Matt
baca483fcb Comprehensive round system audit: fix 27 logic bugs, add manual project/assignment features, improve UI/UX
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m23s
## Critical Logic Fixes (Tier 1)
- Fix requiredReviews config key mismatch (always defaulted to 3)
- Fix double-email + stageName/roundName metadata mismatch in notifications
- Fix snake_case config reads in peer review (peerReviewEnabled was always blocked)
- Add server-side COI check to evaluation submit (was client-only)
- Fix hard-coded feedbackText.min(10) — now uses config values
- Fix binaryDecision corruption in non-binary scoring modes
- Fix advanceProjects: add competition/sort-order/status validations, move autoPass into tx
- Fix removeFromRound: now cleans up orphaned Assignment records
- Fix 3-day reminder sending wrong email template (was using 24h template)

## High-Priority Logic Fixes (Tier 2)
- Add project state transition whitelist (prevent invalid transitions like REJECTED→PASSED)
- Scope AI assignment job to jury group members (was querying all JURY_MEMBERs)
- Add COI awareness to AI assignment generation
- Enforce requireAllCriteriaScored server-side
- Fix expireIntentsForRound nested transaction (now uses caller's tx)
- Implement notifyOnEntry for advancement path
- Implement notifyOnAdvance (was dead config)
- Fix checkRequirementsAndTransition for SubmissionFileRequirement model

## New Features (Tier 3)
- Add Project to Round: dialog with "Create New" and "From Pool" tabs
- Assignment "By Project" mode: select project → assign multiple jurors
- Backend: project.createAndAssignToRound procedure

## UI/UX Improvements (Tier 4+5)
- Add AlertDialog confirmation to header status dropdown
- Replace native confirm() with AlertDialog in assignments table
- Jury stats card now display-only with "Change" link
- Assignments tab restructured into logical card groups
- Inline-editable round name in header
- Back button shows destination label
- Readiness checklist: green check instead of strikethrough
- Gate assignments tab when no jury group assigned
- Relative time on window stats card
- Toast feedback on date saves
- Disable advance button when no target round
- COI section shows placeholder when empty
- Round position shown as "Round X of Y"
- InlineMemberCap edit icon always visible
- Status badge tooltip with description
- Add REMINDER_3_DAYS email template
- Fix maybeSendEmail to respect notification preferences
- Optimize bulk notification email loop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 12:59:35 +01:00
Matt
ee8b12e59c Fix jury reminders, add notify jurors button, fix checkbox borders, widen assignment modal
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m32s
- Send Reminders button now works: added sendManualReminders() that bypasses
  cron-specific window/deadline/dedup guards so admin can send immediately
- Added Notify Jurors button that sends direct BATCH_ASSIGNED emails to all
  jurors with assignments (not dependent on NotificationEmailSetting config)
- Fixed checkbox component: default border is now neutral grey (border-input),
  red border (border-primary) only applied when checked
- Widened Add Assignment dialog from max-w-2xl to max-w-3xl to prevent overflow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 12:15:51 +01:00
Matt
51e18870b6 Admin UI audit round 2: fix 28 display bugs across 23 files
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m51s
HIGH fixes (broken features / wrong data):
- H1: Fix roundAssignments → projectRoundStates in project router (7 occurrences)
- H2: Fix deliberation results panel blank table (wrong field names)
- H3: Fix deliberation participant names blank (wrong data path)
- H4: Fix awards "Evaluated" stat duplicating "Eligible" count
- H5: Fix cross-round comparison enabled at 1 round (backend requires 2)
- H6: Fix setState during render anti-pattern (6 occurrences)
- H7: Fix round detail jury member count always showing 0
- H8: Remove 4 invalid status values from observer dashboard filter
- H9: Fix filtering progress bar always showing 100%

MEDIUM fixes (misleading display):
- M1: Filter special-award rounds from competition timeline
- M2: Exclude special-award rounds from distinct project count
- M3: Fix MENTORING pipeline node hardcoded "0 mentored"
- M4: Fix DELIB_LOCKED badge using red for success state
- M5: Add status label maps to deliberation session detail
- M6: Humanize deliberation category + tie-break method displays
- M8: Rename setStageId → setRoundId, "Select Stage" → "Select Round"
- M9: Add missing INVITED/ACTIVE/SUSPENDED to members status labels
- M10: Add ROUND_DRAFT/ACTIVE/CLOSED/ARCHIVED to StatusBadge
- M11: Fix unsent messages showing "Scheduled" instead of "Draft"
- M12: Rename misleading totalEvaluations → totalAssignments
- M13: Rename "Stage" column to "Program" in projects page

LOW fixes (cosmetic / edge-case):
- L1: Use unfiltered rounds array for active round detection
- L2: Use all rounds length for new round sort order
- L3: Filter special-award rounds from header count
- L4: Fix single-underscore replace in award status badges
- L5: Fix score bucket boundary gaps (4.99 dropped between buckets)
- L6: Title-case LIVE_FINAL pipeline metric status
- L7: Fix roundType.replace only replacing first underscore
- L8: Remove duplicate severity sort in smart-actions component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 11:11:00 +01:00
1308c3ba87 Admin platform audit: fix bugs, harden backend, add auto-refresh, clean dead code
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m23s
Phase 1 — Critical bugs:
- Fix deliberation participant selection (wire jury group query)
- Fix reports "By Round" tab (inline content instead of 404 route)
- Fix messages "Sent History" (add message.sent procedure, wire tab)
- Add missing fields to competition award form (criteriaText, maxRankedPicks)
- Wire LiveControlPanel buttons (cursor, voting, scores)
- Fix ResultLockControls empty snapshot (fetch actual data before lock)
- Fix SubmissionWindowManager losing fields on edit

Phase 2 — Backend fixes:
- Remove write-in-query from specialAward.get
- Fix award eligibility job overwriting manual shortlist overrides
- Fix filtering startJob deleting all prior results (defer cleanup to post-success)
- Tighten access control: protectedProcedure → adminProcedure on 8 procedures
- Add audit logging to deliberation mutations
- Add FINALIST/SEMIFINALIST delete guard on project.delete/bulkDelete

Phase 3 — Auto-refresh:
- Add refetchInterval to 15+ admin pages/components (10s–30s)
- Fix AI job polling: derive speed from job status for all viewers

Phase 4 — Dead code cleanup:
- Delete unused command-palette, pdf-report, admin-page-transition
- Remove dead subItems sidebar code, unused GripVertical import
- Replace redundant isGenerating state with mutation.isPending
- Add Role column to jury members table
- Remove misleading manual mentor assignment stub

Phase 5 — UX improvements:
- Fix rounds page single-competition assumption (add selector)
- Remove raw UUID fallback in deliberation config
- Fix programs page "Stage" → "Round" terminology

Phase 6 — Backend hardening:
- Complete logAudit calls (add prisma, ipAddress, userAgent)
- Batch analytics queries (fix N+1 in getCrossRoundComparison, getYearOverYear)
- Batch user.bulkCreate writes (assignments, jury memberships, intents)
- Remove any casts from deliberation service (typed PrismaClient + TransactionClient)
- Fix stale DeliberationStatus enum values blocking build

40 files changed, 1010 insertions(+), 612 deletions(-)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 08:20:13 +01:00
aa1bf564ee Fix award eligibility FK constraint + add country column to round projects
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m13s
- specialAward.setEligibility: add ensureUserExists() guard and use Prisma
  connect syntax to prevent FK violation on stale session user IDs
- specialAward.confirmShortlist: same ensureUserExists() guard for confirmedBy
- Round projects table: add Country column showing project origin

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 22:47:20 +01:00