57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
|
|
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
|
||
|
|
}),
|
||
|
|
})
|