# Tasks: Event List on Home Page **Input**: Design documents from `/specs/009-list-events/` **Prerequisites**: plan.md, spec.md, research.md, data-model.md **Tests**: Unit tests (Vitest) and E2E tests (Playwright) are included per constitution (Principle II: Test-Driven Methodology). **Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story. ## Format: `[ID] [P?] [Story] Description` - **[P]**: Can run in parallel (different files, no dependencies) - **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3) - Include exact file paths in descriptions --- ## Phase 1: Setup (Shared Infrastructure) **Purpose**: Composable extensions and utility functions shared across all user stories - [x] T000 Rename router param `:token` to `:eventToken` in `frontend/src/router/index.ts` and update all references in `EventDetailView.vue`, `EventStubView.vue`, and their test files (consistency with `StoredEvent.eventToken` field name) - [x] T001 Add `isValidStoredEvent` type guard and validation filter to `frontend/src/composables/useEventStorage.ts` (FR-010) - [x] T002 Add `removeEvent(eventToken: string)` function to `frontend/src/composables/useEventStorage.ts` (needed by US3) - [x] T003 [P] Create `useRelativeTime` composable in `frontend/src/composables/useRelativeTime.ts` (Intl.RelativeTimeFormat wrapper, FR-002) - [x] T004 [P] Add unit tests for `isValidStoredEvent` and `removeEvent` in `frontend/src/composables/__tests__/useEventStorage.spec.ts` - [x] T005 [P] Create unit tests for `useRelativeTime` in `frontend/src/composables/__tests__/useRelativeTime.spec.ts` **Checkpoint**: Composable layer complete — all shared logic tested and available for components. --- ## Phase 2: User Story 1 — View My Events (Priority: P1) 🎯 MVP **Goal**: Home page shows all stored events in a sorted list with title and relative time. Tapping navigates to event detail. **Independent Test**: Simulate localStorage entries, visit home page, verify all events appear sorted with correct titles and relative times. Tap an event and verify navigation to `/events/:eventToken`. ### Unit Tests for User Story 1 - [x] T006 [P] [US1] Create unit tests for EventCard component in `frontend/src/components/__tests__/EventCard.spec.ts` — include test cases for `isPast` prop (faded styling) and role badge rendering (organizer vs. attendee) - [x] T007 [P] [US1] Create unit tests for EventList component in `frontend/src/components/__tests__/EventList.spec.ts` ### Implementation for User Story 1 - [x] T008 [P] [US1] Create `EventCard.vue` component in `frontend/src/components/EventCard.vue` — displays title, relative time, role badge; emits click for navigation - [x] T009 [US1] Create `EventList.vue` component in `frontend/src/components/EventList.vue` — reads events from composable, validates, sorts (upcoming asc, past desc), renders EventCard list - [x] T010 [US1] Refactor `HomeView.vue` in `frontend/src/views/HomeView.vue` — integrate EventList, conditionally show list when events exist - [x] T011 [US1] Add event card and list styles to `frontend/src/assets/main.css` ### E2E Tests for User Story 1 - [x] T012 [US1] Create E2E test file `frontend/e2e/home-events.spec.ts` — tests: events displayed with title and relative time, sorted correctly, click navigates to detail page **Checkpoint**: MVP complete — returning users see their events and can navigate to details. --- ## Phase 3: User Story 2 — Empty State (Priority: P2) **Goal**: New users with no stored events see an inviting empty state with a "Create Event" call-to-action. **Independent Test**: Clear localStorage, visit home page, verify empty state message and "Create Event" button are visible. ### Unit Tests for User Story 2 - [x] T013 [P] [US2] Create unit tests for EmptyState component in `frontend/src/components/__tests__/EmptyState.spec.ts` ### Implementation for User Story 2 - [x] T014 [US2] Create `EmptyState.vue` component in `frontend/src/components/EmptyState.vue` — shows message and "Create Event" RouterLink - [x] T015 [US2] Update `HomeView.vue` in `frontend/src/views/HomeView.vue` — show EmptyState when no valid events, show EventList otherwise - [x] T016 [US2] Add empty state styles to `frontend/src/assets/main.css` ### E2E Tests for User Story 2 - [x] T017 [US2] Add E2E tests to `frontend/e2e/home-events.spec.ts` — tests: empty state shown when no events, hidden when events exist **Checkpoint**: Home page handles both new and returning users. --- ## Phase 4: User Story 4 — Past Events Appear Faded (Priority: P2) **Goal**: Events whose date/time has passed appear with reduced visual prominence (muted colors, lower contrast) while remaining interactive. **Independent Test**: Have both future and past events in localStorage, verify past events display faded while remaining clickable. ### Implementation for User Story 4 - [x] T018 [US4] Add `.event-card--past` modifier class with `opacity: 0.6; filter: saturate(0.5)` to `frontend/src/components/EventCard.vue` or `frontend/src/assets/main.css` - [x] T019 [US4] Pass `isPast` computed property to EventCard in `EventList.vue` and apply modifier class in `frontend/src/components/EventCard.vue` ### E2E Tests for User Story 4 - [x] T020 [US4] Add E2E tests to `frontend/e2e/home-events.spec.ts` — tests: past events have faded class, upcoming events do not, past events remain clickable **Checkpoint**: Visual hierarchy distinguishes upcoming from past events. --- ## Phase 5: User Story 3 — Remove Event from List (Priority: P3) **Goal**: Users can remove events from their local list via delete icon (and later swipe) with confirmation. **Independent Test**: Have multiple events, remove one via delete icon, verify it disappears while others remain. ### Unit Tests for User Story 3 - [x] T021 [P] [US3] Create unit tests for ConfirmDialog component in `frontend/src/components/__tests__/ConfirmDialog.spec.ts` ### Implementation for User Story 3 - [x] T022 [US3] Create `ConfirmDialog.vue` component in `frontend/src/components/ConfirmDialog.vue` — teleport-to-body modal with confirm/cancel, focus trapping, Escape key - [x] T023 [US3] Add delete icon button to `EventCard.vue` in `frontend/src/components/EventCard.vue` — emits `delete` event with eventToken (FR-006a) - [x] T024 [US3] Wire delete flow in `EventList.vue` in `frontend/src/components/EventList.vue` — listen for delete event, show ConfirmDialog, call `removeEvent()` on confirm - [x] T025 [US3] Add delete icon and confirm dialog styles to `frontend/src/assets/main.css` ### E2E Tests for User Story 3 - [x] T026 [US3] Add E2E tests to `frontend/e2e/home-events.spec.ts` — tests: delete icon visible, confirmation dialog appears, confirm removes event, cancel keeps event **Checkpoint**: Users can manage their event list. --- ## Phase 6: User Story 5 — Visual Distinction for Event Roles (Priority: P3) **Goal**: Events show a badge indicating whether the user is the organizer or an attendee. **Independent Test**: Have events with organizerToken and rsvpToken in localStorage, verify different badges displayed. ### Implementation for User Story 5 - [x] T027 [US5] Add role badge (Organizer/Attendee) to `EventCard.vue` in `frontend/src/components/EventCard.vue` — derive from organizerToken/rsvpToken presence - [x] T028 [US5] Add role badge styles to `frontend/src/assets/main.css` ### E2E Tests for User Story 5 - [x] T029 [US5] Add E2E tests to `frontend/e2e/home-events.spec.ts` — tests: organizer badge shown for events with organizerToken, attendee badge for events with rsvpToken only **Checkpoint**: Role distinction visible at a glance. --- ## Phase 7: Polish & Cross-Cutting Concerns **Purpose**: FAB, swipe gesture, accessibility, and final polish - [x] T030 Create `CreateEventFab.vue` in `frontend/src/components/CreateEventFab.vue` — fixed FAB at bottom-right, navigates to `/create` (FR-011) - [x] T031 Add FAB to `HomeView.vue` in `frontend/src/views/HomeView.vue` — visible when events exist (empty state has its own CTA) - [x] T032 Add FAB styles to `frontend/src/assets/main.css` - [x] T033 Implement swipe-to-delete gesture on EventCard in `frontend/src/components/EventCard.vue` — native Touch API (FR-006b) - [x] T034 Accessibility review: verify ARIA labels, keyboard navigation (Tab/Enter/Escape), focus trapping in ConfirmDialog, WCAG AA contrast on faded cards - [x] T035 Add E2E tests for FAB to `frontend/e2e/home-events.spec.ts` — tests: FAB visible when events exist, navigates to create page --- ## Dependencies & Execution Order ### Phase Dependencies - **Phase 1 (Setup)**: No dependencies — start immediately - **Phase 2 (US1)**: Depends on T001, T003 (validation + relative time composable) - **Phase 3 (US2)**: Depends on T001 (validation); can run in parallel with US1 - **Phase 4 (US4)**: Depends on Phase 2 completion (EventCard must exist) - **Phase 5 (US3)**: Depends on Phase 2 completion (EventList must exist) + T002 (removeEvent) - **Phase 6 (US5)**: Depends on Phase 2 completion (EventCard must exist) - **Phase 7 (Polish)**: Depends on Phases 2–6 completion ### User Story Dependencies - **US1 (P1)**: Depends only on Phase 1 — no other story dependencies - **US2 (P2)**: Depends only on Phase 1 — independent of US1 but shares HomeView - **US4 (P2)**: Depends on US1 (extends EventCard with past styling) - **US3 (P3)**: Depends on US1 (extends EventList with delete flow) - **US5 (P3)**: Depends on US1 (extends EventCard with role badge) ### Parallel Opportunities - T003 + T004 + T005 can all run in parallel (different files) - T006 + T007 can run in parallel (different test files) - T008 can run in parallel with T006/T007 (component vs test files) - US4, US5 can start in parallel once US1 is done (both extend EventCard independently) --- ## Implementation Strategy ### MVP First (User Story 1 Only) 1. Complete Phase 1: Setup composables 2. Complete Phase 2: US1 — EventCard, EventList, HomeView refactor 3. **STOP and VALIDATE**: Test the event list end-to-end 4. Deploy/demo if ready ### Incremental Delivery 1. Phase 1 → Composable layer ready 2. Phase 2 (US1) → Event list works → MVP! 3. Phase 3 (US2) → Empty state for new users 4. Phase 4 (US4) → Past events faded 5. Phase 5 (US3) → Remove events from list 6. Phase 6 (US5) → Role badges 7. Phase 7 → FAB, swipe, accessibility polish --- ## Notes - [P] tasks = different files, no dependencies - [Story] label maps task to specific user story for traceability - This is a **frontend-only** feature — no backend changes needed - All data comes from existing `useEventStorage` composable (localStorage) - E2E tests consolidated in single file `home-events.spec.ts` with separate `describe` blocks per story