Files
NextChair/src/features/booking/schemas.ts
T
Stefan Lazic d3bbad09c6 Fixes
Fixed an issue where media manager only shows files uploaded in specific sections.

Fixed an issue with icon picker names.

Removed jumbo rounding and a few other style tweaks.
2026-08-05 09:25:59 +01:00

108 lines
3.2 KiB
TypeScript

import { z } from "zod";
/**
* Input shapes for the booking Server Actions. Kept separate from the
* scheduling services' own TS types deliberately — these describe what
* crosses the client→server boundary as JSON (dates as ISO strings, no
* Date objects), the services describe the domain.
*/
export const getAvailableServicesSchema = z.object({
businessId: z.string(),
categoryId: z.string().optional(),
staffId: z.string().optional(),
});
/** Home's Services tab "Book" button — see preselectServiceAction. Only a service id ever crosses this boundary; price/duration/eligibility are always re-read from the database server-side, never trusted from the client. */
export const preselectServiceSchema = z.object({
serviceId: z.string().min(1),
});
export const getAvailableBarbersSchema = z.object({
businessId: z.string(),
serviceIds: z.array(z.string()).min(1),
});
export const getAvailableDatesSchema = z.object({
businessId: z.string(),
serviceIds: z.array(z.string()).min(1),
staffId: z.string().optional(),
fromDate: z.string(),
toDate: z.string(),
});
export const getAvailableTimeSlotsSchema = z.object({
businessId: z.string(),
serviceIds: z.array(z.string()).min(1),
staffId: z.string().optional(),
date: z.string(),
});
export const createBookingSchema = z.object({
businessId: z.string(),
customerId: z.string(),
serviceIds: z.array(z.string()).min(1),
staffId: z.string().optional(),
startAt: z.iso.datetime(),
notes: z.string().optional(),
});
export const rescheduleBookingSchema = z.object({
appointmentId: z.string(),
staffId: z.string().optional(),
startAt: z.iso.datetime(),
});
export const cancelBookingSchema = z.object({
appointmentId: z.string(),
cancelledByUserId: z.string().optional(),
reason: z.string().optional(),
});
export const updateBookingNotesSchema = z.object({
appointmentId: z.string(),
notes: z.string().max(2000),
});
// ── Customer booking-flow draft steps ────────────────────────────────────
export const saveServicesStepSchema = z.object({
businessId: z.string(),
serviceIds: z.array(z.string()).min(1, "Select at least one service"),
});
export const saveBarberTimeStepSchema = z.object({
businessId: z.string(),
staffId: z.string().optional(),
date: z.string(),
startAt: z.iso.datetime(),
});
export const saveDetailsStepSchema = z.object({
businessId: z.string(),
firstName: z.string().trim().min(1, "First name is required").optional(),
lastName: z.string().trim().min(1, "Last name is required").optional(),
email: z.email("Enter a valid email address").optional(),
phone: z.string().trim().min(1, "Phone number is required").optional(),
notes: z.string().max(2000).optional(),
policyAcknowledged: z.boolean(),
});
export const startRebookSchema = z.object({
appointmentId: z.string(),
guestToken: z.string().optional(),
});
export const customerCancelSchema = z.object({
appointmentId: z.string(),
reason: z.string().max(500).optional(),
guestToken: z.string().optional(),
});
export const customerRescheduleSchema = z.object({
appointmentId: z.string(),
staffId: z.string().optional(),
startAt: z.iso.datetime(),
guestToken: z.string().optional(),
});