# Tasks: Watch Event
**Input**: Design documents from `/specs/017-watch-event/`
**Prerequisites**: plan.md, spec.md, research.md, data-model.md, quickstart.md
**Tests**: Included — constitution mandates TDD (Red → Green → Refactor).
**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: Foundational (Composable & Data Layer)
**Purpose**: Extend `useEventStorage` with watch capabilities and update role detection across list components. These changes are required by all user stories.
**⚠️ CRITICAL**: No user story work can begin until this phase is complete.
### Tests
- [x] T001 [P] Unit tests for `saveWatch()` and `isStored()` methods in `frontend/src/composables/__tests__/useEventStorage.spec.ts` — test saving a watch-only event (no rsvpToken, no organizerToken), test `isStored()` returns true for watched/attended/organized events and false for unknown tokens
- [x] T002 [P] Unit tests for watcher role detection in `frontend/src/components/__tests__/EventList.spec.ts` — test `getRole()` returns `'watcher'` when event has no organizerToken and no rsvpToken
- [x] T003 [P] Unit tests for watcher badge display in `frontend/src/components/__tests__/EventCard.spec.ts` — test that `eventRole="watcher"` renders badge with text "Watching"
### Implementation
- [x] T004 Add `saveWatch(eventToken, title, dateTime)` and `isStored(eventToken)` methods to `frontend/src/composables/useEventStorage.ts` — `saveWatch` creates a StoredEvent with only eventToken/title/dateTime, `isStored` checks if eventToken exists in storage
- [x] T005 Update `getRole()` in `frontend/src/components/EventList.vue` to return `'watcher'` as fallback when event has no organizerToken and no rsvpToken (role hierarchy: organizer > attendee > watcher)
- [x] T006 [P] Extend `eventRole` prop type in `frontend/src/components/EventCard.vue` from `'organizer' | 'attendee'` to `'organizer' | 'attendee' | 'watcher'`, add "Watching" label text and `.event-card__badge--watcher` styling (glass style, matching design system)
**Checkpoint**: Composable supports watch storage, role detection returns 'watcher', event cards display "Watching" badge.
---
## Phase 2: User Story 1 & 2 — Watch / Un-watch from Detail Page (Priority: P1) 🎯 MVP
**Goal**: Add bookmark icon left of event title on detail page. Unfilled = not stored, filled = stored. Tapping toggles watch state for non-attendee/non-organizer users.
**Independent Test**: Open an event detail page, tap bookmark to watch (icon fills, event appears in list with "Watching" label), tap again to un-watch (icon unfills, event disappears from list).
### Tests
- [x] T007 Unit tests for bookmark icon in `frontend/src/views/__tests__/EventDetailView.spec.ts` — test icon renders unfilled when event not in storage, test icon renders filled when event is in storage, test tapping unfilled icon calls `saveWatch()`, test tapping filled icon calls `removeEvent()` when user is watcher
- [x] T008 E2E test for US1 (watch) in `frontend/e2e/watch-event.spec.ts` — visit event detail page, verify bookmark is unfilled, tap bookmark, verify it fills, navigate to event list, verify event appears with "Watching" label
- [x] T009 E2E test for US2 (un-watch) in `frontend/e2e/watch-event.spec.ts` — watch an event, tap filled bookmark, verify it unfills, navigate to event list, verify event is gone
### Implementation
- [x] T010 [US1] [US2] Add bookmark icon to `frontend/src/views/EventDetailView.vue` — wrap title in flex container (`display: flex; align-items: center; gap: var(--spacing-sm)`), add bookmark button to the left of `
`, icon is unfilled outline when `!isStored(eventToken)` and filled when `isStored(eventToken)`. Tapping calls `saveWatch()` or `removeEvent()` based on current state. Use semantic `