feat(portal): multi-step volunteer registration form with public event endpoint

- Add GET /api/v1/public/events/{slug}/registration-data endpoint for fetching
  event sections and time slots without auth
- Create 5-step registration form: personal info, details, motivation, section
  preferences, availability
- VeeValidate + Zod validation per step with Dutch error messages
- Auth-aware: pre-fills name/email for authenticated users
- Mobile responsive with custom chip-based step indicator
- Success page with contextual actions (dashboard vs login)
- Types, composable (TanStack Query), and Zod schemas

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-10 18:41:20 +02:00
parent 60ea1f0b40
commit 3400e4cc7e
12 changed files with 1077 additions and 8 deletions

View File

@@ -389,4 +389,33 @@ Response: `{ "confirmed": 2, "errors": [{ "match_id": "ulid3", "error": "User al
- `GET /events/{event}/persons?tag={person_tag_id}` — filter persons by single tag
- `GET /events/{event}/persons?tags=ulid1,ulid2` — filter persons by multiple tags (AND logic: must have all)
## Public Registration Data
- `GET /public/events/{slug}/registration-data` — public, no auth. Returns event info, available sections, and volunteer time slots for the registration form. Only returns events with status `registration_open`. Excludes `cross_event` sections. Only includes time slots with `person_type = VOLUNTEER`. Resolves sub-events to parent festival.
### Response
```json
{
"data": {
"event": { "id": "01JXYZ...", "name": "Echt Feesten 2026", "start_date": "2026-07-10", "end_date": "2026-07-12", "organisation_id": "01JXYZ..." },
"sections": [{ "id": "01JXYZ...", "name": "Hoofdpodium Bar", "category": "Bar", "icon": "tabler-glass" }],
"time_slots": [{ "id": "01JXYZ...", "name": "Vrijdag Avond", "date": "2026-07-10", "start_time": "18:00:00", "end_time": "02:00:00", "duration_hours": 8 }]
}
}
```
### Error Responses
- `404` — Event not found or not accepting registrations
## Volunteer Registration
- `POST /events/{event}/volunteer-register` — public, auth-aware (optional Sanctum). Registers a volunteer for an event. Resolves sub-events to the parent festival. Accepts name, email, phone, tshirt_size, motivation, section_preferences, availabilities. Authenticated users have their name/email taken from the auth token. Returns `PersonResource` (201 on new, 200 on re-registration of rejected person).
## Portal
- `POST /portal/token-auth` — public. Validates a portal token against artists/production_requests tables. Returns `{ context, data, event }` on success. Returns 501 if token tables don't exist yet, 401 if token is invalid.
- `GET /portal/me` — auth:sanctum. Returns the authenticated user's person record for a given event. Query param: `event_id` (required, ULID). Resolves sub-events to parent festival. Returns `PersonResource` with crowdType, shiftAssignments, and volunteerAvailabilities eager-loaded. Returns 404 if no registration found.
_(Extend this contract per module as endpoints are implemented.)_