import 'package:drift/drift.dart'; import '../app_database.dart'; import '../tables.dart'; part 'mood_dao.g.dart'; // Joined result — entry + its activities class MoodEntryWithActivities { final MoodEntry entry; final List activities; final List tags; MoodEntryWithActivities({ required this.entry, required this.activities, required this.tags, }); } @DriftAccessor( tables: [MoodEntries, EntryActivities, Activities, EntryTags, Tags]) class MoodDao extends DatabaseAccessor with _$MoodDaoMixin { MoodDao(super.db); // ── Writes ────────────────────────────────────────────────────────────────── Future insertEntry(MoodEntriesCompanion entry) => into(moodEntries).insert(entry); Future insertEntryWithActivities({ required MoodEntriesCompanion entry, required List activityIds, required List tagIds, }) async { await transaction(() async { final entryId = await into(moodEntries).insert(entry); for (final actId in activityIds) { await into(entryActivities).insert( EntryActivitiesCompanion.insert(entryId: entryId, activityId: actId), ); } for (final tagId in tagIds) { await into(entryTags).insert( EntryTagsCompanion.insert(entryId: entryId, tagId: tagId), ); } }); } Future deleteEntry(int id) => (delete(moodEntries)..where((t) => t.id.equals(id))).go(); Future updateEntry(MoodEntriesCompanion entry) => (update(moodEntries)..where((t) => t.id.equals(entry.id.value))) .write(entry); // ── Reads ─────────────────────────────────────────────────────────────────── Stream> watchAllEntries() => (select(moodEntries)..orderBy([(t) => OrderingTerm.desc(t.timestamp)])) .watch(); Stream> watchEntriesForDay(DateTime day) { final start = DateTime(day.year, day.month, day.day); final end = start.add(const Duration(days: 1)); return (select(moodEntries) ..where((t) => t.timestamp.isBetweenValues(start, end)) ..orderBy([(t) => OrderingTerm.desc(t.timestamp)])) .watch(); } Future> getEntriesInRange(DateTime start, DateTime end) => (select(moodEntries) ..where((t) => t.timestamp.isBetweenValues(start, end)) ..orderBy([(t) => OrderingTerm.asc(t.timestamp)])) .get(); // Average mood per day — used by calendar heatmap Future> getDailyAverages( DateTime start, DateTime end) async { final entries = await getEntriesInRange(start, end); final Map> grouped = {}; for (final e in entries) { final day = DateTime(e.timestamp.year, e.timestamp.month, e.timestamp.day); grouped.putIfAbsent(day, () => []).add(e.moodLevel); } return grouped.map( (day, levels) => MapEntry(day, levels.reduce((a, b) => a + b) / levels.length), ); } }