feat: external lunch attendees CRUD

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt
2026-04-29 02:31:28 +02:00
parent 1f24f5539c
commit 06b171b0d4
2 changed files with 166 additions and 0 deletions

View File

@@ -129,6 +129,102 @@ export const lunchRouter = router({
return { ok: true as const }
}),
// ─── External attendees CRUD ─────────────────────────────────────────────
listExternals: adminProcedure
.input(z.object({ lunchEventId: z.string() }))
.query(({ ctx, input }) =>
ctx.prisma.externalAttendee.findMany({
where: { lunchEventId: input.lunchEventId },
orderBy: { createdAt: 'asc' },
include: { project: { select: { id: true, title: true } } },
}),
),
createExternal: adminProcedure
.input(
z.object({
lunchEventId: z.string(),
name: z.string().min(1).max(200),
email: z.string().email().optional(),
projectId: z.string().nullable().optional(),
roleNote: z.string().max(500).optional(),
dishId: z.string().nullable().optional(),
allergens: allergens.optional(),
allergenOther: z.string().max(500).optional(),
}),
)
.mutation(async ({ ctx, input }) => {
const ext = await ctx.prisma.externalAttendee.create({
data: {
lunchEventId: input.lunchEventId,
name: input.name,
email: input.email,
projectId: input.projectId ?? null,
roleNote: input.roleNote,
dishId: input.dishId ?? null,
allergens: input.allergens ?? [],
allergenOther: input.allergenOther,
},
})
await logAudit({
prisma: ctx.prisma,
userId: ctx.user.id,
action: 'LUNCH_EXTERNAL_CREATED',
entityType: 'ExternalAttendee',
entityId: ext.id,
detailsJson: { name: ext.name, projectId: ext.projectId },
})
return ext
}),
updateExternal: adminProcedure
.input(
z.object({
externalId: z.string(),
name: z.string().min(1).max(200).optional(),
email: z.string().email().nullable().optional(),
projectId: z.string().nullable().optional(),
roleNote: z.string().max(500).nullable().optional(),
dishId: z.string().nullable().optional(),
allergens: allergens.optional(),
allergenOther: z.string().max(500).nullable().optional(),
}),
)
.mutation(async ({ ctx, input }) => {
const { externalId, ...patch } = input
const ext = await ctx.prisma.externalAttendee.update({
where: { id: externalId },
data: patch,
})
await logAudit({
prisma: ctx.prisma,
userId: ctx.user.id,
action: 'LUNCH_EXTERNAL_UPDATED',
entityType: 'ExternalAttendee',
entityId: ext.id,
detailsJson: patch as Record<string, unknown>,
})
return ext
}),
deleteExternal: adminProcedure
.input(z.object({ externalId: z.string() }))
.mutation(async ({ ctx, input }) => {
const ext = await ctx.prisma.externalAttendee.delete({
where: { id: input.externalId },
})
await logAudit({
prisma: ctx.prisma,
userId: ctx.user.id,
action: 'LUNCH_EXTERNAL_DELETED',
entityType: 'ExternalAttendee',
entityId: ext.id,
detailsJson: { name: ext.name },
})
return { ok: true as const }
}),
/** Patch any subset of LunchEvent config fields. Audit-logged. */
updateEvent: adminProcedure
.input(