Commit Graph

227 Commits

Author SHA1 Message Date
Matt
7bc2b84d1d refactor(awards): remove AWARD_MASTER role, fold features into jury chair flow
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m5s
The AWARD_MASTER role split sponsor jurors into a parallel UI that hid
project files (only showed when the award was anchored to an evaluation
round) and duplicated the jury voting path with no real difference in
authority — tie-break and finalize were already governed by AwardJuror.isChair
regardless of the user's global role. Inviting a juror via the award page
defaulted to AWARD_MASTER, randomly fragmenting jury panels.

This collapses the role into JURY_MEMBER + isChair:

- specialAward.getMyAwardDetail now returns evaluation scores, chair
  visibility into other jurors' votes, and juror roster
- specialAward.submitVote accepts an optional justification per vote
- specialAward.confirmWinner moves from awardMasterProcedure to
  protectedProcedure (juror+chair check inside)
- bulkInviteJurors creates JURY_MEMBER accounts and, when the award has
  a juryGroupId, also adds them to that JuryGroup so they appear on
  the round-page jury panel
- jury award page renders justification, eval-score badges, and a
  chair tools panel with vote tally + finalize-winner CTA
- juryGroup.list includes attached SpecialAwards; the jury-list UI
  shows a trophy pill alongside round pills
- (award-master) route group, awardMasterProcedure, AWARD_MASTER role
  enum value, and AWARD_MASTER_DECISION decisionMode are deleted
- migration demotes any residual AWARD_MASTER users to JURY_MEMBER and
  recreates the UserRole enum without the value

Coup de Coeur on prod: Didier (the sponsor juror added today as
AWARD_MASTER by the buggy invite form) was migrated to JURY_MEMBER and
attached to the existing "Coup de Coeur" JuryGroup; the SpecialAward
itself was linked to that group (juryGroupId was NULL).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:21:09 +02:00
Matt
6e36704bb1 feat(awards): notify jurors on assignment + admin reminder button
All checks were successful
Build and Push Docker Image / build (push) Successful in 11m41s
The previous addJuror / bulkAddJurors / bulkInviteJurors flows silently
created AwardJuror rows with no notification when the user already had
an account. The result: assigned jurors had no idea they were assigned
unless they happened to log in and check /jury/awards manually.

Three changes:

1. New email template + sender (sendAwardJurorNotificationEmail). Tells
   the juror what the award is, how many projects are eligible, when
   voting closes, and links straight to /jury/awards/<id>. Reused for
   both the initial assignment notification and admin reminders.

2. Auto-send on assignment. addJuror / bulkAddJurors / bulkInviteJurors
   now send the email to newly-attached jurors. bulkInviteJurors checks
   for a prior AwardJuror row before sending so duplicate "Bulk Invite"
   clicks don't spam jurors who were already assigned. addJuror /
   bulkAddJurors accept a `sendEmail` flag so admin tooling can opt out.

3. New admin procedure specialAward.notifyJurors(awardId, userIds?,
   customMessage?). Surfaced in the Jurors tab as a "Send reminder to
   all" button at the top and a per-row mail icon for individual
   reminders. Audit-logged with action: 'JUROR_REMINDER'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:17:29 +02:00
Matt
6fcabc89d7 feat: lunch tab scaffold + un-disable trigger
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 02:40:32 +02:00
Matt
eb19cb11a1 chore: drop dead Logistics tabs + move visa toggle to settings
- Remove the Documents tab — visa documents are out of scope for this
  edition and there is no other concrete document need.
- Remove the Logistics > Settings disabled tab — every per-edition
  configuration knob now lives at /admin/settings > Edition.
- Replace the inline "Visible to teams" toggle on the Visas tab with a
  small "Edition settings" button that links straight to the
  consolidated settings page. The toggle itself moved to that page in
  the previous commit.
- Drop the now-unused getVisaVisibility / setVisaVisibility wiring
  inside VisasTab. (The procedures still exist server-side; the new
  Edition tab uses program.updateEditionSettings instead.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 20:09:50 +02:00
Matt
62ab27a05a feat: mentor detail side sheet + Teams column
The mentor list now ends with a Teams column showing chips of each
mentor's active assignments (truncated at 2 + overflow badge). Clicking
any row opens a right-side Sheet with the mentor's profile (expertise,
country, joined date, max assignments) and a per-team activity feed —
project, status (active / completed / dropped), assignment date, and
counts of messages / files / milestones with their last timestamp.

Stat cards on both the Mentor and Mentee panels were stale and not
particularly informative, so they're gone — the table itself is now
the focal element on each panel.

getMentorPool gained an activeTeams[] field; new getMentorDetail query
backs the side sheet.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 19:52:17 +02:00
Matt
030db533e1 fix: size logistics tab bar to fit buttons + horizontal scrollbar
The fixed h-10 wasn't tall enough to fit a 32px tab button plus the
overflow-x scrollbar, so buttons clipped and a vertical scroll appeared
inside the bar. Switching to h-auto + pb-2 lets the bar size naturally
and reserves space below the row for the scrollbar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 19:45:52 +02:00
Matt
7824b00ff4 fix: horizontal scroll on logistics tab bar instead of wrapping
Stacking 8 tabs onto two rows looked rough. Switching the TabsList to
w-full + justify-start + overflow-x-auto keeps every tab on one line
and lets the bar scroll horizontally on narrower viewports.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 19:44:38 +02:00
Matt
fe630e0e2d feat: admin Visas tab — table + edit dialog + visibility toggle
Activates the previously-disabled Visas tab on /admin/logistics.

VisasTab renders a flat table joined per attendee per project, sorted
by status priority. Status filter pills mirror the Confirmations tab.
The header carries a "Visible to teams" Switch backed by a new
logistics.getVisaVisibility query and the existing setVisaVisibility
mutation; toggling it controls whether members see their own status.

VisaEditDialog is a per-row editor with a status dropdown,
nationality input, three native date inputs (invitation / appointment
/ decision), and a notes textarea. No file uploads — the platform
deliberately holds zero document artifacts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 19:37:55 +02:00
Matt
57ec28edad feat: logistics page shell + Confirmations/Travel/Hotels tabs
- /admin/logistics page with shadcn Tabs (3 active + 5 disabled "(soon)"
  placeholder tabs for Visas / Lunch / Documents / Email Templates / Settings).
- Sidebar entry "Logistics" between Mentors and Awards (Plane icon).
- Confirmations tab: read-only table with status filter pills, browser-
  local-time deadline display, attendee count, decline reason snippet.
- Hotels tab: single-hotel form (name/address/link/notes) with live
  email-preview card showing what teams will see.
- Travel tab: per-attendee flight tracker with arrival/departure
  datetimes, flight numbers, IATA airports, click-to-toggle status badge,
  edit Sheet, and unfilled/pending/confirmed filter pills.

Smoke-tested end-to-end: navigation, sidebar entry, all three tabs
render, hotel save persists to DB and renders in preview card.
2026-04-28 18:25:29 +02:00
Matt
95055e0dae feat: admin UI for finalist slot quotas + waitlist on grand-finale round
- New components/admin/grand-finale/finalist-slots-card: per-category
  quota editor with confirmed/pending counts, dirty-tracking, save button.
  Renders an empty editor for both Startup and Business Concept categories
  even when no quota exists yet.
- New components/admin/grand-finale/waitlist-card: per-category ranked
  waitlist display with status badges + manual-promote AlertDialog
  (audit-logged via FINALIST_MANUAL_PROMOTE).
- Round detail page: embeds both cards conditionally when
  roundType === 'LIVE_FINAL'.
- New finalist router queries: listQuotas, listCategoryCounts (groupBy
  on category+status), listWaitlist (rank-ordered with project relation).

Smoke-tested: setting Startup quota to 3 persists to DB; UI renders
quota editor and waitlist card cleanly with empty state.
2026-04-28 18:07:55 +02:00
Matt
d0058b46ed feat: Mentees & Activity tab on /admin/mentors
Adds a project-centric ops view for mentor management:
- New mentor.getMenteeActivity tRPC procedure aggregates every project
  with wantsMentorship=true and derives a status (unassigned / assigned
  / active / stalled) from the latest message + file activity.
- /admin/mentors becomes a tabbed page: existing Mentor list +
  new Mentees & Activity table with status pills, search, and a
  per-row Assign/Open CTA linking to /admin/projects/[id]/mentor.
- Includes 2 unit tests covering classification + program scoping.

Also: ignore .remember/ (plugin scratch dir).
2026-04-28 16:47:53 +02:00
Matt
e37f3a5874 fix: render enum labels as proper title case
formatEnumLabel was leaving inputs uppercase ("TECHNOLOGY_INNOVATION"
became "TECHNOLOGY INNOVATION"); lowercasing first yields proper
title case ("Technology Innovation") and improves labels app-wide.
Apply it on the project mentor page for Ocean Issue + Category.
2026-04-28 16:28:30 +02:00
Matt
70a9752d73 refactor(layouts): shared RoleSwitcherPill across dashboards (§D.6)
Extract ROLE_SWITCH_OPTIONS + switchableRoles computation from the two
duplicated copies (role-nav.tsx + admin-sidebar.tsx) into a single
src/components/layouts/role-switcher.tsx module.

Adds a RoleSwitcherPill component placed top-right of every dashboard:
  - Hidden for single-role users
  - Hidden during impersonation
  - Same visual + click target across /jury, /mentor, /applicant,
    /observer, /award-master AND /admin (admin layout gains a small
    top-bar to host the pill)

Removes the duplicate role-switcher items from the admin sidebar's
bottom user-menu — one source of truth instead of three.

Plan: docs/superpowers/plans/2026-04-28-pr6-multi-role-and-workspace-previews.md
2026-04-28 16:09:40 +02:00
Matt
34bd267c32 feat(admin): real /admin/mentors list page (§B)
Replaces the redirect-to-/admin/members stub with a sortable, searchable
list of all MENTOR-role users powered by mentor.getMentorPool. Columns:
name, expertise tags, country, active count, completed count, capacity
remaining, last activity. Header summary cards show pool size, total
active assignments, and average load.

Row links continue to /admin/members/[id]; /admin/mentors/[id] remains
a redirect (mentor-detail view deferred to a future PR).

Plan: docs/superpowers/plans/2026-04-28-pr5-mentor-round-overview.md
2026-04-28 15:28:09 +02:00
Matt
a0a2c5f06a feat(mentor): mentoring-specific Round Overview card grid (§B)
Renders above Round Details when round.roundType === 'MENTORING':
  - Top-line counts: requested + assigned (with awaiting badge)
  - Request window: countdown pill (amber <48h, red <12h)
  - Mentor pool: size + avg load + 'View all' link to /admin/mentors
  - Workspace activity: msgs / files / milestones / last activity

Round Details panel now shows 'Mentor Pool: N members' (linked) instead
of an always-empty 'Jury Group' row on MENTORING rounds.

Plan: docs/superpowers/plans/2026-04-28-pr5-mentor-round-overview.md
2026-04-28 15:26:31 +02:00
Matt
2b07c12c18 feat(mentor): round-level auto-fill toolbar on Projects tab (§C)
Adds an 'Auto-fill remaining' button above ProjectStatesTable on the
MENTORING round Projects tab. Calls mentor.autoAssignBulkForRound,
respecting the round's configJson.eligibility:
  - requested_only / all_advancing: enabled, count from new
    round.getProjectsNeedingMentor query
  - admin_selected: disabled with explanatory copy

Plan: docs/superpowers/plans/2026-04-28-pr4-mentor-assignment-ux.md
2026-04-28 14:58:32 +02:00
Matt
ddae34c8f5 feat(mentor): rewrite project mentor-assignment page (§C)
Replaces single-section AI-only stub with three sections (Project Context,
Currently Assigned, Pick a Mentor). Pick a Mentor is a tab strip:
  - Manual Picker (default): all MENTOR-role users sorted by expertise
    overlap %, with search + load/capacity columns. Assign sends
    method=MANUAL.
  - AI Suggestions: existing pane, with an amber 'AI matching unavailable'
    banner + 'Tag overlap' pills when OPENAI_API_KEY is unset.

Plan: docs/superpowers/plans/2026-04-28-pr4-mentor-assignment-ux.md
2026-04-28 14:56:46 +02:00
Matt
b867c45114 feat: Email Team button + custom-email dialog on project page
Adds a PROJECT_TEAM recipient type to the message router (resolver
returns team members + project lead) and an "Email Team" button on
the admin project detail page that opens a self-contained dialog
matching the look of /admin/messages: subject, body (pre-filled
with "Hello [Project Title] team,\n\n"), live HTML preview iframe,
"Send test to me" + "Send to N" actions.

The composer reuses the existing message.previewEmail and
message.send tRPC procedures end-to-end — no parallel email
infrastructure introduced.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 14:29:42 +02:00
Matt
16156111a6 feat: complete MENTORING round config form (§A)
Surfaces every MentoringConfigSchema field on the round Config tab:

- Adds "Mentoring Request Window" card with mentoringRequestDeadlineDays
  numeric input (1-90 days, default 14) and passThroughIfNoRequest toggle
  (default ON; OFF holds projects PENDING until manual mentor assignment).
- Adds inline help-text for the Eligibility dropdown explaining each
  option's effect on auto-PASS behavior.
- Hides the General Settings card on MENTORING rounds (it only renders
  Advancement Targets, which don't apply to a pass-through round).
- Relaxes the Launch Readiness "File requirements set" gate for MENTORING
  rounds without filePromotionEnabled + a target window — file requirements
  only matter when files will be promoted to a downstream submission window.

Spec: docs/superpowers/specs/2026-04-28-mentor-round-readiness-design.md §A
Plan: docs/superpowers/plans/2026-04-28-pr3-mentoring-config-completeness.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 14:25:23 +02:00
Matt
2e080a5d09 feat: lift round selector to reports page top-level
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m42s
Top-level selector in the URL (?round=...) drives every single-round tab
(Overview, Analytics, Juror Consistency, Diversity) and narrows the Pipeline
tab to the selected program. Cross-Round keeps its own multi-select because
it compares multiple rounds by design.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 18:39:18 +02:00
Matt
982d5193c5 feat: surface juror-balanced scores and AI calibration advisory
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m27s
Adds a shared juror-balancing utility (z-score normalization per juror,
rescaled back onto the raw 1-10 scale) and wires it into:

- Admin reports page: Top-10 project table now shows "Raw Avg" and
  "Balanced" columns side by side, and the summary stats row shows a
  balanced-average tile. Sort defaults to balanced so harsh and lenient
  graders no longer skew the ranking.
- Ranking dashboard: each project row shows a green/amber balanced-score
  chip next to the raw average when the two differ by ≥0.05, making it
  obvious when juror calibration moved a project's effective ranking.

Also adds AI Juror Calibration Advisory — a mutation that takes
anonymized per-juror stats, calls OpenAI, and produces a plain-language
explanation of the cohort's grading patterns plus per-juror severity
(normal / notable / outlier) with a one-sentence narrative. The advisory
describes the statistical balance that already runs; it does not
introduce a new weighting layer. Rendered as a panel in the Juror
Consistency tab when a specific round is selected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 16:19:00 +02:00
Matt
f37a9b49b5 test: add integration coverage for admin proxy evaluation
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m0s
Seven scenarios covering the new admin procedures:
- non-admin users are rejected on adminStart/adminSubmitOnBehalf
- admin can list a juror's assignments with COI flag surfaced
- admin can complete the full draft→autosave→submit cycle with the
  voting window already closed, confirming bypass works
- COI-declared assignments still block admin submission
- feedback minimum length is enforced on admin submit
- adminAutosave refuses to overwrite a SUBMITTED evaluation
- audit log captures admin id, juror id, and bypassedWindow flag

Also swaps a lucide icon alias (FileEdit → Pencil) in the juror
assignments page to avoid the deprecated alias form.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 17:00:03 +02:00
Matt
9cb3b9de13 feat: admin can fill in evaluations on behalf of jurors
All checks were successful
Build and Push Docker Image / build (push) Successful in 11m54s
When a juror cannot connect during an evaluation round, an admin
can now submit evaluations for them.

Router — new admin procedures:
- adminStart / adminAutosave: create and save drafts for any juror.
- adminSubmitOnBehalf: submit bypassing ROUND_ACTIVE and voting-window
  checks. COI block and feedback/criterion validation still enforced.
  Audit log records both admin and juror IDs plus bypassedWindow flag.
- getJurorAssignmentsForRound: list a juror's assignments + eval state.

UI — two new admin pages under /admin/rounds/[roundId]/jurors/[userId]/:
- evaluate: list of pending + completed assignments, COI flagged.
- evaluate/[projectId]: evaluation form reusing the juror's scoring UI,
  with an "acting on behalf" banner and confirmation dialog before
  submit. Back button returns to the assignments list.

Entry point: FilePen icon on each juror row in JuryProgressTable.

Refactor: extracted the scoring form JSX into shared
EvaluationFormFields component so the juror page and the admin proxy
page render identical inputs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 16:41:14 +02:00
Matt
acd75427b3 feat: add jury group import to special awards and fix juror dropdown
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m43s
The juror dropdown was always empty because the page requested
perPage: 200 but the user.list API caps at 100 (Zod validation).
Fixed to perPage: 100 with role filter for JURY_MEMBER/AWARD_MASTER.

Added "Import from Jury Group" section to the awards juror tab:
select a jury group, see members with checkboxes (already-assigned
shown as disabled), bulk-add selected members via bulkAddJurors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:39:34 -04:00
Matt
c7488b3e07 fix: save roundId on admin file upload and group assignments by round
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m45s
The admin upload flow accepted roundId but never wrote it to the
ProjectFile record, causing all admin-uploaded files to appear under
"General". Fixed the create call, the listByProject filter, and the
listByProjectForStage grouping to also use the direct roundId field.

Jury assignments on the project detail page are now grouped by round
with per-round completion counts instead of a flat list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:20:48 -04:00
Matt
a51241f7ff feat: add multi-role editor to member detail page
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m42s
Adds an "Additional Roles" checkbox section below the primary Role
dropdown. Admins can now grant a user multiple dashboard views (e.g.,
Observer + Jury Member) without changing their primary role. The roles
array is saved alongside the primary role and used by the role switcher.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 21:08:32 -04:00
Matt
2d6cee394f feat: add bulk invite to jury group page + widen member search role filter
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m48s
Adds bulkInviteMembers procedure to juryGroup router and integrates
BulkInviteForm into the jury group members tab. Also removes the
JURY_MEMBER-only filter from the user search — any user can now be
added to a jury group.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:37:25 -04:00
Matt
5537946b5a feat: add bulk invite form to award juror tab, widen role filter to all users
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m57s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:15:55 -04:00
Matt
29502a2b88 feat: add Decision Mode dropdown to award edit page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:13:51 -04:00
Matt
b901047418 fix: show jury group selector at top of assignments tab when none assigned
Previously showed "Select a jury group below" but the selector was
buried at the bottom (or not rendered at all when no jury was assigned).
Now shows the actual dropdown + "New Jury" button right where the
empty state message was.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:12:25 -04:00
Matt
0be8c5ecc7 feat: add chair toggle to admin award juror management
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:45:25 -04:00
Matt
3ccf9b0542 feat: per-category evaluation criteria (startup vs business concept)
Add ability to define completely different evaluation criteria for each
competition category. Admins toggle "Separate Criteria per Category" in
round config, then configure criteria independently via tabbed editor.

- Schema: add nullable `category` to EvaluationForm with updated constraints
- Config: add `perCategoryCriteria` boolean to EvaluationConfigSchema
- Helper: new `findActiveForm()` with category-aware resolution + fallback
- Backend: getForm, upsertForm, getStageForm, startStage all category-aware
- AI services: use project category for form lookup in summaries + ranking
- Export/ranking: merge criteria from all active forms for cross-category reports
- Admin UI: toggle switch + tabbed criteria editor with per-category builders
- Jury UI: auto-selects correct form based on project category (invisible to juror)
- Fully backwards compatible: toggle defaults OFF, existing forms unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 13:03:22 -04:00
Matt
7ead21114e fix: pipeline progress, message variables, jury invite flow, accept-invite UX
- Pipeline: SUBMISSION rounds count IN_PROGRESS + COMPLETED for progress %
- Round engine: remove phantom SubmissionFileRequirement check blocking auto-transition
- Messages: implement {{userName}}, {{projectName}}, {{roundName}}, {{programName}}, {{deadline}} substitution
- Email preview: show greeting, CTA button, and footer matching actual sent email
- Message composer: add green dot indicator for active rounds in round selector
- User create: generate invite token atomically (prevents stuck INVITED state on email failure)
- Jury invites: use jury-specific email template mentioning round context
- Bulk invite: animated progress bar, batch size hint, success/failure counts
- Accept invite: distinguish server errors (retry button) from expired tokens (redirect)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:47:42 -04:00
1356809cb1 fix: tech debt batch 1 — TS errors, vulnerabilities, dead code
- Fixed 12 TypeScript errors across analytics.ts, observer-project-detail.tsx, bulk-upload/page.tsx, settings/profile/page.tsx
- npm audit: 8 vulnerabilities resolved (1 critical, 4 high, 3 moderate)
- Deleted 3 dead files: live-control.ts (618 lines), feature-flags.ts, file-type-categories.ts
- Removed typescript.ignoreBuildErrors: true — TS errors now block builds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:51:44 +01:00
1ebdf5f9c9 fix: batch 5 — input validation tightening + health check endpoint
- z.any() replaced with z.record(z.string()) on webhook headers
- availabilityJson typed with z.array(z.object({ start, end }))
- Frontend webhook headers converted from array to Record before API call
- Docker HEALTHCHECK added to Dockerfile (health endpoint already existed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:26:28 +01:00
ec30dc83d6 feat: country flag display in remaining app pages (mentor, jury, admin, applicant)
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m23s
Extends CountryDisplay component usage to all remaining pages that showed
raw country codes: mentor dashboard/projects, jury competitions/awards,
admin awards/project detail, applicant team, and project-list-compact.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 15:07:40 +01:00
a1e758bc39 feat: router.back() navigation, read-only evaluation view, auth audit logging
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m53s
- Convert all Back buttons platform-wide (38 files) to use router.back()
  for natural browser-back behavior regardless of entry point
- Add read-only view for submitted evaluations in closed rounds with
  blue banner, disabled inputs, and contextual back navigation
- Add auth audit logs: MAGIC_LINK_SENT, PASSWORD_RESET_LINK_CLICKED,
  PASSWORD_RESET_LINK_EXPIRED, PASSWORD_RESET_LINK_INVALID
- Learning Hub links navigate in same window for all roles
- Update settings descriptions to reflect all-user scope

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 14:25:56 +01:00
a556732b46 feat: observer UX overhaul — reports, projects, charts, session & email
All checks were successful
Build and Push Docker Image / build (push) Successful in 11m2s
- Observer projects: default sort by status (rejected last), sortable status column
- Observer projects: search by country, institution, geographic zone
- Observer project detail: vertical timeline connectors between rounds
- Fix React key warning in ExpandableJurorTable and FilteringReportTabs
- Fix ScoreBadge text always white for better contrast on all backgrounds
- Remove misleading /30 denominator from heatmap juror reviewed count
- INTAKE stats: show Start-ups, Business Concepts, Countries (not States/Categories)
- DiversityMetrics: extractCountry() for country-only display in charts
- Fix nested button hydration error in filtering report mobile view
- Color project titles by outcome in filtering report (green/red/amber)
- Redesign CrossStageComparisonChart: funnel viz + metrics table with attrition %
- Center doughnut chart in StatusBreakdownChart
- Remove redundant RoundTypeStatsCards from evaluation report
- Move evaluation tab bar below overview header, rename to "Juror Assignments"
- Dev email override system (DEV_EMAIL_OVERRIDE env var)
- Session refresh on role change without re-login
- Role switcher in user dropdown menu
- formatCategory() utility for consistent category display
- Activity feed max height constraint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:37:50 +01:00
e7b99fff63 feat: multi-round messaging, login logo, applicant seed user
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m40s
- Communication hub now supports selecting multiple rounds when sending
  to Round Jury or Round Applicants (checkbox list instead of dropdown)
- Recipients are unioned across selected rounds with deduplication
- Recipient details grouped by round when multiple rounds selected
- Added MOPC logo above "Welcome back" on login page
- Added matt@letsbe.solutions as seeded APPLICANT account

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 12:22:01 +01:00
3180bfa946 feat: document language checker on round overview
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m15s
- New roundLanguageSummary query in file router aggregates per-round document
  language data from existing detectedLang/langConfidence fields
- Document Languages card on round overview tab shows analysis status and
  flags non-English documents grouped by project with confidence scores
- Green border when all documents are English, amber when issues detected
- Project names link to project detail page for easy navigation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 11:53:43 +01:00
d4c946470a feat: audit log clickable links, communication hub recipient details & link options
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- Audit log: user names link to /admin/members/{id}, entity IDs link to
  relevant detail pages (projects, rounds, awards, users)
- Communication hub: expandable "View Recipients" section in sidebar shows
  actual users/projects that will receive the message, with collapsible
  project-level detail for applicants and juror assignment counts
- Email link type selector: choose between no link, messages inbox, login
  page, or invite/accept link (auto-detects new vs existing members)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 11:49:49 +01:00
a358e9940d feat: revamp admin member detail page, observer dashboard round timeline
All checks were successful
Build and Push Docker Image / build (push) Successful in 13m37s
- Member detail: tabs layout, impersonate button, icon-pill card headers,
  profile details grid, quick info sidebar, jury groups, mentor assignments
- Observer dashboard: round timeline with special award support,
  round node cards, completion indicators
- Analytics: include specialAwardId/Name in observer round overview

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:39:21 +01:00
34fc0b81e0 feat: revamp communication hub with recipient preview and state filtering
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- New previewRecipients query shows live project/applicant counts as you
  compose, with per-state breakdown for Round Applicants
- Exclude Rejected/Withdrawn checkboxes filter out terminal-state projects
- Compose form now has 2/3 + 1/3 layout with always-visible recipient
  summary sidebar showing project counts, applicant counts, state badges
- Preview dialog enlarged (max-w-3xl) with split layout: email preview
  on left, recipient/delivery summary on right
- Send button now shows recipient count ("Send to N Recipients")
- resolveRecipients accepts excludeStates param for ROUND_APPLICANTS

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:32:03 +01:00
6852278f92 fix: group project files by round in admin project detail
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m15s
- Sort files by round sortOrder first (via requirement.round.sortOrder)
- Admin project detail now uses grouped file view with round headers
- Files without a round requirement appear under "General" group

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 17:36:13 +01:00
0d94ee1fe8 feat: clickable status badges, observer status alignment, CSV export all
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m36s
- Admin projects: status summary badges are clickable to filter by round state
  with ring highlight, opacity fade, and clear button
- Add roundStates filter param to project.list backend query
  (filters by latest round state per project, consistent with counts)
- Observer status dropdown now uses ProjectRoundState values
  (Pending/In Progress/Completed/Passed/Rejected/Withdrawn)
- Observer status derived from latest ProjectRoundState instead of stale Project.status
- Observer CSV export fetches all matching projects, not just current page
- Add PENDING and PASSED styles to StatusBadge component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 17:19:12 +01:00
6b6f5e33f5 fix: admin role change, logo access, magic link validation, login help
- Add updateTeamMemberRole mutation for admins to change team member roles
- Allow any team member (not just lead) to change project logo
- Add visible "Add logo"/"Change" label under logo for discoverability
- Pre-check email existence before sending magic link (show error)
- Add "forgot which email" contact link on login page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:37:45 +01:00
461551b489 fix: separate main pipeline from award tracks on rounds page
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m24s
Award-specific rounds (e.g. Spotlight on Africa) were mixed into the
main pipeline as a flat list, making them look like sequential steps
after Deliberation. Now they render in their own amber-tinted card
sections below the main pipeline, each with a header showing award
name, pool size, eligibility mode, and status.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:55:17 +01:00
b7905a82e1 fix: impersonation, dashboard counter, logo lightbox, submission config, auth logs
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m12s
- Fix impersonation by bypassing useSession().update() loading gate with direct session POST
- Fix dashboard account counter defaulting to latest round with PASSED projects
- Add clickToEnlarge lightbox for project logos on admin detail page
- Remove submission eligibility config (all passed projects must upload)
- Suppress CredentialsSignin auth errors in production (minified name check)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:40:08 +01:00
fd2624f198 feat: fix project status counts, add top pagination and sortable columns
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m39s
- Status counts now show each project's latest round state only
  (no more inflated counts from projects passing multiple rounds)
- Add pagination controls at top of projects, members, and observer lists
- Add sortable column headers to admin projects table (title, category,
  program, assignments, status) and members table (name, role, status,
  last login)
- Backend: add sortBy/sortDir params to project.list and user.list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:49:17 +01:00
8cdcc85555 feat: round user tracker + fix INVITED status not updating on login
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- Replace Semi-Finalist Tracker with Round User Tracker on dashboard
- New getRoundUserStats query: round-aware account activation stats
- Round selector dropdown to view any round's passed projects
- sendAccountReminders now accepts optional roundId for scoped reminders
- Fix: signIn callback now sets status=ACTIVE for INVITED users on login
- DB fix: 5 users who logged in via magic link but stayed INVITED → ACTIVE

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:00:19 +01:00