Files
Tracker/lib/models/cycle_entry.dart

443 lines
10 KiB
Dart

import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import '../theme/app_theme.dart';
part 'cycle_entry.g.dart';
/// Mood levels for tracking
@HiveType(typeId: 3)
enum MoodLevel {
@HiveField(0)
verySad,
@HiveField(1)
sad,
@HiveField(2)
neutral,
@HiveField(3)
happy,
@HiveField(4)
veryHappy,
}
/// Flow intensity for period days
@HiveType(typeId: 4)
enum FlowIntensity {
@HiveField(4)
none, // No flow / Precautionary
@HiveField(0)
spotting,
@HiveField(1)
light,
@HiveField(2)
medium,
@HiveField(3)
heavy,
}
/// Cervical mucus type for NFP tracking
@HiveType(typeId: 5)
enum CervicalMucusType {
@HiveField(0)
dry,
@HiveField(1)
sticky,
@HiveField(2)
creamy,
@HiveField(3)
eggWhite,
@HiveField(4)
watery,
}
/// Cycle phase
@HiveType(typeId: 6)
enum CyclePhase {
@HiveField(0)
menstrual,
@HiveField(1)
follicular,
@HiveField(2)
ovulation,
@HiveField(3)
luteal,
}
/// Daily cycle entry
@HiveType(typeId: 7)
class CycleEntry extends HiveObject {
@HiveField(0)
String id;
@HiveField(1)
DateTime date;
@HiveField(2, defaultValue: false)
bool isPeriodDay;
@HiveField(3)
FlowIntensity? flowIntensity;
@HiveField(4)
MoodLevel? mood;
@HiveField(5)
int? energyLevel; // 1-5
@HiveField(6)
int? crampIntensity; // 1-5
@HiveField(7, defaultValue: false)
bool hasHeadache;
@HiveField(8, defaultValue: false)
bool hasBloating;
@HiveField(9, defaultValue: false)
bool hasBreastTenderness;
@HiveField(10, defaultValue: false)
bool hasFatigue;
@HiveField(11, defaultValue: false)
bool hasAcne;
@HiveField(22, defaultValue: false)
bool hasLowerBackPain;
@HiveField(23, defaultValue: false)
bool hasConstipation;
@HiveField(24, defaultValue: false)
bool hasDiarrhea;
@HiveField(25)
int? stressLevel; // 1-5
@HiveField(26, defaultValue: false)
bool hasInsomnia;
@HiveField(12)
double? basalBodyTemperature; // in Fahrenheit
@HiveField(13)
CervicalMucusType? cervicalMucus;
@HiveField(14)
bool? ovulationTestPositive;
@HiveField(15)
String? notes;
@HiveField(16)
int? sleepHours;
@HiveField(17)
int? waterIntake; // glasses
@HiveField(18, defaultValue: false)
bool hadExercise;
@HiveField(19, defaultValue: false)
bool hadIntimacy; // For married users only
@HiveField(20)
DateTime createdAt;
@HiveField(21)
DateTime updatedAt;
@HiveField(27)
List<String>? cravings;
@HiveField(28)
String? husbandNotes; // Separate notes for husband
@HiveField(29)
bool?
intimacyProtected; // null = no selection, true = protected, false = unprotected
@HiveField(30, defaultValue: false)
bool usedPantyliner;
@HiveField(31, defaultValue: 0)
int pantylinerCount;
@HiveField(32)
String? prayerRequest;
CycleEntry({
required this.id,
required this.date,
this.isPeriodDay = false,
this.flowIntensity,
this.mood,
this.energyLevel,
this.crampIntensity,
this.hasHeadache = false,
this.hasBloating = false,
this.hasBreastTenderness = false,
this.hasFatigue = false,
this.hasAcne = false,
this.hasLowerBackPain = false,
this.hasConstipation = false,
this.hasDiarrhea = false,
this.stressLevel,
this.hasInsomnia = false,
this.basalBodyTemperature,
this.cervicalMucus,
this.ovulationTestPositive,
this.notes,
this.cravings,
this.sleepHours,
this.waterIntake,
this.hadExercise = false,
this.hadIntimacy = false,
this.intimacyProtected,
required this.createdAt,
required this.updatedAt,
this.husbandNotes,
this.usedPantyliner = false,
this.pantylinerCount = 0,
this.prayerRequest,
});
List<bool> get _symptomsList => [
hasHeadache,
hasBloating,
hasBreastTenderness,
hasFatigue,
hasAcne,
hasLowerBackPain,
hasConstipation,
hasDiarrhea,
hasInsomnia,
(crampIntensity != null && crampIntensity! > 0),
(stressLevel != null && stressLevel! > 1),
];
/// Check if any symptoms are logged
bool get hasSymptoms => _symptomsList.contains(true);
/// Check if NFP data is logged
bool get hasNFPData =>
basalBodyTemperature != null ||
cervicalMucus != null ||
ovulationTestPositive != null;
/// Get symptom count
int get symptomCount => _symptomsList.where((s) => s).length;
// ... (omitted getters)
/// Copy with updated fields
CycleEntry copyWith({
String? id,
DateTime? date,
bool? isPeriodDay,
FlowIntensity? flowIntensity,
MoodLevel? mood,
int? energyLevel,
int? crampIntensity,
bool? hasHeadache,
bool? hasBloating,
bool? hasBreastTenderness,
bool? hasFatigue,
bool? hasAcne,
bool? hasLowerBackPain,
bool? hasConstipation,
bool? hasDiarrhea,
int? stressLevel,
bool? hasInsomnia,
double? basalBodyTemperature,
CervicalMucusType? cervicalMucus,
bool? ovulationTestPositive,
String? notes,
List<String>? cravings,
int? sleepHours,
int? waterIntake,
bool? hadExercise,
bool? hadIntimacy,
bool? intimacyProtected,
DateTime? createdAt,
DateTime? updatedAt,
String? husbandNotes,
bool? usedPantyliner,
int? pantylinerCount,
String? prayerRequest,
}) {
return CycleEntry(
id: id ?? this.id,
date: date ?? this.date,
isPeriodDay: isPeriodDay ?? this.isPeriodDay,
flowIntensity: flowIntensity ?? this.flowIntensity,
mood: mood ?? this.mood,
energyLevel: energyLevel ?? this.energyLevel,
crampIntensity: crampIntensity ?? this.crampIntensity,
hasHeadache: hasHeadache ?? this.hasHeadache,
hasBloating: hasBloating ?? this.hasBloating,
hasBreastTenderness: hasBreastTenderness ?? this.hasBreastTenderness,
hasFatigue: hasFatigue ?? this.hasFatigue,
hasAcne: hasAcne ?? this.hasAcne,
hasLowerBackPain: hasLowerBackPain ?? this.hasLowerBackPain,
hasConstipation: hasConstipation ?? this.hasConstipation,
hasDiarrhea: hasDiarrhea ?? this.hasDiarrhea,
stressLevel: stressLevel ?? this.stressLevel,
hasInsomnia: hasInsomnia ?? this.hasInsomnia,
basalBodyTemperature: basalBodyTemperature ?? this.basalBodyTemperature,
cervicalMucus: cervicalMucus ?? this.cervicalMucus,
ovulationTestPositive:
ovulationTestPositive ?? this.ovulationTestPositive,
notes: notes ?? this.notes,
cravings: cravings ?? this.cravings,
sleepHours: sleepHours ?? this.sleepHours,
waterIntake: waterIntake ?? this.waterIntake,
hadExercise: hadExercise ?? this.hadExercise,
hadIntimacy: hadIntimacy ?? this.hadIntimacy,
intimacyProtected: intimacyProtected ?? this.intimacyProtected,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? DateTime.now(),
husbandNotes: husbandNotes ?? this.husbandNotes,
usedPantyliner: usedPantyliner ?? this.usedPantyliner,
pantylinerCount: pantylinerCount ?? this.pantylinerCount,
prayerRequest: prayerRequest ?? this.prayerRequest,
);
}
}
/// Extension to get display string for enums
extension MoodLevelExtension on MoodLevel {
String get emoji {
switch (this) {
case MoodLevel.verySad:
return '😢';
case MoodLevel.sad:
return '😕';
case MoodLevel.neutral:
return '😐';
case MoodLevel.happy:
return '🙂';
case MoodLevel.veryHappy:
return '😄';
}
}
String get label {
switch (this) {
case MoodLevel.verySad:
return 'Very Sad';
case MoodLevel.sad:
return 'Sad';
case MoodLevel.neutral:
return 'Neutral';
case MoodLevel.happy:
return 'Happy';
case MoodLevel.veryHappy:
return 'Very Happy';
}
}
}
extension FlowIntensityExtension on FlowIntensity {
String get label {
switch (this) {
case FlowIntensity.none:
return 'No Flow';
case FlowIntensity.spotting:
return 'Spotting';
case FlowIntensity.light:
return 'Light';
case FlowIntensity.medium:
return 'Regular';
case FlowIntensity.heavy:
return 'Heavy';
}
}
}
extension CyclePhaseExtension on CyclePhase {
String get label {
switch (this) {
case CyclePhase.menstrual:
return 'Menstrual';
case CyclePhase.follicular:
return 'Follicular';
case CyclePhase.ovulation:
return 'Ovulation';
case CyclePhase.luteal:
return 'Luteal';
}
}
String get emoji {
switch (this) {
case CyclePhase.menstrual:
return '🩸';
case CyclePhase.follicular:
return '🌱';
case CyclePhase.ovulation:
return '🌸';
case CyclePhase.luteal:
return '🌙';
}
}
Color get color {
switch (this) {
case CyclePhase.menstrual:
return AppColors.menstrualPhase;
case CyclePhase.follicular:
return AppColors.follicularPhase;
case CyclePhase.ovulation:
return AppColors.ovulationPhase;
case CyclePhase.luteal:
return AppColors.lutealPhase;
}
}
List<Color> get gradientColors {
switch (this) {
case CyclePhase.menstrual:
return [AppColors.rose, AppColors.menstrualPhase, AppColors.blushPink];
case CyclePhase.follicular:
return [
AppColors.sageGreen,
AppColors.follicularPhase,
AppColors.sageGreen.withOpacity(0.7)
];
case CyclePhase.ovulation:
return [AppColors.lavender, AppColors.ovulationPhase, AppColors.rose];
case CyclePhase.luteal:
return [AppColors.lutealPhase, AppColors.lavender, AppColors.blushPink];
}
}
String get description {
switch (this) {
case CyclePhase.menstrual:
return 'A time for rest and reflection';
case CyclePhase.follicular:
return 'A time of renewal and energy';
case CyclePhase.ovulation:
return 'Peak fertility window';
case CyclePhase.luteal:
return 'A time for patience and self-care';
}
}
}