import { TRPCError } from '@trpc/server'; import { asc, eq, sql } from 'drizzle-orm'; import { stakeholder } from '@cockpit/db'; import { StakeholderSchemas } from '@cockpit/shared'; import { router, protectedProcedure } from '../trpc.js'; export const stakeholderRouter = router({ forProject: protectedProcedure .input(StakeholderSchemas.stakeholderForProjectInput) .query(async ({ ctx, input }) => { return ctx.db .select() .from(stakeholder) .where(eq(stakeholder.projectId, input.projectId)) .orderBy(asc(stakeholder.order), asc(stakeholder.createdAt)); }), create: protectedProcedure .input(StakeholderSchemas.createStakeholderInput) .mutation(async ({ ctx, input }) => { const count = ( await ctx.db .select({ c: sql`count(*)::int` }) .from(stakeholder) .where(eq(stakeholder.projectId, input.projectId)) )[0]?.c ?? 0; const [created] = await ctx.db .insert(stakeholder) .values({ projectId: input.projectId, name: input.name, rolle: input.rolle ?? null, interesse: input.interesse, einfluss: input.einfluss, haltung: input.haltung, beduerfnis: input.beduerfnis ?? null, notiz: input.notiz ?? null, order: count, }) .returning(); return created; }), update: protectedProcedure .input(StakeholderSchemas.updateStakeholderInput) .mutation(async ({ ctx, input }) => { const { id, ...patch } = input; if (Object.keys(patch).length === 0) { const existing = ( await ctx.db.select().from(stakeholder).where(eq(stakeholder.id, id)).limit(1) )[0]; if (!existing) throw new TRPCError({ code: 'NOT_FOUND', message: 'Stakeholder nicht gefunden.' }); return existing; } const [updated] = await ctx.db .update(stakeholder) .set(patch) .where(eq(stakeholder.id, id)) .returning(); if (!updated) throw new TRPCError({ code: 'NOT_FOUND', message: 'Stakeholder nicht gefunden.' }); return updated; }), remove: protectedProcedure .input(StakeholderSchemas.removeStakeholderInput) .mutation(async ({ ctx, input }) => { await ctx.db.delete(stakeholder).where(eq(stakeholder.id, input.id)); return { ok: true as const }; }), });