feat(06-03): expose hasRrule on expanded occurrences

- Add hasRrule: boolean to CalendarOccurrence interface
- Capture isRecurring = event.isRecurring() once before the branch
- Set hasRrule: isRecurring in non-recurring push (always false)
- Set hasRrule: isRecurring in recurring push (always true)
- All 10 expand.test.ts tests pass (RED→GREEN)
This commit is contained in:
Lucas Berger
2026-06-10 11:17:13 -04:00
parent 593302ee41
commit 44d336c01b
+8 -1
View File
@@ -64,6 +64,8 @@ export interface CalendarOccurrence {
allDay: boolean
location: string | null
description: string | null
/** True when this occurrence belongs to a recurring series (has RRULE). False for single events. */
hasRrule: boolean
}
/**
@@ -219,8 +221,11 @@ export function expandOccurrences(
const occurrences: CalendarOccurrence[] = []
// Capture once — used in both the non-recurring and recurring branches to populate hasRrule.
const isRecurring = event.isRecurring()
// --- 4. Non-recurring event: single occurrence check ---
if (!event.isRecurring()) {
if (!isRecurring) {
if (dtstart.compare(rangeStart) >= 0 && dtstart.compare(rangeEnd) < 0) {
// Use ICAL.Event.endDate which derives end from DTEND, or DTSTART+DURATION, or sensible default.
// Do NOT use getFirstPropertyValue('dtend') directly — events with only DURATION set return null,
@@ -253,6 +258,7 @@ export function expandOccurrences(
allDay,
location: event.location ?? null,
description: event.description ?? null,
hasRrule: isRecurring, // always false in the non-recurring branch
})
}
return occurrences
@@ -299,6 +305,7 @@ export function expandOccurrences(
allDay,
location: event.location ?? null,
description: event.description ?? null,
hasRrule: isRecurring, // always true in the recurring branch
})
}