Files
dezky/services/platform-api/src/scheduling/public/dto/public-dtos.ts
T

78 lines
1.7 KiB
TypeScript

import { IsEmail, IsISO8601, IsOptional, IsString, Matches, MaxLength } from 'class-validator'
// IANA timezone sanity check (Area/Location, optionally a third segment). Not a
// full tz-database membership test — Luxon rejects unknown zones downstream.
const TZ = /^[A-Za-z]+\/[A-Za-z0-9_+-]+(\/[A-Za-z0-9_+-]+)?$/
export class SlotsQueryDto {
@IsISO8601()
from!: string
@IsISO8601()
to!: string
@IsString()
@MaxLength(64)
@Matches(TZ, { message: 'timezone must be an IANA zone like Europe/Copenhagen' })
timezone!: string
}
export class CreateHoldDto {
@IsISO8601()
startUtc!: string
// Optional captcha token (e.g. Cloudflare Turnstile). Enforced server-side
// only when a captcha provider is configured; ignored otherwise.
@IsOptional()
@IsString()
@MaxLength(4096)
captchaToken?: string
}
export class CreateBookingDto {
@IsISO8601()
startUtc!: string
@IsString()
@MaxLength(120)
attendeeName!: string
@IsEmail()
@MaxLength(254)
attendeeEmail!: string
@IsString()
@MaxLength(64)
@Matches(TZ, { message: 'attendeeTimezone must be an IANA zone like Europe/Copenhagen' })
attendeeTimezone!: string
@IsOptional()
@IsString()
@MaxLength(2000)
attendeeNotes?: string
@IsOptional()
@IsString()
@MaxLength(64)
holdId?: string
// Optional captcha token (e.g. Cloudflare Turnstile). Enforced server-side
// only when a captcha provider is configured; ignored otherwise.
@IsOptional()
@IsString()
@MaxLength(4096)
captchaToken?: string
}
export class CancelBookingDto {
@IsOptional()
@IsString()
@MaxLength(500)
reason?: string
}
export class RescheduleBookingDto {
@IsISO8601()
startUtc!: string
}