167 lines
4.5 KiB
TypeScript
167 lines
4.5 KiB
TypeScript
import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
|
|
import zod from 'zod/v4';
|
|
import {
|
|
existingUserIdServerSchema,
|
|
PublicUserSchema,
|
|
} from '../user/validation';
|
|
import { ParticipantSchema } from './[eventID]/participant/validation';
|
|
|
|
extendZodWithOpenApi(zod);
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Event ID Validation
|
|
//
|
|
// ----------------------------------------
|
|
export const eventIdSchema = zod.string().min(1, 'Event ID is required');
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Event Title Validation
|
|
//
|
|
// ----------------------------------------
|
|
export const eventTitleSchema = zod
|
|
.string()
|
|
.min(1, 'Title is required')
|
|
.max(100, 'Title must be at most 100 characters long');
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Event Description Validation
|
|
//
|
|
// ----------------------------------------
|
|
export const eventDescriptionSchema = zod
|
|
.string()
|
|
.max(500, 'Description must be at most 500 characters long');
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Event start time Validation
|
|
//
|
|
// ----------------------------------------
|
|
export const eventStartTimeSchema = zod.iso
|
|
.datetime()
|
|
.or(zod.date().transform((date) => date.toISOString()))
|
|
.refine((date) => !isNaN(new Date(date).getTime()), {
|
|
message: 'Invalid start time',
|
|
});
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Event end time Validation
|
|
//
|
|
// ----------------------------------------
|
|
export const eventEndTimeSchema = zod.iso.datetime().or(
|
|
zod
|
|
.date()
|
|
.transform((date) => date.toISOString())
|
|
.refine((date) => !isNaN(new Date(date).getTime()), {
|
|
message: 'Invalid end time',
|
|
}),
|
|
);
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Event Location Validation
|
|
//
|
|
// ----------------------------------------
|
|
export const eventLocationSchema = zod
|
|
.string()
|
|
.max(200, 'Location must be at most 200 characters long');
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Event Participants Validation
|
|
//
|
|
// ----------------------------------------
|
|
export const eventParticipantsSchema = zod.array(existingUserIdServerSchema);
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Event Status Validation
|
|
//
|
|
// ----------------------------------------
|
|
export const eventStatusSchema = zod.enum([
|
|
'TENTATIVE',
|
|
'CONFIRMED',
|
|
'CANCELLED',
|
|
]);
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Create Event Schema
|
|
//
|
|
// ----------------------------------------
|
|
export const createEventSchema = zod
|
|
.object({
|
|
title: eventTitleSchema,
|
|
description: eventDescriptionSchema.optional(),
|
|
start_time: eventStartTimeSchema,
|
|
end_time: eventEndTimeSchema,
|
|
location: eventLocationSchema.optional().default(''),
|
|
participants: eventParticipantsSchema.optional(),
|
|
status: eventStatusSchema.optional().default('TENTATIVE'),
|
|
})
|
|
.refine((data) => new Date(data.start_time) < new Date(data.end_time), {
|
|
message: 'Start time must be before end time',
|
|
});
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Update Event Schema
|
|
//
|
|
// ----------------------------------------
|
|
export const updateEventSchema = zod
|
|
.object({
|
|
title: eventTitleSchema.optional(),
|
|
description: eventDescriptionSchema.optional(),
|
|
start_time: eventStartTimeSchema.optional(),
|
|
end_time: eventEndTimeSchema.optional(),
|
|
location: eventLocationSchema.optional().default(''),
|
|
participants: eventParticipantsSchema.optional(),
|
|
status: eventStatusSchema.optional(),
|
|
})
|
|
.refine(
|
|
(data) => {
|
|
if (data.start_time && data.end_time) {
|
|
return new Date(data.start_time) < new Date(data.end_time);
|
|
}
|
|
return true;
|
|
},
|
|
{
|
|
message: 'Start time must be before end time',
|
|
},
|
|
);
|
|
|
|
// ----------------------------------------
|
|
//
|
|
// Event Schema Validation (for API responses)
|
|
//
|
|
// ----------------------------------------
|
|
export const EventSchema = zod
|
|
.object({
|
|
id: eventIdSchema,
|
|
title: eventTitleSchema,
|
|
description: eventDescriptionSchema.nullish(),
|
|
start_time: eventStartTimeSchema,
|
|
end_time: eventEndTimeSchema,
|
|
location: eventLocationSchema.nullish(),
|
|
status: eventStatusSchema,
|
|
created_at: zod.date(),
|
|
updated_at: zod.date(),
|
|
organizer: PublicUserSchema,
|
|
participants: zod.array(ParticipantSchema).nullish(),
|
|
})
|
|
.openapi('Event', {
|
|
description: 'Event information including all fields',
|
|
});
|
|
|
|
export const EventResponseSchema = zod.object({
|
|
success: zod.boolean(),
|
|
event: EventSchema,
|
|
});
|
|
|
|
export const EventsResponseSchema = zod.object({
|
|
success: zod.boolean(),
|
|
events: zod.array(EventSchema),
|
|
});
|