From f055926b6f8c81ac180e0eb38f70206167a3f836 Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 27 Feb 2026 09:56:07 +0100 Subject: [PATCH] =?UTF-8?q?docs(02-03):=20complete=20Advance=20Top=20N=20p?= =?UTF-8?q?lan=20=E2=80=94=20SUMMARY,=20STATE,=20ROADMAP=20updated?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Phase 2 complete: all 3 plans done (DASH-01 through DASH-07 fulfilled) - REQUIREMENTS.md: marked DASH-05, DASH-06, DASH-07 complete - ROADMAP.md: Phase 2 updated to Complete (3/3 plans) - STATE.md: advanced to Phase 2 complete, added 3 new decisions --- .planning/REQUIREMENTS.md | 24 ++-- .planning/ROADMAP.md | 4 +- .planning/STATE.md | 26 +++-- .../02-ranking-dashboard-ui/02-03-SUMMARY.md | 104 ++++++++++++++++++ 4 files changed, 133 insertions(+), 25 deletions(-) create mode 100644 .planning/phases/02-ranking-dashboard-ui/02-03-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 2227fd7..b7bafc4 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -23,12 +23,12 @@ Requirements for this milestone. Each maps to roadmap phases. ### Ranking Dashboard - [x] **DASH-01**: Admin sees ranked project list per category on the round detail page (new tab) -- [ ] **DASH-02**: Admin can drag-and-drop to reorder projects in the ranked list -- [ ] **DASH-03**: Drag-and-drop state is isolated from server state to prevent snap-back race conditions -- [ ] **DASH-04**: Admin can click a project to see full evaluation data in a side panel (scores, votes, juror comments, pass/fail) -- [ ] **DASH-05**: Admin can select "Advance top X" to promote the top N projects to the next round -- [ ] **DASH-06**: Admin can batch-reject remaining non-advanced projects -- [ ] **DASH-07**: Advance button is disabled until any pending reorder mutations settle +- [x] **DASH-02**: Admin can drag-and-drop to reorder projects in the ranked list +- [x] **DASH-03**: Drag-and-drop state is isolated from server state to prevent snap-back race conditions +- [x] **DASH-04**: Admin can click a project to see full evaluation data in a side panel (scores, votes, juror comments, pass/fail) +- [x] **DASH-05**: Admin can select "Advance top X" to promote the top N projects to the next round +- [x] **DASH-06**: Admin can batch-reject remaining non-advanced projects +- [x] **DASH-07**: Advance button is disabled until any pending reorder mutations settle ### Email & Notifications @@ -98,12 +98,12 @@ Which phases cover which requirements. Updated during roadmap creation. | RANK-09 | Phase 1 | Complete | | RANK-10 | Phase 1 | Complete | | DASH-01 | Phase 2 | Complete | -| DASH-02 | Phase 2 | Pending | -| DASH-03 | Phase 2 | Pending | -| DASH-04 | Phase 2 | Pending | -| DASH-05 | Phase 2 | Pending | -| DASH-06 | Phase 2 | Pending | -| DASH-07 | Phase 2 | Pending | +| DASH-02 | Phase 2 | Complete | +| DASH-03 | Phase 2 | Complete | +| DASH-04 | Phase 2 | Complete | +| DASH-05 | Phase 2 | Complete | +| DASH-06 | Phase 2 | Complete | +| DASH-07 | Phase 2 | Complete | | MAIL-01 | Phase 3 | Pending | | MAIL-02 | Phase 3 | Pending | | MAIL-03 | Phase 3 | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 73f836b..9eac4ac 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -13,7 +13,7 @@ This milestone extends the MOPC jury voting platform with four capabilities: an Decimal phases appear between their surrounding integers in numeric order. - [x] **Phase 1: AI Ranking Backend** - AI service, tRPC router, schema, and auto-trigger for ranking projects per category using natural-language criteria (completed 2026-02-27) -- [ ] **Phase 2: Ranking Dashboard UI** - Drag-and-drop ranking tab on the round detail page with criteria input, preview-confirm dialog, and project detail side panel +- [x] **Phase 2: Ranking Dashboard UI** - Drag-and-drop ranking tab on the round detail page with criteria input, preview-confirm dialog, and project detail side panel (completed 2026-02-27) - [ ] **Phase 3: Advancement + Email** - Bulk advancement flow with reject/advance in one operation, notify-vs-silent toggle, and admin-editable email templates - [ ] **Phase 4: Mentor Persistence** - Mentor assignment during any round type with cross-round carryover and COI re-validation @@ -76,6 +76,6 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 (Phase 4 can be parallelize | Phase | Plans Complete | Status | Completed | |-------|----------------|--------|-----------| | 1. AI Ranking Backend | 4/4 | Complete | 2026-02-27 | -| 2. Ranking Dashboard UI | 2/3 | In Progress| | +| 2. Ranking Dashboard UI | 3/3 | Complete | 2026-02-27 | | 3. Advancement + Email | 0/TBD | Not started | - | | 4. Mentor Persistence | 0/TBD | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index b4616ed..3ec84ab 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,12 +3,12 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: in_progress -last_updated: "2026-02-27T08:48:11Z" +last_updated: "2026-02-27T08:56:00Z" progress: total_phases: 4 - completed_phases: 1 + completed_phases: 2 total_plans: 10 - completed_plans: 6 + completed_plans: 7 --- # Project State @@ -22,12 +22,12 @@ See: .planning/PROJECT.md (updated 2026-02-26) ## Current Position -Phase: 2 of 4 (Ranking Dashboard UI) -Plan: 2 of 3 in current phase (Phase 2 Plan 2 complete) -Status: In progress -Last activity: 2026-02-27 — Plan 02-02 complete: Full RankingDashboard with drag-and-drop, AI vs override badges, Sheet detail panel +Phase: 2 of 4 (Ranking Dashboard UI) — COMPLETE +Plan: 3 of 3 in current phase (Phase 2 all plans complete) +Status: In progress (Phase 3 next) +Last activity: 2026-02-27 — Plan 02-03 complete: Advance Top N dialog + batch-reject wired to tRPC mutations -Progress: [█████░░░░░] ~60% +Progress: [███████░░░] ~70% ## Performance Metrics @@ -41,15 +41,16 @@ Progress: [█████░░░░░] ~60% | Phase | Plans | Total | Avg/Plan | |-------|-------|-------|----------| | 01-ai-ranking-backend | 4 | ~18 min | ~5 min | -| 02-ranking-dashboard-ui | 1 | ~5 min | ~5 min | +| 02-ranking-dashboard-ui | 3 | ~18 min | ~6 min | **Recent Trend:** -- Last 5 plans: 01-02 (~3 min), 01-03 (~4 min), 01-04 (~8 min), 02-01 (~5 min), 02-02 (~8 min) +- Last 5 plans: 01-04 (~8 min), 02-01 (~5 min), 02-02 (~8 min), 02-03 (~5 min) - Trend: Fast (service-layer + UI implementation tasks) *Updated after each plan completion* | Phase 02-ranking-dashboard-ui P01 | 5 | 2 tasks | 3 files | | Phase 02-ranking-dashboard-ui P02 | 8 | 1 task | 1 file | +| Phase 02-ranking-dashboard-ui P03 | 5 | 1 task | 1 file | ## Accumulated Context @@ -77,6 +78,9 @@ Recent decisions affecting current work: - [02-02]: Double cast (as unknown as RankedProjectEntry[]) required for Prisma JsonValue — direct cast rejected by TypeScript strict mode - [02-02]: getFullDetail returns { project, assignments, stats } shape — title accessed via .project.title not root level - [02-02]: saveReorder has no onSuccess invalidation — avoids re-fetch that would reset localOrder and cause snap-back +- [02-03]: Advance button disabled via saveReorderMutation.isPending (reactive) not pendingReorderCount.current (ref, non-reactive) +- [02-03]: topNStartup + topNConceptual === 0 disables confirm button — prevents no-op advance calls +- [02-03]: batchRejectMutation fires conditionally (only if includeReject and rejectIds.length > 0) ### Pending Todos @@ -91,5 +95,5 @@ None yet. ## Session Continuity Last session: 2026-02-27 -Stopped at: Completed 02-02-PLAN.md (Full RankingDashboard with drag-and-drop, AI vs override badges, Sheet detail panel) +Stopped at: Completed 02-03-PLAN.md (Advance Top N dialog + batch-reject — Phase 2 complete) Resume file: None diff --git a/.planning/phases/02-ranking-dashboard-ui/02-03-SUMMARY.md b/.planning/phases/02-ranking-dashboard-ui/02-03-SUMMARY.md new file mode 100644 index 0000000..f30e3ea --- /dev/null +++ b/.planning/phases/02-ranking-dashboard-ui/02-03-SUMMARY.md @@ -0,0 +1,104 @@ +--- +phase: 02-ranking-dashboard-ui +plan: 03 +subsystem: ui +tags: [react, trpc, dialog, shadcn, ranking, advance-projects, batch-reject] + +# Dependency graph +requires: + - phase: 02-02 + provides: Full RankingDashboard with drag-and-drop, AI vs override badges, Sheet detail panel, saveReorderMutation +provides: + - Advance Top N dialog wired to trpc.round.advanceProjects with per-category N inputs + - Batch-reject checkbox in advance dialog wired to trpc.roundEngine.batchTransition + - DASH-07 disabled state: Advance button disabled while saveReorderMutation.isPending +affects: [] + +# Tech tracking +tech-stack: + added: [] + patterns: + - "pendingReorderCount useRef pattern: onMutate increments, onSettled decrements — provides belt-and-suspenders for rapid drag scenarios alongside isPending reactive signal" + - "Parallel mutation from single handler: advanceMutation.mutate + batchRejectMutation.mutate fired in same handleAdvance — fire-and-forget both, each handles own onSuccess/onError" + +key-files: + created: [] + modified: + - src/components/admin/round/ranking-dashboard.tsx + +key-decisions: + - "Advance button disabled via saveReorderMutation.isPending (reactive) not pendingReorderCount.current (ref, non-reactive) — ref used for belt-and-suspenders coverage, boolean state for actual UI" + - "topNStartup + topNConceptual === 0 disables the Advance button inside the dialog — prevents no-op advance calls" + - "batchRejectMutation fired conditionally (only if includeReject and rejectIds.length > 0) — avoids empty batch call" + +patterns-established: + - "Per-category N inputs with min/max clamping via Math.max/Math.min on parseInt — prevents out-of-range values" + - "Preview section in dialog: live count of advancing/rejecting projects — feedback before confirmation" + +requirements-completed: [DASH-05, DASH-06, DASH-07] + +# Metrics +duration: 5min +completed: 2026-02-27 +--- + +# Phase 2 Plan 03: Advance Top N Dialog + Batch-Reject Summary + +**Advance Top N dialog with per-category numeric inputs, optional batch-reject checkbox, and disabled state tied to pending reorder mutations — completing the full advancement workflow for the RankingDashboard** + +## Performance + +- **Duration:** ~5 min +- **Started:** 2026-02-27T08:51:01Z +- **Completed:** 2026-02-27T08:56:00Z +- **Tasks:** 1 +- **Files modified:** 1 + +## Accomplishments + +- DASH-05: Admin can click "Advance Top N" button to open a dialog, enter a number N per category, and advance the top N projects from each category to the next round +- DASH-06: Admin can enable "Also batch-reject non-advanced projects" checkbox in the dialog — fires batchTransition for non-advanced projects; toasts use `.succeeded.length` per MEMORY.md +- DASH-07: Advance button is disabled while `saveReorderMutation.isPending` is true (reorder in flight) and when no snapshot exists +- pendingReorderCount ref added to saveReorderMutation (onMutate++, onSettled--) for belt-and-suspenders reorder tracking +- Full dialog: per-category N inputs with range clamping, live preview of advance/reject counts, cancel/confirm buttons +- Both mutations invalidate `roundEngine.getProjectStates` on success to refresh downstream state +- TypeScript strict mode: 0 errors; build: PASSED + +## Task Commits + +| Task | Name | Commit | Files | +|------|------|--------|-------| +| 1 | Add Advance Top N dialog + batch-reject to RankingDashboard | a6f3945 | src/components/admin/round/ranking-dashboard.tsx | + +## Files Created/Modified + +- `src/components/admin/round/ranking-dashboard.tsx` — Added Dialog, Input, Label imports; pendingReorderCount ref; advanceMutation; batchRejectMutation; handleAdvance; Advance Top N button; Dialog JSX (681 lines total, +197 insertions) + +## Decisions Made + +- **Advance button disabled state uses `saveReorderMutation.isPending`** (reactive) as the primary signal, not `pendingReorderCount.current` (useRef is not reactive — React won't re-render on ref mutation). The ref still provides belt-and-suspenders for rapid multi-drag scenarios but is not the gating signal. +- **topNStartup + topNConceptual === 0** disables the confirm button inside the dialog — prevents a no-op advance call when both inputs are zero. +- **batchRejectMutation fires conditionally** — only when `includeReject` is true AND `rejectIds.length > 0`. Avoids sending an empty projectIds array to the mutation. + +## Deviations from Plan + +None — plan executed exactly as written. + +## Issues Encountered + +None. + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +- All 7 DASH requirements (DASH-01 through DASH-07) completed across plans 01-03 +- Phase 2 (Ranking Dashboard UI) is fully complete +- Phase 3 (Notification Templates) or Phase 4 (Juror Criterion Progress) can begin next +- Full build and typecheck pass with 0 errors + +--- +*Phase: 02-ranking-dashboard-ui* +*Completed: 2026-02-27*