# TT-004 — Repository Implementations **Type:** Story **Priority:** High **Labels:** data-layer, repositories **Depends on:** TT-002, TT-003 **Blocks:** TT-005 --- ## Summary Implement the concrete repository classes for each feature. Repositories act as the single access point for the data layer; they delegate to Drift DAOs and map DB rows to domain models. ## Repositories to implement ### `ProjectsRepository` File: `lib/features/projects/data/projects_repository.dart` ```dart abstract class ProjectsRepository { Stream> watchAll(); Stream> watchActive(); // archivedAt IS NULL Future getById(int id); Future create({required String name, required int colorValue, String? description}); Future update(Project project); Future archive(int id); // sets archivedAt = now Future delete(int id); } ``` ### `TimeEntriesRepository` File: `lib/features/entries/data/entries_repository.dart` ```dart abstract class TimeEntriesRepository { Stream> watchAll(); Stream> watchByProject(int projectId); Stream> watchByDateRange(DateTime from, DateTime to); Future getActiveEntry(); // end_time IS NULL Future create(TimeEntry entry); Future update(TimeEntry entry); Future delete(int id); } ``` ### `TagsRepository` File: `lib/features/entries/data/tags_repository.dart` ```dart abstract class TagsRepository { Stream> watchAll(); Future findOrCreate(String name); Future setTagsForEntry(int entryId, List tagNames); Future> getTagsForEntry(int entryId); } ``` ### `ReportsRepository` File: `lib/features/reports/data/reports_repository.dart` ```dart abstract class ReportsRepository { Future getTotalDuration(DateTime from, DateTime to, {int? projectId}); Future> getDurationByProject(DateTime from, DateTime to); Future> getDurationByWeekday(DateTime weekStart); Future> getDurationByDay(DateTime monthStart); } ``` ## Acceptance Criteria - [ ] Abstract interface + concrete `DriftXxxRepository` implementation for each - [ ] Riverpod provider for each concrete implementation - [ ] All DB access goes through DAOs — no raw SQL in repositories - [ ] Mapper extension methods convert `Drift row → domain model` - [ ] Unit tests for each repository method using in-memory Drift DB ## Files to create / modify - `lib/features/projects/data/projects_repository.dart` (replace stub) - `lib/features/projects/data/drift_projects_repository.dart` - `lib/features/entries/data/entries_repository.dart` (replace stub) - `lib/features/entries/data/drift_entries_repository.dart` - `lib/features/entries/data/tags_repository.dart` - `lib/features/entries/data/drift_tags_repository.dart` - `lib/features/reports/data/reports_repository.dart` (replace stub) - `lib/features/reports/data/drift_reports_repository.dart` - `test/features/*/` — unit tests for each ## Notes - Keep repositories free of Flutter/UI imports - Streams from Drift are reactive — repositories expose them directly to Riverpod providers