Validation layer using Zod + React Hook Form for an event booking system
src/app/
├── schemas/
│ └── bookingSchema.js
└── components/
├── BookingForm/
│ └── BookingForm.jsx
└── ErrorMessage/
├── ErrorMessage.jsx
└── ErrorMessage.module.css
| Field | Type | Required | Rule |
|---|---|---|---|
| Booker Name | string |
✅ | Min 2 characters |
| Booker Email | string |
❌ | Valid email format |
| Event Name | string |
✅ | Min 2 characters |
| Event Date | Date |
✅ | Must be a future date |
| Number of Guests | number |
✅ | Integer · min 1 · max 10 |
| Time Slot | string |
✅ | Must match slots from /api/time-slots |
| Event Link | string |
✅ | Valid URL format |
Zod schema located in schemas/bookingSchema.js. Accepts available time slots as a dynamic array to validate the selected option against the backend response.
React Hook Form component. Fetches time slots from /api/time-slots, registers all fields, and resolves against bookingSchema via @hookform/resolvers/zod. On successful submit shows alert("Booking successful!").
Accepts a message prop. Renders a <p> only when a message is present. Styled via ErrorMessage.module.css.
<ErrorMessage message={errors.bookerName?.message} />Validation trigger
Validation runs on the form submitted. Individual field errors are displayed inline below each input via the ErrorMessage component.
Time slots - dynamic enum
Available time slots are fetched from the backend and passed into the schema at runtime, so the z.enum() check always reflects the actual server state.
Email is optional
All fields are required except bookerEmail, which may be omitted. When provided, it must still pass email format validation.