# Feature Specification: iCal Download

**Feature Branch**: `019-ical-download`
**Created**: 2026-03-13
**Status**: Draft
**Input**: User description: "Add iCal (.ics) calendar download button to event detail page"

## User Scenarios & Testing *(mandatory)*

### User Story 1 - Download event as calendar file (Priority: P1)

As a user viewing an event, I want to add it to my personal calendar so I don't forget the date and time.

The user taps a calendar icon button in the bottom action bar. The browser downloads a `.ics` file containing the current event details. The user opens the file in their preferred calendar app (Apple Calendar, Google Calendar, Outlook, Thunderbird, etc.) and the event appears in their calendar.

**Why this priority**: Core value of the feature — getting the event into the user's calendar.

**Independent Test**: Can be fully tested by viewing an event, tapping the calendar button, and verifying the downloaded .ics file opens correctly in a calendar app.

**Acceptance Scenarios**:

1. **Given** a user views an active event (as attendee, pre-RSVP visitor, or organizer), **When** they tap the calendar icon in the action bar, **Then** a valid `.ics` file is downloaded containing the event's title, date/time, location, and description.
2. **Given** the event is cancelled, **When** the user views the event detail page, **Then** the calendar button is NOT shown.
3. **Given** the downloaded `.ics` file, **When** opened in any major calendar app, **Then** the event is created without errors.
4. **Given** the user downloads the `.ics` file multiple times, **Then** the generated file is identical each time (deterministic output from the same event data).

---

### Edge Cases

- What happens when the event has no location set? The `.ics` file omits the location field.
- What happens when the event has no description? The `.ics` file omits the description field.
- What happens when event title or description contains special characters (umlauts, emoji, newlines)? The `.ics` file uses proper UTF-8 encoding and RFC 5545 text escaping.
- What happens on a browser that blocks Blob downloads? The download should work via standard browser download mechanisms; no special fallback is needed since all modern browsers support Blob downloads.

## Clarifications

### Session 2026-03-13

- Q: Event hat kein Endzeit-Feld — wie soll DTEND in der .ics gehandhabt werden? → A: Kein DTEND/DURATION — nur DTSTART (punktuelles Ereignis gemäß RFC 5545).
- Q: Dateiname-Sanitierung bei Sonderzeichen, Umlauten, langen Titeln? → A: Slugify — ASCII-Transliteration (ä→ae etc.), Leerzeichen→Bindestrich, max 60 Zeichen.
- Q: Gibt es ein Konzept von "aktualisierten" .ics-Dateien? → A: Nein. Jeder Download erzeugt die gleiche Datei aus den aktuellen Event-Daten. Kein Update-Mechanismus.
- Q: Button bei abgesagten Events? → A: Nein, kein Button wenn Event cancelled.
- Q: Nur für Attendees oder auch für Organisatoren? → A: Alle Rollen — Attendee, Besucher ohne RSVP, Organisator. Button an gleicher Position.

## Requirements *(mandatory)*

### Functional Requirements

- **FR-001**: System MUST generate a valid `.ics` file (RFC 5545 VEVENT) client-side without requiring backend changes.
- **FR-002**: The `.ics` file MUST contain: UID, DTSTAMP, DTSTART, SUMMARY. DTEND and DURATION MUST NOT be included (the event has no end time; RFC 5545 treats a VEVENT with only DTSTART as a point-in-time event). It MUST include LOCATION and DESCRIPTION when those fields are present on the event.
- **FR-003**: The UID MUST be derived from the event token (e.g. `{eventToken}@fete`) to produce a stable identifier for the calendar entry.
- **FR-004**: The `.ics` file MUST include a SEQUENCE number of `0`.
- **FR-006**: The calendar icon button MUST appear in the bottom action bar for all users (attendees, pre-RSVP visitors, and organizers), adapting its visual style to match the surrounding elements:
  - **Before RSVP (attendee)**: Button order (left to right): bookmark, "I'm attending!" CTA, calendar. The calendar button MUST use the same glow-border + glass-inner style as the bookmark button.
  - **After RSVP (attendee)**: The calendar button MUST appear to the right of the "You're attending!" status bar. It MUST use the same glassmorphic bar style (gradient background, glass border, backdrop blur) as the status bar — not the glow-border style. Layout: "You're attending!" status (flex), calendar icon button (fixed width).
  - **Organizer**: The calendar button MUST appear in the same fixed bottom position. Styling TBD (consistent with existing organizer UI).
- **FR-007**: The calendar button MUST NOT be shown when the event is cancelled.
- **FR-008**: The downloaded file MUST use UTF-8 encoding and the `text/calendar` MIME type.
- **FR-009**: The filename MUST be human-readable, derived from the event title using ASCII slugification (e.g. `Sommerfest am See` → `sommerfest-am-see.ics`). Rules: lowercase, umlauts transliterated (ä→ae, ü→ue, ö→oe, ß→ss), non-ASCII characters removed, spaces/special chars replaced with hyphens, consecutive hyphens collapsed, max 60 characters before `.ics` extension.

### Key Entities

- **iCal Event (VEVENT)**: A calendar entry generated from fete event data. Key attributes: UID (from event token), SUMMARY (title), DTSTART (date/time, no DTEND — point-in-time event), LOCATION, DESCRIPTION, SEQUENCE, DTSTAMP.

## Success Criteria *(mandatory)*

### Measurable Outcomes

- **SC-001**: Any user (attendee, visitor, organizer) can download a calendar file with 1 tap.
- **SC-002**: Downloaded `.ics` files import successfully into Apple Calendar, Google Calendar, and Outlook without errors.
- **SC-003**: The calendar button does not disrupt the existing bottom bar layout or interaction patterns on devices from 320px to 768px width.

## Assumptions

- The `.ics` file generation is entirely client-side (no new backend endpoints needed), since all required event data is already available in the frontend after fetching event details.
- The generated `.ics` file is deterministic: same event data always produces the same output. There is no concept of "updated" files — each download is a fresh snapshot of the current event data.
- SEQUENCE is always `0`.
- The calendar button is visible for all user roles (attendee, visitor, organizer) on active events. Not shown for cancelled events.
- All date/time values in the `.ics` file use UTC format (Z suffix) since the event times are already stored in UTC.
