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

92 lines
3.0 KiB
Markdown

# 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
```typescript
type SectionKey = 'today' | 'thisWeek' | 'later' | 'past'
```
Enum-like union type for the four temporal sections. Ordering is fixed: today → thisWeek → later → past.
### EventSection
```typescript
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
```typescript
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.