336 lines
6.9 KiB
Dart
336 lines
6.9 KiB
Dart
import 'package:hive/hive.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(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)
|
|
bool isPeriodDay;
|
|
|
|
@HiveField(3)
|
|
FlowIntensity? flowIntensity;
|
|
|
|
@HiveField(4)
|
|
MoodLevel? mood;
|
|
|
|
@HiveField(5)
|
|
int? energyLevel; // 1-5
|
|
|
|
@HiveField(6)
|
|
int? crampIntensity; // 1-5
|
|
|
|
@HiveField(7)
|
|
bool hasHeadache;
|
|
|
|
@HiveField(8)
|
|
bool hasBloating;
|
|
|
|
@HiveField(9)
|
|
bool hasBreastTenderness;
|
|
|
|
@HiveField(10)
|
|
bool hasFatigue;
|
|
|
|
@HiveField(11)
|
|
bool hasAcne;
|
|
|
|
@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)
|
|
bool hadExercise;
|
|
|
|
@HiveField(19)
|
|
bool hadIntimacy; // For married users only
|
|
|
|
@HiveField(20)
|
|
DateTime createdAt;
|
|
|
|
@HiveField(21)
|
|
DateTime updatedAt;
|
|
|
|
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.basalBodyTemperature,
|
|
this.cervicalMucus,
|
|
this.ovulationTestPositive,
|
|
this.notes,
|
|
this.sleepHours,
|
|
this.waterIntake,
|
|
this.hadExercise = false,
|
|
this.hadIntimacy = false,
|
|
required this.createdAt,
|
|
required this.updatedAt,
|
|
});
|
|
|
|
/// Check if any symptoms are logged
|
|
bool get hasSymptoms =>
|
|
hasHeadache ||
|
|
hasBloating ||
|
|
hasBreastTenderness ||
|
|
hasFatigue ||
|
|
hasAcne ||
|
|
(crampIntensity != null && crampIntensity! > 0);
|
|
|
|
/// Check if NFP data is logged
|
|
bool get hasNFPData =>
|
|
basalBodyTemperature != null ||
|
|
cervicalMucus != null ||
|
|
ovulationTestPositive != null;
|
|
|
|
/// Get symptom count
|
|
int get symptomCount {
|
|
int count = 0;
|
|
if (hasHeadache) count++;
|
|
if (hasBloating) count++;
|
|
if (hasBreastTenderness) count++;
|
|
if (hasFatigue) count++;
|
|
if (hasAcne) count++;
|
|
if (crampIntensity != null && crampIntensity! > 0) count++;
|
|
return count;
|
|
}
|
|
|
|
/// 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,
|
|
double? basalBodyTemperature,
|
|
CervicalMucusType? cervicalMucus,
|
|
bool? ovulationTestPositive,
|
|
String? notes,
|
|
int? sleepHours,
|
|
int? waterIntake,
|
|
bool? hadExercise,
|
|
bool? hadIntimacy,
|
|
DateTime? createdAt,
|
|
DateTime? updatedAt,
|
|
}) {
|
|
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,
|
|
basalBodyTemperature: basalBodyTemperature ?? this.basalBodyTemperature,
|
|
cervicalMucus: cervicalMucus ?? this.cervicalMucus,
|
|
ovulationTestPositive: ovulationTestPositive ?? this.ovulationTestPositive,
|
|
notes: notes ?? this.notes,
|
|
sleepHours: sleepHours ?? this.sleepHours,
|
|
waterIntake: waterIntake ?? this.waterIntake,
|
|
hadExercise: hadExercise ?? this.hadExercise,
|
|
hadIntimacy: hadIntimacy ?? this.hadIntimacy,
|
|
createdAt: createdAt ?? this.createdAt,
|
|
updatedAt: updatedAt ?? DateTime.now(),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 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.spotting:
|
|
return 'Spotting';
|
|
case FlowIntensity.light:
|
|
return 'Light';
|
|
case FlowIntensity.medium:
|
|
return 'Medium';
|
|
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 '🌙';
|
|
}
|
|
}
|
|
|
|
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';
|
|
}
|
|
}
|
|
}
|