110 lines
4.9 KiB
Markdown
110 lines
4.9 KiB
Markdown
# Tasks: iCal Download
|
||
|
||
**Input**: Design documents from `/specs/019-ical-download/`
|
||
**Prerequisites**: plan.md, spec.md
|
||
|
||
**Tests**: TDD is mandated by the project constitution. Tests are written first and must fail before implementation.
|
||
|
||
**Organization**: Single user story (US1). Foundational phase covers the two pure utility modules; US1 phase covers component integration.
|
||
|
||
## 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)
|
||
- Include exact file paths in descriptions
|
||
|
||
---
|
||
|
||
## Phase 1: Foundational (Pure Utilities)
|
||
|
||
**Purpose**: iCal generation and slug utility — pure functions with no UI dependencies
|
||
|
||
### Tests (RED)
|
||
|
||
- [x] T001 [P] Write unit tests for slugify (umlaut transliteration, special chars, max length, empty input) in `frontend/src/utils/__tests__/slugify.spec.ts`
|
||
- [x] T002 [P] Write unit tests for iCal generation (required fields, optional LOCATION/DESCRIPTION omission, UTF-8 text escaping, UID format, deterministic output, DTSTAMP) in `frontend/src/composables/__tests__/useIcalDownload.spec.ts`
|
||
|
||
### Implementation (GREEN)
|
||
|
||
- [x] T003 Implement slugify utility in `frontend/src/utils/slugify.ts` — ASCII transliteration (ä→ae, ü→ue, ö→oe, ß→ss), lowercase, non-ASCII removal, hyphens for spaces/special chars, collapse consecutive hyphens, max 60 chars
|
||
- [x] T004 Implement `generateIcs()` function and `useIcalDownload()` composable in `frontend/src/composables/useIcalDownload.ts` — RFC 5545 VEVENT with UID (`{eventToken}@fete`), DTSTAMP, DTSTART (UTC), SUMMARY, SEQUENCE:0, optional LOCATION/DESCRIPTION, Blob download with `text/calendar` MIME type, slugified filename
|
||
|
||
**Checkpoint**: `npm run test:unit` passes — both utilities work in isolation
|
||
|
||
---
|
||
|
||
## Phase 2: User Story 1 — Download event as calendar file (Priority: P1) 🎯 MVP
|
||
|
||
**Goal**: Calendar icon button in the bottom action bar for all user roles (attendee pre-RSVP, attendee post-RSVP, organizer). Tap triggers `.ics` download. Not shown for cancelled events.
|
||
|
||
**Independent Test**: View any active event → tap calendar button → `.ics` file downloads → opens in calendar app.
|
||
|
||
### Tests (RED)
|
||
|
||
- [x] T005 Write E2E test for calendar download button in `frontend/e2e/ical-download.spec.ts` — verify button visible for pre-RSVP visitor, post-RSVP attendee, and organizer; verify button NOT visible for cancelled event; verify download triggers with correct filename
|
||
|
||
### Implementation (GREEN)
|
||
|
||
- [x] T006 [US1] Add calendar button and `calendar` emit to RsvpBar in `frontend/src/components/RsvpBar.vue` — pre-RSVP state: glow-border + glass-inner icon button after CTA; post-RSVP state: glassmorphic icon button right of status bar
|
||
- [x] T007 [US1] Add calendar button for organizer view in `frontend/src/views/EventDetailView.vue` — fixed bottom position next to existing "Cancel event" button, consistent glassmorphic styling
|
||
- [x] T008 [US1] Wire calendar download handler in `frontend/src/views/EventDetailView.vue` — import `useIcalDownload`, call on `@calendar` emit from RsvpBar and on organizer button click, pass event data
|
||
|
||
**Checkpoint**: All acceptance scenarios pass — any user on an active event can download a valid `.ics` file with 1 tap
|
||
|
||
---
|
||
|
||
## Phase 3: Polish & Cross-Cutting Concerns
|
||
|
||
- [ ] T009 Verify calendar button layout does not disrupt existing RsvpBar on 320px–768px viewports (visual check via `browser-interactive-testing` skill)
|
||
|
||
---
|
||
|
||
## Dependencies & Execution Order
|
||
|
||
### Phase Dependencies
|
||
|
||
- **Foundational (Phase 1)**: No dependencies — can start immediately
|
||
- **US1 (Phase 2)**: Depends on Phase 1 completion (T003, T004 must be done)
|
||
- **Polish (Phase 3)**: Depends on Phase 2 completion
|
||
|
||
### Within Phases
|
||
|
||
- T001 and T002 are parallel (different files)
|
||
- T003 before T004 (`useIcalDownload` imports `slugify`)
|
||
- T005 can be written before T006–T008 (TDD: test fails first)
|
||
- T006 and T007 are parallel (different files)
|
||
- T008 depends on T006 and T007 (wires them together)
|
||
|
||
### Parallel Opportunities
|
||
|
||
```text
|
||
# Phase 1 tests (parallel):
|
||
T001: slugify unit tests
|
||
T002: iCal generation unit tests
|
||
|
||
# Phase 2 implementation (parallel after T005):
|
||
T006: RsvpBar calendar button
|
||
T007: Organizer calendar button
|
||
```
|
||
|
||
---
|
||
|
||
## Implementation Strategy
|
||
|
||
### MVP (Single Pass)
|
||
|
||
1. Complete Phase 1: Write tests → implement slugify → implement iCal generation
|
||
2. Complete Phase 2: Write E2E → add buttons to RsvpBar + organizer view → wire handler
|
||
3. Complete Phase 3: Visual verification
|
||
4. **DONE**: Single user story, single deliverable
|
||
|
||
---
|
||
|
||
## Notes
|
||
|
||
- No backend changes required — all client-side
|
||
- Zero new dependencies — hand-rolled iCal generation
|
||
- `generateIcs()` must be a pure function (deterministic, no side effects) for easy testing
|
||
- `useIcalDownload()` wraps `generateIcs()` + Blob download trigger
|
||
- Calendar SVG icon: use a calendar outline matching the existing date/time meta icon style
|