Add design artifacts for view event feature (007)
Spec, research, data model, API contract, implementation plan, and task breakdown for the public event detail page. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
89
specs/007-view-event/plan.md
Normal file
89
specs/007-view-event/plan.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Implementation Plan: View Event Landing Page
|
||||
|
||||
**Branch**: `007-view-event` | **Date**: 2026-03-06 | **Spec**: [spec.md](spec.md)
|
||||
**Input**: Feature specification from `/specs/007-view-event/spec.md`
|
||||
|
||||
## Summary
|
||||
|
||||
Add a public event detail page at `/events/:token` that displays event information (title, date/time with IANA timezone, description, location, attendee count) without requiring authentication. The page handles four states: loaded, expired ("event has ended"), not found (404), and server error (retry button). Loading uses skeleton-shimmer placeholders. Backend adds `GET /events/{token}` endpoint and a `timezone` field to the Event model (cross-cutting change to US-1).
|
||||
|
||||
## Technical Context
|
||||
|
||||
**Language/Version**: Java 25 (backend), TypeScript 5.9 (frontend)
|
||||
**Primary Dependencies**: Spring Boot 3.5.x, Vue 3, Vue Router 5, openapi-fetch, openapi-typescript
|
||||
**Storage**: PostgreSQL (JPA via Spring Data, Liquibase migrations)
|
||||
**Testing**: JUnit (backend), Vitest (frontend unit), Playwright + MSW (frontend E2E)
|
||||
**Target Platform**: Self-hosted web application (Docker)
|
||||
**Project Type**: Web service + SPA
|
||||
**Performance Goals**: N/A (single-user scale, self-hosted)
|
||||
**Constraints**: No external resources (CDNs, fonts, tracking), WCAG AA, privacy-first
|
||||
**Scale/Scope**: Single new view + one new API endpoint + one cross-cutting model change
|
||||
|
||||
## Constitution Check
|
||||
|
||||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||||
|
||||
| Principle | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| I. Privacy by Design | PASS | No PII exposed. Only attendee count shown (not names). No external resources. No tracking. |
|
||||
| II. Test-Driven Methodology | PASS | TDD enforced: backend unit tests, frontend unit tests, E2E tests per spec. |
|
||||
| III. API-First Development | PASS | OpenAPI spec updated first. Types generated. Response schemas include `example:` fields. |
|
||||
| IV. Simplicity & Quality | PASS | Minimal changes: one GET endpoint, one new view, one model field. `attendeeCount` returns 0 (no RSVP stub). Cancelled state deferred. |
|
||||
| V. Dependency Discipline | PASS | No new dependencies. Skeleton shimmer is CSS-only. |
|
||||
| VI. Accessibility | PASS | Semantic HTML, ARIA attributes, keyboard navigable, WCAG AA contrast via design system. |
|
||||
|
||||
**Post-Phase-1 re-check**: All gates still pass. The `timezone` field addition is a justified cross-cutting change documented in research.md R-1.
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```text
|
||||
specs/007-view-event/
|
||||
├── plan.md # This file
|
||||
├── spec.md # Feature specification
|
||||
├── research.md # Phase 0: research decisions
|
||||
├── data-model.md # Phase 1: entity definitions
|
||||
├── quickstart.md # Phase 1: implementation overview
|
||||
├── contracts/
|
||||
│ └── get-event.yaml # Phase 1: GET endpoint contract
|
||||
└── tasks.md # Phase 2: implementation tasks (via /speckit.tasks)
|
||||
```
|
||||
|
||||
### Source Code (repository root)
|
||||
|
||||
```text
|
||||
backend/
|
||||
├── src/main/java/de/fete/
|
||||
│ ├── domain/
|
||||
│ │ ├── model/Event.java # Add timezone field
|
||||
│ │ └── port/in/GetEventUseCase.java # NEW: inbound port
|
||||
│ ├── application/service/EventService.java # Implement GetEventUseCase
|
||||
│ ├── adapter/
|
||||
│ │ ├── in/web/EventController.java # Implement getEvent()
|
||||
│ │ └── out/persistence/
|
||||
│ │ ├── EventJpaEntity.java # Add timezone column
|
||||
│ │ └── EventPersistenceAdapter.java # Map timezone field
|
||||
│ └── config/
|
||||
├── src/main/resources/
|
||||
│ ├── openapi/api.yaml # Add GET endpoint + timezone
|
||||
│ └── db/changelog/ # Liquibase: add timezone column
|
||||
└── src/test/java/de/fete/ # Unit + integration tests
|
||||
|
||||
frontend/
|
||||
├── src/
|
||||
│ ├── api/schema.d.ts # Regenerated from OpenAPI
|
||||
│ ├── views/EventDetailView.vue # NEW: event detail page
|
||||
│ ├── views/EventCreateView.vue # Add timezone to create request
|
||||
│ ├── router/index.ts # Point /events/:token to EventDetailView
|
||||
│ └── assets/main.css # Skeleton shimmer styles
|
||||
├── e2e/
|
||||
│ └── event-view.spec.ts # NEW: E2E tests for view event
|
||||
└── src/__tests__/ # Unit tests for EventDetailView
|
||||
```
|
||||
|
||||
**Structure Decision**: Existing web application structure (backend + frontend). No new packages or modules — extends existing hexagonal architecture with one new inbound port and one new frontend view.
|
||||
|
||||
## Complexity Tracking
|
||||
|
||||
No constitution violations. No entries needed.
|
||||
Reference in New Issue
Block a user