import { FastifyInstance } from "fastify"; import { PrismaClient } from "@prisma/client"; import { z } from "zod"; const prisma = new PrismaClient(); const createBoardBody = z.object({ slug: z.string().min(2).max(50).regex(/^[a-z0-9-]+$/), name: z.string().min(1).max(100), description: z.string().max(500).optional(), externalUrl: z.string().url().optional(), voteBudget: z.number().int().min(0).default(10), voteBudgetReset: z.enum(["weekly", "monthly", "quarterly", "yearly", "never"]).default("monthly"), allowMultiVote: z.boolean().default(false), }); const updateBoardBody = z.object({ name: z.string().min(1).max(100).optional(), description: z.string().max(500).optional().nullable(), externalUrl: z.string().url().optional().nullable(), isArchived: z.boolean().optional(), voteBudget: z.number().int().min(0).optional(), voteBudgetReset: z.enum(["weekly", "monthly", "quarterly", "yearly", "never"]).optional(), allowMultiVote: z.boolean().optional(), }); export default async function adminBoardRoutes(app: FastifyInstance) { app.get( "/admin/boards", { preHandler: [app.requireAdmin] }, async (_req, reply) => { const boards = await prisma.board.findMany({ orderBy: { createdAt: "asc" }, include: { _count: { select: { posts: true } }, }, }); reply.send(boards); } ); app.post<{ Body: z.infer }>( "/admin/boards", { preHandler: [app.requireAdmin] }, async (req, reply) => { const body = createBoardBody.parse(req.body); const existing = await prisma.board.findUnique({ where: { slug: body.slug } }); if (existing) { reply.status(409).send({ error: "Slug already taken" }); return; } const board = await prisma.board.create({ data: body }); reply.status(201).send(board); } ); app.put<{ Params: { id: string }; Body: z.infer }>( "/admin/boards/:id", { preHandler: [app.requireAdmin] }, async (req, reply) => { const board = await prisma.board.findUnique({ where: { id: req.params.id } }); if (!board) { reply.status(404).send({ error: "Board not found" }); return; } const body = updateBoardBody.parse(req.body); const updated = await prisma.board.update({ where: { id: board.id }, data: body, }); reply.send(updated); } ); app.post<{ Params: { id: string } }>( "/admin/boards/:id/reset-budget", { preHandler: [app.requireAdmin] }, async (req, reply) => { const board = await prisma.board.findUnique({ where: { id: req.params.id } }); if (!board) { reply.status(404).send({ error: "Board not found" }); return; } const updated = await prisma.board.update({ where: { id: board.id }, data: { lastBudgetReset: new Date() }, }); reply.send(updated); } ); app.delete<{ Params: { id: string } }>( "/admin/boards/:id", { preHandler: [app.requireAdmin] }, async (req, reply) => { const board = await prisma.board.findUnique({ where: { id: req.params.id } }); if (!board) { reply.status(404).send({ error: "Board not found" }); return; } await prisma.board.delete({ where: { id: board.id } }); reply.status(204).send(); } ); }