Your commit message here

This commit is contained in:
2025-12-19 22:47:27 -06:00
parent 5d746d694e
commit 464692ce56
21 changed files with 3018 additions and 0 deletions

View File

@@ -1,5 +1,14 @@
<<<<<<< HEAD
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
=======
#Fri Dec 19 21:26:00 CST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
>>>>>>> 6742220 (Your commit message here)

View File

@@ -24,6 +24,10 @@ void main() async {
Hive.registerAdapter(CervicalMucusTypeAdapter()); Hive.registerAdapter(CervicalMucusTypeAdapter());
Hive.registerAdapter(CyclePhaseAdapter()); Hive.registerAdapter(CyclePhaseAdapter());
Hive.registerAdapter(UserRoleAdapter()); Hive.registerAdapter(UserRoleAdapter());
<<<<<<< HEAD
=======
Hive.registerAdapter(BibleTranslationAdapter());
>>>>>>> 6742220 (Your commit message here)
// Open boxes // Open boxes
await Hive.openBox<UserProfile>('user_profile'); await Hive.openBox<UserProfile>('user_profile');

View File

@@ -1,4 +1,9 @@
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
<<<<<<< HEAD
=======
import 'package:flutter/material.dart';
import '../theme/app_theme.dart';
>>>>>>> 6742220 (Your commit message here)
part 'cycle_entry.g.dart'; part 'cycle_entry.g.dart';
@@ -111,6 +116,24 @@ class CycleEntry extends HiveObject {
@HiveField(11) @HiveField(11)
bool hasAcne; bool hasAcne;
<<<<<<< HEAD
=======
@HiveField(22)
bool hasLowerBackPain;
@HiveField(23)
bool hasConstipation;
@HiveField(24)
bool hasDiarrhea;
@HiveField(25)
int? stressLevel; // 1-5
@HiveField(26)
bool hasInsomnia;
>>>>>>> 6742220 (Your commit message here)
@HiveField(12) @HiveField(12)
double? basalBodyTemperature; // in Fahrenheit double? basalBodyTemperature; // in Fahrenheit
@@ -154,6 +177,14 @@ class CycleEntry extends HiveObject {
this.hasBreastTenderness = false, this.hasBreastTenderness = false,
this.hasFatigue = false, this.hasFatigue = false,
this.hasAcne = false, this.hasAcne = false,
<<<<<<< HEAD
=======
this.hasLowerBackPain = false,
this.hasConstipation = false,
this.hasDiarrhea = false,
this.stressLevel,
this.hasInsomnia = false,
>>>>>>> 6742220 (Your commit message here)
this.basalBodyTemperature, this.basalBodyTemperature,
this.cervicalMucus, this.cervicalMucus,
this.ovulationTestPositive, this.ovulationTestPositive,
@@ -173,7 +204,16 @@ class CycleEntry extends HiveObject {
hasBreastTenderness || hasBreastTenderness ||
hasFatigue || hasFatigue ||
hasAcne || hasAcne ||
<<<<<<< HEAD
(crampIntensity != null && crampIntensity! > 0); (crampIntensity != null && crampIntensity! > 0);
=======
hasLowerBackPain ||
hasConstipation ||
hasDiarrhea ||
hasInsomnia ||
(crampIntensity != null && crampIntensity! > 0) ||
(stressLevel != null && stressLevel! > 1);
>>>>>>> 6742220 (Your commit message here)
/// Check if NFP data is logged /// Check if NFP data is logged
bool get hasNFPData => bool get hasNFPData =>
@@ -189,7 +229,16 @@ class CycleEntry extends HiveObject {
if (hasBreastTenderness) count++; if (hasBreastTenderness) count++;
if (hasFatigue) count++; if (hasFatigue) count++;
if (hasAcne) count++; if (hasAcne) count++;
<<<<<<< HEAD
if (crampIntensity != null && crampIntensity! > 0) count++; if (crampIntensity != null && crampIntensity! > 0) count++;
=======
if (hasLowerBackPain) count++;
if (hasConstipation) count++;
if (hasDiarrhea) count++;
if (hasInsomnia) count++;
if (crampIntensity != null && crampIntensity! > 0) count++;
if (stressLevel != null && stressLevel! > 1) count++;
>>>>>>> 6742220 (Your commit message here)
return count; return count;
} }
@@ -207,6 +256,14 @@ class CycleEntry extends HiveObject {
bool? hasBreastTenderness, bool? hasBreastTenderness,
bool? hasFatigue, bool? hasFatigue,
bool? hasAcne, bool? hasAcne,
<<<<<<< HEAD
=======
bool? hasLowerBackPain,
bool? hasConstipation,
bool? hasDiarrhea,
int? stressLevel,
bool? hasInsomnia,
>>>>>>> 6742220 (Your commit message here)
double? basalBodyTemperature, double? basalBodyTemperature,
CervicalMucusType? cervicalMucus, CervicalMucusType? cervicalMucus,
bool? ovulationTestPositive, bool? ovulationTestPositive,
@@ -231,6 +288,14 @@ class CycleEntry extends HiveObject {
hasBreastTenderness: hasBreastTenderness ?? this.hasBreastTenderness, hasBreastTenderness: hasBreastTenderness ?? this.hasBreastTenderness,
hasFatigue: hasFatigue ?? this.hasFatigue, hasFatigue: hasFatigue ?? this.hasFatigue,
hasAcne: hasAcne ?? this.hasAcne, hasAcne: hasAcne ?? this.hasAcne,
<<<<<<< HEAD
=======
hasLowerBackPain: hasLowerBackPain ?? this.hasLowerBackPain,
hasConstipation: hasConstipation ?? this.hasConstipation,
hasDiarrhea: hasDiarrhea ?? this.hasDiarrhea,
stressLevel: stressLevel ?? this.stressLevel,
hasInsomnia: hasInsomnia ?? this.hasInsomnia,
>>>>>>> 6742220 (Your commit message here)
basalBodyTemperature: basalBodyTemperature ?? this.basalBodyTemperature, basalBodyTemperature: basalBodyTemperature ?? this.basalBodyTemperature,
cervicalMucus: cervicalMucus ?? this.cervicalMucus, cervicalMucus: cervicalMucus ?? this.cervicalMucus,
ovulationTestPositive: ovulationTestPositive ?? this.ovulationTestPositive, ovulationTestPositive: ovulationTestPositive ?? this.ovulationTestPositive,
@@ -319,6 +384,35 @@ extension CyclePhaseExtension on CyclePhase {
return '🌙'; return '🌙';
} }
} }
<<<<<<< HEAD
=======
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];
}
}
>>>>>>> 6742220 (Your commit message here)
String get description { String get description {
switch (this) { switch (this) {

View File

@@ -29,6 +29,14 @@ class CycleEntryAdapter extends TypeAdapter<CycleEntry> {
hasBreastTenderness: fields[9] as bool, hasBreastTenderness: fields[9] as bool,
hasFatigue: fields[10] as bool, hasFatigue: fields[10] as bool,
hasAcne: fields[11] as bool, hasAcne: fields[11] as bool,
<<<<<<< HEAD
=======
hasLowerBackPain: fields[22] as bool,
hasConstipation: fields[23] as bool,
hasDiarrhea: fields[24] as bool,
stressLevel: fields[25] as int?,
hasInsomnia: fields[26] as bool,
>>>>>>> 6742220 (Your commit message here)
basalBodyTemperature: fields[12] as double?, basalBodyTemperature: fields[12] as double?,
cervicalMucus: fields[13] as CervicalMucusType?, cervicalMucus: fields[13] as CervicalMucusType?,
ovulationTestPositive: fields[14] as bool?, ovulationTestPositive: fields[14] as bool?,
@@ -45,7 +53,11 @@ class CycleEntryAdapter extends TypeAdapter<CycleEntry> {
@override @override
void write(BinaryWriter writer, CycleEntry obj) { void write(BinaryWriter writer, CycleEntry obj) {
writer writer
<<<<<<< HEAD
..writeByte(22) ..writeByte(22)
=======
..writeByte(27)
>>>>>>> 6742220 (Your commit message here)
..writeByte(0) ..writeByte(0)
..write(obj.id) ..write(obj.id)
..writeByte(1) ..writeByte(1)
@@ -70,6 +82,19 @@ class CycleEntryAdapter extends TypeAdapter<CycleEntry> {
..write(obj.hasFatigue) ..write(obj.hasFatigue)
..writeByte(11) ..writeByte(11)
..write(obj.hasAcne) ..write(obj.hasAcne)
<<<<<<< HEAD
=======
..writeByte(22)
..write(obj.hasLowerBackPain)
..writeByte(23)
..write(obj.hasConstipation)
..writeByte(24)
..write(obj.hasDiarrhea)
..writeByte(25)
..write(obj.stressLevel)
..writeByte(26)
..write(obj.hasInsomnia)
>>>>>>> 6742220 (Your commit message here)
..writeByte(12) ..writeByte(12)
..write(obj.basalBodyTemperature) ..write(obj.basalBodyTemperature)
..writeByte(13) ..writeByte(13)

View File

@@ -1,18 +1,37 @@
<<<<<<< HEAD
/// Scripture model for daily verses and devotionals /// Scripture model for daily verses and devotionals
class Scripture { class Scripture {
final String verse; final String verse;
=======
import 'user_profile.dart';
/// Scripture model for daily verses and devotionals
class Scripture {
final Map<BibleTranslation, String> verses;
>>>>>>> 6742220 (Your commit message here)
final String reference; final String reference;
final String? reflection; final String? reflection;
final List<String> applicablePhases; final List<String> applicablePhases;
final List<String> applicableContexts; final List<String> applicableContexts;
const Scripture({ const Scripture({
<<<<<<< HEAD
required this.verse, required this.verse,
=======
required this.verses,
>>>>>>> 6742220 (Your commit message here)
required this.reference, required this.reference,
this.reflection, this.reflection,
this.applicablePhases = const [], this.applicablePhases = const [],
this.applicableContexts = const [], this.applicableContexts = const [],
}); });
<<<<<<< HEAD
=======
String getVerse(BibleTranslation translation) {
return verses[translation] ?? verses[BibleTranslation.esv] ?? verses.values.first;
}
>>>>>>> 6742220 (Your commit message here)
} }
/// Pre-defined scriptures for the app /// Pre-defined scriptures for the app
@@ -20,17 +39,38 @@ class ScriptureDatabase {
/// Scriptures for menstrual phase (rest, comfort) /// Scriptures for menstrual phase (rest, comfort)
static const List<Scripture> menstrualScriptures = [ static const List<Scripture> menstrualScriptures = [
Scripture( Scripture(
<<<<<<< HEAD
verse: "Come to me, all you who are weary and burdened, and I will give you rest.", verse: "Come to me, all you who are weary and burdened, and I will give you rest.",
=======
verses: {
BibleTranslation.esv: "Come to me, all who labor and are heavy laden, and I will give you rest.",
BibleTranslation.niv: "Come to me, all you who are weary and burdened, and I will give you rest.",
BibleTranslation.nkjv: "Come to me, all you who labor and are heavy laden, and I will give you rest.",
BibleTranslation.nlt: "Come to me, all of you who are weary and carry heavy burdens, and I will give you rest.",
BibleTranslation.nasb: "Come to Me, all who are weary and burdened, and I will give you rest.",
BibleTranslation.kjv: "Come unto me, all ye that labour and are heavy laden, and I will give you rest.",
},
>>>>>>> 6742220 (Your commit message here)
reference: "Matthew 11:28", reference: "Matthew 11:28",
reflection: "Your body is doing important work. Rest is not weakness—it's wisdom.", reflection: "Your body is doing important work. Rest is not weakness—it's wisdom.",
applicablePhases: ['menstrual'], applicablePhases: ['menstrual'],
), ),
Scripture( Scripture(
<<<<<<< HEAD
verse: "He gives strength to the weary and increases the power of the weak.", verse: "He gives strength to the weary and increases the power of the weak.",
=======
verses: {
BibleTranslation.esv: "He gives power to the faint, and to him who has no might he increases strength.",
BibleTranslation.niv: "He gives strength to the weary and increases the power of the weak.",
BibleTranslation.nkjv: "He gives power to the weak, and to those who have no might He increases strength.",
BibleTranslation.nasb: "He gives strength to the weary, and to the one who lacks might He increases power.",
},
>>>>>>> 6742220 (Your commit message here)
reference: "Isaiah 40:29", reference: "Isaiah 40:29",
applicablePhases: ['menstrual'], applicablePhases: ['menstrual'],
), ),
Scripture( Scripture(
<<<<<<< HEAD
verse: "The Lord is my shepherd; I shall not want. He makes me lie down in green pastures.", verse: "The Lord is my shepherd; I shall not want. He makes me lie down in green pastures.",
reference: "Psalm 23:1-2", reference: "Psalm 23:1-2",
applicablePhases: ['menstrual'], applicablePhases: ['menstrual'],
@@ -46,22 +86,50 @@ class ScriptureDatabase {
reference: "2 Corinthians 12:9", reference: "2 Corinthians 12:9",
applicablePhases: ['menstrual'], applicablePhases: ['menstrual'],
), ),
=======
verses: {
BibleTranslation.esv: "The LORD is my shepherd; I shall not want. He makes me lie down in green pastures.",
BibleTranslation.niv: "The LORD is my shepherd, I lack nothing. He makes me lie down in green pastures.",
BibleTranslation.nkjv: "The LORD is my shepherd; I shall not want. He makes me to lie down in green pastures.",
},
reference: "Psalm 23:1-2",
applicablePhases: ['menstrual'],
),
>>>>>>> 6742220 (Your commit message here)
]; ];
/// Scriptures for follicular phase (renewal, strength) /// Scriptures for follicular phase (renewal, strength)
static const List<Scripture> follicularScriptures = [ static const List<Scripture> follicularScriptures = [
Scripture( Scripture(
<<<<<<< HEAD
verse: "She is clothed with strength and dignity; she can laugh at the days to come.", verse: "She is clothed with strength and dignity; she can laugh at the days to come.",
=======
verses: {
BibleTranslation.esv: "Strength and dignity are her clothing, and she laughs at the time to come.",
BibleTranslation.niv: "She is clothed with strength and dignity; she can laugh at the days to come.",
BibleTranslation.nkjv: "Strength and honor are her clothing; she shall rejoice in time to come.",
BibleTranslation.nlt: "She is clothed with strength and dignity, and she laughs without fear of the future.",
},
>>>>>>> 6742220 (Your commit message here)
reference: "Proverbs 31:25", reference: "Proverbs 31:25",
reflection: "You're entering a season of renewed energy. Use it for His glory.", reflection: "You're entering a season of renewed energy. Use it for His glory.",
applicablePhases: ['follicular'], applicablePhases: ['follicular'],
), ),
Scripture( Scripture(
<<<<<<< HEAD
verse: "I can do all this through him who gives me strength.", verse: "I can do all this through him who gives me strength.",
=======
verses: {
BibleTranslation.esv: "I can do all things through him who strengthens me.",
BibleTranslation.niv: "I can do all this through him who gives me strength.",
BibleTranslation.nkjv: "I can do all things through Christ who strengthens me.",
},
>>>>>>> 6742220 (Your commit message here)
reference: "Philippians 4:13", reference: "Philippians 4:13",
applicablePhases: ['follicular'], applicablePhases: ['follicular'],
), ),
Scripture( Scripture(
<<<<<<< HEAD
verse: "But those who hope in the Lord will renew their strength. They will soar on wings like eagles.", verse: "But those who hope in the Lord will renew their strength. They will soar on wings like eagles.",
reference: "Isaiah 40:31", reference: "Isaiah 40:31",
applicablePhases: ['follicular'], applicablePhases: ['follicular'],
@@ -76,17 +144,35 @@ class ScriptureDatabase {
reference: "Zephaniah 3:17", reference: "Zephaniah 3:17",
applicablePhases: ['follicular'], applicablePhases: ['follicular'],
), ),
=======
verses: {
BibleTranslation.esv: "but they who wait for the LORD shall renew their strength; they shall mount up with wings like eagles.",
BibleTranslation.niv: "but those who hope in the LORD will renew their strength. They will soar on wings like eagles.",
},
reference: "Isaiah 40:31",
applicablePhases: ['follicular'],
),
>>>>>>> 6742220 (Your commit message here)
]; ];
/// Scriptures for ovulation phase (creation, beauty) /// Scriptures for ovulation phase (creation, beauty)
static const List<Scripture> ovulationScriptures = [ static const List<Scripture> ovulationScriptures = [
Scripture( Scripture(
<<<<<<< HEAD
verse: "For you created my inmost being; you knit me together in my mother's womb. I praise you because I am fearfully and wonderfully made.", verse: "For you created my inmost being; you knit me together in my mother's womb. I praise you because I am fearfully and wonderfully made.",
=======
verses: {
BibleTranslation.esv: "For you formed my inmost parts; you knitted me together in my mother's womb. I praise you, for I am fearfully and wonderfully made.",
BibleTranslation.niv: "For you created my inmost being; you knit me together in my mothers womb. I praise you because I am fearfully and wonderfully made.",
BibleTranslation.nkjv: "For You formed my inward parts; You covered me in my mothers womb. I will praise You, for I am fearfully and wonderfully made.",
},
>>>>>>> 6742220 (Your commit message here)
reference: "Psalm 139:13-14", reference: "Psalm 139:13-14",
reflection: "Your body reflects the incredible creativity of God.", reflection: "Your body reflects the incredible creativity of God.",
applicablePhases: ['ovulation'], applicablePhases: ['ovulation'],
), ),
Scripture( Scripture(
<<<<<<< HEAD
verse: "Children are a heritage from the Lord, offspring a reward from him.", verse: "Children are a heritage from the Lord, offspring a reward from him.",
reference: "Psalm 127:3", reference: "Psalm 127:3",
applicablePhases: ['ovulation'], applicablePhases: ['ovulation'],
@@ -101,22 +187,48 @@ class ScriptureDatabase {
reference: "James 1:17", reference: "James 1:17",
applicablePhases: ['ovulation'], applicablePhases: ['ovulation'],
), ),
=======
verses: {
BibleTranslation.esv: "Behold, children are a heritage from the LORD, the fruit of the womb a reward.",
BibleTranslation.niv: "Children are a heritage from the LORD, offspring a reward from him.",
BibleTranslation.nkjv: "Behold, children are a heritage from the LORD, the fruit of the womb is a reward.",
},
reference: "Psalm 127:3",
applicablePhases: ['ovulation'],
),
>>>>>>> 6742220 (Your commit message here)
]; ];
/// Scriptures for luteal phase / TWW (patience, trust) /// Scriptures for luteal phase / TWW (patience, trust)
static const List<Scripture> lutealScriptures = [ static const List<Scripture> lutealScriptures = [
Scripture( Scripture(
<<<<<<< HEAD
verse: "For I know the plans I have for you, declares the Lord, plans to prosper you and not to harm you, plans to give you hope and a future.", verse: "For I know the plans I have for you, declares the Lord, plans to prosper you and not to harm you, plans to give you hope and a future.",
=======
verses: {
BibleTranslation.esv: "For I know the plans I have for you, declares the LORD, plans for welfare and not for evil, to give you a future and a hope.",
BibleTranslation.niv: "For I know the plans I have for you,” declares the LORD, “plans to prosper you and not to harm you, plans to give you hope and a future.",
BibleTranslation.nkjv: "For I know the thoughts that I think toward you, says the LORD, thoughts of peace and not of evil, to give you a future and a hope.",
},
>>>>>>> 6742220 (Your commit message here)
reference: "Jeremiah 29:11", reference: "Jeremiah 29:11",
reflection: "Whatever this season holds, God's plans for you are good.", reflection: "Whatever this season holds, God's plans for you are good.",
applicablePhases: ['luteal'], applicablePhases: ['luteal'],
), ),
Scripture( Scripture(
<<<<<<< HEAD
verse: "Do not be anxious about anything, but in every situation, by prayer and petition, with thanksgiving, present your requests to God.", verse: "Do not be anxious about anything, but in every situation, by prayer and petition, with thanksgiving, present your requests to God.",
=======
verses: {
BibleTranslation.esv: "do not be anxious about anything, but in everything by prayer and supplication with thanksgiving let your requests be made known to God.",
BibleTranslation.niv: "Do not be anxious about anything, but in every situation, by prayer and petition, with thanksgiving, present your requests to God.",
},
>>>>>>> 6742220 (Your commit message here)
reference: "Philippians 4:6", reference: "Philippians 4:6",
applicablePhases: ['luteal'], applicablePhases: ['luteal'],
), ),
Scripture( Scripture(
<<<<<<< HEAD
verse: "Trust in the Lord with all your heart and lean not on your own understanding.", verse: "Trust in the Lord with all your heart and lean not on your own understanding.",
reference: "Proverbs 3:5", reference: "Proverbs 3:5",
applicablePhases: ['luteal'], applicablePhases: ['luteal'],
@@ -136,16 +248,33 @@ class ScriptureDatabase {
reference: "Psalm 27:14", reference: "Psalm 27:14",
applicablePhases: ['luteal'], applicablePhases: ['luteal'],
), ),
=======
verses: {
BibleTranslation.esv: "Trust in the LORD with all your heart, and do not lean on your own understanding.",
BibleTranslation.niv: "Trust in the LORD with all your heart and lean not on your own understanding.",
},
reference: "Proverbs 3:5",
applicablePhases: ['luteal'],
),
>>>>>>> 6742220 (Your commit message here)
]; ];
/// Scriptures for husbands /// Scriptures for husbands
static const List<Scripture> husbandScriptures = [ static const List<Scripture> husbandScriptures = [
Scripture( Scripture(
<<<<<<< HEAD
verse: "Husbands, love your wives, just as Christ loved the church and gave himself up for her.", verse: "Husbands, love your wives, just as Christ loved the church and gave himself up for her.",
=======
verses: {
BibleTranslation.esv: "Husbands, love your wives, as Christ loved the church and gave himself up for her.",
BibleTranslation.niv: "Husbands, love your wives, just as Christ loved the church and gave himself up for her.",
},
>>>>>>> 6742220 (Your commit message here)
reference: "Ephesians 5:25", reference: "Ephesians 5:25",
reflection: "Love sacrificially—putting her needs before your own.", reflection: "Love sacrificially—putting her needs before your own.",
), ),
Scripture( Scripture(
<<<<<<< HEAD
verse: "Husbands, in the same way be considerate as you live with your wives, and treat them with respect.", verse: "Husbands, in the same way be considerate as you live with your wives, and treat them with respect.",
reference: "1 Peter 3:7", reference: "1 Peter 3:7",
), ),
@@ -169,11 +298,20 @@ class ScriptureDatabase {
verse: "He who finds a wife finds what is good and receives favor from the Lord.", verse: "He who finds a wife finds what is good and receives favor from the Lord.",
reference: "Proverbs 18:22", reference: "Proverbs 18:22",
), ),
=======
verses: {
BibleTranslation.esv: "Likewise, husbands, live with your wives in an understanding way, showing honor to the woman.",
BibleTranslation.niv: "Husbands, in the same way be considerate as you live with your wives, and treat them with respect.",
},
reference: "1 Peter 3:7",
),
>>>>>>> 6742220 (Your commit message here)
]; ];
/// General womanhood scriptures /// General womanhood scriptures
static const List<Scripture> womanhoodScriptures = [ static const List<Scripture> womanhoodScriptures = [
Scripture( Scripture(
<<<<<<< HEAD
verse: "Charm is deceptive, and beauty is fleeting; but a woman who fears the Lord is to be praised.", verse: "Charm is deceptive, and beauty is fleeting; but a woman who fears the Lord is to be praised.",
reference: "Proverbs 31:30", reference: "Proverbs 31:30",
), ),
@@ -191,6 +329,102 @@ class ScriptureDatabase {
), ),
]; ];
=======
verses: {
BibleTranslation.esv: "Charm is deceitful, and beauty is vain, but a woman who fears the LORD is to be praised.",
BibleTranslation.niv: "Charm is deceptive, and beauty is fleeting; but a woman who fears the LORD is to be praised.",
},
reference: "Proverbs 31:30",
),
Scripture(
verses: {
BibleTranslation.esv: "She opens her mouth with wisdom, and the teaching of kindness is on her tongue.",
BibleTranslation.niv: "She opens her mouth with wisdom, and the teaching of kindness is on her tongue.",
},
reference: "Proverbs 31:26",
),
];
/// Scriptures for specific needs (contextual)
static const Map<String, List<Scripture>> contextualScriptures = {
'pain': [
Scripture(
verses: {
BibleTranslation.esv: "The LORD is near to the brokenhearted and saves the crushed in spirit.",
BibleTranslation.niv: "The LORD is close to the brokenhearted and saves those who are crushed in spirit.",
},
reference: "Psalm 34:18",
reflection: "He sees your pain and draws near to you in your discomfort.",
),
Scripture(
verses: {
BibleTranslation.esv: "Cast your burden on the LORD, and he will sustain you.",
BibleTranslation.niv: "Cast your cares on the LORD and he will sustain you.",
},
reference: "Psalm 55:22",
),
],
'fatigue': [
Scripture(
verses: {
BibleTranslation.esv: "He gives power to the faint, and to him who has no might he increases strength.",
BibleTranslation.niv: "He gives strength to the weary and increases the power of the weak.",
},
reference: "Isaiah 40:29",
),
Scripture(
verses: {
BibleTranslation.esv: "My grace is sufficient for you, for my power is made perfect in weakness.",
BibleTranslation.niv: "My grace is sufficient for you, for my power is made perfect in weakness.",
},
reference: "2 Corinthians 12:9",
),
],
'anxiety': [
Scripture(
verses: {
BibleTranslation.esv: "When the cares of my heart are many, your consolations cheer my soul.",
BibleTranslation.niv: "When anxiety was great within me, your consolation brought me joy.",
},
reference: "Psalm 94:19",
),
Scripture(
verses: {
BibleTranslation.esv: "Peace I leave with you; my peace I give to you. Not as the world gives do I give to you. Let not your hearts be troubled, neither let them be afraid.",
BibleTranslation.niv: "Peace I leave with you; my peace I give to you. I do not give to you as the world gives. Do not let your hearts be troubled and do not be afraid.",
},
reference: "John 14:27",
),
],
'joy': [
Scripture(
verses: {
BibleTranslation.esv: "The LORD is my strength and my shield; in him my heart trusts, and I am helped; my heart exults, and with my song I give thanks to him.",
BibleTranslation.niv: "The LORD is my strength and my shield; my heart trusts in him, and he helps me. My heart leaps for joy, and with my song I praise him.",
},
reference: "Psalm 28:7",
),
],
};
/// Get recommended scripture based on entry
static Scripture? getRecommendedScripture(CycleEntry entry) {
if (entry.mood == MoodLevel.verySad || entry.mood == MoodLevel.sad || (entry.stressLevel != null && entry.stressLevel! > 3)) {
return contextualScriptures['anxiety']![DateTime.now().day % contextualScriptures['anxiety']!.length];
}
if ((entry.crampIntensity != null && entry.crampIntensity! >= 3) || entry.hasHeadache || entry.hasLowerBackPain) {
return contextualScriptures['pain']![DateTime.now().day % contextualScriptures['pain']!.length];
}
if (entry.hasFatigue || entry.hasInsomnia || (entry.energyLevel != null && entry.energyLevel! <= 2)) {
return contextualScriptures['fatigue']![DateTime.now().day % contextualScriptures['fatigue']!.length];
}
if (entry.mood == MoodLevel.veryHappy) {
return contextualScriptures['joy']![DateTime.now().day % contextualScriptures['joy']!.length];
}
return null;
}
>>>>>>> 6742220 (Your commit message here)
/// Get scripture for current phase /// Get scripture for current phase
static Scripture getScriptureForPhase(String phase) { static Scripture getScriptureForPhase(String phase) {
final List<Scripture> scriptures; final List<Scripture> scriptures;

View File

@@ -28,6 +28,25 @@ enum FertilityGoal {
justTracking, justTracking,
} }
<<<<<<< HEAD
=======
@HiveType(typeId: 9)
enum BibleTranslation {
@HiveField(0)
esv,
@HiveField(1)
niv,
@HiveField(2)
nkjv,
@HiveField(3)
nlt,
@HiveField(4)
nasb,
@HiveField(5)
kjv,
}
>>>>>>> 6742220 (Your commit message here)
/// User profile model /// User profile model
@HiveType(typeId: 2) @HiveType(typeId: 2)
class UserProfile extends HiveObject { class UserProfile extends HiveObject {
@@ -75,6 +94,12 @@ class UserProfile extends HiveObject {
@HiveField(15, defaultValue: false) @HiveField(15, defaultValue: false)
bool isIrregularCycle; bool isIrregularCycle;
<<<<<<< HEAD
=======
@HiveField(16, defaultValue: BibleTranslation.esv)
BibleTranslation bibleTranslation;
>>>>>>> 6742220 (Your commit message here)
UserProfile({ UserProfile({
required this.id, required this.id,
@@ -90,9 +115,15 @@ class UserProfile extends HiveObject {
required this.createdAt, required this.createdAt,
required this.updatedAt, required this.updatedAt,
this.partnerName, this.partnerName,
<<<<<<< HEAD
this.role = UserRole.wife, this.role = UserRole.wife,
this.isIrregularCycle = false, this.isIrregularCycle = false,
=======
this.role = UserRole.wife,
this.isIrregularCycle = false,
this.bibleTranslation = BibleTranslation.esv,
>>>>>>> 6742220 (Your commit message here)
}); });
/// Check if user is married /// Check if user is married
@@ -129,9 +160,15 @@ class UserProfile extends HiveObject {
DateTime? createdAt, DateTime? createdAt,
DateTime? updatedAt, DateTime? updatedAt,
String? partnerName, String? partnerName,
<<<<<<< HEAD
UserRole? role, UserRole? role,
bool? isIrregularCycle, bool? isIrregularCycle,
=======
UserRole? role,
bool? isIrregularCycle,
BibleTranslation? bibleTranslation,
>>>>>>> 6742220 (Your commit message here)
}) { }) {
return UserProfile( return UserProfile(
id: id ?? this.id, id: id ?? this.id,
@@ -147,13 +184,35 @@ class UserProfile extends HiveObject {
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? DateTime.now(), updatedAt: updatedAt ?? DateTime.now(),
partnerName: partnerName ?? this.partnerName, partnerName: partnerName ?? this.partnerName,
<<<<<<< HEAD
role: role ?? this.role, role: role ?? this.role,
isIrregularCycle: isIrregularCycle ?? this.isIrregularCycle, isIrregularCycle: isIrregularCycle ?? this.isIrregularCycle,
=======
role: role ?? this.role,
isIrregularCycle: isIrregularCycle ?? this.isIrregularCycle,
bibleTranslation: bibleTranslation ?? this.bibleTranslation,
>>>>>>> 6742220 (Your commit message here)
); );
} }
} }
<<<<<<< HEAD
=======
extension BibleTranslationExtension on BibleTranslation {
String get label {
switch (this) {
case BibleTranslation.esv: return 'ESV';
case BibleTranslation.niv: return 'NIV';
case BibleTranslation.nkjv: return 'NKJV';
case BibleTranslation.nlt: return 'NLT';
case BibleTranslation.nasb: return 'NASB';
case BibleTranslation.kjv: return 'KJV';
}
}
}
>>>>>>> 6742220 (Your commit message here)
@HiveType(typeId: 8) @HiveType(typeId: 8)
enum UserRole { enum UserRole {
@HiveField(0) @HiveField(0)

View File

@@ -32,13 +32,23 @@ class UserProfileAdapter extends TypeAdapter<UserProfile> {
partnerName: fields[12] as String?, partnerName: fields[12] as String?,
role: fields[14] == null ? UserRole.wife : fields[14] as UserRole, role: fields[14] == null ? UserRole.wife : fields[14] as UserRole,
isIrregularCycle: fields[15] == null ? false : fields[15] as bool, isIrregularCycle: fields[15] == null ? false : fields[15] as bool,
<<<<<<< HEAD
=======
bibleTranslation: fields[16] == null
? BibleTranslation.esv
: fields[16] as BibleTranslation,
>>>>>>> 6742220 (Your commit message here)
); );
} }
@override @override
void write(BinaryWriter writer, UserProfile obj) { void write(BinaryWriter writer, UserProfile obj) {
writer writer
<<<<<<< HEAD
..writeByte(15) ..writeByte(15)
=======
..writeByte(16)
>>>>>>> 6742220 (Your commit message here)
..writeByte(0) ..writeByte(0)
..write(obj.id) ..write(obj.id)
..writeByte(1) ..writeByte(1)
@@ -68,7 +78,13 @@ class UserProfileAdapter extends TypeAdapter<UserProfile> {
..writeByte(14) ..writeByte(14)
..write(obj.role) ..write(obj.role)
..writeByte(15) ..writeByte(15)
<<<<<<< HEAD
..write(obj.isIrregularCycle); ..write(obj.isIrregularCycle);
=======
..write(obj.isIrregularCycle)
..writeByte(16)
..write(obj.bibleTranslation);
>>>>>>> 6742220 (Your commit message here)
} }
@override @override
@@ -170,6 +186,68 @@ class FertilityGoalAdapter extends TypeAdapter<FertilityGoal> {
typeId == other.typeId; typeId == other.typeId;
} }
<<<<<<< HEAD
=======
class BibleTranslationAdapter extends TypeAdapter<BibleTranslation> {
@override
final int typeId = 9;
@override
BibleTranslation read(BinaryReader reader) {
switch (reader.readByte()) {
case 0:
return BibleTranslation.esv;
case 1:
return BibleTranslation.niv;
case 2:
return BibleTranslation.nkjv;
case 3:
return BibleTranslation.nlt;
case 4:
return BibleTranslation.nasb;
case 5:
return BibleTranslation.kjv;
default:
return BibleTranslation.esv;
}
}
@override
void write(BinaryWriter writer, BibleTranslation obj) {
switch (obj) {
case BibleTranslation.esv:
writer.writeByte(0);
break;
case BibleTranslation.niv:
writer.writeByte(1);
break;
case BibleTranslation.nkjv:
writer.writeByte(2);
break;
case BibleTranslation.nlt:
writer.writeByte(3);
break;
case BibleTranslation.nasb:
writer.writeByte(4);
break;
case BibleTranslation.kjv:
writer.writeByte(5);
break;
}
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is BibleTranslationAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
>>>>>>> 6742220 (Your commit message here)
class UserRoleAdapter extends TypeAdapter<UserRole> { class UserRoleAdapter extends TypeAdapter<UserRole> {
@override @override
final int typeId = 8; final int typeId = 8;

View File

@@ -0,0 +1,14 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
/// Provider to manage the bottom navigation index across the app
final navigationProvider = StateNotifierProvider<NavigationNotifier, int>((ref) {
return NavigationNotifier();
});
class NavigationNotifier extends StateNotifier<int> {
NavigationNotifier() : super(0);
void setIndex(int index) {
state = index;
}
}

View File

@@ -7,6 +7,10 @@ import '../../models/cycle_entry.dart';
import '../../providers/user_provider.dart'; import '../../providers/user_provider.dart';
import '../../services/cycle_service.dart'; import '../../services/cycle_service.dart';
import '../../theme/app_theme.dart'; import '../../theme/app_theme.dart';
<<<<<<< HEAD
=======
import '../log/log_screen.dart';
>>>>>>> 6742220 (Your commit message here)
class CalendarScreen extends ConsumerStatefulWidget { class CalendarScreen extends ConsumerStatefulWidget {
const CalendarScreen({super.key}); const CalendarScreen({super.key});
@@ -141,6 +145,7 @@ class _CalendarScreenState extends ConsumerState<CalendarScreen> {
), ),
), ),
calendarBuilders: CalendarBuilders( calendarBuilders: CalendarBuilders(
<<<<<<< HEAD
markerBuilder: (context, date, events) { markerBuilder: (context, date, events) {
// Check if it's a logged period day // Check if it's a logged period day
final isLoggedPeriod = _isLoggedPeriodDay(date, entries); final isLoggedPeriod = _isLoggedPeriodDay(date, entries);
@@ -174,6 +179,58 @@ class _CalendarScreenState extends ConsumerState<CalendarScreen> {
); );
} }
return null; return null;
=======
markerBuilder: (context, date, entries) {
final entry = _getEntryForDate(date, entries);
if (entry == null) {
final phase = _getPhaseForDate(date, lastPeriodStart, cycleLength);
if (phase != null) {
return Positioned(
bottom: 1,
child: Container(
width: 4,
height: 4,
decoration: BoxDecoration(
color: _getPhaseColor(phase).withOpacity(0.3),
shape: BoxShape.circle,
),
),
);
}
return null;
}
// If we have an entry, show icons/markers
return Positioned(
bottom: 1,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (entry.isPeriodDay)
Container(
width: 6,
height: 6,
margin: const EdgeInsets.symmetric(horizontal: 1),
decoration: const BoxDecoration(
color: AppColors.menstrualPhase,
shape: BoxShape.circle,
),
),
if (entry.mood != null || entry.energyLevel != 3 || entry.hasSymptoms)
Container(
width: 6,
height: 6,
margin: const EdgeInsets.symmetric(horizontal: 1),
decoration: const BoxDecoration(
color: AppColors.softGold,
shape: BoxShape.circle,
),
),
],
),
);
>>>>>>> 6742220 (Your commit message here)
}, },
), ),
), ),
@@ -279,6 +336,7 @@ class _CalendarScreenState extends ConsumerState<CalendarScreen> {
Widget _buildDayInfo(DateTime date, DateTime? lastPeriodStart, int cycleLength, List<CycleEntry> entries) { Widget _buildDayInfo(DateTime date, DateTime? lastPeriodStart, int cycleLength, List<CycleEntry> entries) {
final phase = _getPhaseForDate(date, lastPeriodStart, cycleLength); final phase = _getPhaseForDate(date, lastPeriodStart, cycleLength);
final entry = _getEntryForDate(date, entries); final entry = _getEntryForDate(date, entries);
<<<<<<< HEAD
final isLoggedPeriod = entry?.isPeriodDay ?? false; final isLoggedPeriod = entry?.isPeriodDay ?? false;
return Container( return Container(
@@ -287,10 +345,27 @@ class _CalendarScreenState extends ConsumerState<CalendarScreen> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
=======
return Container(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Theme.of(context).cardTheme.color,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
>>>>>>> 6742220 (Your commit message here)
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
<<<<<<< HEAD
Text( Text(
'${_getMonthName(date.month)} ${date.day}, ${date.year}', '${_getMonthName(date.month)} ${date.day}, ${date.year}',
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
@@ -352,6 +427,180 @@ class _CalendarScreenState extends ConsumerState<CalendarScreen> {
phase?.description ?? 'No cycle data for this date', phase?.description ?? 'No cycle data for this date',
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 14, fontSize: 14,
=======
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${_getMonthName(date.month)} ${date.day}, ${date.year}',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w600,
),
),
if (entry != null)
const Icon(Icons.check_circle, color: AppColors.sageGreen, size: 20),
],
),
const SizedBox(height: 16),
if (phase != null)
Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: _getPhaseColor(phase).withOpacity(0.15),
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(phase.emoji),
const SizedBox(width: 6),
Text(
phase.label,
style: GoogleFonts.outfit(
fontSize: 14,
fontWeight: FontWeight.w500,
color: _getPhaseColor(phase),
),
),
],
),
),
),
if (entry == null)
Text(
phase?.description ?? 'No data for this date',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: AppColors.warmGray,
),
)
else ...[
// Period Detail
if (entry.isPeriodDay)
_buildDetailRow(Icons.water_drop, 'Period Day', AppColors.menstrualPhase,
value: entry.flowIntensity?.label),
// Mood Detail
if (entry.mood != null)
_buildDetailRow(Icons.emoji_emotions_outlined, 'Mood', AppColors.softGold,
value: '${entry.mood!.emoji} ${entry.mood!.label}'),
// Energy Detail
_buildDetailRow(Icons.flash_on, 'Energy Level', AppColors.follicularPhase,
value: _getEnergyLabel(entry.energyLevel)),
// Symptoms
if (entry.hasSymptoms)
_buildDetailRow(Icons.healing_outlined, 'Symptoms', AppColors.lavender,
value: _getSymptomsString(entry)),
// Contextual Recommendation
_buildRecommendation(entry),
// Notes
if (entry.notes?.isNotEmpty == true)
Padding(
padding: const EdgeInsets.only(top: 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Notes', style: GoogleFonts.outfit(fontSize: 12, fontWeight: FontWeight.w600, color: AppColors.warmGray)),
const SizedBox(height: 4),
Text(entry.notes!, style: GoogleFonts.outfit(fontSize: 14)),
],
),
),
],
const SizedBox(height: 24),
// Action Buttons
Row(
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Scaffold(
appBar: AppBar(
title: Text('Log for ${_getMonthName(date.month)} ${date.day}'),
),
body: LogScreen(initialDate: date),
),
),
);
},
icon: Icon(entry != null ? Icons.edit_note : Icons.add_circle_outline),
label: Text(entry != null ? 'Edit Log' : 'Add Log'),
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.sageGreen,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 12),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
),
),
),
],
),
],
),
);
}
Widget _buildRecommendation(CycleEntry entry) {
final scripture = ScriptureDatabase.getRecommendedScripture(entry);
if (scripture == null) return const SizedBox.shrink();
final user = ref.read(userProfileProvider);
final translation = user?.bibleTranslation ?? BibleTranslation.esv;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Container(
margin: const EdgeInsets.only(top: 16),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.softGold.withOpacity(isDark ? 0.15 : 0.1),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: AppColors.softGold.withOpacity(0.3)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
const Icon(Icons.auto_awesome, color: AppColors.softGold, size: 18),
const SizedBox(width: 8),
Text(
'Daily Encouragement',
style: GoogleFonts.outfit(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.softGold,
),
),
],
),
const SizedBox(height: 12),
Text(
'"${scripture.getVerse(translation)}"',
style: GoogleFonts.lora(
fontSize: 14,
fontStyle: FontStyle.italic,
color: isDark ? Colors.white : AppColors.charcoal,
height: 1.5,
),
),
const SizedBox(height: 8),
Text(
'${scripture.reference}',
style: GoogleFonts.outfit(
fontSize: 12,
fontWeight: FontWeight.w500,
>>>>>>> 6742220 (Your commit message here)
color: AppColors.warmGray, color: AppColors.warmGray,
), ),
), ),
@@ -360,6 +609,59 @@ class _CalendarScreenState extends ConsumerState<CalendarScreen> {
); );
} }
<<<<<<< HEAD
=======
Widget _buildDetailRow(IconData icon, String label, Color color, {String? value}) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(icon, color: color, size: 18),
),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: GoogleFonts.outfit(
fontSize: 12,
color: AppColors.warmGray,
),
),
if (value != null)
Text(
value,
style: GoogleFonts.outfit(
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
],
),
],
),
);
}
String _getSymptomsString(CycleEntry entry) {
List<String> s = [];
if (entry.crampIntensity != null && entry.crampIntensity! > 0) s.add('Cramps (${entry.crampIntensity}/5)');
if (entry.hasHeadache) s.add('Headache');
if (entry.hasBloating) s.add('Bloating');
if (entry.hasBreastTenderness) s.add('Breast Tenderness');
if (entry.hasFatigue) s.add('Fatigue');
if (entry.hasAcne) s.add('Acne');
return s.join(', ');
}
>>>>>>> 6742220 (Your commit message here)
CyclePhase? _getPhaseForDate(DateTime date, DateTime? lastPeriodStart, int cycleLength) { CyclePhase? _getPhaseForDate(DateTime date, DateTime? lastPeriodStart, int cycleLength) {
if (lastPeriodStart == null) return null; if (lastPeriodStart == null) return null;

View File

@@ -6,10 +6,57 @@ import '../../providers/user_provider.dart';
import '../../services/cycle_service.dart'; import '../../services/cycle_service.dart';
import '../../models/cycle_entry.dart'; import '../../models/cycle_entry.dart';
import '../../theme/app_theme.dart'; import '../../theme/app_theme.dart';
<<<<<<< HEAD
=======
import '../../widgets/scripture_card.dart';
import '../../models/user_profile.dart';
>>>>>>> 6742220 (Your commit message here)
class DevotionalScreen extends ConsumerWidget { class DevotionalScreen extends ConsumerWidget {
const DevotionalScreen({super.key}); const DevotionalScreen({super.key});
<<<<<<< HEAD
=======
Future<void> _showTranslationPicker(BuildContext context, WidgetRef ref, UserProfile? user) async {
if (user == null) return;
final selected = await showModalBottomSheet<BibleTranslation>(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (context) => Container(
padding: const EdgeInsets.symmetric(vertical: 20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Text(
'Select Bible Translation',
style: Theme.of(context).textTheme.titleLarge,
),
),
...BibleTranslation.values.map((t) => ListTile(
title: Text(t.label),
trailing: user.bibleTranslation == t
? Icon(Icons.check, color: AppColors.sageGreen)
: null,
onTap: () => Navigator.pop(context, t),
)),
],
),
),
);
if (selected != null) {
await ref.read(userProfileProvider.notifier).updateProfile(
user.copyWith(bibleTranslation: selected)
);
}
}
>>>>>>> 6742220 (Your commit message here)
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final user = ref.watch(userProfileProvider); final user = ref.watch(userProfileProvider);
@@ -71,6 +118,7 @@ class DevotionalScreen extends ConsumerWidget {
const SizedBox(height: 32), const SizedBox(height: 32),
// Main Scripture Card // Main Scripture Card
<<<<<<< HEAD
Container( Container(
width: double.infinity, width: double.infinity,
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@@ -130,6 +178,14 @@ class DevotionalScreen extends ConsumerWidget {
), ),
], ],
), ),
=======
ScriptureCard(
verse: scripture.getVerse(user?.bibleTranslation ?? BibleTranslation.esv),
reference: scripture.reference,
translation: (user?.bibleTranslation ?? BibleTranslation.esv).label,
phase: phase,
onTranslationTap: () => _showTranslationPicker(context, ref, user),
>>>>>>> 6742220 (Your commit message here)
), ),
const SizedBox(height: 24), const SizedBox(height: 24),

View File

@@ -1,7 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
<<<<<<< HEAD
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_flutter/hive_flutter.dart';
=======
>>>>>>> 6742220 (Your commit message here)
import '../../theme/app_theme.dart'; import '../../theme/app_theme.dart';
import '../../models/user_profile.dart'; import '../../models/user_profile.dart';
import '../../models/cycle_entry.dart'; import '../../models/cycle_entry.dart';
@@ -14,6 +17,7 @@ import '../../widgets/cycle_ring.dart';
import '../../widgets/scripture_card.dart'; import '../../widgets/scripture_card.dart';
import '../../widgets/quick_log_buttons.dart'; import '../../widgets/quick_log_buttons.dart';
import '../../providers/user_provider.dart'; import '../../providers/user_provider.dart';
<<<<<<< HEAD
import '../../services/cycle_service.dart'; import '../../services/cycle_service.dart';
class HomeScreen extends ConsumerStatefulWidget { class HomeScreen extends ConsumerStatefulWidget {
@@ -31,28 +35,60 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
return Scaffold( return Scaffold(
body: IndexedStack( body: IndexedStack(
index: _selectedIndex, index: _selectedIndex,
=======
import '../../providers/navigation_provider.dart';
import '../../services/cycle_service.dart';
import '../../services/bible_utils.dart';
class HomeScreen extends ConsumerWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final selectedIndex = ref.watch(navigationProvider);
return Scaffold(
body: IndexedStack(
index: selectedIndex,
>>>>>>> 6742220 (Your commit message here)
children: [ children: [
const _DashboardTab(), const _DashboardTab(),
const CalendarScreen(), const CalendarScreen(),
const LogScreen(), const LogScreen(),
const DevotionalScreen(), const DevotionalScreen(),
<<<<<<< HEAD
_SettingsTab(onReset: () => setState(() => _selectedIndex = 0)), _SettingsTab(onReset: () => setState(() => _selectedIndex = 0)),
=======
_SettingsTab(onReset: () => ref.read(navigationProvider.notifier).setIndex(0)),
>>>>>>> 6742220 (Your commit message here)
], ],
), ),
bottomNavigationBar: Container( bottomNavigationBar: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
<<<<<<< HEAD
color: Colors.white, color: Colors.white,
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: AppColors.charcoal.withOpacity(0.1), color: AppColors.charcoal.withOpacity(0.1),
=======
color: Theme.of(context).bottomNavigationBarTheme.backgroundColor,
boxShadow: [
BoxShadow(
color: (Theme.of(context).brightness == Brightness.dark ? Colors.black : AppColors.charcoal).withOpacity(0.1),
>>>>>>> 6742220 (Your commit message here)
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, -2), offset: const Offset(0, -2),
), ),
], ],
), ),
child: BottomNavigationBar( child: BottomNavigationBar(
<<<<<<< HEAD
currentIndex: _selectedIndex, currentIndex: _selectedIndex,
onTap: (index) => setState(() => _selectedIndex = index), onTap: (index) => setState(() => _selectedIndex = index),
=======
currentIndex: selectedIndex,
onTap: (index) => ref.read(navigationProvider.notifier).setIndex(index),
>>>>>>> 6742220 (Your commit message here)
items: const [ items: const [
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.home_outlined), icon: Icon(Icons.home_outlined),
@@ -91,6 +127,7 @@ class _DashboardTab extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
<<<<<<< HEAD
final user = ref.watch(userProfileProvider); final user = ref.watch(userProfileProvider);
final cycleInfo = ref.watch(currentCycleInfoProvider); final cycleInfo = ref.watch(currentCycleInfoProvider);
@@ -100,6 +137,18 @@ class _DashboardTab extends ConsumerWidget {
final cycleLength = user?.averageCycleLength ?? 28; final cycleLength = user?.averageCycleLength ?? 28;
// Get scripture for current phase // Get scripture for current phase
=======
final name = ref.watch(userProfileProvider.select((u) => u?.name)) ?? 'Friend';
final translation = ref.watch(userProfileProvider.select((u) => u?.bibleTranslation)) ?? BibleTranslation.esv;
final role = ref.watch(userProfileProvider.select((u) => u?.role)) ?? UserRole.wife;
final isMarried = ref.watch(userProfileProvider.select((u) => u?.isMarried)) ?? false;
final averageCycleLength = ref.watch(userProfileProvider.select((u) => u?.averageCycleLength)) ?? 28;
final cycleInfo = ref.watch(currentCycleInfoProvider);
final phase = cycleInfo['phase'] as CyclePhase;
final dayOfCycle = cycleInfo['dayOfCycle'] as int;
>>>>>>> 6742220 (Your commit message here)
final scripture = ScriptureDatabase.getScriptureForPhase(phase.name); final scripture = ScriptureDatabase.getScriptureForPhase(phase.name);
return SafeArea( return SafeArea(
@@ -108,6 +157,7 @@ class _DashboardTab extends ConsumerWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
<<<<<<< HEAD
// Greeting // Greeting
_buildGreeting(name), _buildGreeting(name),
const SizedBox(height: 24), const SizedBox(height: 24),
@@ -137,15 +187,50 @@ class _DashboardTab extends ConsumerWidget {
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.charcoal, color: AppColors.charcoal,
=======
_buildGreeting(context, name),
const SizedBox(height: 24),
Center(
child: CycleRing(
dayOfCycle: dayOfCycle,
totalDays: averageCycleLength,
phase: phase,
),
),
const SizedBox(height: 32),
ScriptureCard(
verse: scripture.getVerse(translation),
reference: scripture.reference,
translation: translation.label,
phase: phase,
onTranslationTap: () => BibleUtils.showTranslationPicker(context, ref),
),
const SizedBox(height: 24),
Text(
'Quick Log',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontSize: 18,
fontWeight: FontWeight.w600,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
const QuickLogButtons(), const QuickLogButtons(),
<<<<<<< HEAD
const SizedBox(height: 20), const SizedBox(height: 20),
// Today's Tip - Only show if not just tracking or husband (though husband has own screen) // Today's Tip - Only show if not just tracking or husband (though husband has own screen)
if (user?.role == UserRole.wife) if (user?.role == UserRole.wife)
TipCard(phase: phase, isMarried: user?.isMarried ?? false), TipCard(phase: phase, isMarried: user?.isMarried ?? false),
=======
const SizedBox(height: 24),
if (role == UserRole.wife)
TipCard(phase: phase, isMarried: isMarried),
>>>>>>> 6742220 (Your commit message here)
const SizedBox(height: 20), const SizedBox(height: 20),
], ],
), ),
@@ -153,7 +238,12 @@ class _DashboardTab extends ConsumerWidget {
); );
} }
<<<<<<< HEAD
Widget _buildGreeting(String name) { Widget _buildGreeting(String name) {
=======
Widget _buildGreeting(BuildContext context, String name) {
final theme = Theme.of(context);
>>>>>>> 6742220 (Your commit message here)
final hour = DateTime.now().hour; final hour = DateTime.now().hour;
String greeting; String greeting;
if (hour < 12) { if (hour < 12) {
@@ -174,15 +264,26 @@ class _DashboardTab extends ConsumerWidget {
'$greeting,', '$greeting,',
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 16, fontSize: 16,
<<<<<<< HEAD
color: AppColors.warmGray, color: AppColors.warmGray,
=======
color: theme.colorScheme.onSurfaceVariant,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
Text( Text(
name, name,
<<<<<<< HEAD
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 28, fontSize: 28,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.charcoal, color: AppColors.charcoal,
=======
style: theme.textTheme.displaySmall?.copyWith(
fontSize: 28,
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
], ],
@@ -192,19 +293,31 @@ class _DashboardTab extends ConsumerWidget {
width: 48, width: 48,
height: 48, height: 48,
decoration: BoxDecoration( decoration: BoxDecoration(
<<<<<<< HEAD
color: AppColors.blushPink, color: AppColors.blushPink,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: const Icon( child: const Icon(
Icons.notifications_outlined, Icons.notifications_outlined,
color: AppColors.rose, color: AppColors.rose,
=======
color: theme.colorScheme.primaryContainer.withOpacity(0.5),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
Icons.notifications_outlined,
color: theme.colorScheme.primary,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
], ],
); );
} }
<<<<<<< HEAD
// Placeholder _calculateCycleInfo removed as it's now in CycleService // Placeholder _calculateCycleInfo removed as it's now in CycleService
=======
>>>>>>> 6742220 (Your commit message here)
} }
class _SettingsTab extends ConsumerWidget { class _SettingsTab extends ConsumerWidget {
@@ -213,6 +326,7 @@ class _SettingsTab extends ConsumerWidget {
Widget _buildSettingsTile(BuildContext context, IconData icon, String title, {VoidCallback? onTap}) { Widget _buildSettingsTile(BuildContext context, IconData icon, String title, {VoidCallback? onTap}) {
return ListTile( return ListTile(
<<<<<<< HEAD
leading: Icon(icon, color: AppColors.charcoal), leading: Icon(icon, color: AppColors.charcoal),
title: Text( title: Text(
title, title,
@@ -222,6 +336,16 @@ class _SettingsTab extends ConsumerWidget {
), ),
), ),
trailing: Icon(Icons.chevron_right, color: AppColors.lightGray), trailing: Icon(Icons.chevron_right, color: AppColors.lightGray),
=======
leading: Icon(icon, color: Theme.of(context).colorScheme.onSurface.withOpacity(0.8)),
title: Text(
title,
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
fontSize: 16,
),
),
trailing: const Icon(Icons.chevron_right, color: AppColors.lightGray),
>>>>>>> 6742220 (Your commit message here)
onTap: onTap ?? () { onTap: onTap ?? () {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Settings coming soon!')), const SnackBar(content: Text('Settings coming soon!')),
@@ -259,7 +383,14 @@ class _SettingsTab extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
<<<<<<< HEAD
final user = ref.watch(userProfileProvider); final user = ref.watch(userProfileProvider);
=======
final name = ref.watch(userProfileProvider.select((u) => u?.name)) ?? 'Guest';
final roleSymbol = ref.watch(userProfileProvider.select((u) => u?.role)) == UserRole.husband ? 'HUSBAND' : null;
final relationshipStatus = ref.watch(userProfileProvider.select((u) => u?.relationshipStatus.name.toUpperCase())) ?? 'SINGLE';
final translationLabel = ref.watch(userProfileProvider.select((u) => u?.bibleTranslation.label)) ?? 'ESV';
>>>>>>> 6742220 (Your commit message here)
return SafeArea( return SafeArea(
child: SingleChildScrollView( child: SingleChildScrollView(
@@ -269,14 +400,22 @@ class _SettingsTab extends ConsumerWidget {
children: [ children: [
Text( Text(
'Settings', 'Settings',
<<<<<<< HEAD
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 28, fontSize: 28,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.charcoal, color: AppColors.charcoal,
=======
style: Theme.of(context).textTheme.displayMedium?.copyWith(
fontSize: 28,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurface,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
<<<<<<< HEAD
// Profile Card // Profile Card
Container( Container(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
@@ -290,6 +429,14 @@ class _SettingsTab extends ConsumerWidget {
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
], ],
=======
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Theme.of(context).cardTheme.color,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Theme.of(context).colorScheme.outline.withOpacity(0.05)),
>>>>>>> 6742220 (Your commit message here)
), ),
child: Row( child: Row(
children: [ children: [
@@ -306,7 +453,11 @@ class _SettingsTab extends ConsumerWidget {
), ),
child: Center( child: Center(
child: Text( child: Text(
<<<<<<< HEAD
user?.name.isNotEmpty == true ? user!.name[0].toUpperCase() : '?', user?.name.isNotEmpty == true ? user!.name[0].toUpperCase() : '?',
=======
name.isNotEmpty ? name[0].toUpperCase() : '?',
>>>>>>> 6742220 (Your commit message here)
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -321,6 +472,7 @@ class _SettingsTab extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
<<<<<<< HEAD
user?.name ?? 'Guest', user?.name ?? 'Guest',
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 18, fontSize: 18,
@@ -332,6 +484,16 @@ class _SettingsTab extends ConsumerWidget {
user?.role == UserRole.husband user?.role == UserRole.husband
? 'HUSBAND' ? 'HUSBAND'
: (user?.relationshipStatus.name.toUpperCase() ?? 'SINGLE'), : (user?.relationshipStatus.name.toUpperCase() ?? 'SINGLE'),
=======
name,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
Text(
roleSymbol ?? relationshipStatus,
>>>>>>> 6742220 (Your commit message here)
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 12, fontSize: 12,
letterSpacing: 1, letterSpacing: 1,
@@ -341,27 +503,50 @@ class _SettingsTab extends ConsumerWidget {
], ],
), ),
), ),
<<<<<<< HEAD
Icon(Icons.chevron_right, color: AppColors.warmGray), Icon(Icons.chevron_right, color: AppColors.warmGray),
=======
const Icon(Icons.chevron_right, color: AppColors.warmGray),
>>>>>>> 6742220 (Your commit message here)
], ],
), ),
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
<<<<<<< HEAD
// Settings Groups // Settings Groups
_buildSettingsGroup('Preferences', [ _buildSettingsGroup('Preferences', [
_buildSettingsTile(context, Icons.notifications_outlined, 'Notifications'), _buildSettingsTile(context, Icons.notifications_outlined, 'Notifications'),
=======
_buildSettingsGroup(context, 'Preferences', [
_buildSettingsTile(context, Icons.notifications_outlined, 'Notifications'),
_buildSettingsTile(
context,
Icons.book_outlined,
'Bible Version ($translationLabel)',
onTap: () => BibleUtils.showTranslationPicker(context, ref),
),
>>>>>>> 6742220 (Your commit message here)
_buildSettingsTile(context, Icons.palette_outlined, 'Appearance'), _buildSettingsTile(context, Icons.palette_outlined, 'Appearance'),
_buildSettingsTile(context, Icons.lock_outline, 'Privacy'), _buildSettingsTile(context, Icons.lock_outline, 'Privacy'),
]), ]),
const SizedBox(height: 16), const SizedBox(height: 16),
<<<<<<< HEAD
_buildSettingsGroup('Cycle', [ _buildSettingsGroup('Cycle', [
=======
_buildSettingsGroup(context, 'Cycle', [
>>>>>>> 6742220 (Your commit message here)
_buildSettingsTile(context, Icons.calendar_today_outlined, 'Cycle Settings'), _buildSettingsTile(context, Icons.calendar_today_outlined, 'Cycle Settings'),
_buildSettingsTile(context, Icons.trending_up_outlined, 'Cycle History'), _buildSettingsTile(context, Icons.trending_up_outlined, 'Cycle History'),
_buildSettingsTile(context, Icons.download_outlined, 'Export Data'), _buildSettingsTile(context, Icons.download_outlined, 'Export Data'),
]), ]),
const SizedBox(height: 16), const SizedBox(height: 16),
<<<<<<< HEAD
_buildSettingsGroup('Account', [ _buildSettingsGroup('Account', [
=======
_buildSettingsGroup(context, 'Account', [
>>>>>>> 6742220 (Your commit message here)
_buildSettingsTile( _buildSettingsTile(
context, context,
Icons.logout, Icons.logout,
@@ -376,7 +561,11 @@ class _SettingsTab extends ConsumerWidget {
); );
} }
<<<<<<< HEAD
Widget _buildSettingsGroup(String title, List<Widget> tiles) { Widget _buildSettingsGroup(String title, List<Widget> tiles) {
=======
Widget _buildSettingsGroup(BuildContext context, String title, List<Widget> tiles) {
>>>>>>> 6742220 (Your commit message here)
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -392,8 +581,14 @@ class _SettingsTab extends ConsumerWidget {
const SizedBox(height: 8), const SizedBox(height: 8),
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
<<<<<<< HEAD
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
=======
color: Theme.of(context).cardTheme.color,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Theme.of(context).colorScheme.outline.withOpacity(0.05)),
>>>>>>> 6742220 (Your commit message here)
), ),
child: Column( child: Column(
children: tiles, children: tiles,
@@ -403,4 +598,7 @@ class _SettingsTab extends ConsumerWidget {
); );
} }
} }
<<<<<<< HEAD
=======
>>>>>>> 6742220 (Your commit message here)

View File

@@ -28,6 +28,10 @@ class _HusbandHomeScreenState extends ConsumerState<HusbandHomeScreen> {
index: _selectedIndex, index: _selectedIndex,
children: [ children: [
const _HusbandDashboard(), const _HusbandDashboard(),
<<<<<<< HEAD
=======
const _HusbandWifeStatus(),
>>>>>>> 6742220 (Your commit message here)
const _HusbandTipsScreen(), const _HusbandTipsScreen(),
const _HusbandLearnScreen(), const _HusbandLearnScreen(),
const _HusbandSettingsScreen(), const _HusbandSettingsScreen(),
@@ -58,6 +62,14 @@ class _HusbandHomeScreenState extends ConsumerState<HusbandHomeScreen> {
label: 'Home', label: 'Home',
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
<<<<<<< HEAD
=======
icon: Icon(Icons.favorite_border),
activeIcon: Icon(Icons.favorite),
label: 'Status',
),
BottomNavigationBarItem(
>>>>>>> 6742220 (Your commit message here)
icon: Icon(Icons.lightbulb_outline), icon: Icon(Icons.lightbulb_outline),
activeIcon: Icon(Icons.lightbulb), activeIcon: Icon(Icons.lightbulb),
label: 'Tips', label: 'Tips',
@@ -829,3 +841,278 @@ class _HusbandSettingsScreen extends ConsumerWidget {
); );
} }
} }
<<<<<<< HEAD
=======
class _HusbandWifeStatus extends ConsumerWidget {
const _HusbandWifeStatus();
@override
Widget build(BuildContext context, WidgetRef ref) {
final user = ref.watch(userProfileProvider);
final cycleInfo = ref.watch(currentCycleInfoProvider);
final entries = ref.watch(cycleEntriesProvider);
final wifeName = user?.partnerName ?? "Wife";
final phase = cycleInfo['phase'] as CyclePhase;
final dayOfCycle = cycleInfo['dayOfCycle'] as int;
// Find today's entry
final todayEntry = entries.firstWhere(
(e) => DateUtils.isSameDay(e.date, DateTime.now()),
orElse: () => CycleEntry(
id: '',
date: DateTime.now(),
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
),
);
return SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Wife\'s Status',
style: GoogleFonts.outfit(
fontSize: 28,
fontWeight: FontWeight.w600,
color: AppColors.navyBlue,
),
),
const SizedBox(height: 8),
Text(
'Real-time updates on how $wifeName is doing',
style: GoogleFonts.outfit(
fontSize: 14,
color: AppColors.warmGray,
),
),
const SizedBox(height: 24),
// Phase and Day summary
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: AppColors.navyBlue.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Row(
children: [
_buildStatusCircle(dayOfCycle, phase),
const SizedBox(width: 20),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
phase.label,
style: GoogleFonts.outfit(
fontSize: 20,
fontWeight: FontWeight.w600,
color: AppColors.navyBlue,
),
),
Text(
'Cycle Day $dayOfCycle',
style: GoogleFonts.outfit(
fontSize: 14,
color: AppColors.warmGray,
),
),
const SizedBox(height: 8),
Text(
phase.description,
style: GoogleFonts.outfit(
fontSize: 13,
color: AppColors.charcoal.withOpacity(0.8),
),
),
],
),
),
],
),
),
const SizedBox(height: 24),
// Symptoms for Today
if (todayEntry.hasSymptoms || todayEntry.mood != null) ...[
Text(
'Today\'s Logs',
style: GoogleFonts.outfit(
fontSize: 18,
fontWeight: FontWeight.w600,
color: AppColors.navyBlue,
),
),
const SizedBox(height: 12),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.navyBlue.withOpacity(0.03),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.navyBlue.withOpacity(0.05)),
),
child: Column(
children: [
if (todayEntry.mood != null)
_buildLogTile(Icons.emoji_emotions_outlined, 'Mood', '${todayEntry.mood!.emoji} ${todayEntry.mood!.label}'),
if (todayEntry.hasSymptoms)
_buildLogTile(Icons.healing_outlined, 'Symptoms', _getSymptomsSummary(todayEntry)),
if (todayEntry.energyLevel != null)
_buildLogTile(Icons.flash_on, 'Energy', '${todayEntry.energyLevel}/5'),
],
),
),
const SizedBox(height: 24),
],
// Support Checklist
Text(
'Support Checklist',
style: GoogleFonts.outfit(
fontSize: 18,
fontWeight: FontWeight.w600,
color: AppColors.navyBlue,
),
),
const SizedBox(height: 12),
..._generateChecklist(todayEntry, phase).map((item) => _buildCheckItem(item)),
const SizedBox(height: 40),
],
),
),
);
}
Widget _buildStatusCircle(int day, CyclePhase phase) {
return Container(
width: 70,
height: 70,
decoration: BoxDecoration(
color: phase.color.withOpacity(0.15),
shape: BoxShape.circle,
border: Border.all(color: phase.color.withOpacity(0.3), width: 2),
),
child: Center(
child: Text(
day.toString(),
style: GoogleFonts.outfit(
fontSize: 24,
fontWeight: FontWeight.w700,
color: phase.color,
),
),
),
);
}
Widget _buildLogTile(IconData icon, String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
children: [
Icon(icon, size: 20, color: AppColors.steelBlue),
const SizedBox(width: 12),
Text(
'$label: ',
style: GoogleFonts.outfit(fontWeight: FontWeight.w500, fontSize: 14),
),
Expanded(
child: Text(
value,
style: GoogleFonts.outfit(fontSize: 14, color: AppColors.charcoal),
),
),
],
),
);
}
Widget _buildCheckItem(String text) {
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: AppColors.navyBlue.withOpacity(0.05)),
),
child: Row(
children: [
Icon(Icons.check_circle_outline, color: AppColors.sageGreen, size: 20),
const SizedBox(width: 12),
Expanded(
child: Text(
text,
style: GoogleFonts.outfit(fontSize: 14, color: AppColors.navyBlue),
),
),
],
),
);
}
String _getSymptomsSummary(CycleEntry entry) {
List<String> s = [];
if (entry.crampIntensity != null && entry.crampIntensity! > 0) s.add('Cramps');
if (entry.hasHeadache) s.add('Headache');
if (entry.hasBloating) s.add('Bloating');
if (entry.hasFatigue) s.add('Fatigue');
if (entry.hasLowerBackPain) s.add('Back Pain');
return s.isNotEmpty ? s.join(', ') : 'None';
}
List<String> _generateChecklist(CycleEntry entry, CyclePhase phase) {
List<String> list = [];
// Symptom-based tips
if (entry.crampIntensity != null && entry.crampIntensity! >= 3) {
list.add('Bring her a heating pad or hot water bottle.');
}
if (entry.hasHeadache) {
list.add('Suggest some quiet time with dimmed lights.');
}
if (entry.hasFatigue || (entry.energyLevel != null && entry.energyLevel! <= 2)) {
list.add('Take over dinner or household chores tonight.');
}
if (entry.mood == MoodLevel.sad || entry.mood == MoodLevel.verySad) {
list.add('Offer a listening ear and extra comfort.');
}
// Phase-based fallback tips
if (list.length < 3) {
switch (phase) {
case CyclePhase.menstrual:
list.add('Suggest a relaxing movie night.');
list.add('Bring her a warm tea or cocoa.');
break;
case CyclePhase.follicular:
list.add('Plan a fun outdoor activity.');
list.add('Compliment her renewed energy.');
break;
case CyclePhase.ovulation:
list.add('Plan a romantic date night.');
list.add('Focus on quality connection time.');
break;
case CyclePhase.luteal:
list.add('Surprise her with her favorite comfort snack.');
list.add('Be extra patient if she\'s easily frustrated.');
break;
}
}
return list.take(4).toList();
}
}
>>>>>>> 6742220 (Your commit message here)

View File

@@ -7,13 +7,23 @@ import '../../theme/app_theme.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
class LogScreen extends ConsumerStatefulWidget { class LogScreen extends ConsumerStatefulWidget {
<<<<<<< HEAD
const LogScreen({super.key}); const LogScreen({super.key});
=======
final DateTime? initialDate;
const LogScreen({super.key, this.initialDate});
>>>>>>> 6742220 (Your commit message here)
@override @override
ConsumerState<LogScreen> createState() => _LogScreenState(); ConsumerState<LogScreen> createState() => _LogScreenState();
} }
class _LogScreenState extends ConsumerState<LogScreen> { class _LogScreenState extends ConsumerState<LogScreen> {
<<<<<<< HEAD
=======
late DateTime _selectedDate;
String? _existingEntryId;
>>>>>>> 6742220 (Your commit message here)
bool _isPeriodDay = false; bool _isPeriodDay = false;
FlowIntensity? _flowIntensity; FlowIntensity? _flowIntensity;
MoodLevel? _mood; MoodLevel? _mood;
@@ -24,9 +34,61 @@ class _LogScreenState extends ConsumerState<LogScreen> {
bool _hasBreastTenderness = false; bool _hasBreastTenderness = false;
bool _hasFatigue = false; bool _hasFatigue = false;
bool _hasAcne = false; bool _hasAcne = false;
<<<<<<< HEAD
final TextEditingController _notesController = TextEditingController(); final TextEditingController _notesController = TextEditingController();
@override @override
=======
bool _hasLowerBackPain = false;
bool _hasConstipation = false;
bool _hasDiarrhea = false;
bool _hasInsomnia = false;
int _stressLevel = 1;
final TextEditingController _notesController = TextEditingController();
@override
void initState() {
super.initState();
_selectedDate = widget.initialDate ?? DateTime.now();
// Defer data loading to avoid build-time ref.read
WidgetsBinding.instance.addPostFrameCallback((_) {
_loadExistingData();
});
}
void _loadExistingData() {
final entries = ref.read(cycleEntriesProvider);
try {
final entry = entries.firstWhere(
(e) => DateUtils.isSameDay(e.date, _selectedDate),
);
setState(() {
_existingEntryId = entry.id;
_isPeriodDay = entry.isPeriodDay;
_flowIntensity = entry.flowIntensity;
_mood = entry.mood;
_energyLevel = entry.energyLevel;
_crampIntensity = entry.crampIntensity ?? 0;
_hasHeadache = entry.hasHeadache;
_hasBloating = entry.hasBloating;
_hasBreastTenderness = entry.hasBreastTenderness;
_hasFatigue = entry.hasFatigue;
_hasAcne = entry.hasAcne;
_hasLowerBackPain = entry.hasLowerBackPain;
_hasConstipation = entry.hasConstipation;
_hasDiarrhea = entry.hasDiarrhea;
_hasInsomnia = entry.hasInsomnia;
_stressLevel = entry.stressLevel ?? 1;
_notesController.text = entry.notes ?? '';
});
} catch (_) {
// No existing entry for this day
}
}
@override
>>>>>>> 6742220 (Your commit message here)
void dispose() { void dispose() {
_notesController.dispose(); _notesController.dispose();
super.dispose(); super.dispose();
@@ -34,8 +96,13 @@ class _LogScreenState extends ConsumerState<LogScreen> {
Future<void> _saveEntry() async { Future<void> _saveEntry() async {
final entry = CycleEntry( final entry = CycleEntry(
<<<<<<< HEAD
id: const Uuid().v4(), id: const Uuid().v4(),
date: DateTime.now(), date: DateTime.now(),
=======
id: _existingEntryId ?? const Uuid().v4(),
date: _selectedDate,
>>>>>>> 6742220 (Your commit message here)
isPeriodDay: _isPeriodDay, isPeriodDay: _isPeriodDay,
flowIntensity: _isPeriodDay ? _flowIntensity : null, flowIntensity: _isPeriodDay ? _flowIntensity : null,
mood: _mood, mood: _mood,
@@ -46,28 +113,60 @@ class _LogScreenState extends ConsumerState<LogScreen> {
hasBreastTenderness: _hasBreastTenderness, hasBreastTenderness: _hasBreastTenderness,
hasFatigue: _hasFatigue, hasFatigue: _hasFatigue,
hasAcne: _hasAcne, hasAcne: _hasAcne,
<<<<<<< HEAD
=======
hasLowerBackPain: _hasLowerBackPain,
hasConstipation: _hasConstipation,
hasDiarrhea: _hasDiarrhea,
hasInsomnia: _hasInsomnia,
stressLevel: _stressLevel > 1 ? _stressLevel : null,
>>>>>>> 6742220 (Your commit message here)
notes: _notesController.text.isNotEmpty ? _notesController.text : null, notes: _notesController.text.isNotEmpty ? _notesController.text : null,
createdAt: DateTime.now(), createdAt: DateTime.now(),
updatedAt: DateTime.now(), updatedAt: DateTime.now(),
); );
<<<<<<< HEAD
await ref.read(cycleEntriesProvider.notifier).addEntry(entry); await ref.read(cycleEntriesProvider.notifier).addEntry(entry);
=======
if (_existingEntryId != null) {
await ref.read(cycleEntriesProvider.notifier).updateEntry(entry);
} else {
await ref.read(cycleEntriesProvider.notifier).addEntry(entry);
}
>>>>>>> 6742220 (Your commit message here)
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text('Entry saved!', style: GoogleFonts.outfit()), content: Text('Entry saved!', style: GoogleFonts.outfit()),
<<<<<<< HEAD
backgroundColor: AppColors.sageGreen, backgroundColor: AppColors.sageGreen,
=======
backgroundColor: AppColors.success,
>>>>>>> 6742220 (Your commit message here)
behavior: SnackBarBehavior.floating, behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
), ),
); );
<<<<<<< HEAD
_resetForm(); _resetForm();
=======
if (widget.initialDate != null) {
Navigator.pop(context);
} else {
_resetForm();
}
>>>>>>> 6742220 (Your commit message here)
} }
} }
void _resetForm() { void _resetForm() {
setState(() { setState(() {
<<<<<<< HEAD
=======
_existingEntryId = null;
>>>>>>> 6742220 (Your commit message here)
_isPeriodDay = false; _isPeriodDay = false;
_flowIntensity = null; _flowIntensity = null;
_mood = null; _mood = null;
@@ -78,12 +177,26 @@ class _LogScreenState extends ConsumerState<LogScreen> {
_hasBreastTenderness = false; _hasBreastTenderness = false;
_hasFatigue = false; _hasFatigue = false;
_hasAcne = false; _hasAcne = false;
<<<<<<< HEAD
=======
_hasLowerBackPain = false;
_hasConstipation = false;
_hasDiarrhea = false;
_hasInsomnia = false;
_stressLevel = 1;
>>>>>>> 6742220 (Your commit message here)
_notesController.clear(); _notesController.clear();
}); });
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
<<<<<<< HEAD
=======
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
>>>>>>> 6742220 (Your commit message here)
return SafeArea( return SafeArea(
child: SingleChildScrollView( child: SingleChildScrollView(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
@@ -91,6 +204,7 @@ class _LogScreenState extends ConsumerState<LogScreen> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Header // Header
<<<<<<< HEAD
Text( Text(
'How are you feeling?', 'How are you feeling?',
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
@@ -105,11 +219,49 @@ class _LogScreenState extends ConsumerState<LogScreen> {
fontSize: 14, fontSize: 14,
color: AppColors.warmGray, color: AppColors.warmGray,
), ),
=======
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'How are you feeling?',
style: GoogleFonts.outfit(
fontSize: 28,
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface,
),
),
Text(
_formatDate(_selectedDate),
style: GoogleFonts.outfit(
fontSize: 14,
color: theme.colorScheme.onSurfaceVariant,
),
),
],
),
if (widget.initialDate == null)
IconButton(
onPressed: () => ref.read(navigationProvider.notifier).setIndex(0),
icon: const Icon(Icons.close),
style: IconButton.styleFrom(
backgroundColor: theme.colorScheme.surfaceVariant.withOpacity(0.5),
),
),
],
>>>>>>> 6742220 (Your commit message here)
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
// Period Toggle // Period Toggle
_buildSectionCard( _buildSectionCard(
<<<<<<< HEAD
=======
context,
>>>>>>> 6742220 (Your commit message here)
title: 'Period', title: 'Period',
child: Row( child: Row(
children: [ children: [
@@ -118,7 +270,11 @@ class _LogScreenState extends ConsumerState<LogScreen> {
'Is today a period day?', 'Is today a period day?',
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 16, fontSize: 16,
<<<<<<< HEAD
color: AppColors.charcoal, color: AppColors.charcoal,
=======
color: theme.colorScheme.onSurface,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
), ),
@@ -135,6 +291,10 @@ class _LogScreenState extends ConsumerState<LogScreen> {
if (_isPeriodDay) ...[ if (_isPeriodDay) ...[
const SizedBox(height: 16), const SizedBox(height: 16),
_buildSectionCard( _buildSectionCard(
<<<<<<< HEAD
=======
context,
>>>>>>> 6742220 (Your commit message here)
title: 'Flow Intensity', title: 'Flow Intensity',
child: Row( child: Row(
children: FlowIntensity.values.map((flow) { children: FlowIntensity.values.map((flow) {
@@ -142,17 +302,31 @@ class _LogScreenState extends ConsumerState<LogScreen> {
return Expanded( return Expanded(
child: GestureDetector( child: GestureDetector(
onTap: () => setState(() => _flowIntensity = flow), onTap: () => setState(() => _flowIntensity = flow),
<<<<<<< HEAD
child: Container( child: Container(
=======
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
>>>>>>> 6742220 (Your commit message here)
margin: const EdgeInsets.symmetric(horizontal: 4), margin: const EdgeInsets.symmetric(horizontal: 4),
padding: const EdgeInsets.symmetric(vertical: 12), padding: const EdgeInsets.symmetric(vertical: 12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: isSelected color: isSelected
<<<<<<< HEAD
? AppColors.menstrualPhase.withOpacity(0.2) ? AppColors.menstrualPhase.withOpacity(0.2)
: AppColors.lightGray.withOpacity(0.1), : AppColors.lightGray.withOpacity(0.1),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
border: isSelected border: isSelected
? Border.all(color: AppColors.menstrualPhase) ? Border.all(color: AppColors.menstrualPhase)
: null, : null,
=======
? AppColors.menstrualPhase.withOpacity(isDark ? 0.3 : 0.2)
: theme.colorScheme.surfaceVariant.withOpacity(0.3),
borderRadius: BorderRadius.circular(10),
border: isSelected
? Border.all(color: AppColors.menstrualPhase)
: Border.all(color: Colors.transparent),
>>>>>>> 6742220 (Your commit message here)
), ),
child: Column( child: Column(
children: [ children: [
@@ -160,7 +334,11 @@ class _LogScreenState extends ConsumerState<LogScreen> {
Icons.water_drop, Icons.water_drop,
color: isSelected color: isSelected
? AppColors.menstrualPhase ? AppColors.menstrualPhase
<<<<<<< HEAD
: AppColors.warmGray, : AppColors.warmGray,
=======
: theme.colorScheme.onSurfaceVariant,
>>>>>>> 6742220 (Your commit message here)
size: 20, size: 20,
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
@@ -168,9 +346,16 @@ class _LogScreenState extends ConsumerState<LogScreen> {
flow.label, flow.label,
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 11, fontSize: 11,
<<<<<<< HEAD
color: isSelected color: isSelected
? AppColors.menstrualPhase ? AppColors.menstrualPhase
: AppColors.warmGray, : AppColors.warmGray,
=======
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
color: isSelected
? AppColors.menstrualPhase
: theme.colorScheme.onSurfaceVariant,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
], ],
@@ -187,6 +372,10 @@ class _LogScreenState extends ConsumerState<LogScreen> {
// Mood // Mood
_buildSectionCard( _buildSectionCard(
<<<<<<< HEAD
=======
context,
>>>>>>> 6742220 (Your commit message here)
title: 'Mood', title: 'Mood',
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
@@ -194,16 +383,29 @@ class _LogScreenState extends ConsumerState<LogScreen> {
final isSelected = _mood == mood; final isSelected = _mood == mood;
return GestureDetector( return GestureDetector(
onTap: () => setState(() => _mood = mood), onTap: () => setState(() => _mood = mood),
<<<<<<< HEAD
child: Container( child: Container(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: isSelected color: isSelected
? AppColors.softGold.withOpacity(0.2) ? AppColors.softGold.withOpacity(0.2)
=======
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: isSelected
? AppColors.softGold.withOpacity(isDark ? 0.3 : 0.2)
>>>>>>> 6742220 (Your commit message here)
: Colors.transparent, : Colors.transparent,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: isSelected border: isSelected
? Border.all(color: AppColors.softGold) ? Border.all(color: AppColors.softGold)
<<<<<<< HEAD
: null, : null,
=======
: Border.all(color: Colors.transparent),
>>>>>>> 6742220 (Your commit message here)
), ),
child: Column( child: Column(
children: [ children: [
@@ -218,9 +420,16 @@ class _LogScreenState extends ConsumerState<LogScreen> {
mood.label, mood.label,
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 10, fontSize: 10,
<<<<<<< HEAD
color: isSelected color: isSelected
? AppColors.softGold ? AppColors.softGold
: AppColors.warmGray, : AppColors.warmGray,
=======
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
color: isSelected
? AppColors.softGold
: theme.colorScheme.onSurfaceVariant,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
], ],
@@ -233,6 +442,7 @@ class _LogScreenState extends ConsumerState<LogScreen> {
const SizedBox(height: 16), const SizedBox(height: 16),
<<<<<<< HEAD
// Energy Level // Energy Level
_buildSectionCard( _buildSectionCard(
title: 'Energy Level', title: 'Energy Level',
@@ -241,17 +451,43 @@ class _LogScreenState extends ConsumerState<LogScreen> {
Row( Row(
children: [ children: [
const Icon(Icons.battery_1_bar, color: AppColors.warmGray), const Icon(Icons.battery_1_bar, color: AppColors.warmGray),
=======
// Energy & Stress Levels
_buildSectionCard(
context,
title: 'Daily Levels',
child: Column(
children: [
// Energy Level
Row(
children: [
SizedBox(
width: 80,
child: Text(
'Energy',
style: GoogleFonts.outfit(
fontSize: 14,
color: theme.colorScheme.onSurface,
),
),
),
>>>>>>> 6742220 (Your commit message here)
Expanded( Expanded(
child: Slider( child: Slider(
value: _energyLevel.toDouble(), value: _energyLevel.toDouble(),
min: 1, min: 1,
max: 5, max: 5,
divisions: 4, divisions: 4,
<<<<<<< HEAD
=======
activeColor: AppColors.sageGreen,
>>>>>>> 6742220 (Your commit message here)
onChanged: (value) { onChanged: (value) {
setState(() => _energyLevel = value.round()); setState(() => _energyLevel = value.round());
}, },
), ),
), ),
<<<<<<< HEAD
const Icon(Icons.battery_full, color: AppColors.sageGreen), const Icon(Icons.battery_full, color: AppColors.sageGreen),
], ],
), ),
@@ -261,6 +497,59 @@ class _LogScreenState extends ConsumerState<LogScreen> {
fontSize: 13, fontSize: 13,
color: AppColors.warmGray, color: AppColors.warmGray,
), ),
=======
SizedBox(
width: 50,
child: Text(
_getEnergyLabel(_energyLevel),
textAlign: TextAlign.end,
style: GoogleFonts.outfit(
fontSize: 11,
color: theme.colorScheme.onSurfaceVariant,
),
),
),
],
),
const SizedBox(height: 12),
// Stress Level
Row(
children: [
SizedBox(
width: 80,
child: Text(
'Stress',
style: GoogleFonts.outfit(
fontSize: 14,
color: theme.colorScheme.onSurface,
),
),
),
Expanded(
child: Slider(
value: _stressLevel.toDouble(),
min: 1,
max: 5,
divisions: 4,
activeColor: AppColors.ovulationPhase,
onChanged: (value) {
setState(() => _stressLevel = value.round());
},
),
),
SizedBox(
width: 50,
child: Text(
'$_stressLevel/5',
textAlign: TextAlign.end,
style: GoogleFonts.outfit(
fontSize: 12,
color: theme.colorScheme.onSurfaceVariant,
),
),
),
],
>>>>>>> 6742220 (Your commit message here)
), ),
], ],
), ),
@@ -270,6 +559,10 @@ class _LogScreenState extends ConsumerState<LogScreen> {
// Symptoms // Symptoms
_buildSectionCard( _buildSectionCard(
<<<<<<< HEAD
=======
context,
>>>>>>> 6742220 (Your commit message here)
title: 'Symptoms', title: 'Symptoms',
child: Column( child: Column(
children: [ children: [
@@ -282,7 +575,11 @@ class _LogScreenState extends ConsumerState<LogScreen> {
'Cramps', 'Cramps',
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 14, fontSize: 14,
<<<<<<< HEAD
color: AppColors.charcoal, color: AppColors.charcoal,
=======
color: theme.colorScheme.onSurface,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
), ),
@@ -299,12 +596,22 @@ class _LogScreenState extends ConsumerState<LogScreen> {
), ),
), ),
SizedBox( SizedBox(
<<<<<<< HEAD
width: 40, width: 40,
child: Text( child: Text(
_crampIntensity == 0 ? 'None' : '$_crampIntensity/5', _crampIntensity == 0 ? 'None' : '$_crampIntensity/5',
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 12, fontSize: 12,
color: AppColors.warmGray, color: AppColors.warmGray,
=======
width: 50,
child: Text(
_crampIntensity == 0 ? 'None' : '$_crampIntensity/5',
textAlign: TextAlign.end,
style: GoogleFonts.outfit(
fontSize: 11,
color: theme.colorScheme.onSurfaceVariant,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
), ),
@@ -316,11 +623,23 @@ class _LogScreenState extends ConsumerState<LogScreen> {
spacing: 8, spacing: 8,
runSpacing: 8, runSpacing: 8,
children: [ children: [
<<<<<<< HEAD
_buildSymptomChip('Headache', _hasHeadache, (v) => setState(() => _hasHeadache = v)), _buildSymptomChip('Headache', _hasHeadache, (v) => setState(() => _hasHeadache = v)),
_buildSymptomChip('Bloating', _hasBloating, (v) => setState(() => _hasBloating = v)), _buildSymptomChip('Bloating', _hasBloating, (v) => setState(() => _hasBloating = v)),
_buildSymptomChip('Breast Tenderness', _hasBreastTenderness, (v) => setState(() => _hasBreastTenderness = v)), _buildSymptomChip('Breast Tenderness', _hasBreastTenderness, (v) => setState(() => _hasBreastTenderness = v)),
_buildSymptomChip('Fatigue', _hasFatigue, (v) => setState(() => _hasFatigue = v)), _buildSymptomChip('Fatigue', _hasFatigue, (v) => setState(() => _hasFatigue = v)),
_buildSymptomChip('Acne', _hasAcne, (v) => setState(() => _hasAcne = v)), _buildSymptomChip('Acne', _hasAcne, (v) => setState(() => _hasAcne = v)),
=======
_buildSymptomChip(context, 'Headache', _hasHeadache, (v) => setState(() => _hasHeadache = v)),
_buildSymptomChip(context, 'Bloating', _hasBloating, (v) => setState(() => _hasBloating = v)),
_buildSymptomChip(context, 'Breast Tenderness', _hasBreastTenderness, (v) => setState(() => _hasBreastTenderness = v)),
_buildSymptomChip(context, 'Fatigue', _hasFatigue, (v) => setState(() => _hasFatigue = v)),
_buildSymptomChip(context, 'Acne', _hasAcne, (v) => setState(() => _hasAcne = v)),
_buildSymptomChip(context, 'Back Pain', _hasLowerBackPain, (v) => setState(() => _hasLowerBackPain = v)),
_buildSymptomChip(context, 'Constipation', _hasConstipation, (v) => setState(() => _hasConstipation = v)),
_buildSymptomChip(context, 'Diarrhea', _hasDiarrhea, (v) => setState(() => _hasDiarrhea = v)),
_buildSymptomChip(context, 'Insomnia', _hasInsomnia, (v) => setState(() => _hasInsomnia = v)),
>>>>>>> 6742220 (Your commit message here)
], ],
), ),
], ],
@@ -331,12 +650,17 @@ class _LogScreenState extends ConsumerState<LogScreen> {
// Notes // Notes
_buildSectionCard( _buildSectionCard(
<<<<<<< HEAD
=======
context,
>>>>>>> 6742220 (Your commit message here)
title: 'Notes', title: 'Notes',
child: TextField( child: TextField(
controller: _notesController, controller: _notesController,
maxLines: 3, maxLines: 3,
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Add any notes about how you\'re feeling...', hintText: 'Add any notes about how you\'re feeling...',
<<<<<<< HEAD
hintStyle: GoogleFonts.outfit( hintStyle: GoogleFonts.outfit(
color: AppColors.lightGray, color: AppColors.lightGray,
fontSize: 14, fontSize: 14,
@@ -346,6 +670,18 @@ class _LogScreenState extends ConsumerState<LogScreen> {
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 14, fontSize: 14,
color: AppColors.charcoal, color: AppColors.charcoal,
=======
filled: true,
fillColor: isDark ? theme.colorScheme.surface : theme.colorScheme.surfaceVariant.withOpacity(0.1),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide.none,
),
),
style: GoogleFonts.outfit(
fontSize: 14,
color: theme.colorScheme.onSurface,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
), ),
@@ -355,6 +691,10 @@ class _LogScreenState extends ConsumerState<LogScreen> {
// Save Button // Save Button
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
<<<<<<< HEAD
=======
height: 54,
>>>>>>> 6742220 (Your commit message here)
child: ElevatedButton( child: ElevatedButton(
onPressed: _saveEntry, onPressed: _saveEntry,
child: const Text('Save Entry'), child: const Text('Save Entry'),
@@ -367,16 +707,32 @@ class _LogScreenState extends ConsumerState<LogScreen> {
); );
} }
<<<<<<< HEAD
Widget _buildSectionCard({required String title, required Widget child}) { Widget _buildSectionCard({required String title, required Widget child}) {
=======
Widget _buildSectionCard(BuildContext context, {required String title, required Widget child}) {
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
>>>>>>> 6742220 (Your commit message here)
return Container( return Container(
width: double.infinity, width: double.infinity,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
<<<<<<< HEAD
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: AppColors.charcoal.withOpacity(0.05), color: AppColors.charcoal.withOpacity(0.05),
=======
color: theme.cardTheme.color,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: theme.colorScheme.outline.withOpacity(0.05)),
boxShadow: isDark ? null : [
BoxShadow(
color: Colors.black.withOpacity(0.05),
>>>>>>> 6742220 (Your commit message here)
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -390,7 +746,11 @@ class _LogScreenState extends ConsumerState<LogScreen> {
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
<<<<<<< HEAD
color: AppColors.charcoal, color: AppColors.charcoal,
=======
color: theme.colorScheme.onSurface,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
@@ -400,6 +760,7 @@ class _LogScreenState extends ConsumerState<LogScreen> {
); );
} }
<<<<<<< HEAD
Widget _buildSymptomChip(String label, bool isSelected, ValueChanged<bool> onChanged) { Widget _buildSymptomChip(String label, bool isSelected, ValueChanged<bool> onChanged) {
return GestureDetector( return GestureDetector(
onTap: () => onChanged(!isSelected), onTap: () => onChanged(!isSelected),
@@ -416,6 +777,36 @@ class _LogScreenState extends ConsumerState<LogScreen> {
fontSize: 13, fontSize: 13,
color: isSelected ? AppColors.ovulationPhase : AppColors.warmGray, color: isSelected ? AppColors.ovulationPhase : AppColors.warmGray,
fontWeight: isSelected ? FontWeight.w500 : FontWeight.w400, fontWeight: isSelected ? FontWeight.w500 : FontWeight.w400,
=======
Widget _buildSymptomChip(BuildContext context, String label, bool isSelected, ValueChanged<bool> onChanged) {
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
return Material(
color: Colors.transparent,
child: InkWell(
onTap: () => onChanged(!isSelected),
borderRadius: BorderRadius.circular(20),
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
decoration: BoxDecoration(
color: isSelected
? theme.colorScheme.tertiary.withOpacity(isDark ? 0.3 : 0.2)
: theme.colorScheme.surfaceVariant.withOpacity(0.3),
borderRadius: BorderRadius.circular(20),
border: isSelected
? Border.all(color: theme.colorScheme.tertiary)
: Border.all(color: Colors.transparent),
),
child: Text(
label,
style: GoogleFonts.outfit(
fontSize: 13,
color: isSelected ? theme.colorScheme.onSurface : theme.colorScheme.onSurfaceVariant,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
), ),
@@ -423,12 +814,28 @@ class _LogScreenState extends ConsumerState<LogScreen> {
} }
String _formatDate(DateTime date) { String _formatDate(DateTime date) {
<<<<<<< HEAD
=======
final now = DateTime.now();
if (DateUtils.isSameDay(date, now)) {
return 'Today, ${_getMonth(date.month)} ${date.day}';
}
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
return '${days[date.weekday - 1]}, ${_getMonth(date.month)} ${date.day}';
}
String _getMonth(int month) {
>>>>>>> 6742220 (Your commit message here)
const months = [ const months = [
'January', 'February', 'March', 'April', 'May', 'June', 'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December' 'July', 'August', 'September', 'October', 'November', 'December'
]; ];
<<<<<<< HEAD
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
return '${days[date.weekday - 1]}, ${months[date.month - 1]} ${date.day}'; return '${days[date.weekday - 1]}, ${months[date.month - 1]} ${date.day}';
=======
return months[month - 1];
>>>>>>> 6742220 (Your commit message here)
} }
String _getEnergyLabel(int level) { String _getEnergyLabel(int level) {

View File

@@ -140,8 +140,19 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
<<<<<<< HEAD
// Different background color for husband flow // Different background color for husband flow
final bgColor = _role == UserRole.husband ? AppColors.warmCream : AppColors.cream; final bgColor = _role == UserRole.husband ? AppColors.warmCream : AppColors.cream;
=======
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
// Different background color for husband flow
final isHusband = _role == UserRole.husband;
final bgColor = isHusband
? (isDark ? const Color(0xFF1A1C1E) : AppColors.warmCream)
: theme.scaffoldBackgroundColor;
>>>>>>> 6742220 (Your commit message here)
return Scaffold( return Scaffold(
backgroundColor: bgColor, backgroundColor: bgColor,
@@ -154,13 +165,22 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
child: SmoothPageIndicator( child: SmoothPageIndicator(
controller: _pageController, controller: _pageController,
<<<<<<< HEAD
count: _role == UserRole.husband ? 2 : 5, count: _role == UserRole.husband ? 2 : 5,
=======
count: isHusband ? 2 : 5,
>>>>>>> 6742220 (Your commit message here)
effect: WormEffect( effect: WormEffect(
dotHeight: 8, dotHeight: 8,
dotWidth: 8, dotWidth: 8,
spacing: 12, spacing: 12,
<<<<<<< HEAD
activeDotColor: _role == UserRole.husband ? AppColors.navyBlue : AppColors.sageGreen, activeDotColor: _role == UserRole.husband ? AppColors.navyBlue : AppColors.sageGreen,
dotColor: AppColors.lightGray.withOpacity(0.3), dotColor: AppColors.lightGray.withOpacity(0.3),
=======
activeDotColor: isHusband ? AppColors.navyBlue : AppColors.sageGreen,
dotColor: theme.colorScheme.outline.withOpacity(0.2),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
), ),
@@ -189,6 +209,11 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
} }
Widget _buildRolePage() { Widget _buildRolePage() {
<<<<<<< HEAD
=======
final theme = Theme.of(context);
>>>>>>> 6742220 (Your commit message here)
return Padding( return Padding(
padding: const EdgeInsets.all(32), padding: const EdgeInsets.all(32),
child: Column( child: Column(
@@ -215,10 +240,17 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
Text( Text(
'Who is this app for?', 'Who is this app for?',
textAlign: TextAlign.center, textAlign: TextAlign.center,
<<<<<<< HEAD
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 28, fontSize: 28,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.charcoal, color: AppColors.charcoal,
=======
style: theme.textTheme.displayMedium?.copyWith(
fontSize: 28,
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(height: 48), const SizedBox(height: 48),
@@ -230,6 +262,10 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
const Spacer(), const Spacer(),
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
<<<<<<< HEAD
=======
height: 54,
>>>>>>> 6742220 (Your commit message here)
child: ElevatedButton( child: ElevatedButton(
onPressed: _nextPage, onPressed: _nextPage,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
@@ -244,10 +280,20 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
} }
Widget _buildRoleOption(UserRole role, String title, String subtitle, IconData icon) { Widget _buildRoleOption(UserRole role, String title, String subtitle, IconData icon) {
<<<<<<< HEAD
final isSelected = _role == role; final isSelected = _role == role;
// Dynamic colors based on role selection // Dynamic colors based on role selection
final activeColor = role == UserRole.wife ? AppColors.sageGreen : AppColors.navyBlue; final activeColor = role == UserRole.wife ? AppColors.sageGreen : AppColors.navyBlue;
final activeBg = role == UserRole.wife ? AppColors.sageGreen.withOpacity(0.1) : AppColors.navyBlue.withOpacity(0.1); final activeBg = role == UserRole.wife ? AppColors.sageGreen.withOpacity(0.1) : AppColors.navyBlue.withOpacity(0.1);
=======
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
final isSelected = _role == role;
// Dynamic colors based on role selection
final activeColor = role == UserRole.wife ? AppColors.sageGreen : AppColors.navyBlue;
final activeBg = activeColor.withOpacity(isDark ? 0.3 : 0.1);
>>>>>>> 6742220 (Your commit message here)
return GestureDetector( return GestureDetector(
onTap: () => setState(() => _role = role), onTap: () => setState(() => _role = role),
@@ -255,6 +301,7 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
<<<<<<< HEAD
color: isSelected ? activeBg : Colors.white, color: isSelected ? activeBg : Colors.white,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
border: Border.all( border: Border.all(
@@ -268,18 +315,34 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
offset: const Offset(0, 4), offset: const Offset(0, 4),
) )
] : [], ] : [],
=======
color: isSelected ? activeBg : theme.cardTheme.color,
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: isSelected ? activeColor : theme.colorScheme.outline.withOpacity(0.1),
width: isSelected ? 2 : 1,
),
>>>>>>> 6742220 (Your commit message here)
), ),
child: Row( child: Row(
children: [ children: [
Container( Container(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
decoration: BoxDecoration( decoration: BoxDecoration(
<<<<<<< HEAD
color: isSelected ? activeColor : AppColors.lightGray.withOpacity(0.1), color: isSelected ? activeColor : AppColors.lightGray.withOpacity(0.1),
=======
color: isSelected ? activeColor : theme.colorScheme.surfaceVariant,
>>>>>>> 6742220 (Your commit message here)
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
child: Icon( child: Icon(
icon, icon,
<<<<<<< HEAD
color: isSelected ? Colors.white : AppColors.warmGray, color: isSelected ? Colors.white : AppColors.warmGray,
=======
color: isSelected ? Colors.white : theme.colorScheme.onSurfaceVariant,
>>>>>>> 6742220 (Your commit message here)
size: 24, size: 24,
), ),
), ),
@@ -290,18 +353,30 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
children: [ children: [
Text( Text(
title, title,
<<<<<<< HEAD
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.charcoal, color: AppColors.charcoal,
=======
style: theme.textTheme.titleLarge?.copyWith(
fontSize: 18,
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
subtitle, subtitle,
<<<<<<< HEAD
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 14, fontSize: 14,
color: AppColors.warmGray, color: AppColors.warmGray,
=======
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
], ],
@@ -316,6 +391,10 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
} }
Widget _buildNamePage() { Widget _buildNamePage() {
<<<<<<< HEAD
=======
final theme = Theme.of(context);
>>>>>>> 6742220 (Your commit message here)
final isHusband = _role == UserRole.husband; final isHusband = _role == UserRole.husband;
final activeColor = isHusband ? AppColors.navyBlue : AppColors.sageGreen; final activeColor = isHusband ? AppColors.navyBlue : AppColors.sageGreen;
@@ -327,18 +406,30 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
const SizedBox(height: 40), const SizedBox(height: 40),
Text( Text(
isHusband ? 'What\'s your name, sir?' : 'What\'s your name?', isHusband ? 'What\'s your name, sir?' : 'What\'s your name?',
<<<<<<< HEAD
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 28, fontSize: 28,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: isHusband ? AppColors.navyBlue : AppColors.charcoal, color: isHusband ? AppColors.navyBlue : AppColors.charcoal,
=======
style: theme.textTheme.displaySmall?.copyWith(
fontSize: 28,
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'We\'ll use this to personalize the app.', 'We\'ll use this to personalize the app.',
<<<<<<< HEAD
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 14, fontSize: 14,
color: AppColors.warmGray, color: AppColors.warmGray,
=======
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(height: 32), const SizedBox(height: 32),
@@ -349,6 +440,7 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
hintText: 'Enter your name', hintText: 'Enter your name',
prefixIcon: Icon( prefixIcon: Icon(
Icons.person_outline, Icons.person_outline,
<<<<<<< HEAD
color: AppColors.warmGray, color: AppColors.warmGray,
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
@@ -357,6 +449,16 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
), ),
), ),
style: GoogleFonts.outfit(fontSize: 16), style: GoogleFonts.outfit(fontSize: 16),
=======
color: theme.colorScheme.onSurfaceVariant,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: activeColor, width: 2),
),
),
style: theme.textTheme.bodyLarge,
>>>>>>> 6742220 (Your commit message here)
textCapitalization: TextCapitalization.words, textCapitalization: TextCapitalization.words,
), ),
@@ -365,6 +467,7 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
Row( Row(
children: [ children: [
Expanded( Expanded(
<<<<<<< HEAD
child: OutlinedButton( child: OutlinedButton(
onPressed: _previousPage, onPressed: _previousPage,
style: OutlinedButton.styleFrom( style: OutlinedButton.styleFrom(
@@ -372,16 +475,40 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
side: BorderSide(color: isHusband ? AppColors.navyBlue : AppColors.sageGreen), side: BorderSide(color: isHusband ? AppColors.navyBlue : AppColors.sageGreen),
), ),
child: const Text('Back'), child: const Text('Back'),
=======
child: SizedBox(
height: 54,
child: OutlinedButton(
onPressed: _previousPage,
style: OutlinedButton.styleFrom(
foregroundColor: activeColor,
side: BorderSide(color: activeColor),
),
child: const Text('Back'),
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
Expanded( Expanded(
<<<<<<< HEAD
child: ElevatedButton( child: ElevatedButton(
onPressed: (_name.isNotEmpty && !_isNavigating) ? _nextPage : null, onPressed: (_name.isNotEmpty && !_isNavigating) ? _nextPage : null,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: activeColor, backgroundColor: activeColor,
), ),
child: Text(isHusband ? 'Finish Setup' : 'Continue'), child: Text(isHusband ? 'Finish Setup' : 'Continue'),
=======
child: SizedBox(
height: 54,
child: ElevatedButton(
onPressed: (_name.isNotEmpty && !_isNavigating) ? _nextPage : null,
style: ElevatedButton.styleFrom(
backgroundColor: activeColor,
),
child: Text(isHusband ? 'Finish Setup' : 'Continue'),
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
], ],
@@ -392,6 +519,11 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
} }
Widget _buildRelationshipPage() { Widget _buildRelationshipPage() {
<<<<<<< HEAD
=======
final theme = Theme.of(context);
>>>>>>> 6742220 (Your commit message here)
return Padding( return Padding(
padding: const EdgeInsets.all(32), padding: const EdgeInsets.all(32),
child: Column( child: Column(
@@ -400,10 +532,17 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
const SizedBox(height: 40), const SizedBox(height: 40),
Text( Text(
'Tell us about yourself', 'Tell us about yourself',
<<<<<<< HEAD
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 28, fontSize: 28,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.charcoal, color: AppColors.charcoal,
=======
style: theme.textTheme.displaySmall?.copyWith(
fontSize: 28,
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(height: 32), const SizedBox(height: 32),
@@ -418,17 +557,39 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
Row( Row(
children: [ children: [
Expanded( Expanded(
<<<<<<< HEAD
child: OutlinedButton( child: OutlinedButton(
onPressed: _previousPage, onPressed: _previousPage,
style: OutlinedButton.styleFrom(foregroundColor: AppColors.sageGreen, side: BorderSide(color: AppColors.sageGreen)), style: OutlinedButton.styleFrom(foregroundColor: AppColors.sageGreen, side: BorderSide(color: AppColors.sageGreen)),
child: const Text('Back'), child: const Text('Back'),
=======
child: SizedBox(
height: 54,
child: OutlinedButton(
onPressed: _previousPage,
style: OutlinedButton.styleFrom(
foregroundColor: AppColors.sageGreen,
side: const BorderSide(color: AppColors.sageGreen)
),
child: const Text('Back'),
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
Expanded( Expanded(
<<<<<<< HEAD
child: ElevatedButton( child: ElevatedButton(
onPressed: (_relationshipStatus != null && !_isNavigating) ? _nextPage : null, onPressed: (_relationshipStatus != null && !_isNavigating) ? _nextPage : null,
child: const Text('Continue'), child: const Text('Continue'),
=======
child: SizedBox(
height: 54,
child: ElevatedButton(
onPressed: (_relationshipStatus != null && !_isNavigating) ? _nextPage : null,
child: const Text('Continue'),
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
], ],
@@ -439,30 +600,67 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
} }
Widget _buildRelationshipOption(RelationshipStatus status, String title, String subtitle, IconData icon) { Widget _buildRelationshipOption(RelationshipStatus status, String title, String subtitle, IconData icon) {
<<<<<<< HEAD
final isSelected = _relationshipStatus == status; final isSelected = _relationshipStatus == status;
=======
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
final isSelected = _relationshipStatus == status;
>>>>>>> 6742220 (Your commit message here)
return GestureDetector( return GestureDetector(
onTap: () => setState(() => _relationshipStatus = status), onTap: () => setState(() => _relationshipStatus = status),
child: AnimatedContainer( child: AnimatedContainer(
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
<<<<<<< HEAD
color: isSelected ? AppColors.sageGreen.withOpacity(0.1) : Colors.white, color: isSelected ? AppColors.sageGreen.withOpacity(0.1) : Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all( border: Border.all(
color: isSelected ? AppColors.sageGreen : AppColors.lightGray.withOpacity(0.5), color: isSelected ? AppColors.sageGreen : AppColors.lightGray.withOpacity(0.5),
=======
color: isSelected ? AppColors.sageGreen.withOpacity(isDark ? 0.3 : 0.1) : theme.cardTheme.color,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: isSelected ? AppColors.sageGreen : theme.colorScheme.outline.withOpacity(0.1),
>>>>>>> 6742220 (Your commit message here)
width: isSelected ? 2 : 1, width: isSelected ? 2 : 1,
), ),
), ),
child: Row( child: Row(
children: [ children: [
<<<<<<< HEAD
Icon(icon, color: isSelected ? AppColors.sageGreen : AppColors.warmGray), Icon(icon, color: isSelected ? AppColors.sageGreen : AppColors.warmGray),
=======
Icon(
icon,
color: isSelected ? AppColors.sageGreen : theme.colorScheme.onSurfaceVariant
),
>>>>>>> 6742220 (Your commit message here)
const SizedBox(width: 16), const SizedBox(width: 16),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
<<<<<<< HEAD
Text(title, style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.charcoal)), Text(title, style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.charcoal)),
Text(subtitle, style: GoogleFonts.outfit(fontSize: 13, color: AppColors.warmGray)), Text(subtitle, style: GoogleFonts.outfit(fontSize: 13, color: AppColors.warmGray)),
=======
Text(
title,
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface
)
),
Text(
subtitle,
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onSurfaceVariant
)
),
>>>>>>> 6742220 (Your commit message here)
], ],
), ),
), ),
@@ -474,13 +672,29 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
} }
Widget _buildFertilityGoalPage() { Widget _buildFertilityGoalPage() {
<<<<<<< HEAD
=======
final theme = Theme.of(context);
>>>>>>> 6742220 (Your commit message here)
return Padding( return Padding(
padding: const EdgeInsets.all(32), padding: const EdgeInsets.all(32),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 40), const SizedBox(height: 40),
<<<<<<< HEAD
Text('What\'s your goal?', style: GoogleFonts.outfit(fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.charcoal)), Text('What\'s your goal?', style: GoogleFonts.outfit(fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.charcoal)),
=======
Text(
'What\'s your goal?',
style: theme.textTheme.displaySmall?.copyWith(
fontSize: 28,
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface
)
),
>>>>>>> 6742220 (Your commit message here)
const SizedBox(height: 32), const SizedBox(height: 32),
_buildGoalOption(FertilityGoal.tryingToConceive, 'Trying to Conceive', 'Track fertile days', Icons.child_care_outlined), _buildGoalOption(FertilityGoal.tryingToConceive, 'Trying to Conceive', 'Track fertile days', Icons.child_care_outlined),
const SizedBox(height: 12), const SizedBox(height: 12),
@@ -491,17 +705,39 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
Row( Row(
children: [ children: [
Expanded( Expanded(
<<<<<<< HEAD
child: OutlinedButton( child: OutlinedButton(
onPressed: _previousPage, onPressed: _previousPage,
style: OutlinedButton.styleFrom(foregroundColor: AppColors.sageGreen, side: BorderSide(color: AppColors.sageGreen)), style: OutlinedButton.styleFrom(foregroundColor: AppColors.sageGreen, side: BorderSide(color: AppColors.sageGreen)),
child: const Text('Back'), child: const Text('Back'),
=======
child: SizedBox(
height: 54,
child: OutlinedButton(
onPressed: _previousPage,
style: OutlinedButton.styleFrom(
foregroundColor: AppColors.sageGreen,
side: const BorderSide(color: AppColors.sageGreen)
),
child: const Text('Back'),
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
Expanded( Expanded(
<<<<<<< HEAD
child: ElevatedButton( child: ElevatedButton(
onPressed: (_fertilityGoal != null && !_isNavigating) ? _nextPage : null, onPressed: (_fertilityGoal != null && !_isNavigating) ? _nextPage : null,
child: const Text('Continue'), child: const Text('Continue'),
=======
child: SizedBox(
height: 54,
child: ElevatedButton(
onPressed: (_fertilityGoal != null && !_isNavigating) ? _nextPage : null,
child: const Text('Continue'),
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
], ],
@@ -512,30 +748,67 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
} }
Widget _buildGoalOption(FertilityGoal goal, String title, String subtitle, IconData icon) { Widget _buildGoalOption(FertilityGoal goal, String title, String subtitle, IconData icon) {
<<<<<<< HEAD
final isSelected = _fertilityGoal == goal; final isSelected = _fertilityGoal == goal;
=======
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
final isSelected = _fertilityGoal == goal;
>>>>>>> 6742220 (Your commit message here)
return GestureDetector( return GestureDetector(
onTap: () => setState(() => _fertilityGoal = goal), onTap: () => setState(() => _fertilityGoal = goal),
child: AnimatedContainer( child: AnimatedContainer(
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
<<<<<<< HEAD
color: isSelected ? AppColors.sageGreen.withOpacity(0.1) : Colors.white, color: isSelected ? AppColors.sageGreen.withOpacity(0.1) : Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all( border: Border.all(
color: isSelected ? AppColors.sageGreen : AppColors.lightGray.withOpacity(0.5), color: isSelected ? AppColors.sageGreen : AppColors.lightGray.withOpacity(0.5),
=======
color: isSelected ? AppColors.sageGreen.withOpacity(isDark ? 0.3 : 0.1) : theme.cardTheme.color,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: isSelected ? AppColors.sageGreen : theme.colorScheme.outline.withOpacity(0.1),
>>>>>>> 6742220 (Your commit message here)
width: isSelected ? 2 : 1, width: isSelected ? 2 : 1,
), ),
), ),
child: Row( child: Row(
children: [ children: [
<<<<<<< HEAD
Icon(icon, color: isSelected ? AppColors.sageGreen : AppColors.warmGray), Icon(icon, color: isSelected ? AppColors.sageGreen : AppColors.warmGray),
=======
Icon(
icon,
color: isSelected ? AppColors.sageGreen : theme.colorScheme.onSurfaceVariant
),
>>>>>>> 6742220 (Your commit message here)
const SizedBox(width: 16), const SizedBox(width: 16),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
<<<<<<< HEAD
Text(title, style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.charcoal)), Text(title, style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.charcoal)),
Text(subtitle, style: GoogleFonts.outfit(fontSize: 13, color: AppColors.warmGray)), Text(subtitle, style: GoogleFonts.outfit(fontSize: 13, color: AppColors.warmGray)),
=======
Text(
title,
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface
)
),
Text(
subtitle,
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onSurfaceVariant
)
),
>>>>>>> 6742220 (Your commit message here)
], ],
), ),
), ),
@@ -547,16 +820,42 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
} }
Widget _buildCyclePage() { Widget _buildCyclePage() {
<<<<<<< HEAD
=======
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
>>>>>>> 6742220 (Your commit message here)
return Padding( return Padding(
padding: const EdgeInsets.all(32), padding: const EdgeInsets.all(32),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 40), const SizedBox(height: 40),
<<<<<<< HEAD
Text('About your cycle', style: GoogleFonts.outfit(fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.charcoal)), Text('About your cycle', style: GoogleFonts.outfit(fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.charcoal)),
const SizedBox(height: 32), const SizedBox(height: 32),
Text('Average cycle length', style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w500, color: AppColors.charcoal)), Text('Average cycle length', style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w500, color: AppColors.charcoal)),
=======
Text(
'About your cycle',
style: theme.textTheme.displaySmall?.copyWith(
fontSize: 28,
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface
)
),
const SizedBox(height: 32),
Text(
'Average cycle length',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w500,
color: theme.colorScheme.onSurface
)
),
>>>>>>> 6742220 (Your commit message here)
Row( Row(
children: [ children: [
Expanded( Expanded(
@@ -565,16 +864,39 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
min: 21, min: 21,
max: 40, max: 40,
divisions: 19, divisions: 19,
<<<<<<< HEAD
onChanged: (value) => setState(() => _averageCycleLength = value.round()), onChanged: (value) => setState(() => _averageCycleLength = value.round()),
), ),
), ),
Text('$_averageCycleLength days', style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.sageGreen)), Text('$_averageCycleLength days', style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.sageGreen)),
=======
activeColor: AppColors.sageGreen,
onChanged: (value) => setState(() => _averageCycleLength = value.round()),
),
),
Text(
'$_averageCycleLength days',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
color: AppColors.sageGreen
)
),
>>>>>>> 6742220 (Your commit message here)
], ],
), ),
// Irregular Cycle Checkbox // Irregular Cycle Checkbox
CheckboxListTile( CheckboxListTile(
<<<<<<< HEAD
title: Text('My cycles are irregular', style: GoogleFonts.outfit(fontSize: 14, color: AppColors.charcoal)), title: Text('My cycles are irregular', style: GoogleFonts.outfit(fontSize: 14, color: AppColors.charcoal)),
=======
title: Text(
'My cycles are irregular',
style: theme.textTheme.bodyLarge?.copyWith(
color: theme.colorScheme.onSurface
)
),
>>>>>>> 6742220 (Your commit message here)
value: _isIrregularCycle, value: _isIrregularCycle,
onChanged: (val) => setState(() => _isIrregularCycle = val ?? false), onChanged: (val) => setState(() => _isIrregularCycle = val ?? false),
activeColor: AppColors.sageGreen, activeColor: AppColors.sageGreen,
@@ -583,7 +905,17 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
<<<<<<< HEAD
Text('Last period start date', style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w500, color: AppColors.charcoal)), Text('Last period start date', style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w500, color: AppColors.charcoal)),
=======
Text(
'Last period start date',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w500,
color: theme.colorScheme.onSurface
)
),
>>>>>>> 6742220 (Your commit message here)
const SizedBox(height: 8), const SizedBox(height: 8),
GestureDetector( GestureDetector(
onTap: () async { onTap: () async {
@@ -594,8 +926,16 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
lastDate: DateTime.now(), lastDate: DateTime.now(),
builder: (context, child) { builder: (context, child) {
return Theme( return Theme(
<<<<<<< HEAD
data: Theme.of(context).copyWith( data: Theme.of(context).copyWith(
colorScheme: const ColorScheme.light(primary: AppColors.sageGreen, onPrimary: Colors.white, surface: Colors.white, onSurface: AppColors.charcoal), colorScheme: const ColorScheme.light(primary: AppColors.sageGreen, onPrimary: Colors.white, surface: Colors.white, onSurface: AppColors.charcoal),
=======
data: theme.copyWith(
colorScheme: theme.colorScheme.copyWith(
primary: AppColors.sageGreen,
onPrimary: Colors.white,
),
>>>>>>> 6742220 (Your commit message here)
), ),
child: child!, child: child!,
); );
@@ -605,12 +945,32 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
}, },
child: Container( child: Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
<<<<<<< HEAD
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.lightGray.withOpacity(0.5))), decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.lightGray.withOpacity(0.5))),
child: Row( child: Row(
children: [ children: [
Icon(Icons.calendar_today, color: AppColors.warmGray), Icon(Icons.calendar_today, color: AppColors.warmGray),
const SizedBox(width: 12), const SizedBox(width: 12),
Text(_lastPeriodStart != null ? "${_lastPeriodStart!.month}/${_lastPeriodStart!.day}/${_lastPeriodStart!.year}" : "Select Date", style: GoogleFonts.outfit(fontSize: 16, color: AppColors.charcoal)), Text(_lastPeriodStart != null ? "${_lastPeriodStart!.month}/${_lastPeriodStart!.day}/${_lastPeriodStart!.year}" : "Select Date", style: GoogleFonts.outfit(fontSize: 16, color: AppColors.charcoal)),
=======
decoration: BoxDecoration(
color: theme.cardTheme.color,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: theme.colorScheme.outline.withOpacity(0.1))
),
child: Row(
children: [
Icon(Icons.calendar_today, color: theme.colorScheme.onSurfaceVariant),
const SizedBox(width: 12),
Text(
_lastPeriodStart != null
? "${_lastPeriodStart!.month}/${_lastPeriodStart!.day}/${_lastPeriodStart!.year}"
: "Select Date",
style: theme.textTheme.bodyLarge?.copyWith(
color: theme.colorScheme.onSurface
)
),
>>>>>>> 6742220 (Your commit message here)
], ],
), ),
), ),
@@ -620,17 +980,39 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
Row( Row(
children: [ children: [
Expanded( Expanded(
<<<<<<< HEAD
child: OutlinedButton( child: OutlinedButton(
onPressed: _previousPage, onPressed: _previousPage,
style: OutlinedButton.styleFrom(foregroundColor: AppColors.sageGreen, side: BorderSide(color: AppColors.sageGreen)), style: OutlinedButton.styleFrom(foregroundColor: AppColors.sageGreen, side: BorderSide(color: AppColors.sageGreen)),
child: const Text('Back'), child: const Text('Back'),
=======
child: SizedBox(
height: 54,
child: OutlinedButton(
onPressed: _previousPage,
style: OutlinedButton.styleFrom(
foregroundColor: AppColors.sageGreen,
side: const BorderSide(color: AppColors.sageGreen)
),
child: const Text('Back'),
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
Expanded( Expanded(
<<<<<<< HEAD
child: ElevatedButton( child: ElevatedButton(
onPressed: (_lastPeriodStart != null && !_isNavigating) ? _nextPage : null, onPressed: (_lastPeriodStart != null && !_isNavigating) ? _nextPage : null,
child: const Text('Get Started'), child: const Text('Get Started'),
=======
child: SizedBox(
height: 54,
child: ElevatedButton(
onPressed: (_lastPeriodStart != null && !_isNavigating) ? _nextPage : null,
child: const Text('Get Started'),
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
], ],

View File

@@ -0,0 +1,48 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/user_profile.dart';
import '../models/scripture.dart';
import '../theme/app_theme.dart';
import '../providers/user_provider.dart';
class BibleUtils {
static Future<void> showTranslationPicker(BuildContext context, WidgetRef ref) async {
final user = ref.read(userProfileProvider);
if (user == null) return;
final selected = await showModalBottomSheet<BibleTranslation>(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (context) => Container(
padding: const EdgeInsets.symmetric(vertical: 20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Text(
'Select Bible Translation',
style: Theme.of(context).textTheme.titleLarge,
),
),
...BibleTranslation.values.map((t) => ListTile(
title: Text(t.label),
trailing: user.bibleTranslation == t
? const Icon(Icons.check, color: AppColors.sageGreen)
: null,
onTap: () => Navigator.pop(context, t),
)),
],
),
),
);
if (selected != null) {
await ref.read(userProfileProvider.notifier).updateProfile(
user.copyWith(bibleTranslation: selected)
);
}
}
}

View File

@@ -248,6 +248,7 @@ class AppTheme {
useMaterial3: true, useMaterial3: true,
brightness: Brightness.dark, brightness: Brightness.dark,
<<<<<<< HEAD
colorScheme: const ColorScheme.dark( colorScheme: const ColorScheme.dark(
primary: AppColors.sageGreen, primary: AppColors.sageGreen,
secondary: AppColors.rose, secondary: AppColors.rose,
@@ -258,12 +259,73 @@ class AppTheme {
scaffoldBackgroundColor: const Color(0xFF121212), scaffoldBackgroundColor: const Color(0xFF121212),
=======
// Color Scheme
colorScheme: ColorScheme.dark(
primary: AppColors.sageGreen,
secondary: AppColors.rose,
tertiary: AppColors.lavender,
surface: const Color(0xFF1E1E1E),
error: AppColors.error,
onPrimary: Colors.white,
onSecondary: Colors.white,
onSurface: Colors.white,
onSurfaceVariant: Colors.white70,
outline: Colors.white.withOpacity(0.1),
),
// Scaffold
scaffoldBackgroundColor: const Color(0xFF121212),
// AppBar
appBarTheme: AppBarTheme(
backgroundColor: const Color(0xFF121212),
foregroundColor: Colors.white,
elevation: 0,
centerTitle: true,
titleTextStyle: GoogleFonts.outfit(
fontSize: 20,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
// Text Theme
>>>>>>> 6742220 (Your commit message here)
textTheme: TextTheme( textTheme: TextTheme(
displayLarge: GoogleFonts.outfit( displayLarge: GoogleFonts.outfit(
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.white, color: Colors.white,
), ),
<<<<<<< HEAD
=======
displayMedium: GoogleFonts.outfit(
fontSize: 28,
fontWeight: FontWeight.w600,
color: Colors.white,
),
headlineLarge: GoogleFonts.outfit(
fontSize: 24,
fontWeight: FontWeight.w600,
color: Colors.white,
),
headlineMedium: GoogleFonts.outfit(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Colors.white,
),
titleLarge: GoogleFonts.outfit(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Colors.white,
),
titleMedium: GoogleFonts.outfit(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.white,
),
>>>>>>> 6742220 (Your commit message here)
bodyLarge: GoogleFonts.outfit( bodyLarge: GoogleFonts.outfit(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
@@ -274,6 +336,7 @@ class AppTheme {
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Colors.white70, color: Colors.white70,
), ),
<<<<<<< HEAD
), ),
cardTheme: CardTheme( cardTheme: CardTheme(
@@ -282,6 +345,121 @@ class AppTheme {
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
), ),
=======
bodySmall: GoogleFonts.outfit(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.white54,
),
labelLarge: GoogleFonts.outfit(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
// Card Theme
cardTheme: CardTheme(
color: const Color(0xFF1E1E1E),
elevation: 0, // Material 3 uses color/opacity for elevation in dark mode
shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
side: BorderSide(color: Colors.white.withOpacity(0.05)),
),
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
),
// Button Themes
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.sageGreen,
foregroundColor: Colors.white,
elevation: 0,
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
textStyle: GoogleFonts.outfit(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
foregroundColor: AppColors.sageGreen,
side: BorderSide(color: AppColors.sageGreen.withOpacity(0.5), width: 1.5),
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
textStyle: GoogleFonts.outfit(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
// Input Decoration
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: const Color(0xFF1E1E1E),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.white.withOpacity(0.1)),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.white.withOpacity(0.1)),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: AppColors.sageGreen, width: 2),
),
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
hintStyle: GoogleFonts.outfit(
color: Colors.white38,
fontSize: 14,
),
),
// Bottom Navigation
bottomNavigationBarTheme: BottomNavigationBarThemeData(
backgroundColor: const Color(0xFF1E1E1E),
selectedItemColor: AppColors.sageGreen,
unselectedItemColor: Colors.white38,
type: BottomNavigationBarType.fixed,
elevation: 0,
selectedLabelStyle: GoogleFonts.outfit(
fontSize: 12,
fontWeight: FontWeight.w500,
),
unselectedLabelStyle: GoogleFonts.outfit(
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
// Slider Theme
sliderTheme: SliderThemeData(
activeTrackColor: AppColors.sageGreen,
inactiveTrackColor: Colors.white.withOpacity(0.1),
thumbColor: AppColors.sageGreen,
overlayColor: AppColors.sageGreen.withOpacity(0.2),
trackHeight: 4,
tickMarkShape: const RoundSliderTickMarkShape(),
activeTickMarkColor: Colors.white24,
inactiveTickMarkColor: Colors.white10,
),
// Divider
dividerTheme: DividerThemeData(
color: Colors.white.withOpacity(0.05),
thickness: 1,
space: 24,
>>>>>>> 6742220 (Your commit message here)
), ),
); );
} }
@@ -289,19 +467,35 @@ class AppTheme {
/// Scripture text style /// Scripture text style
TextStyle scriptureStyle(BuildContext context, {double? fontSize}) { TextStyle scriptureStyle(BuildContext context, {double? fontSize}) {
<<<<<<< HEAD
return GoogleFonts.lora( return GoogleFonts.lora(
fontSize: fontSize ?? 16, fontSize: fontSize ?? 16,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
color: AppColors.charcoal, color: AppColors.charcoal,
=======
final isDark = Theme.of(context).brightness == Brightness.dark;
return GoogleFonts.lora(
fontSize: fontSize ?? 16,
fontStyle: FontStyle.italic,
color: isDark ? Colors.white : AppColors.charcoal,
>>>>>>> 6742220 (Your commit message here)
height: 1.6, height: 1.6,
); );
} }
/// Scripture reference style /// Scripture reference style
TextStyle scriptureRefStyle(BuildContext context) { TextStyle scriptureRefStyle(BuildContext context) {
<<<<<<< HEAD
return GoogleFonts.outfit( return GoogleFonts.outfit(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.warmGray, color: AppColors.warmGray,
=======
final isDark = Theme.of(context).brightness == Brightness.dark;
return GoogleFonts.outfit(
fontSize: 12,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white54 : AppColors.warmGray,
>>>>>>> 6742220 (Your commit message here)
); );
} }

View File

@@ -4,7 +4,11 @@ import 'dart:math' as math;
import '../theme/app_theme.dart'; import '../theme/app_theme.dart';
import '../models/cycle_entry.dart'; import '../models/cycle_entry.dart';
<<<<<<< HEAD
class CycleRing extends StatelessWidget { class CycleRing extends StatelessWidget {
=======
class CycleRing extends StatefulWidget {
>>>>>>> 6742220 (Your commit message here)
final int dayOfCycle; final int dayOfCycle;
final int totalDays; final int totalDays;
final CyclePhase phase; final CyclePhase phase;
@@ -17,6 +21,7 @@ class CycleRing extends StatelessWidget {
}); });
@override @override
<<<<<<< HEAD
Widget build(BuildContext context) { Widget build(BuildContext context) {
final progress = dayOfCycle / totalDays; final progress = dayOfCycle / totalDays;
final daysUntilNextPeriod = totalDays - dayOfCycle; final daysUntilNextPeriod = totalDays - dayOfCycle;
@@ -82,12 +87,128 @@ class CycleRing extends StatelessWidget {
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 12, fontSize: 12,
color: AppColors.warmGray, color: AppColors.warmGray,
=======
State<CycleRing> createState() => _CycleRingState();
}
class _CycleRingState extends State<CycleRing> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1500),
);
_animation = CurvedAnimation(
parent: _controller,
curve: Curves.easeOutCubic,
);
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final targetProgress = widget.dayOfCycle / widget.totalDays;
final daysUntilNextPeriod = widget.totalDays - widget.dayOfCycle;
final isDark = Theme.of(context).brightness == Brightness.dark;
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
final currentProgress = targetProgress * _animation.value;
return SizedBox(
width: 220,
height: 220,
child: Stack(
alignment: Alignment.center,
children: [
// Background ring
CustomPaint(
size: const Size(220, 220),
painter: _CycleRingPainter(
progress: currentProgress,
phase: widget.phase,
isDark: isDark,
),
),
// Center content with scale and fade animation
Transform.scale(
scale: 0.8 + (0.2 * _animation.value),
child: Opacity(
opacity: _animation.value,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Day ${widget.dayOfCycle}',
style: Theme.of(context).textTheme.displayMedium?.copyWith(
fontSize: 32,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurface,
),
),
const SizedBox(height: 4),
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: _getPhaseColor(widget.phase).withOpacity(isDark ? 0.3 : 0.2),
borderRadius: BorderRadius.circular(20),
border: isDark ? Border.all(color: _getPhaseColor(widget.phase).withOpacity(0.5)) : null,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
widget.phase.emoji,
style: const TextStyle(fontSize: 14),
),
const SizedBox(width: 6),
Text(
widget.phase.label,
style: GoogleFonts.outfit(
fontSize: 14,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : _getPhaseColor(widget.phase),
),
),
],
),
),
const SizedBox(height: 8),
Text(
daysUntilNextPeriod > 0
? '$daysUntilNextPeriod days until period'
: 'Period expected',
style: Theme.of(context).textTheme.bodySmall?.copyWith(
fontSize: 12,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
], ],
), ),
<<<<<<< HEAD
], ],
), ),
=======
);
},
>>>>>>> 6742220 (Your commit message here)
); );
} }
@@ -108,8 +229,18 @@ class CycleRing extends StatelessWidget {
class _CycleRingPainter extends CustomPainter { class _CycleRingPainter extends CustomPainter {
final double progress; final double progress;
final CyclePhase phase; final CyclePhase phase;
<<<<<<< HEAD
_CycleRingPainter({required this.progress, required this.phase}); _CycleRingPainter({required this.progress, required this.phase});
=======
final bool isDark;
_CycleRingPainter({
required this.progress,
required this.phase,
required this.isDark,
});
>>>>>>> 6742220 (Your commit message here)
@override @override
void paint(Canvas canvas, Size size) { void paint(Canvas canvas, Size size) {
@@ -119,7 +250,11 @@ class _CycleRingPainter extends CustomPainter {
// Background arc // Background arc
final bgPaint = Paint() final bgPaint = Paint()
<<<<<<< HEAD
..color = AppColors.lightGray.withOpacity(0.2) ..color = AppColors.lightGray.withOpacity(0.2)
=======
..color = (isDark ? Colors.white : AppColors.lightGray).withOpacity(isDark ? 0.05 : 0.1)
>>>>>>> 6742220 (Your commit message here)
..style = PaintingStyle.stroke ..style = PaintingStyle.stroke
..strokeWidth = strokeWidth ..strokeWidth = strokeWidth
..strokeCap = StrokeCap.round; ..strokeCap = StrokeCap.round;
@@ -152,7 +287,11 @@ class _CycleRingPainter extends CustomPainter {
final dotY = center.dy + radius * math.sin(dotAngle); final dotY = center.dy + radius * math.sin(dotAngle);
final dotPaint = Paint() final dotPaint = Paint()
<<<<<<< HEAD
..color = Colors.white ..color = Colors.white
=======
..color = isDark ? const Color(0xFF1E1E1E) : Colors.white
>>>>>>> 6742220 (Your commit message here)
..style = PaintingStyle.fill; ..style = PaintingStyle.fill;
final dotBorderPaint = Paint() final dotBorderPaint = Paint()

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
<<<<<<< HEAD
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import '../theme/app_theme.dart'; import '../theme/app_theme.dart';
import '../screens/log/log_screen.dart'; import '../screens/log/log_screen.dart';
@@ -36,11 +37,56 @@ class QuickLogButtons extends StatelessWidget {
label: 'Symptoms', label: 'Symptoms',
color: AppColors.lavender, color: AppColors.lavender,
onTap: () => _navigateToLog(context), onTap: () => _navigateToLog(context),
=======
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import '../theme/app_theme.dart';
import '../providers/navigation_provider.dart';
class QuickLogButtons extends ConsumerWidget {
const QuickLogButtons({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Row(
children: [
_buildQuickButton(
context,
icon: Icons.water_drop_outlined,
label: 'Period',
color: AppColors.menstrualPhase,
onTap: () => _navigateToLog(ref),
),
const SizedBox(width: 12),
_buildQuickButton(
context,
icon: Icons.emoji_emotions_outlined,
label: 'Mood',
color: AppColors.softGold,
onTap: () => _navigateToLog(ref),
),
const SizedBox(width: 12),
_buildQuickButton(
context,
icon: Icons.flash_on_outlined,
label: 'Energy',
color: AppColors.follicularPhase,
onTap: () => _navigateToLog(ref),
),
const SizedBox(width: 12),
_buildQuickButton(
context,
icon: Icons.healing_outlined,
label: 'Symptoms',
color: AppColors.lavender,
onTap: () => _navigateToLog(ref),
>>>>>>> 6742220 (Your commit message here)
), ),
], ],
); );
} }
<<<<<<< HEAD
void _navigateToLog(BuildContext context) { void _navigateToLog(BuildContext context) {
// Navigate to the Log tab (index 2) of HomeScreen if possible, // Navigate to the Log tab (index 2) of HomeScreen if possible,
// but since we are inside a tab, we can't easily switch the parent tab index without context. Using a provider or callback would be best. // but since we are inside a tab, we can't easily switch the parent tab index without context. Using a provider or callback would be best.
@@ -59,11 +105,21 @@ class QuickLogButtons extends StatelessWidget {
} }
Widget _buildQuickButton({ Widget _buildQuickButton({
=======
void _navigateToLog(WidgetRef ref) {
// Navigate to the Log tab (index 2)
ref.read(navigationProvider.notifier).setIndex(2);
}
Widget _buildQuickButton(
BuildContext context, {
>>>>>>> 6742220 (Your commit message here)
required IconData icon, required IconData icon,
required String label, required String label,
required Color color, required Color color,
required VoidCallback onTap, required VoidCallback onTap,
}) { }) {
<<<<<<< HEAD
return Expanded( return Expanded(
child: GestureDetector( child: GestureDetector(
onTap: onTap, onTap: onTap,
@@ -87,6 +143,38 @@ class QuickLogButtons extends StatelessWidget {
), ),
), ),
], ],
=======
final isDark = Theme.of(context).brightness == Brightness.dark;
return Expanded(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 16),
decoration: BoxDecoration(
color: color.withOpacity(isDark ? 0.2 : 0.15),
borderRadius: BorderRadius.circular(12),
border: isDark ? Border.all(color: color.withOpacity(0.3)) : null,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, color: color, size: 24),
const SizedBox(height: 6),
Text(
label,
style: GoogleFonts.outfit(
fontSize: 11,
fontWeight: FontWeight.w600,
color: isDark ? Colors.white.withOpacity(0.9) : color,
),
),
],
),
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
), ),

View File

@@ -6,35 +6,66 @@ import '../models/cycle_entry.dart';
class ScriptureCard extends StatelessWidget { class ScriptureCard extends StatelessWidget {
final String verse; final String verse;
final String reference; final String reference;
<<<<<<< HEAD
final CyclePhase phase; final CyclePhase phase;
=======
final String? translation;
final CyclePhase phase;
final VoidCallback? onTranslationTap;
>>>>>>> 6742220 (Your commit message here)
const ScriptureCard({ const ScriptureCard({
super.key, super.key,
required this.verse, required this.verse,
required this.reference, required this.reference,
<<<<<<< HEAD
required this.phase, required this.phase,
=======
this.translation,
required this.phase,
this.onTranslationTap,
>>>>>>> 6742220 (Your commit message here)
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
<<<<<<< HEAD
return Container( return Container(
width: double.infinity, width: double.infinity,
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
colors: _getGradientColors(phase), colors: _getGradientColors(phase),
=======
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
return Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: _getGradientColors(context, phase),
>>>>>>> 6742220 (Your commit message here)
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
), ),
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
<<<<<<< HEAD
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: _getPhaseColor(phase).withOpacity(0.2), color: _getPhaseColor(phase).withOpacity(0.2),
=======
border: Border.all(color: isDark ? Colors.white.withOpacity(0.05) : Colors.black.withOpacity(0.05)),
boxShadow: [
BoxShadow(
color: _getPhaseColor(phase).withOpacity(isDark ? 0.05 : 0.15),
>>>>>>> 6742220 (Your commit message here)
blurRadius: 15, blurRadius: 15,
offset: const Offset(0, 8), offset: const Offset(0, 8),
), ),
], ],
), ),
<<<<<<< HEAD
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -90,10 +121,103 @@ class ScriptureCard extends StatelessWidget {
), ),
), ),
], ],
=======
child: Material(
color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Scripture icon
Row(
children: [
Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: (isDark ? Colors.white : Colors.black).withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(
Icons.menu_book_outlined,
size: 18,
color: isDark ? Colors.white70 : AppColors.charcoal.withOpacity(0.8),
),
),
const SizedBox(width: 8),
Text(
'Today\'s Verse',
style: theme.textTheme.labelLarge?.copyWith(
fontSize: 12,
color: isDark ? Colors.white60 : AppColors.charcoal.withOpacity(0.7),
letterSpacing: 0.5,
),
),
],
),
const SizedBox(height: 16),
// Verse
Text(
'"$verse"',
style: scriptureStyle(context, fontSize: 17),
),
const SizedBox(height: 12),
// Reference & Translation
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'$reference',
style: scriptureRefStyle(context).copyWith(fontSize: 13, fontWeight: FontWeight.w600),
),
if (translation != null)
InkWell(
onTap: onTranslationTap,
borderRadius: BorderRadius.circular(8),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
decoration: BoxDecoration(
color: (isDark ? Colors.white : Colors.black).withOpacity(0.05),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: (isDark ? Colors.white : Colors.black).withOpacity(0.1),
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
translation!,
style: scriptureRefStyle(context).copyWith(
fontSize: 10,
fontWeight: FontWeight.w800,
letterSpacing: 0.8,
),
),
const SizedBox(width: 4),
Icon(
Icons.swap_horiz,
size: 14,
color: isDark ? Colors.white38 : AppColors.warmGray,
),
],
),
),
),
],
),
],
),
),
>>>>>>> 6742220 (Your commit message here)
), ),
); );
} }
<<<<<<< HEAD
List<Color> _getGradientColors(CyclePhase phase) { List<Color> _getGradientColors(CyclePhase phase) {
switch (phase) { switch (phase) {
case CyclePhase.menstrual: case CyclePhase.menstrual:
@@ -115,6 +239,32 @@ class ScriptureCard extends StatelessWidget {
return [ return [
AppColors.lutealPhase.withOpacity(0.3), AppColors.lutealPhase.withOpacity(0.3),
AppColors.cream, AppColors.cream,
=======
List<Color> _getGradientColors(BuildContext context, CyclePhase phase) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final baseColor = isDark ? const Color(0xFF1E1E1E) : AppColors.cream;
switch (phase) {
case CyclePhase.menstrual:
return [
AppColors.menstrualPhase.withOpacity(isDark ? 0.15 : 0.6),
baseColor,
];
case CyclePhase.follicular:
return [
AppColors.follicularPhase.withOpacity(isDark ? 0.15 : 0.3),
baseColor,
];
case CyclePhase.ovulation:
return [
AppColors.ovulationPhase.withOpacity(isDark ? 0.15 : 0.5),
baseColor,
];
case CyclePhase.luteal:
return [
AppColors.lutealPhase.withOpacity(isDark ? 0.15 : 0.3),
baseColor,
>>>>>>> 6742220 (Your commit message here)
]; ];
} }
} }

View File

@@ -15,17 +15,31 @@ class TipCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
<<<<<<< HEAD
=======
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
>>>>>>> 6742220 (Your commit message here)
final tip = _getTipForPhase(phase, isMarried); final tip = _getTipForPhase(phase, isMarried);
return Container( return Container(
width: double.infinity, width: double.infinity,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
<<<<<<< HEAD
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: AppColors.charcoal.withOpacity(0.05), color: AppColors.charcoal.withOpacity(0.05),
=======
color: theme.cardColor,
borderRadius: BorderRadius.circular(16),
border: isDark ? Border.all(color: Colors.white.withOpacity(0.05)) : null,
boxShadow: [
BoxShadow(
color: (isDark ? Colors.black : AppColors.charcoal).withOpacity(0.05),
>>>>>>> 6742220 (Your commit message here)
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -38,7 +52,11 @@ class TipCard extends StatelessWidget {
width: 40, width: 40,
height: 40, height: 40,
decoration: BoxDecoration( decoration: BoxDecoration(
<<<<<<< HEAD
color: AppColors.sageGreen.withOpacity(0.15), color: AppColors.sageGreen.withOpacity(0.15),
=======
color: AppColors.sageGreen.withOpacity(isDark ? 0.2 : 0.15),
>>>>>>> 6742220 (Your commit message here)
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: const Icon( child: const Icon(
@@ -54,21 +72,57 @@ class TipCard extends StatelessWidget {
children: [ children: [
Text( Text(
'Today\'s Tip', 'Today\'s Tip',
<<<<<<< HEAD
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.charcoal, color: AppColors.charcoal,
=======
style: theme.textTheme.titleMedium?.copyWith(
fontSize: 14,
fontWeight: FontWeight.w600,
>>>>>>> 6742220 (Your commit message here)
), ),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
tip, tip,
<<<<<<< HEAD
style: GoogleFonts.outfit( style: GoogleFonts.outfit(
fontSize: 13, fontSize: 13,
color: AppColors.warmGray, color: AppColors.warmGray,
height: 1.4, height: 1.4,
), ),
), ),
=======
style: theme.textTheme.bodyMedium?.copyWith(
fontSize: 13,
height: 1.4,
),
),
const SizedBox(height: 12),
InkWell(
onTap: () => _showDetailedInsights(context),
child: Row(
children: [
Text(
'Learn More',
style: GoogleFonts.outfit(
fontSize: 12,
fontWeight: FontWeight.w600,
color: AppColors.sageGreen,
),
),
const SizedBox(width: 4),
const Icon(
Icons.arrow_forward_ios,
size: 10,
color: AppColors.sageGreen,
),
],
),
),
>>>>>>> 6742220 (Your commit message here)
], ],
), ),
), ),
@@ -77,6 +131,7 @@ class TipCard extends StatelessWidget {
); );
} }
<<<<<<< HEAD
String _getTipForPhase(CyclePhase phase, bool isMarried) { String _getTipForPhase(CyclePhase phase, bool isMarried) {
switch (phase) { switch (phase) {
case CyclePhase.menstrual: case CyclePhase.menstrual:
@@ -90,6 +145,123 @@ class TipCard extends StatelessWidget {
return 'You may feel more social and confident during this phase. It\'s a great time for important conversations and presentations.'; return 'You may feel more social and confident during this phase. It\'s a great time for important conversations and presentations.';
case CyclePhase.luteal: case CyclePhase.luteal:
return 'As you enter the luteal phase, focus on nourishing foods, adequate sleep, and stress management. Be gentle with yourself.'; return 'As you enter the luteal phase, focus on nourishing foods, adequate sleep, and stress management. Be gentle with yourself.';
=======
void _showDetailedInsights(BuildContext context) {
final details = _getDetailsForPhase(phase);
showDialog(
context: context,
builder: (context) => AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
title: Column(
children: [
Text(
'Phase Insight: ${phase.label}',
textAlign: TextAlign.center,
style: GoogleFonts.outfit(fontWeight: FontWeight.w600),
),
const SizedBox(height: 8),
Text(
phase.emoji,
style: const TextStyle(fontSize: 32),
),
],
),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildDetailSection('Nutrition', details['nutrition']!, Icons.restaurant),
const SizedBox(height: 16),
_buildDetailSection('Movement', details['movement']!, Icons.fitness_center),
const SizedBox(height: 16),
Text(
'Note: While these are general trends, your body is unique. Always listen to your own energy levels.',
style: GoogleFonts.outfit(
fontSize: 11,
fontStyle: FontStyle.italic,
color: AppColors.warmGray,
),
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('Got it', style: GoogleFonts.outfit(color: AppColors.sageGreen)),
),
],
),
);
}
Widget _buildDetailSection(String title, String content, IconData icon) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(icon, size: 16, color: AppColors.sageGreen),
const SizedBox(width: 6),
Text(
title,
style: GoogleFonts.outfit(
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
],
),
const SizedBox(height: 6),
Text(
content,
style: GoogleFonts.outfit(
fontSize: 13,
color: AppColors.charcoal,
),
),
],
);
}
String _getTipForPhase(CyclePhase phase, bool isMarried) {
switch (phase) {
case CyclePhase.menstrual:
return 'Focus on iron-rich foods and gentle rest. Your body is working hard; honor it with hydration and Vitamin C.';
case CyclePhase.follicular:
return 'Energy is rising! Support your cycle with cruciferous vegetables and lean protein as you transition to more active movement.';
case CyclePhase.ovulation:
if (isMarried) {
return 'Peak energy and connection. Focus on healthy fats for hormonal support and prioritize quality time with your spouse.';
}
return 'Peak confidence and social energy. Support your peak energy with complex carbs and social engagement.';
case CyclePhase.luteal:
return 'Nourish your nervous system with magnesium-rich foods and steady mobility. Transition to restorative self-care.';
}
}
Map<String, String> _getDetailsForPhase(CyclePhase phase) {
switch (phase) {
case CyclePhase.menstrual:
return {
'nutrition': 'Incorporate leafy greens, red meat or lentils for iron. Pair with citrus for better absorption.',
'movement': 'Gentle walking, restorative yoga, or just deep breathing. Avoid high-intensity stress.',
};
case CyclePhase.follicular:
return {
'nutrition': 'Broccoli, cauliflower, and fermented foods help balance rising estrogen. Focus on lean proteins.',
'movement': 'Strength training and steady cardio. Your body is primed for building and renewal.',
};
case CyclePhase.ovulation:
return {
'nutrition': 'Avocados, nuts, and seeds provide healthy fats for peak hormonal health. Keep hydration high.',
'movement': 'Highest intensity workouts, HIIT, or group sports. You have peak stamina and strength right now.',
};
case CyclePhase.luteal:
return {
'nutrition': 'Dark chocolate (70%+), pumpkin seeds, and bananas for magnesium to help with cramps.',
'movement': 'Pilates, steady-state swimming, or hiking. Focus on persistence rather than peak intensity.',
};
>>>>>>> 6742220 (Your commit message here)
} }
} }
} }

View File

@@ -5,23 +5,41 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
<<<<<<< HEAD
sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "72.0.0" version: "72.0.0"
=======
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
url: "https://pub.dev"
source: hosted
version: "76.0.0"
>>>>>>> 6742220 (Your commit message here)
_macros: _macros:
dependency: transitive dependency: transitive
description: dart description: dart
source: sdk source: sdk
<<<<<<< HEAD
version: "0.3.2" version: "0.3.2"
=======
version: "0.3.3"
>>>>>>> 6742220 (Your commit message here)
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
<<<<<<< HEAD
sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.7.0" version: "6.7.0"
=======
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
url: "https://pub.dev"
source: hosted
version: "6.11.0"
>>>>>>> 6742220 (Your commit message here)
args: args:
dependency: transitive dependency: transitive
description: description:
@@ -146,10 +164,17 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
<<<<<<< HEAD
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.18.0" version: "1.18.0"
=======
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
url: "https://pub.dev"
source: hosted
version: "1.19.0"
>>>>>>> 6742220 (Your commit message here)
convert: convert:
dependency: transitive dependency: transitive
description: description:
@@ -417,18 +442,32 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
<<<<<<< HEAD
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.5" version: "10.0.5"
=======
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
url: "https://pub.dev"
source: hosted
version: "10.0.7"
>>>>>>> 6742220 (Your commit message here)
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
<<<<<<< HEAD
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.5" version: "3.0.5"
=======
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
url: "https://pub.dev"
source: hosted
version: "3.0.8"
>>>>>>> 6742220 (Your commit message here)
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
@@ -457,10 +496,17 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: macros name: macros
<<<<<<< HEAD
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.2-main.4" version: "0.1.2-main.4"
=======
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
url: "https://pub.dev"
source: hosted
version: "0.1.3-main.0"
>>>>>>> 6742220 (Your commit message here)
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@@ -713,7 +759,11 @@ packages:
dependency: transitive dependency: transitive
description: flutter description: flutter
source: sdk source: sdk
<<<<<<< HEAD
version: "0.0.99" version: "0.0.99"
=======
version: "0.0.0"
>>>>>>> 6742220 (Your commit message here)
smooth_page_indicator: smooth_page_indicator:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -750,10 +800,17 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
<<<<<<< HEAD
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.11.1" version: "1.11.1"
=======
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
url: "https://pub.dev"
source: hosted
version: "1.12.0"
>>>>>>> 6742220 (Your commit message here)
state_notifier: state_notifier:
dependency: transitive dependency: transitive
description: description:
@@ -782,10 +839,17 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
<<<<<<< HEAD
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
=======
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
>>>>>>> 6742220 (Your commit message here)
table_calendar: table_calendar:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -806,10 +870,17 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
<<<<<<< HEAD
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.2" version: "0.7.2"
=======
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
url: "https://pub.dev"
source: hosted
version: "0.7.3"
>>>>>>> 6742220 (Your commit message here)
timezone: timezone:
dependency: transitive dependency: transitive
description: description:
@@ -878,10 +949,17 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
<<<<<<< HEAD
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.2.5" version: "14.2.5"
=======
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
url: "https://pub.dev"
source: hosted
version: "14.3.0"
>>>>>>> 6742220 (Your commit message here)
watcher: watcher:
dependency: transitive dependency: transitive
description: description: