Files
Epicnabbo-Catalogus-Updated…/src/lib/validators/event.ts
T
2026-07-13 21:57:41 +02:00

75 lines
2.7 KiB
TypeScript

import { z } from "zod";
/** Convert empty strings to undefined so optional/nullable fields pass validation */
const emptyToUndefined = (v: unknown) => (v === "" ? undefined : v);
export const eventTypeSchema = z.object({
name: z.string().min(1, "Name is required").max(100),
slug: z
.string()
.min(1)
.max(100)
.regex(/^[a-z0-9-]+$/, "Slug must be lowercase with hyphens"),
description: z.string().max(500).optional().default(""),
color: z.string().max(20).optional().default("#3b82f6"),
icon: z.string().max(50).optional().default("calendar"),
isActive: z.coerce.number().int().min(0).max(1).default(1),
minRank: z.coerce.number().int().min(0).max(7).default(0),
});
export const createEventSchema = z.object({
title: z.string().min(1, "Title is required").max(255),
description: z.string().min(1, "Description is required"),
typeId: z.coerce.number().int().positive(),
roomId: z.preprocess(
emptyToUndefined,
z.coerce.number().int().positive().nullable().optional(),
),
startsAt: z.coerce.date(),
endsAt: z.preprocess(emptyToUndefined, z.coerce.date().nullable().optional()),
maxPlayers: z.preprocess(
emptyToUndefined,
z.coerce.number().int().positive().nullable().optional(),
),
isRecurring: z.coerce.number().int().min(0).max(1).default(0),
recurrenceRule: z.preprocess(
emptyToUndefined,
z.string().max(255).nullable().optional(),
),
status: z
.enum(["draft", "published", "cancelled", "completed"])
.default("draft"),
image: z.preprocess(
emptyToUndefined,
z.string().max(500).nullable().optional(),
),
});
export const updateEventSchema = createEventSchema.partial();
export const eventPrizeSchema = z.object({
eventId: z.coerce.number().int().positive(),
position: z.coerce.number().int().positive().default(1),
prizeType: z
.enum(["badge", "credits", "pixels", "points", "item"])
.default("badge"),
badgeCode: z.string().max(50).nullable().optional(),
credits: z.coerce.number().int().min(0).default(0),
pixels: z.coerce.number().int().min(0).default(0),
points: z.coerce.number().int().min(0).default(0),
itemId: z.coerce.number().int().positive().nullable().optional(),
description: z.string().max(255).optional().default(""),
});
export const eventWinnerSchema = z.object({
eventId: z.coerce.number().int().positive(),
userId: z.coerce.number().int().positive(),
position: z.coerce.number().int().positive().default(1),
});
export type EventTypeInput = z.infer<typeof eventTypeSchema>;
export type CreateEventInput = z.infer<typeof createEventSchema>;
export type UpdateEventInput = z.infer<typeof updateEventSchema>;
export type EventPrizeInput = z.infer<typeof eventPrizeSchema>;
export type EventWinnerInput = z.infer<typeof eventWinnerSchema>;