103 lines
2.9 KiB
TypeScript
103 lines
2.9 KiB
TypeScript
import { z } from 'zod'
|
|
import { pikkuSessionlessFunc } from '#pikku'
|
|
import { BookingZ } from '#pikku/db/zod.gen.js'
|
|
|
|
export const GetEventsListingInput = z.object({
|
|
venueSlug: z.string().default('drawehn'),
|
|
filter: z.enum(['this_year', 'next_year', 'all']).default('all'),
|
|
search: z.string().optional(),
|
|
})
|
|
|
|
const Card = BookingZ
|
|
.pick({
|
|
bookingId: true,
|
|
eventName: true,
|
|
eventOutline: true,
|
|
description: true,
|
|
coverImageUrl: true,
|
|
organiserWebsite: true,
|
|
})
|
|
.extend({
|
|
startDate: z.date(),
|
|
endDate: z.date(),
|
|
clientName: z.string().nullable(),
|
|
})
|
|
|
|
export const GetEventsListingOutput = z.object({
|
|
events: z.array(Card),
|
|
})
|
|
|
|
export const getEventsListing = pikkuSessionlessFunc({
|
|
expose: true,
|
|
description: 'Public events listing — opted-in bookings only.',
|
|
input: GetEventsListingInput,
|
|
output: GetEventsListingOutput,
|
|
func: async ({ kysely }, { venueSlug, filter, search }) => {
|
|
const venue = await kysely
|
|
.selectFrom('venue')
|
|
.where('slug', '=', venueSlug)
|
|
.select('venueId')
|
|
.executeTakeFirstOrThrow()
|
|
|
|
const today = new Date().toISOString().slice(0, 10)
|
|
const year = Number(today.slice(0, 4))
|
|
|
|
let q = kysely
|
|
.selectFrom('booking')
|
|
.innerJoin('client', 'client.clientId', 'booking.clientId')
|
|
.where('booking.venueId', '=', venue.venueId)
|
|
.where('booking.onlineAd', '=', 1)
|
|
.where('booking.status', 'not in', ['cancelled', 'enquiry'])
|
|
.where('booking.endDate', '>=', today)
|
|
|
|
if (filter === 'this_year') {
|
|
q = q.where('booking.startDate', '<=', `${year}-12-31`)
|
|
} else if (filter === 'next_year') {
|
|
q = q.where('booking.startDate', '>=', `${year + 1}-01-01`)
|
|
.where('booking.startDate', '<=', `${year + 1}-12-31`)
|
|
}
|
|
if (search?.trim()) {
|
|
const term = `%${search.trim()}%`
|
|
q = q.where((eb) =>
|
|
eb.or([
|
|
eb('booking.eventName', 'like', term),
|
|
eb('client.name', 'like', term),
|
|
]),
|
|
)
|
|
}
|
|
|
|
const rows = await q
|
|
.orderBy('booking.startDate', 'asc')
|
|
.select([
|
|
'booking.bookingId',
|
|
'booking.eventName',
|
|
'booking.startDate',
|
|
'booking.endDate',
|
|
'booking.eventOutline',
|
|
'booking.description',
|
|
'booking.coverImageUrl',
|
|
'booking.organiserWebsite',
|
|
'client.name as clientName',
|
|
])
|
|
.execute()
|
|
|
|
const events = rows
|
|
.filter((r): r is typeof r & { startDate: string; endDate: string } =>
|
|
r.startDate != null && r.endDate != null,
|
|
)
|
|
.map((r) => ({
|
|
bookingId: r.bookingId,
|
|
eventName: r.eventName,
|
|
startDate: new Date(r.startDate),
|
|
endDate: new Date(r.endDate),
|
|
eventOutline: r.eventOutline,
|
|
description: r.description,
|
|
coverImageUrl: r.coverImageUrl,
|
|
organiserWebsite: r.organiserWebsite,
|
|
clientName: r.clientName,
|
|
}))
|
|
|
|
return { events }
|
|
},
|
|
})
|