Implement husband-wife connection dialogue and theme support for learn articles

This commit is contained in:
2026-01-05 17:09:15 -06:00
parent 02d25d0cc7
commit 96655f9a74
36 changed files with 3849 additions and 819 deletions

View File

@@ -12,11 +12,13 @@ import '../devotional/devotional_screen.dart';
import '../settings/appearance_screen.dart';
import '../settings/cycle_settings_screen.dart';
import '../settings/relationship_settings_screen.dart';
import '../settings/goal_settings_screen.dart'; // Add this
import '../settings/goal_settings_screen.dart';
import '../settings/cycle_history_screen.dart';
import '../settings/sharing_settings_screen.dart';
import '../settings/notification_settings_screen.dart';
import '../settings/privacy_settings_screen.dart';
import '../settings/supplies_settings_screen.dart';
import '../settings/export_data_screen.dart';
import '../learn/wife_learn_screen.dart';
import '../../widgets/tip_card.dart';
import '../../widgets/cycle_ring.dart';
@@ -36,19 +38,47 @@ class HomeScreen extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final selectedIndex = ref.watch(navigationProvider);
final isPadTrackingEnabled = ref.watch(userProfileProvider.select((u) => u?.isPadTrackingEnabled ?? false));
final isSingle = ref.watch(userProfileProvider.select((u) => u?.relationshipStatus == RelationshipStatus.single));
final tabs = [
const _DashboardTab(),
const CalendarScreen(),
const LogScreen(),
if (isPadTrackingEnabled) const PadTrackerScreen(),
const DevotionalScreen(),
const WifeLearnScreen(),
_SettingsTab(
onReset: () =>
ref.read(navigationProvider.notifier).setIndex(0)),
];
final List<Widget> tabs;
final List<BottomNavigationBarItem> navBarItems;
if (isPadTrackingEnabled) {
tabs = [
const _DashboardTab(),
const CalendarScreen(),
const PadTrackerScreen(),
const LogScreen(),
const DevotionalScreen(),
const WifeLearnScreen(),
_SettingsTab(onReset: () => ref.read(navigationProvider.notifier).setIndex(0)),
];
navBarItems = [
const BottomNavigationBarItem(icon: Icon(Icons.home_outlined), activeIcon: Icon(Icons.home), label: 'Home'),
const BottomNavigationBarItem(icon: Icon(Icons.calendar_today_outlined), activeIcon: Icon(Icons.calendar_today), label: 'Calendar'),
const BottomNavigationBarItem(icon: Icon(Icons.inventory_2_outlined), activeIcon: Icon(Icons.inventory_2), label: 'Supplies'),
const BottomNavigationBarItem(icon: Icon(Icons.add_circle_outline), activeIcon: Icon(Icons.add_circle), label: 'Log'),
const BottomNavigationBarItem(icon: Icon(Icons.menu_book_outlined), activeIcon: Icon(Icons.menu_book), label: 'Devotional'),
const BottomNavigationBarItem(icon: Icon(Icons.school_outlined), activeIcon: Icon(Icons.school), label: 'Learn'),
const BottomNavigationBarItem(icon: Icon(Icons.settings_outlined), activeIcon: Icon(Icons.settings), label: 'Settings'),
];
} else {
tabs = [
const _DashboardTab(),
const CalendarScreen(),
const DevotionalScreen(),
const LogScreen(),
const WifeLearnScreen(),
_SettingsTab(onReset: () => ref.read(navigationProvider.notifier).setIndex(0)),
];
navBarItems = [
const BottomNavigationBarItem(icon: Icon(Icons.home_outlined), activeIcon: Icon(Icons.home), label: 'Home'),
const BottomNavigationBarItem(icon: Icon(Icons.calendar_today_outlined), activeIcon: Icon(Icons.calendar_today), label: 'Calendar'),
const BottomNavigationBarItem(icon: Icon(Icons.menu_book_outlined), activeIcon: Icon(Icons.menu_book), label: 'Devotional'),
const BottomNavigationBarItem(icon: Icon(Icons.add_circle_outline), activeIcon: Icon(Icons.add_circle), label: 'Log'),
const BottomNavigationBarItem(icon: Icon(Icons.school_outlined), activeIcon: Icon(Icons.school), label: 'Learn'),
const BottomNavigationBarItem(icon: Icon(Icons.settings_outlined), activeIcon: Icon(Icons.settings), label: 'Settings'),
];
}
return Scaffold(
body: IndexedStack(
@@ -73,44 +103,7 @@ class HomeScreen extends ConsumerWidget {
currentIndex: selectedIndex >= tabs.length ? 0 : selectedIndex,
onTap: (index) =>
ref.read(navigationProvider.notifier).setIndex(index),
items: [
const BottomNavigationBarItem(
icon: Icon(Icons.home_outlined),
activeIcon: Icon(Icons.home),
label: 'Home',
),
const BottomNavigationBarItem(
icon: Icon(Icons.calendar_today_outlined),
activeIcon: Icon(Icons.calendar_today),
label: 'Calendar',
),
const BottomNavigationBarItem(
icon: Icon(Icons.add_circle_outline),
activeIcon: Icon(Icons.add_circle),
label: 'Log',
),
if (isPadTrackingEnabled)
const BottomNavigationBarItem(
icon: Icon(Icons.inventory_2_outlined),
activeIcon: Icon(Icons.inventory_2),
label: 'Supplies',
),
const BottomNavigationBarItem(
icon: Icon(Icons.menu_book_outlined),
activeIcon: Icon(Icons.menu_book),
label: 'Devotional',
),
const BottomNavigationBarItem(
icon: Icon(Icons.school_outlined),
activeIcon: Icon(Icons.school),
label: 'Learn',
),
const BottomNavigationBarItem(
icon: Icon(Icons.settings_outlined),
activeIcon: Icon(Icons.settings),
label: 'Settings',
),
],
items: navBarItems,
),
),
);
@@ -528,7 +521,14 @@ class _SettingsTab extends ConsumerWidget {
'My Favorites',
onTap: () => _showFavoritesDialog(context, ref),
),
_buildSettingsTile(context, Icons.lock_outline, 'Privacy'),
_buildSettingsTile(
context, Icons.security, 'Privacy & Security',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const PrivacySettingsScreen()));
}),
if (!isSingle)
_buildSettingsTile(
context,
@@ -538,7 +538,8 @@ class _SettingsTab extends ConsumerWidget {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SharingSettingsScreen()));
builder: (context) =>
const SharingSettingsScreen()));
},
),
]),
@@ -561,7 +562,13 @@ class _SettingsTab extends ConsumerWidget {
builder: (context) => CycleHistoryScreen()));
}),
_buildSettingsTile(
context, Icons.download_outlined, 'Export Data'),
context, Icons.download_outlined, 'Export Data',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ExportDataScreen()));
}),
]),
const SizedBox(height: 16),
_buildSettingsGroup(context, 'Account', [
@@ -605,14 +612,54 @@ class _SettingsTab extends ConsumerWidget {
);
}
void _showFavoritesDialog(BuildContext context, WidgetRef ref) {
Future<bool> _authenticate(BuildContext context, String correctPin) async {
final controller = TextEditingController();
final pin = await showDialog<String>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Enter PIN'),
content: TextField(
controller: controller,
keyboardType: TextInputType.number,
obscureText: true,
maxLength: 4,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 24, letterSpacing: 8),
decoration: const InputDecoration(hintText: '....'),
autofocus: true,
),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text('Cancel')),
ElevatedButton(
onPressed: () => Navigator.pop(context, controller.text),
child: const Text('Unlock'),
),
],
),
);
return pin == correctPin;
}
void _showFavoritesDialog(BuildContext context, WidgetRef ref) async {
final userProfile = ref.read(userProfileProvider);
if (userProfile == null) return;
if (userProfile.isBioProtected && userProfile.privacyPin != null) {
final granted = await _authenticate(context, userProfile.privacyPin!);
if (!granted) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Incorrect PIN')));
}
return;
}
}
final controller = TextEditingController(
text: userProfile.favoriteFoods?.join(', ') ?? '',
);
if (!context.mounted) return;
showDialog(
context: context,
builder: (context) => AlertDialog(