# TT-005 — Riverpod Providers & Notifiers **Type:** Story **Priority:** High **Labels:** state-management, riverpod **Depends on:** TT-003, TT-004 **Blocks:** TT-006, TT-007, TT-008, TT-009 --- ## Summary Implement all Riverpod providers and notifiers for each feature. This is the domain/application layer that connects the data layer (repositories) to the presentation layer (screens/widgets). ## Providers to implement ### Timer Feature File: `lib/features/timer/domain/timer_notifier.dart` ```dart @riverpod class TimerNotifier extends _$TimerNotifier { @override TimerState build(); // reads DB for open entry on init Future start(Project project, {String? note}); Future stop(); Future discard(); void updateNote(String note); } ``` - Uses a `dart:async Timer.periodic(1s)` while running - On `build()`: calls `timeEntriesRepository.getActiveEntry()` to restore state - See `.ai/features/timer.md` for full state-machine spec ### Projects Feature File: `lib/features/projects/domain/projects_provider.dart` ```dart @riverpod Stream> activeProjects(ActiveProjectsRef ref); @riverpod Stream> allProjects(AllProjectsRef ref); @riverpod class ProjectsNotifier extends _$ProjectsNotifier { Future create({required String name, required int colorValue, String? description}); Future update(Project project); Future archive(int id); Future delete(int id); } ``` ### Entries Feature File: `lib/features/entries/domain/entries_provider.dart` ```dart @riverpod Stream> entriesByDateRange( EntriesByDateRangeRef ref, {required DateTime from, required DateTime to}); @riverpod class EntriesNotifier extends _$EntriesNotifier { Future create(TimeEntry entry); Future update(TimeEntry entry); Future delete(int id); } ``` ### Reports Feature File: `lib/features/reports/domain/reports_provider.dart` ```dart @riverpod class ReportsNotifier extends _$ReportsNotifier { @override ReportData build(); void selectPeriod(ReportPeriod period); // day | week | month void goToPrevious(); void goToNext(); void filterByProject(int? projectId); } @freezed class ReportData with _$ReportData { const factory ReportData({ required Duration totalDuration, required Map durationByProject, required List chartValues, // bars for fl_chart required DateTime periodStart, required DateTime periodEnd, }) = _ReportData; } ``` ## Acceptance Criteria - [ ] All providers use `@riverpod` annotation (code-gen) - [ ] `TimerNotifier.build()` restores running timer from DB on app start - [ ] `TimerNotifier` disposes its `dart:async Timer` via `ref.onDispose` - [ ] All providers inject repositories via `ref.watch(xxxRepositoryProvider)` - [ ] Unit tests for `TimerNotifier` (start/stop/discard/restore) - [ ] Unit tests for `ProjectsNotifier` (CRUD operations) ## Files to create - `lib/features/timer/domain/timer_notifier.dart` - `lib/features/projects/domain/projects_provider.dart` - `lib/features/entries/domain/entries_provider.dart` - `lib/features/reports/domain/reports_provider.dart` - `lib/features/reports/domain/report_data.dart` - `test/features/timer/timer_notifier_test.dart` - `test/features/projects/projects_notifier_test.dart`