// Request validation schemas, shared so the web app can validate forms with the same rules as the API. import { z } from 'zod' import { areaKinds, incidentStatuses, incidentTypes, roles, severities } from './enums.ts' const email = z.string().trim().toLowerCase().max(254).pipe(z.email()) const password = z.string().min(10, 'Use at least 10 characters').max(256) const name = z.string().trim().min(1).max(200) const optionalText = (max: number) => z.string().trim().max(max).nullish() const isoDateTime = z.iso.datetime({ offset: true }) export const setupSchema = z.object({ organizationName: name, name, email, password }) export const loginSchema = z.object({ email, password: z.string().min(1).max(256) }) export const changePasswordSchema = z.object({ currentPassword: z.string().min(1).max(256), newPassword: password }) export const createUserSchema = z.object({ name, email, role: z.enum(roles), password }) export const updateUserSchema = z.object({ name: name.optional(), role: z.enum(roles).optional(), active: z.boolean().optional() }) export const createSiteSchema = z.object({ name, address: optionalText(500), timezone: z.string().trim().max(64).optional() }) export const updateSiteSchema = createSiteSchema.partial().extend({ archived: z.boolean().optional() }) export const createAreaSchema = z.object({ name, kind: z.enum(areaKinds).default('area'), parentId: z.uuid().nullish() }) export const updateAreaSchema = z.object({ name: name.optional(), kind: z.enum(areaKinds).optional(), archived: z.boolean().optional() }) export const createIncidentSchema = z.object({ title: name, type: z.enum(incidentTypes), severity: z.enum(severities), occurredAt: isoDateTime, siteId: z.uuid(), areaId: z.uuid().nullish(), locationDetail: optionalText(500), description: optionalText(10_000), immediateAction: optionalText(10_000), anonymous: z.boolean().default(false), }) export const updateIncidentSchema = createIncidentSchema .omit({ anonymous: true }) .partial() .extend({ status: z.enum(incidentStatuses).optional() }) export const incidentListQuery = z.object({ page: z.coerce.number().int().min(1).default(1), pageSize: z.coerce.number().int().min(1).max(100).default(25), q: z.string().trim().max(200).optional(), type: z.enum(incidentTypes).optional(), severity: z.enum(severities).optional(), status: z.enum(incidentStatuses).optional(), siteId: z.uuid().optional(), }) export type SetupInput = z.infer export type CreateIncidentInput = z.input export type UpdateIncidentInput = z.infer export type IncidentListQuery = z.infer