--- phase: 02-ranking-dashboard-ui plan: 01 subsystem: ui tags: [trpc, prisma, ranking, react, nextjs] # Dependency graph requires: - phase: 01-ai-ranking-backend provides: rankingRouter with listSnapshots/getSnapshot, RankingSnapshot model with reordersJson field provides: - saveReorder mutation on rankingRouter (append-only audit log of admin drag-reorders) - Ranking tab visible on EVALUATION round detail pages - RankingDashboard stub component (Plan 02 will flesh out) affects: [02-02-ranking-dashboard-ui] # Tech tracking tech-stack: added: [] patterns: - "Append-only JSON log pattern: read existing array, push new event, write full array as Prisma.InputJsonValue" - "isEvaluation guard for tab/content conditional rendering (matches isFiltering pattern)" key-files: created: - src/components/admin/round/ranking-dashboard.tsx modified: - src/server/routers/ranking.ts - src/app/(admin)/admin/rounds/[roundId]/page.tsx key-decisions: - "ReorderEvent type defined locally in ranking.ts (not exported) — only used by saveReorder" - "saveReorder is append-only: full ordered list stored per event, latest entry per category = current admin order, gives full audit trail" patterns-established: - "Tab conditional: ...(isEvaluation ? [{ value: 'ranking', label: 'Ranking', icon: BarChart3 }] : []) follows existing isFiltering pattern" requirements-completed: [DASH-01] # Metrics duration: 5min completed: 2026-02-27 --- # Phase 2 Plan 01: Ranking Tab Entry Point Summary **saveReorder append-only audit mutation + Ranking tab registered on EVALUATION round detail pages with RankingDashboard stub component** ## Performance - **Duration:** ~5 min - **Started:** 2026-02-27T00:15:00Z - **Completed:** 2026-02-27T00:20:00Z - **Tasks:** 2 - **Files modified:** 3 ## Accomplishments - Added `saveReorder` adminProcedure to rankingRouter — accepts snapshotId, category, orderedProjectIds; appends ReorderEvent to reordersJson (append-only audit log) - Registered Ranking tab in round detail page guarded by `isEvaluation` with BarChart3 icon (already imported) - Created minimal `RankingDashboard` stub component that compiles and renders placeholder text ## Task Commits Each task was committed atomically: 1. **Task 1: Add saveReorder mutation to ranking router** - `68422e6` (feat) 2. **Task 2: Register Ranking tab in round detail page + create component stub** - `8f71527` (feat) **Plan metadata:** (docs commit to follow) ## Files Created/Modified - `src/server/routers/ranking.ts` - Added ReorderEvent local type and saveReorder adminProcedure - `src/components/admin/round/ranking-dashboard.tsx` - New stub component exporting RankingDashboard with competitionId+roundId props - `src/app/(admin)/admin/rounds/[roundId]/page.tsx` - Import RankingDashboard, add Ranking tab to tab array, add TabsContent block ## Decisions Made - `ReorderEvent` type defined locally in ranking.ts (not exported) — only consumed by saveReorder - Stub uses `_competitionId` / `_roundId` underscore prefix to avoid TypeScript unused-var warnings while keeping the correct prop signature for Plan 02 to use ## Deviations from Plan None - plan executed exactly as written. ## Issues Encountered None. ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - saveReorder backend contract established and type-safe - Ranking tab entry point wired — visible when viewing EVALUATION rounds - Plan 02 can now replace the stub body with the full RankingDashboard component - Build and typecheck both pass with 0 errors --- *Phase: 02-ranking-dashboard-ui* *Completed: 2026-02-27*