# Feature Specification: Cancel Event **Feature Branch**: `016-cancel-event` **Created**: 2026-03-12 **Status**: Draft **Input**: User description: "As an organizer, I want to cancel an event so that attendees know the event will not take place" ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Organizer Cancels an Event (Priority: P1) An organizer navigates to their event page (identified by having the organizer token). They decide to cancel the event. They tap a "Cancel Event" button, which opens a bottom sheet (visually similar to the attend/RSVP flow). The bottom sheet contains a text area for an optional cancellation reason and a confirm button. After confirming, the event is permanently marked as cancelled. This action is irreversible. **Why this priority**: This is the core action of the feature. Without it, nothing else matters. **Independent Test**: Can be fully tested by viewing the event with the organizer token, tapping cancel, optionally entering a reason, and confirming. The event's cancelled state persists on reload. **Acceptance Scenarios**: 1. **Given** an active event viewed by someone who has the organizer token, **When** the organizer taps "Cancel Event", **Then** a bottom sheet opens with a text area and a confirm button. 2. **Given** the cancel bottom sheet is open, **When** the organizer enters a cancellation reason and taps the confirm button, **Then** the event is marked as cancelled with the provided reason. 3. **Given** the cancel bottom sheet is open, **When** the organizer taps confirm without entering a reason, **Then** the event is marked as cancelled without a reason. 4. **Given** a cancelled event, **When** the organizer revisits the event page, **Then** the event remains cancelled (irreversible). 5. **Given** the cancel bottom sheet is open, **When** the organizer taps confirm and the API call fails, **Then** an error message is displayed in the bottom sheet, the sheet remains open, and the confirm button is re-enabled for retry. --- ### User Story 2 - Attendee Sees Cancelled Event (Priority: P1) An attendee (or any visitor) opens the event detail page for a cancelled event. A prominent red banner is displayed at the top of the page, clearly communicating that the event has been cancelled. If the organizer provided a cancellation reason, it is shown within the banner. The RSVP buttons are hidden — no new RSVPs can be submitted. **Why this priority**: Equal to P1 because the cancellation must be visible to attendees for the feature to deliver value. Without this, cancelling has no effect from the attendee's perspective. **Independent Test**: Can be tested by viewing a cancelled event's detail page and verifying the banner appears, the reason is displayed (if provided), and RSVP buttons are hidden. **Acceptance Scenarios**: 1. **Given** a cancelled event with a cancellation reason, **When** a visitor opens the event detail page, **Then** a prominent red banner is displayed showing that the event is cancelled along with the reason. 2. **Given** a cancelled event without a cancellation reason, **When** a visitor opens the event detail page, **Then** a prominent red banner is displayed showing that the event is cancelled, without a reason text. 3. **Given** a cancelled event, **When** a visitor opens the event detail page, **Then** the RSVP buttons are not visible. 4. **Given** a cancelled event, **When** a visitor opens the event detail page, **Then** all other event details (title, date, location, description) remain visible. --- ### Edge Cases - What happens when the organizer tries to cancel an already cancelled event? The cancel button is not available on an already cancelled event. - What happens to existing RSVPs when an event is cancelled? They are preserved as-is but no new RSVPs can be submitted. - What happens when the event is both cancelled and expired? The auto-delete mechanism (feature 013) continues to apply normally — cancelled events are deleted on the same schedule as non-cancelled events. - What happens when the cancellation API call fails (network error, server error)? The bottom sheet remains open, a visible error message is displayed within the sheet, and the confirm button is re-enabled so the organizer can retry. - How are cancelled events displayed in the event list? Out of scope for this feature — the event list view is not affected. ## Requirements *(mandatory)* ### Functional Requirements - **FR-001**: System MUST allow the organizer to cancel an event via the organizer view. - **FR-002**: The cancellation interaction MUST use a bottom sheet pattern consistent with the existing RSVP/attend flow. - **FR-003**: The bottom sheet MUST contain a text area for an optional cancellation reason and a confirm button. - **FR-004**: Cancellation MUST be irreversible — once cancelled, there is no way to undo it. - **FR-005**: System MUST store a cancelled flag and an optional cancellation reason for the event. - **FR-006**: System MUST NOT allow new RSVPs for a cancelled event. - **FR-007**: System MUST preserve existing RSVPs when an event is cancelled. - **FR-008**: The event detail page MUST display a prominent red banner for cancelled events. - **FR-009**: The banner MUST include the cancellation reason when one was provided. - **FR-010**: The RSVP buttons MUST be hidden on a cancelled event's detail page. - **FR-011**: All other event information MUST remain visible on a cancelled event's detail page. - **FR-012**: The cancel button MUST NOT be shown on an already cancelled event. - **FR-013**: There MUST be no push notifications, emails, or any active notification mechanism for cancellations. - **FR-014**: If the cancellation API call fails, the bottom sheet MUST remain open, display an error message, and allow the organizer to retry. - **FR-015**: Changes to the event list view for cancelled events are explicitly OUT OF SCOPE for this feature. ### Key Entities - **Event** (extended): Gains a cancelled state (boolean) and an optional cancellation reason (free text). An event can transition from active to cancelled, but not back. ## Success Criteria *(mandatory)* ### Measurable Outcomes - **SC-001**: Organizer can cancel an event in under 30 seconds (open bottom sheet, optionally type reason, confirm). - **SC-002**: 100% of visitors to a cancelled event's detail page see the cancellation banner without scrolling. - **SC-003**: 0% of cancelled events accept new RSVPs. - **SC-004**: Existing RSVPs are fully preserved after cancellation (no data loss). ## Clarifications ### Session 2026-03-12 - Q: How should cancelled events appear in the event list view? → A: Out of scope for this feature — event list view is not affected. - Q: What should happen when the cancellation API call fails? → A: Error message displayed in the bottom sheet, sheet remains open, confirm button re-enabled for retry. ## Assumptions - The bottom sheet component pattern already exists from the RSVP/attend flow and can be reused. - The cancellation reason has a maximum length of 2000 characters (consistent with the event description field). - The cancellation reason is plain text (no formatting or markup).