feat(03-01): implement DailyPlanDao with cross-room join query and completion count
- watchAllTasksWithRoomName: innerJoin tasks+rooms, sorted by nextDueDate asc - watchCompletionsToday: customSelect with readsFrom for proper stream invalidation - All 7 DAO unit tests pass Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,14 +11,42 @@ class DailyPlanDao extends DatabaseAccessor<AppDatabase>
|
|||||||
DailyPlanDao(super.attachedDatabase);
|
DailyPlanDao(super.attachedDatabase);
|
||||||
|
|
||||||
/// Watch all tasks joined with room name, sorted by nextDueDate ascending.
|
/// Watch all tasks joined with room name, sorted by nextDueDate ascending.
|
||||||
|
/// Includes ALL tasks (overdue, today, future) -- filtering is done in the
|
||||||
|
/// provider layer to avoid multiple queries.
|
||||||
Stream<List<TaskWithRoom>> watchAllTasksWithRoomName() {
|
Stream<List<TaskWithRoom>> watchAllTasksWithRoomName() {
|
||||||
// TODO: implement
|
final query = select(tasks).join([
|
||||||
throw UnimplementedError();
|
innerJoin(rooms, rooms.id.equalsExp(tasks.roomId)),
|
||||||
|
]);
|
||||||
|
query.orderBy([OrderingTerm.asc(tasks.nextDueDate)]);
|
||||||
|
|
||||||
|
return query.watch().map((rows) {
|
||||||
|
return rows.map((row) {
|
||||||
|
final task = row.readTable(tasks);
|
||||||
|
final room = row.readTable(rooms);
|
||||||
|
return TaskWithRoom(
|
||||||
|
task: task,
|
||||||
|
roomName: room.name,
|
||||||
|
roomId: room.id,
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Count task completions recorded today.
|
/// Count task completions recorded today.
|
||||||
|
/// Uses customSelect with readsFrom for proper stream invalidation.
|
||||||
Stream<int> watchCompletionsToday({DateTime? today}) {
|
Stream<int> watchCompletionsToday({DateTime? today}) {
|
||||||
// TODO: implement
|
final now = today ?? DateTime.now();
|
||||||
throw UnimplementedError();
|
final startOfDay = DateTime(now.year, now.month, now.day);
|
||||||
|
final endOfDay = startOfDay.add(const Duration(days: 1));
|
||||||
|
|
||||||
|
return customSelect(
|
||||||
|
'SELECT COUNT(*) AS c FROM task_completions '
|
||||||
|
'WHERE completed_at >= ? AND completed_at < ?',
|
||||||
|
variables: [
|
||||||
|
Variable(startOfDay.millisecondsSinceEpoch ~/ 1000),
|
||||||
|
Variable(endOfDay.millisecondsSinceEpoch ~/ 1000),
|
||||||
|
],
|
||||||
|
readsFrom: {taskCompletions},
|
||||||
|
).watchSingle().map((row) => row.read<int>('c'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user