timetracker/lib/features/reports/domain/reports_provider.dart
2026-08-03 21:51:48 +02:00

101 lines
3 KiB
Dart

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<ReportData> 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<ReportData> _loadData() async {
final (from, to) = _periodBounds();
final total = await _repo.getTotalDuration(from, to, projectId: _filterProjectId);
final byProject = await _repo.getDurationByProject(from, to);
final List<double> 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,
);
}
}