169 lines
4.8 KiB
Dart
169 lines
4.8 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 'package:uuid/uuid.dart';
|
|
import '../services/cycle_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();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
Future<void> updateEntry(CycleEntry entry) async {
|
|
final box = Hive.box<CycleEntry>('cycle_entries');
|
|
await box.put(entry.id, entry);
|
|
_loadEntries();
|
|
}
|
|
|
|
Future<void> deleteEntry(String id) async {
|
|
final box = Hive.box<CycleEntry>('cycle_entries');
|
|
await box.delete(id);
|
|
_loadEntries();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
Future<void> clearEntries() async {
|
|
final box = Hive.box<CycleEntry>('cycle_entries');
|
|
await box.clear();
|
|
state = [];
|
|
}
|
|
|
|
Future<void> generateExampleData(String userId) async {
|
|
await clearEntries();
|
|
final box = Hive.box<CycleEntry>('cycle_entries');
|
|
final today = DateTime.now();
|
|
|
|
// Generate 3 past cycles (~28 days each)
|
|
DateTime cycleStart = today.subtract(const Duration(days: 84)); // 3 * 28
|
|
|
|
while (cycleStart.isBefore(today)) {
|
|
// Create Period (5 days)
|
|
for (int i = 0; i < 5; i++) {
|
|
final date = cycleStart.add(Duration(days: i));
|
|
if (date.isAfter(today)) break;
|
|
|
|
final isHeavy = i == 1 || i == 2;
|
|
final entry = CycleEntry(
|
|
id: const Uuid().v4(),
|
|
date: date,
|
|
isPeriodDay: true,
|
|
flowIntensity: isHeavy ? FlowIntensity.heavy : FlowIntensity.medium,
|
|
mood: i == 1 ? MoodLevel.sad : null,
|
|
crampIntensity: i == 0 ? 3 : null,
|
|
hasHeadache: i == 0,
|
|
createdAt: date,
|
|
updatedAt: date,
|
|
);
|
|
await box.put(entry.id, entry);
|
|
}
|
|
|
|
// Add random ovulation symptoms near day 14
|
|
final ovulationDay = cycleStart.add(const Duration(days: 14));
|
|
if (ovulationDay.isBefore(today)) {
|
|
final entry = CycleEntry(
|
|
id: const Uuid().v4(),
|
|
date: ovulationDay,
|
|
isPeriodDay: false,
|
|
energyLevel: 4, // High energy
|
|
mood: MoodLevel.veryHappy,
|
|
createdAt: ovulationDay,
|
|
updatedAt: ovulationDay,
|
|
);
|
|
await box.put(entry.id, entry);
|
|
}
|
|
|
|
cycleStart = cycleStart.add(const Duration(days: 28));
|
|
}
|
|
|
|
_loadEntries();
|
|
}
|
|
}
|
|
|
|
/// 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);
|
|
});
|