import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:timetrack/features/reports/data/drift_reports_repository.dart'; import 'package:timetrack/features/reports/data/reports_repository.dart'; import 'package:timetrack/features/reports/domain/report_data.dart'; part 'reports_provider.g.dart'; @riverpod class ReportsNotifier extends _$ReportsNotifier { @override Future build() => _loadData(); ReportPeriod _period = ReportPeriod.week; DateTime _anchor = DateTime.now(); int? _filterProjectId; ReportsRepository get _repo => ref.read(reportsRepositoryProvider); ReportPeriod get period => _period; void selectPeriod(ReportPeriod period) { _period = period; _anchor = DateTime.now(); ref.invalidateSelf(); } void goToPrevious() { _anchor = _shift(-1); ref.invalidateSelf(); } void goToNext() { _anchor = _shift(1); ref.invalidateSelf(); } void filterByProject(int? projectId) { _filterProjectId = projectId; ref.invalidateSelf(); } DateTime _shift(int direction) { switch (_period) { case ReportPeriod.day: return _anchor.add(Duration(days: direction)); case ReportPeriod.week: return _anchor.add(Duration(days: 7 * direction)); case ReportPeriod.month: return DateTime(_anchor.year, _anchor.month + direction); } } (DateTime, DateTime) _periodBounds() { switch (_period) { case ReportPeriod.day: final start = DateTime(_anchor.year, _anchor.month, _anchor.day); return (start, start.add(const Duration(days: 1))); case ReportPeriod.week: final monday = _anchor.subtract(Duration(days: _anchor.weekday - 1)); final start = DateTime(monday.year, monday.month, monday.day); return (start, start.add(const Duration(days: 7))); case ReportPeriod.month: final start = DateTime(_anchor.year, _anchor.month); return (start, DateTime(_anchor.year, _anchor.month + 1)); } } Future _loadData() async { final (from, to) = _periodBounds(); final total = await _repo.getTotalDuration(from, to, projectId: _filterProjectId); final byProject = await _repo.getDurationByProject(from, to); final List chartValues; switch (_period) { case ReportPeriod.day: chartValues = List.filled(24, 0.0); break; case ReportPeriod.week: final byDay = await _repo.getDurationByWeekday(from); chartValues = List.generate(7, (i) => (byDay[i]?.inMinutes ?? 0).toDouble()); break; case ReportPeriod.month: final byDay = await _repo.getDurationByDay(from); final daysInMonth = to.difference(from).inDays; chartValues = List.generate( daysInMonth, (i) => (byDay[i + 1]?.inMinutes ?? 0).toDouble(), ); break; } return ReportData( totalDuration: total, durationByProject: byProject, chartValues: chartValues, periodStart: from, periodEnd: to, ); } }