getCalendar method
Gets academic calendar events for the given date range.
Returns cached data if fresh (within TTL). Set refresh to true to
bypass TTL (pull-to-refresh).
Implementation
Future<List<CalendarEvent>> getCalendar({
required DateTime startDate,
required DateTime endDate,
bool refresh = false,
}) async {
final user = await _database.getUser();
if (user == null) return [];
// calendarFetchedAt is authoritative for cache presence. The range-filtered
// query below may return an empty list even when the full academic year is
// cached (e.g. a future date range), so we must not use cached.isEmpty as
// the nil-check — that would cause spurious network fetches.
final hasCachedData = user.calendarFetchedAt != null;
final cached = hasCachedData
? await _eventsOverlapping(startDate, endDate).get()
: null;
return fetchWithTtl<List<CalendarEvent>>(
cached: cached,
getFetchedAt: (_) => user.calendarFetchedAt,
fetchFromNetwork: () =>
_fetchCalendarFromNetwork(user.id, startDate, endDate),
refresh: refresh,
);
}