Add 008-rsvp feature spec and design artifacts

Spec, research decisions, implementation plan, data model,
API contract, and task breakdown for the RSVP feature.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 11:48:00 +01:00
parent 9a78ebd9b0
commit 4828d06aba
8 changed files with 731 additions and 35 deletions

View File

@@ -0,0 +1,58 @@
# Quickstart: RSVP to an Event (008)
## What this feature adds
1. **Backend**: New `POST /api/events/{eventToken}/rsvps` endpoint that accepts an RSVP (guest name) and returns an `rsvpToken`. Populates the existing `attendeeCount` field in `GET /events/{token}` with real data.
2. **Frontend**: Bottom sheet RSVP form on the event detail page. Sticky bottom bar with CTA (or status after RSVP). localStorage persistence of RSVP data.
## Implementation order
1. **Token value objects** — Create `EventToken`, `OrganizerToken`, `RsvpToken` records. Refactor `Event` domain model and all layers (service, controller, repository, persistence adapter, tests) to use typed tokens instead of raw UUID.
2. **OpenAPI spec** — Add `CreateRsvpRequest`, `CreateRsvpResponse`, and the `POST /events/{eventToken}/rsvps` endpoint.
3. **Liquibase migration** — Create `rsvps` table (003-create-rsvps-table.xml).
4. **Domain model**`Rsvp` entity using `RsvpToken`.
5. **Ports**`CreateRsvpUseCase` (in), `RsvpRepository` (out).
6. **Persistence adapter**`RsvpJpaEntity`, `RsvpJpaRepository`, `RsvpPersistenceAdapter`.
7. **Service**`RsvpService` implementing `CreateRsvpUseCase`.
8. **Controller** — Add `createRsvp()` to `EventController`.
9. **Attendee count** — Wire `RsvpRepository.countByEventId()` into the GET event flow.
10. **Frontend composable** — Extend `useEventStorage` with `rsvpToken`/`rsvpName`.
11. **Frontend UI** — Bottom sheet component, sticky bar, RSVP form.
12. **E2E tests** — RSVP submission, expired event guard, localStorage verification.
## Key files to touch
### Backend (new)
- `domain/model/EventToken.java`
- `domain/model/OrganizerToken.java`
- `domain/model/Rsvp.java`
- `domain/model/RsvpToken.java`
- `domain/port/in/CreateRsvpUseCase.java`
- `domain/port/out/RsvpRepository.java`
- `application/service/RsvpService.java`
- `adapter/out/persistence/RsvpJpaEntity.java`
- `adapter/out/persistence/RsvpJpaRepository.java`
- `adapter/out/persistence/RsvpPersistenceAdapter.java`
- `db/changelog/003-create-rsvps-table.xml`
### Backend (modified)
- `domain/model/Event.java` — UUID → EventToken/OrganizerToken
- `application/service/EventService.java` — use typed tokens
- `adapter/in/web/EventController.java` — typed tokens + wire attendee count + createRsvp()
- `adapter/in/web/GlobalExceptionHandler.java` — handle `EventExpiredException` (409)
- `adapter/out/persistence/EventPersistenceAdapter.java` — map typed tokens
- `domain/port/out/EventRepository.java` — typed token in signature
- `openapi/api.yaml` — new endpoint + schemas
- `db/changelog/db.changelog-master.xml` — include new migration
- All existing tests — update to use typed tokens
### Frontend (new)
- `src/components/BottomSheet.vue` — reusable bottom sheet
- `src/components/RsvpBar.vue` — sticky bottom bar (CTA or status)
- `e2e/event-rsvp.spec.ts` — E2E tests
### Frontend (modified)
- `src/views/EventDetailView.vue` — integrate RSVP bar + bottom sheet
- `src/composables/useEventStorage.ts` — add rsvpToken/rsvpName fields
- `src/api/schema.d.ts` — regenerated from OpenAPI