Files
Tracker/lib/providers/user_provider.dart

162 lines
4.4 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hive_flutter/hive_flutter.dart';
import '../models/user_profile.dart';
import '../models/cycle_entry.dart';
import '../services/cycle_service.dart';
import '../services/sync_service.dart';
/// Provider for the user profile
final userProfileProvider =
StateNotifierProvider<UserProfileNotifier, UserProfile?>((ref) {
return UserProfileNotifier();
});
/// Notifier for the user profile
class UserProfileNotifier extends StateNotifier<UserProfile?> {
UserProfileNotifier() : super(null) {
_loadProfile();
}
void _loadProfile() {
final box = Hive.box<UserProfile>('user_profile');
state = box.get('current_user');
}
Future<void> updateProfile(UserProfile profile) async {
final box = Hive.box<UserProfile>('user_profile');
await box.put('current_user', profile);
state = profile;
}
Future<void> updateThemeMode(AppThemeMode themeMode) async {
if (state != null) {
await updateProfile(state!.copyWith(themeMode: themeMode));
}
}
Future<void> updateAccentColor(String accentColor) async {
if (state != null) {
await updateProfile(state!.copyWith(accentColor: accentColor));
}
}
Future<void> updateRelationshipStatus(
RelationshipStatus relationshipStatus) async {
if (state != null) {
await updateProfile(
state!.copyWith(relationshipStatus: relationshipStatus));
}
}
Future<void> clearProfile() async {
final box = Hive.box<UserProfile>('user_profile');
await box.clear();
state = null;
}
}
/// Provider for cycle entries
final cycleEntriesProvider =
StateNotifierProvider<CycleEntriesNotifier, List<CycleEntry>>((ref) {
return CycleEntriesNotifier();
});
/// Notifier for cycle entries
class CycleEntriesNotifier extends StateNotifier<List<CycleEntry>> {
CycleEntriesNotifier() : super([]) {
_loadEntries();
syncData(); // Auto-sync on load
}
void _loadEntries() {
final box = Hive.box<CycleEntry>('cycle_entries');
state = box.values.toList()..sort((a, b) => b.date.compareTo(a.date));
}
Future<void> addEntry(CycleEntry entry) async {
final box = Hive.box<CycleEntry>('cycle_entries');
await box.put(entry.id, entry);
_loadEntries();
_push();
}
Future<void> updateEntry(CycleEntry entry) async {
final box = Hive.box<CycleEntry>('cycle_entries');
await box.put(entry.id, entry);
_loadEntries();
_push();
}
Future<void> deleteEntry(String id) async {
final box = Hive.box<CycleEntry>('cycle_entries');
await box.delete(id);
_loadEntries();
_push();
}
Future<void> deleteEntriesForMonth(int year, int month) async {
final box = Hive.box<CycleEntry>('cycle_entries');
final keysToDelete = <dynamic>[];
for (var entry in box.values) {
if (entry.date.year == year && entry.date.month == month) {
keysToDelete.add(entry.key);
}
}
await box.deleteAll(keysToDelete);
_loadEntries();
_push();
}
Future<void> clearEntries() async {
final box = Hive.box<CycleEntry>('cycle_entries');
await box.clear();
state = [];
_push();
}
// Sync Logic
Future<void> syncData() async {
await _pull();
// After pull, we might want to push any local changes not in remote?
// For now, simpler consistency: Pull then Push current state?
// Or just Pull. Push happens on edit.
// Let's just Pull.
}
Future<void> _push() async {
final userBox = Hive.box<UserProfile>('user_profile');
final user = userBox.get('current_user');
if (user != null) {
await SyncService().pushSyncData(user.id, state);
}
}
Future<void> _pull() async {
final userBox = Hive.box<UserProfile>('user_profile');
final user = userBox.get('current_user');
if (user == null) return;
final remoteEntries = await SyncService().pullSyncData(user.id);
if (remoteEntries.isNotEmpty) {
final box = Hive.box<CycleEntry>('cycle_entries');
// Simple merge: Remote wins or Union?
// Union: Upsert all.
for (var entry in remoteEntries) {
await box.put(entry.id, entry);
}
_loadEntries();
}
}
// Example data generation removed
}
/// Computed provider for current cycle info
final currentCycleInfoProvider = Provider((ref) {
final user = ref.watch(userProfileProvider);
final entries = ref.watch(cycleEntriesProvider);
return CycleService.calculateCycleInfo(user, entries);
});