import { z } from "zod"; export const ExecutiveMeetingsReorderBody = z.object({ meetingDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/), orderedIds: z.array(z.number().int().positive()).min(1).max(1000), }); export type ExecutiveMeetingsReorderBodyT = z.infer< typeof ExecutiveMeetingsReorderBody >; // #486: Body for POST /executive-meetings/swap-times. Used by the // schedule row quick-actions popover (Move up / Move down) to swap // just the (startTime, endTime) tuple between two meetings on the // same date without changing daily numbering, so the time column // stays visually anchored. export const ExecutiveMeetingsSwapTimesBody = z.object({ aId: z.number().int().positive(), bId: z.number().int().positive(), // Must be ISO-8601 datetime strings — the route passes them straight // to `new Date(...).toISOString()` and any malformed input would // bubble up as an uncontrolled 500. z.string().datetime() rejects // garbage at the validation boundary so the client gets a 400. expectedUpdatedAtA: z.string().datetime(), expectedUpdatedAtB: z.string().datetime(), }); export type ExecutiveMeetingsSwapTimesBodyT = z.infer< typeof ExecutiveMeetingsSwapTimesBody >; // #489: Body for POST /executive-meetings/rotate-content. Used when the // user drags a meeting from anywhere on its row to a new position. The // server keeps each meeting's slot (startTime, endTime, dailyNumber) // anchored to its physical row in chronological order and rotates the // meeting CONTENT (title, attendees, notes, color, status, merge) so // that visible position i ends up holding the i-th tuple from the // original chronological order. // // `orderedIds` is the new visible content order (same set as the day's // non-cancelled meetings — every visible row must appear exactly once). // `expectedUpdatedAt` carries each visible meeting's last-known // `updatedAt` ISO string so the server can detect concurrent edits and // return 409 `stale_meeting` like the other optimistic-locked routes. export const ExecutiveMeetingsRotateContentBody = z.object({ meetingDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/), orderedIds: z.array(z.number().int().positive()).min(2).max(1000), expectedUpdatedAt: z.record(z.string().regex(/^\d+$/), z.string().datetime()), }); export type ExecutiveMeetingsRotateContentBodyT = z.infer< typeof ExecutiveMeetingsRotateContentBody >;