- dailyPlanProvider: manual StreamProvider.autoDispose with overdue/today/tomorrow partitioning - Stable progress denominator: remaining overdue + remaining today + completedTodayCount - 10 new German localization keys for daily plan sections, progress, empty states - dart analyze clean, full test suite (66/66) passes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
57 lines
2.0 KiB
Dart
57 lines
2.0 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import 'package:household_keeper/core/providers/database_provider.dart';
|
|
import 'package:household_keeper/features/home/domain/daily_plan_models.dart';
|
|
|
|
/// Reactive daily plan data: tasks categorized into overdue/today/tomorrow
|
|
/// with progress tracking.
|
|
///
|
|
/// Defined manually (not @riverpod) because riverpod_generator has trouble
|
|
/// with drift's generated [Task] type. Same pattern as [tasksInRoomProvider].
|
|
final dailyPlanProvider =
|
|
StreamProvider.autoDispose<DailyPlanState>((ref) {
|
|
final db = ref.watch(appDatabaseProvider);
|
|
final taskStream = db.dailyPlanDao.watchAllTasksWithRoomName();
|
|
|
|
return taskStream.asyncMap((allTasks) async {
|
|
// Get today's completion count (latest value from stream)
|
|
final completedToday =
|
|
await db.dailyPlanDao.watchCompletionsToday().first;
|
|
|
|
final now = DateTime.now();
|
|
final today = DateTime(now.year, now.month, now.day);
|
|
final tomorrow = today.add(const Duration(days: 1));
|
|
final dayAfterTomorrow = tomorrow.add(const Duration(days: 1));
|
|
|
|
final overdue = <TaskWithRoom>[];
|
|
final todayList = <TaskWithRoom>[];
|
|
final tomorrowList = <TaskWithRoom>[];
|
|
|
|
for (final tw in allTasks) {
|
|
final dueDate = DateTime(
|
|
tw.task.nextDueDate.year,
|
|
tw.task.nextDueDate.month,
|
|
tw.task.nextDueDate.day,
|
|
);
|
|
if (dueDate.isBefore(today)) {
|
|
overdue.add(tw);
|
|
} else if (dueDate.isBefore(tomorrow)) {
|
|
todayList.add(tw);
|
|
} else if (dueDate.isBefore(dayAfterTomorrow)) {
|
|
tomorrowList.add(tw);
|
|
}
|
|
}
|
|
|
|
// totalTodayCount includes completedTodayCount so the denominator
|
|
// stays stable as tasks are completed (their nextDueDate moves to
|
|
// the future, shrinking overdue+today, but completedToday grows).
|
|
return DailyPlanState(
|
|
overdueTasks: overdue,
|
|
todayTasks: todayList,
|
|
tomorrowTasks: tomorrowList,
|
|
completedTodayCount: completedToday,
|
|
totalTodayCount: overdue.length + todayList.length + completedToday,
|
|
);
|
|
});
|
|
});
|