# Feature Specification: Highlight Changed Event Details **Feature**: `014-highlight-changes` **Created**: 2026-03-06 **Status**: Draft **Source**: Migrated from spec/userstories.md > **NOTE on directory name**: The migration task list specified `us-09-reminders` for this directory, but US-9 in userstories.md is "Highlight changed event details". The directory has been created as `014-highlight-changes` to match the actual story content. This is consistent with corrections made in iterations 16 (us-06-bookmark-event) and 18 (us-08-calendar-export). ## User Scenarios & Testing ### User Story 1 - Guest sees highlight for recently changed fields (Priority: P1) A guest opens an event page that the organizer has edited since the guest's last visit. Changed fields (e.g. new date, new location) are visually highlighted so the guest immediately notices what is different. After the page loads, the highlight is cleared for the next visit. **Why this priority**: Core value of the feature — guests must notice important updates like a rescheduled date or changed location without having to read the entire page again. **Independent Test**: Can be fully tested by creating an event, visiting it (establishing `last_seen_at`), editing it as organizer, then revisiting as guest — changed fields appear highlighted; unmodified fields do not. **Acceptance Scenarios**: 1. **Given** a guest has previously visited an event page (establishing `last_seen_at` in localStorage), **When** the organizer saves an edit that changes one or more fields, **Then** on the guest's next visit those changed fields are visually highlighted with a "recently changed" indicator. 2. **Given** an event with an edit, **When** a guest opens the event page and the `last_edited_at` timestamp is newer than the stored `last_seen_at`, **Then** only the fields changed in the most recent edit are highlighted; unmodified fields are not highlighted. 3. **Given** a guest who has seen the latest edit, **When** they visit the event page again without any new edits having occurred, **Then** no highlights are shown. --- ### User Story 2 - No highlight on first visit (Priority: P2) A guest opens an event page for the first time (no `last_seen_at` in localStorage). Even if the organizer has made edits since creation, no "recently changed" highlights are shown — the event is new to the guest, so labelling fields as changed would be misleading. **Why this priority**: Correctness requirement. Showing highlights on first visit would be confusing because the guest has no reference point for what "changed" means. **Independent Test**: Can be tested by clearing localStorage and opening an edited event page — no highlight indicators should appear. **Acceptance Scenarios**: 1. **Given** no `last_seen_at` value in localStorage for a given event token, **When** a guest opens the event page, **Then** no field highlights are shown regardless of whether the organizer has made edits. 2. **Given** a first visit with no `last_seen_at`, **When** the event page is rendered, **Then** `last_seen_at` is written to localStorage with the current `last_edited_at` value, so the next visit will correctly compare against it. --- ### User Story 3 - Highlight clears after viewing (Priority: P2) After the guest views the highlighted changes, the highlight is cleared on the next visit. Subsequent visits to the same event page (without new edits) show no highlights. **Why this priority**: Without this, the highlight would become permanent noise rather than a meaningful "new change" signal. **Independent Test**: Can be tested by visiting an event page with a change (seeing highlights), then visiting again — highlights should be gone. **Acceptance Scenarios**: 1. **Given** a guest views an event page with highlighted fields, **When** the page is rendered, **Then** `last_seen_at` in localStorage is updated to match the current `last_edited_at`. 2. **Given** `last_seen_at` was updated on the previous visit, **When** the guest visits the event page again (with no new edits), **Then** no highlights are shown. --- ### User Story 4 - Only most recent edit is tracked (Priority: P3) If the organizer makes multiple successive edits, only the fields changed in the most recent edit are highlighted. Intermediate changes between visits are not accumulated. **Why this priority**: Simplicity constraint — tracking the full change history is overengineered for this scope. Guests see what changed last, not everything that ever changed. **Independent Test**: Can be tested by making two successive edits to different fields, then visiting as a guest — only fields from the second edit are highlighted. **Acceptance Scenarios**: 1. **Given** an organizer edits the event twice (first changing title, then changing location), **When** a guest visits the page after both edits, **Then** only the location is highlighted (changed in the most recent edit); title is not highlighted (changed in an earlier edit). 2. **Given** an event with no edits since creation, **When** any guest visits the event page, **Then** no highlights are shown. --- ### Edge Cases - What if the organizer edits the event while the guest has the page open? The highlight logic runs on page load; open-page state is stale and will be corrected on the next visit. - What if localStorage is unavailable (e.g. private browsing)? No `last_seen_at` can be stored, so the guest is treated as a first-time visitor and no highlights are shown. This is safe and graceful. - What if `last_edited_at` is null (event has never been edited)? No highlights are shown. The field-change metadata is only populated on the first actual edit. ## Requirements ### Functional Requirements - **FR-001**: System MUST record which fields changed (title, description, date/time, location) and store a `last_edited_at` timestamp server-side whenever the organizer saves an edit (US-5). - **FR-002**: System MUST include `last_edited_at` and the set of changed field names in the event page API response. - **FR-003**: Client MUST store a `last_seen_at` value per event token in localStorage, set to the event's `last_edited_at` on each page render. - **FR-004**: Client MUST compare the event's `last_edited_at` against the stored `last_seen_at` on page load to determine whether highlights should be shown. - **FR-005**: Client MUST display a "recently changed" visual indicator next to each field that appears in the server's changed-fields set, only when `last_edited_at` is newer than `last_seen_at`. - **FR-006**: Client MUST NOT show any highlights when no `last_seen_at` is present in localStorage for the event (first visit). - **FR-007**: Client MUST NOT show any highlights when `last_edited_at` is null or equal to `last_seen_at`. - **FR-008**: Client MUST update `last_seen_at` in localStorage after rendering the event page, regardless of whether highlights were shown. - **FR-009**: System MUST NOT transmit any visit data or `last_seen_at` value to the server — the read-state tracking is entirely client-side. - **FR-010**: System MUST track only the most recent edit's changed fields; intermediate changes between visits are not accumulated. ### Key Entities - **EditMetadata** (server-side): Records `last_edited_at` timestamp and the set of changed field names for an event. Associated with the event record. Populated on first edit; overwritten on each subsequent edit. - **last_seen_at** (client-side, localStorage): Per-event-token timestamp. Records when the guest last viewed the event page. Used to determine whether highlights should be shown. Never transmitted to the server. ## Success Criteria ### Measurable Outcomes - **SC-001**: A guest who has visited an event page before an edit correctly sees highlight indicators on the changed fields when revisiting after the edit. - **SC-002**: A guest who visits an event page for the first time sees no highlight indicators, even if edits have been made. - **SC-003**: Highlights disappear on the guest's next visit after they have viewed the highlighted changes. - **SC-004**: No server request beyond the normal event page load is required to determine whether highlights should be shown. - **SC-005**: No visit data or read-state information is transmitted to the server — privacy is fully preserved.