import { z } from 'zod' import { ausUhrzeit } from '@/lib/zeit' /** * Regeln fuer Bereiche. Reine Logik, damit Formular und Server Action * dieselbe Antwort geben. */ export const WOCHENTAGE = [ 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag', ] as const export const KAPAZITAET_FELDER = [ 'kapazitaetMo', 'kapazitaetDi', 'kapazitaetMi', 'kapazitaetDo', 'kapazitaetFr', 'kapazitaetSa', 'kapazitaetSo', ] as const export type KapazitaetFeld = (typeof KAPAZITAET_FELDER)[number] /** Hex-Farbe mit Raute, drei- oder sechsstellig. */ export const farbeSchema = z .string() .trim() .regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, 'Bitte eine Farbe wie #2563eb angeben.') .transform((f) => f.toLowerCase()) const uhrzeitSchema = z .string() .trim() .refine((w) => ausUhrzeit(w) !== null, 'Bitte eine Uhrzeit wie 08:00 angeben.') .transform((w) => ausUhrzeit(w) as number) /** Eine Tageskapazitaet: 0 bis 24 Stunden, in Minuten. */ const kapazitaetSchema = z.coerce .number() .int('Bitte ganze Minuten angeben.') .min(0, 'Nicht weniger als 0 Minuten.') .max(1440, 'Nicht mehr als 1440 Minuten, also 24 Stunden.') export const bereichSchema = z .object({ name: z .string() .trim() .min(2, 'Mindestens zwei Zeichen.') .max(40, 'Höchstens 40 Zeichen.'), farbe: farbeSchema, reihenfolge: z.coerce.number().int().min(0).max(999).default(0), aktiv: z.coerce.boolean().default(true), arbeitsfensterVon: uhrzeitSchema, arbeitsfensterBis: uhrzeitSchema, kapazitaetMo: kapazitaetSchema, kapazitaetDi: kapazitaetSchema, kapazitaetMi: kapazitaetSchema, kapazitaetDo: kapazitaetSchema, kapazitaetFr: kapazitaetSchema, kapazitaetSa: kapazitaetSchema, kapazitaetSo: kapazitaetSchema, }) .refine((b) => b.arbeitsfensterVon < b.arbeitsfensterBis, { path: ['arbeitsfensterBis'], message: 'Das Arbeitsfenster muss nach seinem Beginn enden.', }) .refine( (b) => KAPAZITAET_FELDER.every( (feld) => b[feld] <= b.arbeitsfensterBis - b.arbeitsfensterVon, ), { path: ['kapazitaetMo'], message: 'Keine Tageskapazität darf länger sein als das Arbeitsfenster.', }, ) export type BereichEingabe = z.infer /** Summe der Wochenkapazitaet in Minuten. */ export function wochenKapazitaet(bereich: Record): number { return KAPAZITAET_FELDER.reduce((summe, feld) => summe + bereich[feld], 0) } /** Kapazitaet des Wochentags, 0 = Montag. */ export function kapazitaetAmTag( bereich: Record, wochentagIndex: number, ): number { const feld = KAPAZITAET_FELDER[wochentagIndex] return feld ? bereich[feld] : 0 }