Files
fete/specs/010-event-list-grouping/data-model.md
nitrix a52d0cd1d3
All checks were successful
CI / backend-test (push) Successful in 58s
CI / frontend-test (push) Successful in 23s
CI / frontend-e2e (push) Successful in 1m9s
CI / build-and-publish (push) Has been skipped
Add temporal grouping to event list (Today/This Week/Next Week/Later/Past)
Group events into five temporal sections with section headers, date subheaders,
and context-aware time display (clock time for upcoming, relative for past).
Includes new useEventGrouping composable, SectionHeader and DateSubheader
components, full unit and E2E test coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 17:26:58 +01:00

3.0 KiB

Data Model: Event List Temporal Grouping

Feature: 010-event-list-grouping | Date: 2026-03-08

Existing Entities (no changes)

StoredEvent

Location: frontend/src/composables/useEventStorage.ts

Field Type Description
eventToken string UUID v4, unique identifier
organizerToken string? UUID v4, present if user is organizer
title string Event title
dateTime string ISO 8601 with UTC offset (e.g., "2026-03-15T20:00:00+01:00")
expiryDate string ISO 8601 expiry date
rsvpToken string? Present if user has RSVP'd
rsvpName string? Name used for RSVP

Note: No changes to StoredEvent. The dateTime field is the sole input for all grouping and sorting logic.

New Types (frontend only)

SectionKey

type SectionKey = 'today' | 'thisWeek' | 'later' | 'past'

Enum-like union type for the four temporal sections. Ordering is fixed: today → thisWeek → later → past.

EventSection

interface EventSection {
  key: SectionKey
  label: string          // Display label: "Today", "This Week", "Later", "Past"
  dateGroups: DateGroup[]
  emphasized: boolean    // true only for 'today' section
}

Represents one temporal section in the grouped list. Sections with no events are omitted entirely (never constructed).

DateGroup

interface DateGroup {
  dateKey: string        // YYYY-MM-DD (for keying/dedup)
  label: string          // Formatted via Intl.DateTimeFormat, e.g., "Wed, 12 Mar"
  events: StoredEvent[]  // Events on this date, sorted by time
  showSubheader: boolean // false for "Today" section (FR-005)
}

Groups events within a section by their specific calendar date. The showSubheader flag controls whether the date subheader is rendered (always false in "Today" section per FR-005).

Grouping Algorithm

Input: StoredEvent[], now: Date
Output: EventSection[]

1. Compute boundaries:
   - startOfToday = today at 00:00:00 local
   - endOfToday = today at 23:59:59.999 local
   - endOfWeek = next Sunday at 23:59:59.999 local (or today if today is Sunday)

2. Classify each event by dateTime:
   - dateTime < startOfToday → "past"
   - startOfToday ≤ dateTime ≤ endOfToday → "today"
   - endOfToday < dateTime ≤ endOfWeek → "thisWeek"
   - dateTime > endOfWeek → "later"

3. Within each section, group by calendar date (YYYY-MM-DD)

4. Sort:
   - today/thisWeek/later: date groups ascending, events within group ascending by time
   - past: date groups descending, events within group descending by time

5. Emit only non-empty sections in fixed order: today, thisWeek, later, past

State Transitions

None. Events are static data in localStorage. Temporal classification is computed on each render based on current time. No event mutation occurs.

Validation Rules

No new validation. Existing isValidStoredEvent() in useEventStorage.ts already validates the dateTime field as a parseable ISO 8601 string.