feat: Implement husband features and fix iOS Safari web startup
Implement initial features for husband's companion app, including mock data service and husband notes screen. Refactor scripture and cycle services for improved stability and testability. Address iOS Safari web app startup issue by removing deprecated initialization. - Implemented MockDataService and HusbandNotesScreen. - Converted _DashboardTab and DevotionalScreen to StatefulWidgets for robust scripture provider initialization. - Refactored CycleService to use immutable CycleInfo class, reducing UI rebuilds. - Removed deprecated window.flutterConfiguration from index.html, resolving Flutter web app startup failure on iOS Safari. - Updated and fixed related tests.
This commit is contained in:
@@ -6,18 +6,31 @@ import '../../providers/user_provider.dart';
|
||||
import '../../services/cycle_service.dart';
|
||||
import '../../models/cycle_entry.dart';
|
||||
import '../../theme/app_theme.dart';
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
import '../../widgets/scripture_card.dart';
|
||||
import '../../models/user_profile.dart';
|
||||
>>>>>>> 6742220 (Your commit message here)
|
||||
import '../../providers/scripture_provider.dart'; // Import the new provider
|
||||
|
||||
class DevotionalScreen extends ConsumerWidget {
|
||||
class DevotionalScreen extends ConsumerStatefulWidget {
|
||||
const DevotionalScreen({super.key});
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
Future<void> _showTranslationPicker(BuildContext context, WidgetRef ref, UserProfile? user) async {
|
||||
@override
|
||||
ConsumerState<DevotionalScreen> createState() => _DevotionalScreenState();
|
||||
}
|
||||
|
||||
class _DevotionalScreenState extends ConsumerState<DevotionalScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initializeScripture();
|
||||
}
|
||||
|
||||
Future<void> _initializeScripture() async {
|
||||
final phase = ref.read(currentCycleInfoProvider).phase;
|
||||
await ref.read(scriptureProvider.notifier).initializeScripture(phase);
|
||||
}
|
||||
|
||||
Future<void> _showTranslationPicker(
|
||||
BuildContext context, WidgetRef ref, UserProfile? user) async {
|
||||
if (user == null) return;
|
||||
|
||||
final selected = await showModalBottomSheet<BibleTranslation>(
|
||||
@@ -38,32 +51,46 @@ class DevotionalScreen extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
...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),
|
||||
)),
|
||||
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)
|
||||
);
|
||||
await ref
|
||||
.read(userProfileProvider.notifier)
|
||||
.updateProfile(user.copyWith(bibleTranslation: selected));
|
||||
}
|
||||
}
|
||||
|
||||
>>>>>>> 6742220 (Your commit message here)
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
Widget build(BuildContext context) {
|
||||
// Listen for changes in the cycle info to re-initialize scripture if needed
|
||||
ref.listen<CycleInfo>(currentCycleInfoProvider, (previousCycleInfo, newCycleInfo) {
|
||||
if (previousCycleInfo?.phase != newCycleInfo.phase) {
|
||||
_initializeScripture();
|
||||
}
|
||||
});
|
||||
|
||||
final user = ref.watch(userProfileProvider);
|
||||
final cycleInfo = ref.watch(currentCycleInfoProvider);
|
||||
|
||||
final phase = cycleInfo['phase'] as CyclePhase;
|
||||
final scripture = ScriptureDatabase.getScriptureForPhase(phase.name);
|
||||
|
||||
final phase = cycleInfo.phase;
|
||||
|
||||
// Watch the scripture provider for the current scripture
|
||||
final scriptureState = ref.watch(scriptureProvider);
|
||||
final scripture = scriptureState.currentScripture;
|
||||
final maxIndex = scriptureState.maxIndex;
|
||||
|
||||
if (scripture == null) {
|
||||
return const Center(child: CircularProgressIndicator()); // Or some error message
|
||||
}
|
||||
|
||||
return SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
@@ -85,7 +112,8 @@ class DevotionalScreen extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: _getPhaseColor(phase).withOpacity(0.15),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
@@ -117,75 +145,53 @@ class DevotionalScreen extends ConsumerWidget {
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
|
||||
// Main Scripture Card
|
||||
<<<<<<< HEAD
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
_getPhaseColor(phase).withOpacity(0.15),
|
||||
AppColors.cream,
|
||||
],
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
// Main Scripture Card with Navigation
|
||||
Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
ScriptureCard(
|
||||
verse: scripture
|
||||
.getVerse(user?.bibleTranslation ?? BibleTranslation.esv),
|
||||
reference: scripture.reference,
|
||||
translation:
|
||||
(user?.bibleTranslation ?? BibleTranslation.esv).label,
|
||||
phase: phase,
|
||||
onTranslationTap: () =>
|
||||
_showTranslationPicker(context, ref, user),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
border: Border.all(
|
||||
color: _getPhaseColor(phase).withOpacity(0.3),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Quote icon
|
||||
Container(
|
||||
width: 48,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
color: _getPhaseColor(phase).withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.format_quote,
|
||||
color: _getPhaseColor(phase),
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// Verse
|
||||
Text(
|
||||
'"${scripture.verse}"',
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.lora(
|
||||
fontSize: 20,
|
||||
fontStyle: FontStyle.italic,
|
||||
if (maxIndex != null && maxIndex > 1) ...[
|
||||
Positioned(
|
||||
left: 0,
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios),
|
||||
onPressed: () =>
|
||||
ref.read(scriptureProvider.notifier).getPreviousScripture(),
|
||||
color: AppColors.charcoal,
|
||||
height: 1.6,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Reference
|
||||
Text(
|
||||
'— ${scripture.reference}',
|
||||
style: GoogleFonts.outfit(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.warmGray,
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.arrow_forward_ios),
|
||||
onPressed: () =>
|
||||
ref.read(scriptureProvider.notifier).getNextScripture(),
|
||||
color: AppColors.charcoal,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
if (maxIndex != null && maxIndex > 1)
|
||||
Center(
|
||||
child: TextButton.icon(
|
||||
onPressed: () => ref.read(scriptureProvider.notifier).getRandomScripture(),
|
||||
icon: const Icon(Icons.shuffle),
|
||||
label: const Text('Random Verse'),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: AppColors.sageGreen,
|
||||
),
|
||||
),
|
||||
=======
|
||||
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),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user