Files
fete/specs/009-list-events/plan.md
nitrix e56998b17c
All checks were successful
CI / backend-test (push) Successful in 57s
CI / frontend-test (push) Successful in 22s
CI / frontend-e2e (push) Successful in 1m4s
CI / build-and-publish (push) Has been skipped
Add event list feature (009-list-events)
Enable users to see all their saved events on the home screen, sorted
by date with upcoming events first. Key capabilities:

- EventCard with title, relative time display, and organizer/attendee
  role badge
- Sortable EventList with past-event visual distinction (faded style)
- Empty state when no events are stored
- Swipe-to-delete gesture with confirmation dialog
- Floating action button for quick event creation
- Rename router param :token → :eventToken across all views
- useRelativeTime composable (Intl.RelativeTimeFormat)
- useEventStorage: add validation, removeEvent(), reactive versioning
- Full E2E and unit test coverage for all new components

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:53:55 +01:00

4.4 KiB

Implementation Plan: Event List on Home Page

Branch: 009-list-events | Date: 2026-03-08 | Spec: specs/009-list-events/spec.md Input: Feature specification from /specs/009-list-events/spec.md

Summary

Transform the home page from a static empty-state placeholder into a dynamic event list that shows all events stored in the browser's localStorage. Each event card displays title, relative time, and role indicator (organizer/attendee). Events are sorted chronologically (upcoming first), past events appear faded, and users can remove events via delete icon or swipe gesture. A FAB provides persistent access to event creation.

This is a frontend-only feature — no backend or API changes required. The existing useEventStorage composable already provides all necessary data access.

Technical Context

Language/Version: TypeScript 5.9, Vue 3.5 Primary Dependencies: Vue 3, Vue Router 5, Vite Storage: Browser localStorage via useEventStorage composable Testing: Vitest (unit), Playwright + MSW (E2E) Target Platform: Mobile-first PWA (centered 480px column on desktop) Project Type: Web application (frontend-only changes) Performance Goals: Event list renders within 1 second (SC-001) — trivial given localStorage read Constraints: No external dependencies, no tracking, WCAG AA, keyboard navigable Scale/Scope: Typically <50 events in localStorage; no pagination needed

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

Principle Status Notes
I. Privacy by Design PASS Purely client-side. No data leaves the browser. No analytics.
II. Test-Driven Methodology PASS Unit tests for composable, E2E for each user story. TDD enforced.
III. API-First Development N/A No API changes — this feature reads only from localStorage.
IV. Simplicity & Quality PASS Minimal approach: extend existing composable + new components. No over-engineering.
V. Dependency Discipline PASS No new dependencies. Swipe gesture implemented with native Touch API. Relative time via built-in Intl.RelativeTimeFormat.
VI. Accessibility PASS Semantic list markup, ARIA labels, keyboard navigation, WCAG AA contrast on faded past events.

Gate result: PASS — no violations.

Project Structure

Documentation (this feature)

specs/009-list-events/
├── plan.md              # This file
├── spec.md              # Feature specification
├── research.md          # Phase 0 output
├── data-model.md        # Phase 1 output
└── tasks.md             # Phase 2 output (/speckit.tasks command)

Source Code (repository root)

frontend/
├── src/
│   ├── composables/
│   │   ├── useEventStorage.ts       # MODIFY: add removeEvent()
│   │   ├── useRelativeTime.ts       # NEW: Intl.RelativeTimeFormat wrapper
│   │   └── __tests__/
│   │       ├── useEventStorage.spec.ts  # MODIFY: add removeEvent tests
│   │       └── useRelativeTime.spec.ts  # NEW: relative time formatting tests
│   ├── components/
│   │   ├── EventCard.vue            # NEW: individual event list item
│   │   ├── EventList.vue            # NEW: sorted event list container
│   │   ├── EmptyState.vue           # NEW: extracted empty state
│   │   ├── CreateEventFab.vue       # NEW: floating action button
│   │   ├── ConfirmDialog.vue        # NEW: reusable confirmation prompt
│   │   └── __tests__/
│   │       ├── EventCard.spec.ts    # NEW
│   │       ├── EventList.spec.ts    # NEW
│   │       ├── EmptyState.spec.ts   # NEW
│   │       └── ConfirmDialog.spec.ts # NEW
│   ├── views/
│   │   └── HomeView.vue             # MODIFY: compose list/empty/fab
│   └── assets/
│       └── main.css                 # MODIFY: add event card, faded, fab styles
└── e2e/
    └── home-events.spec.ts          # NEW: E2E tests for all user stories

Structure Decision: Frontend-only changes. New components in components/, composable extensions in composables/, styles in existing main.css. No backend changes.

Complexity Tracking

No constitution violations — this section is intentionally empty.