Files
fete/specs/012-local-event-overview/spec.md
nitrix 6aeb4b8bca Migrate project artifacts to spec-kit format
- Move cross-cutting docs (personas, design system, implementation phases,
  Ideen.md) to .specify/memory/
- Move cross-cutting research and plans to .specify/memory/research/ and
  .specify/memory/plans/
- Extract 5 setup tasks from spec/setup-tasks.md into individual
  specs/001-005/spec.md files with spec-kit template format
- Extract 20 user stories from spec/userstories.md into individual
  specs/006-026/spec.md files with spec-kit template format
- Relocate feature-specific research and plan docs into specs/[feature]/
- Add spec-kit constitution, templates, scripts, and slash commands
- Slim down CLAUDE.md to Claude-Code-specific config, delegate principles
  to .specify/memory/constitution.md
- Update ralph.sh with stream-json output and per-iteration logging
- Delete old spec/ and docs/agents/ directories
- Gitignore Ralph iteration JSONL logs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 20:19:41 +01:00

112 lines
8.9 KiB
Markdown

# Feature Specification: Local Event Overview List
**Feature**: `012-local-event-overview`
**Created**: 2026-03-06
**Status**: Draft
**Source**: Migrated from spec/userstories.md
## User Scenarios & Testing
### User Story 1 - View tracked events on the root page (Priority: P1)
A user who has created, bookmarked, or RSVPed to events on this device opens the root page (`/`) and sees a list of all those events, each with the event title, date, and their relationship to the event (organizer / attending / not attending / bookmarked only). Each entry is a link to the event page. The list is rendered entirely from localStorage — no server request is required. If no events are tracked locally, an empty state is shown.
**Why this priority**: This is the core feature — the reason the overview exists. Without this story, no other scenario is meaningful.
**Independent Test**: Can be fully tested by seeding localStorage with event entries (simulating US-1/US-3/US-6 data) and loading the root page. Delivers value by allowing users to navigate back to any tracked event without the original link.
**Acceptance Scenarios**:
1. **Given** the user has created an event from this device (organizer token in localStorage), **When** they navigate to `/`, **Then** the event appears in the list with title, date, and relationship "organizer"
2. **Given** the user has RSVPed "attending" to an event from this device, **When** they navigate to `/`, **Then** the event appears in the list with title, date, and relationship "attending"
3. **Given** the user has RSVPed "not attending" to an event from this device, **When** they navigate to `/`, **Then** the event appears in the list with title, date, and relationship "not attending"
4. **Given** the user has bookmarked an event from this device (US-6), **When** they navigate to `/`, **Then** the event appears in the list with title, date, and relationship "bookmarked only"
5. **Given** no events are tracked in localStorage, **When** the user navigates to `/`, **Then** an empty state message is shown — not an error
6. **Given** the list is rendered, **When** the user clicks an entry, **Then** they are navigated directly to the event page for that entry
---
### User Story 2 - Visually distinguish past events (Priority: P2)
Events whose date has passed are still shown in the list but rendered with a visual distinction (e.g. marked as "ended"), so the user can differentiate between upcoming and past events at a glance.
**Why this priority**: Useful for UX clarity but the overview is still functional without this distinction. Past events in the list are still navigable.
**Independent Test**: Can be tested by placing a past-dated event entry in localStorage and loading the root page. The entry should appear visually distinct from current events.
**Acceptance Scenarios**:
1. **Given** an event in localStorage has a date in the past, **When** the user views the overview, **Then** the entry is visually distinguished (e.g. marked "ended") compared to upcoming events
2. **Given** an event in localStorage has a date in the future, **When** the user views the overview, **Then** the entry is rendered without any "ended" indicator
---
### User Story 3 - Remove an entry from the local list (Priority: P2)
The user can remove individual entries from the local overview. The behavior depends on the entry type: for bookmarked-only events the bookmark is removed; for RSVPed events the local record is removed (server-side RSVP unaffected); for organizer-created events the organizer token and event data are removed from localStorage, with a confirmation warning that organizer access on this device will be lost.
**Why this priority**: Important for list hygiene but not required for the core navigation use case.
**Independent Test**: Can be tested by placing entries of each type in localStorage and verifying removal behavior from the overview UI.
**Acceptance Scenarios**:
1. **Given** a bookmarked-only event is in the local list, **When** the user removes that entry, **Then** the bookmark is removed from localStorage and the entry disappears from the list
2. **Given** an RSVPed event is in the local list, **When** the user removes that entry, **Then** the local RSVP record is removed from localStorage; the server-side RSVP is unaffected
3. **Given** an organizer-created event is in the local list, **When** the user initiates removal, **Then** a confirmation warning is shown explaining that organizer access on this device will be revoked
4. **Given** the organizer confirms removal, **Then** the organizer token and event metadata are removed from localStorage and the entry disappears from the list
---
### User Story 4 - Handle a deleted event when navigating from the overview (Priority: P2)
If the user clicks an entry in the local overview and the server responds that the event no longer exists (deleted per US-12 automatic cleanup or US-19 organizer deletion), the app displays an "event no longer exists" message and offers to remove the entry from the local list.
**Why this priority**: Edge case that improves consistency and prevents stale entries from accumulating, but not core to the overview's primary purpose.
**Independent Test**: Can be tested by navigating to an event whose token does not exist on the server. The app should display a "no longer exists" message and offer removal.
**Acceptance Scenarios**:
1. **Given** an entry exists in the local overview, **When** the user navigates to that event and the server returns "event not found", **Then** the app displays an "event no longer exists" message and offers to remove the entry from the local list
2. **Given** the user confirms removal of the stale entry, **Then** the entry is removed from localStorage and the user is returned to the overview
---
### Edge Cases
- What happens if localStorage is unavailable or disabled in the browser? The overview cannot render — [NEEDS EXPANSION: define fallback message or behavior]
- What happens if the same event appears under multiple localStorage keys (e.g. both RSVPed and organizer)? [NEEDS EXPANSION: define de-duplication or priority rule for relationship label]
- What happens if an event's locally cached title or date is stale (organizer edited via US-5)? Stale values are displayed until the user next visits the event page — this is an accepted trade-off per the story notes.
- What happens when the user has a very large number of tracked events? [NEEDS EXPANSION: pagination or truncation strategy]
## Requirements
### Functional Requirements
- **FR-001**: The root page (`/`) MUST display the local event overview list below a project header/branding section
- **FR-002**: The list MUST include any event for which an organizer token, RSVP record, or bookmark exists in localStorage for this device
- **FR-003**: Each list entry MUST show at minimum: event title, event date, and the user's relationship to the event (organizer / attending / not attending / bookmarked only)
- **FR-004**: Each list entry MUST be a link that navigates directly to the corresponding event page
- **FR-005**: The list MUST be populated entirely from localStorage — no server request is made to render the overview
- **FR-006**: Events whose date has passed MUST be visually distinguished (e.g. marked "ended") from upcoming events
- **FR-007**: An individual entry MUST be removable from the list; removal behavior depends on entry type (bookmark removal, local RSVP record removal, or organizer token removal)
- **FR-008**: Removing an organizer-created event entry MUST require a confirmation warning explaining that organizer access on this device will be revoked
- **FR-009**: No personal data or event data MUST be transmitted to the server when viewing or interacting with the overview
- **FR-010**: If no events are tracked locally, an empty state MUST be shown — not an error or blank screen
- **FR-011**: When navigating from the overview to an event that the server reports as deleted, the app MUST display an "event no longer exists" message and offer to remove the stale entry from the local list
### Key Entities
- **LocalEventEntry**: A localStorage-stored record representing one tracked event. Contains at minimum: event token, event title, event date, and relationship type (organizer / attending / not attending / bookmarked). May also contain: organizer token (for organizer entries), RSVP choice and name (for RSVP entries).
## Success Criteria
### Measurable Outcomes
- **SC-001**: A user with events tracked in localStorage can navigate to `/` and see all tracked events without any server request being made
- **SC-002**: Each event entry links correctly to its event page
- **SC-003**: Past events are visually distinguishable from upcoming events in the list
- **SC-004**: An entry can be removed from the list, and the corresponding localStorage key is cleaned up correctly for each entry type
- **SC-005**: The empty state is shown when no events are tracked in localStorage — no blank page or error state