import { TRPCError } from '@trpc/server'; import { desc, eq } from 'drizzle-orm'; import { changeEntry, user } from '@cockpit/db'; import { ChangeSchemas } from '@cockpit/shared'; import { router, protectedProcedure } from '../trpc.js'; export const changeRouter = router({ forProject: protectedProcedure .input(ChangeSchemas.changeForProjectInput) .query(async ({ ctx, input }) => { const rows = await ctx.db .select({ change: changeEntry, authorName: user.name }) .from(changeEntry) .leftJoin(user, eq(user.id, changeEntry.createdBy)) .where(eq(changeEntry.projectId, input.projectId)) .orderBy(desc(changeEntry.createdAt)); return rows.map((r) => ({ ...r.change, authorName: r.authorName })); }), create: protectedProcedure .input(ChangeSchemas.createChangeInput) .mutation(async ({ ctx, input }) => { const [created] = await ctx.db .insert(changeEntry) .values({ projectId: input.projectId, titel: input.titel, auswirkung: input.auswirkung ?? null, entscheidung: input.entscheidung, createdBy: ctx.user.id, }) .returning(); return created; }), update: protectedProcedure .input(ChangeSchemas.updateChangeInput) .mutation(async ({ ctx, input }) => { const { id, ...patch } = input; if (Object.keys(patch).length === 0) { const existing = ( await ctx.db.select().from(changeEntry).where(eq(changeEntry.id, id)).limit(1) )[0]; if (!existing) throw new TRPCError({ code: 'NOT_FOUND', message: 'Eintrag nicht gefunden.' }); return existing; } const [updated] = await ctx.db .update(changeEntry) .set(patch) .where(eq(changeEntry.id, id)) .returning(); if (!updated) throw new TRPCError({ code: 'NOT_FOUND', message: 'Eintrag nicht gefunden.' }); return updated; }), remove: protectedProcedure .input(ChangeSchemas.removeChangeInput) .mutation(async ({ ctx, input }) => { await ctx.db.delete(changeEntry).where(eq(changeEntry.id, input.id)); return { ok: true as const }; }), });