Commit Graph
7 Commits
Author SHA1 Message Date
Lucas Berger 44d336c01b 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)
2026-06-10 11:17:13 -04:00
Lucas Berger 05d9f70b45 fix(02): window occurrences in UTC, not server-local timezone
ICAL.Time.fromJSDate(window, false) interpreted the UTC-midnight window bounds in the
server's local TZ (America/New_York in dev), shifting the window by the server offset and
dropping evening occurrences near a day window's end (e.g. June 11 17:45-04:00 = 21:45Z was
excluded from the June-11 day view). Use UTC so the window is deterministic and correct.
2026-06-05 15:28:26 -04:00
Lucas Berger 194f6a82a8 fix(02): show owner name / Family in event popover footer
Backend:
- expand.ts: add ownerName: string | null to CalendarOccurrence
  interface and expandOccurrences() signature; thread it onto every
  emitted occurrence.
- events.ts: SELECT users.displayName as ownerName in the join; pass
  it to expandOccurrences().

Frontend:
- client.ts: add ownerName: string | null to CalendarOccurrence.
- EventDetailPopover.tsx: render isShared ? 'Family' :
  (ownerName ?? calendarName) in the footer instead of calendarName.

Tests:
- expand.test.ts: pass ownerName to all expandOccurrences() calls;
  assert ownerName is carried onto occurrences in the DST test.
- events.test.ts: add ownerName to mock rows; assert ownerName present
  on occurrences; add ownerName assertion to timed-recurring test.
- EventDetailPopover.test.tsx: add ownerName to fixtures; split
  "calendar name in footer" into three targeted tests covering
  personal-with-owner, shared→Family, and null-owner fallback.
2026-06-05 15:14:43 -04:00
Lucas Berger ee2281fe81 fix(02): correct DURATION-only event end in expand.ts (BUG 1)
- Replace dtend ?? dtstart with event.endDate which handles DURATION-only VEVENTs
- Add positive-duration guard (PT30M / P1D) to both non-recurring and recurring branches
- Add single-duration.ics fixture and regression test asserting end > start for DURATION-only events
2026-06-05 14:33:00 -04:00
Lucas Berger bef4a83fe0 fix(02): CSS-safe occurrence ids + error boundary to surface render errors
Schedule-X rejects ids containing ':' '[' ']' (the old ${uid}::${iso} form) — mint ev-<uid>-<epochMs> instead. Add an ErrorBoundary so a render throw shows the error instead of a blank page.
2026-06-05 14:30:32 -04:00
Lucas Berger 35f725d450 fix(02): emit IANA-annotated timed strings from serializeTime
Temporal.ZonedDateTime.from() rejects offset-only ISO strings such as
'2026-06-18T08:00:00-04:00'; it requires an IANA bracket, e.g.
'2026-06-18T08:00:00-04:00[America/New_York]'. serializeTime() was
emitting offset-only for named zones and bare 'Z' for UTC — both
unparseable by the frontend, blanking the calendar view.

Changes:
- Named IANA zone: emit '...±HH:MM[tzid]' using t.zone.tzid
- UTC zone: strip trailing 'Z' from toString(), emit '+00:00[UTC]'
- Floating zone (no registered VTIMEZONE): fall back to '+00:00[UTC]'
- Update CalendarOccurrence docstrings to reflect the IANA-annotated contract
- Add temporal-polyfill@0.3.2 as dev dep in api for cross-contract test
2026-06-05 14:02:36 -04:00
Lucas Berger 6736194a4a feat(02-02): add expandOccurrences() with VTIMEZONE + allDay split + EXDATE
- ICAL.TimezoneService.register() runs before RecurExpansion (DST correctness)
- All-day events serialized as YYYY-MM-DD strings (no time shift)
- EXDATE exclusions handled internally by ICAL.RecurExpansion
- Malformed rawVevent returns [] without throwing
- expand.test.ts DST, all-day, EXDATE assertions green (3/3)
2026-06-05 10:30:22 -04:00