From 68422e6c26467cb30085714cd25cc04449d5f208 Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 27 Feb 2026 09:40:03 +0100 Subject: [PATCH] feat(02-01): add saveReorder mutation to ranking router - Define ReorderEvent local type (category, orderedProjectIds, reorderedBy, reorderedAt) - Add saveReorder adminProcedure accepting snapshotId, category, orderedProjectIds - Append-only log: reads existing reordersJson, appends new event, persists full array - Returns { ok: true } on success --- src/server/routers/ranking.ts | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/server/routers/ranking.ts b/src/server/routers/ranking.ts index a75601b..402c674 100644 --- a/src/server/routers/ranking.ts +++ b/src/server/routers/ranking.ts @@ -12,6 +12,15 @@ import { import { logAudit } from '../utils/audit' import type { EvaluationConfig } from '@/types/competition-configs' +// ─── Local Types ─────────────────────────────────────────────────────────────── + +type ReorderEvent = { + category: 'STARTUP' | 'BUSINESS_CONCEPT' + orderedProjectIds: string[] + reorderedBy: string + reorderedAt: string +} + // ─── Zod Schemas ────────────────────────────────────────────────────────────── const ParsedRuleSchema = z.object({ @@ -204,6 +213,38 @@ export const rankingRouter = router({ return snapshot }), + /** Persist admin drag-reorder to RankingSnapshot.reordersJson. Append-only — never overwrites old entries. DASH-02, DASH-03. */ + saveReorder: adminProcedure + .input( + z.object({ + snapshotId: z.string(), + category: z.enum(['STARTUP', 'BUSINESS_CONCEPT']), + orderedProjectIds: z.array(z.string()), + }), + ) + .mutation(async ({ ctx, input }) => { + const snapshot = await ctx.prisma.rankingSnapshot.findUniqueOrThrow({ + where: { id: input.snapshotId }, + select: { reordersJson: true }, + }) + + const existingReorders = (snapshot.reordersJson as ReorderEvent[] | null) ?? [] + + const newReorder: ReorderEvent = { + category: input.category, + orderedProjectIds: input.orderedProjectIds, + reorderedBy: ctx.user.id, + reorderedAt: new Date().toISOString(), + } + + await ctx.prisma.rankingSnapshot.update({ + where: { id: input.snapshotId }, + data: { reordersJson: [...existingReorders, newReorder] as unknown as Prisma.InputJsonValue }, + }) + + return { ok: true } + }), + /** * RANK-09 — Manual trigger for auto-rank (admin button on round detail page). * Reads ranking criteria from round configJson and executes quickRank.