weeklyHeatmap function
26-week × 7-day activity grid (182 buckets, oldest first). Each entry is
a 0..4 intensity bucket derived from session count for that calendar day.
The grid is laid out column-major: index = weekIndex * 7 + dayOfWeek,
with dayOfWeek == 0 Monday and weekIndex == 25 the current week.
Implementation
@riverpod
Future<List<int>> weeklyHeatmap(Ref ref) async {
final ds = ref.watch(supabaseDatasourceProvider);
final now = DateTime.now();
final today = DateTime(now.year, now.month, now.day);
// Anchor on Monday of the current week so the rightmost column is the
// in-progress week and column 0 is 25 weeks back.
final mondayOfThisWeek = today.subtract(
Duration(days: today.weekday - DateTime.monday),
);
final start = mondayOfThisWeek.subtract(const Duration(days: 7 * 25));
final counts = await ds.getSessionCountsByDay(since: start);
return List<int>.generate(182, (i) {
final week = i ~/ 7;
final dow = i % 7;
final day = start.add(Duration(days: week * 7 + dow));
if (day.isAfter(today)) return 0;
final n = counts[day] ?? 0;
if (n == 0) return 0;
if (n == 1) return 1;
if (n == 2) return 2;
if (n <= 4) return 3;
return 4;
});
}