feat: hotel CRUD on logistics router

This commit is contained in:
Matt
2026-04-28 18:18:16 +02:00
parent 88548cbea3
commit 497145b983
3 changed files with 157 additions and 0 deletions

View File

@@ -51,6 +51,7 @@ import { deliberationRouter } from './deliberation'
import { resultLockRouter } from './resultLock'
// Grand-finale logistics
import { finalistRouter } from './finalist'
import { logisticsRouter } from './logistics'
/**
* Root tRPC router that combines all domain routers
@@ -108,6 +109,7 @@ export const appRouter = router({
resultLock: resultLockRouter,
// Grand-finale logistics
finalist: finalistRouter,
logistics: logisticsRouter,
})
export type AppRouter = typeof appRouter

View File

@@ -0,0 +1,56 @@
import { z } from 'zod'
import { router, adminProcedure } from '../trpc'
import { logAudit } from '../utils/audit'
export const logisticsRouter = router({
/** Read the hotel for a program (1:1). Null if not yet set. */
getHotel: adminProcedure
.input(z.object({ programId: z.string() }))
.query(async ({ ctx, input }) => {
return ctx.prisma.hotel.findUnique({ where: { programId: input.programId } })
}),
/** Create or update the program's hotel. Empty link strings are stored as null. */
upsertHotel: adminProcedure
.input(
z.object({
programId: z.string(),
name: z.string().min(1).max(200),
address: z.string().max(500).optional(),
link: z
.string()
.url()
.or(z.literal(''))
.optional(),
notes: z.string().max(2000).optional(),
}),
)
.mutation(async ({ ctx, input }) => {
const link = input.link && input.link.trim().length > 0 ? input.link : null
const hotel = await ctx.prisma.hotel.upsert({
where: { programId: input.programId },
create: {
programId: input.programId,
name: input.name,
address: input.address ?? null,
link,
notes: input.notes ?? null,
},
update: {
name: input.name,
address: input.address ?? null,
link,
notes: input.notes ?? null,
},
})
await logAudit({
prisma: ctx.prisma,
userId: ctx.user.id,
action: 'HOTEL_UPSERT',
entityType: 'Hotel',
entityId: hotel.id,
detailsJson: { programId: input.programId, name: input.name },
})
return hotel
}),
})