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:
58
specs/008-rsvp/quickstart.md
Normal file
58
specs/008-rsvp/quickstart.md
Normal 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
|
||||
Reference in New Issue
Block a user