Implement dynamic scripture loading from XML and fix theming for Learn screens

This commit is contained in:
2026-01-05 17:40:48 -06:00
parent 96655f9a74
commit d50cab3188
2 changed files with 119 additions and 29 deletions

View File

@@ -6,6 +6,7 @@ import '../../models/user_profile.dart';
import '../../models/teaching_plan.dart';
import '../../providers/user_provider.dart';
import '../../theme/app_theme.dart';
import '../../services/bible_xml_parser.dart';
class HusbandDevotionalScreen extends ConsumerStatefulWidget {
const HusbandDevotionalScreen({super.key});
@@ -15,7 +16,62 @@ class HusbandDevotionalScreen extends ConsumerStatefulWidget {
}
class _HusbandDevotionalScreenState extends ConsumerState<HusbandDevotionalScreen> {
final _parser = BibleXmlParser();
Map<String, String> _scriptures = {};
bool _loading = true;
BibleTranslation? _currentTranslation;
@override
void initState() {
super.initState();
// Initial fetch handled in post-frame or via listen, but let's trigger once here if possible
// We need the ref, which is available.
WidgetsBinding.instance.addPostFrameCallback((_) {
_fetchScriptures();
});
}
Future<void> _fetchScriptures() async {
final user = ref.read(userProfileProvider);
if (user == null) return;
final translation = user.bibleTranslation;
if (translation == _currentTranslation && _scriptures.isNotEmpty) return;
setState(() => _loading = true);
try {
final assetPath = 'assets/bible_xml/${translation.name.toUpperCase()}.xml';
// Define verses to fetch
final versesToFetch = [
'1 Corinthians 11:3',
'1 Timothy 3:4',
'1 Timothy 3:5',
'1 Timothy 3:12',
'Titus 1:6',
];
final Map<String, String> results = {};
for (final ref in versesToFetch) {
final text = await _parser.getVerseFromAsset(assetPath, ref);
results[ref] = text ?? 'Verse not found.';
}
if (mounted) {
setState(() {
_scriptures = results;
_currentTranslation = translation;
_loading = false;
});
}
} catch (e) {
debugPrint('Error loading scriptures: $e');
if (mounted) setState(() => _loading = false);
}
}
void _showAddTeachingDialog([TeachingPlan? existingPlan]) {
final titleController = TextEditingController(text: existingPlan?.topic);
final scriptureController = TextEditingController(text: existingPlan?.scriptureReference);
@@ -163,6 +219,13 @@ class _HusbandDevotionalScreenState extends ConsumerState<HusbandDevotionalScree
final upcomingPlans = user?.teachingPlans ?? [];
upcomingPlans.sort((a,b) => a.date.compareTo(b.date));
// Listen for translation changes to re-fetch
ref.listen(userProfileProvider, (prev, next) {
if (next?.bibleTranslation != prev?.bibleTranslation) {
_fetchScriptures();
}
});
return Scaffold(
appBar: AppBar(
title: const Text('Spiritual Leadership'),
@@ -174,7 +237,7 @@ class _HusbandDevotionalScreenState extends ConsumerState<HusbandDevotionalScree
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Informational Card (Headship)
_buildHeadshipCard(),
_buildHeadshipCard(user?.bibleTranslation.label ?? 'ESV'),
const SizedBox(height: 24),
Row(
@@ -289,7 +352,15 @@ class _HusbandDevotionalScreenState extends ConsumerState<HusbandDevotionalScree
);
}
Widget _buildHeadshipCard() {
Widget _buildHeadshipCard(String version) {
// Combine 1 Timothy verses
String timothyText = 'Loading...';
if (!_loading) {
timothyText = '${_scriptures['1 Timothy 3:4'] ?? '...'} ${_scriptures['1 Timothy 3:5'] ?? ''} ... ${_scriptures['1 Timothy 3:12'] ?? ''}';
// Cleanup potential double spaces or missing
timothyText = timothyText.replaceAll(' ', ' ').trim();
}
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
@@ -304,28 +375,43 @@ class _HusbandDevotionalScreenState extends ConsumerState<HusbandDevotionalScree
children: [
const Icon(Icons.menu_book, color: Color(0xFF8B5E3C)),
const SizedBox(width: 12),
Text(
'Biblical Principles',
style: GoogleFonts.lora(
fontSize: 18,
fontWeight: FontWeight.bold,
color: const Color(0xFF5D4037),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Biblical Principles',
style: GoogleFonts.lora(
fontSize: 18,
fontWeight: FontWeight.bold,
color: const Color(0xFF5D4037),
),
),
Text(
version,
style: GoogleFonts.outfit(fontSize: 12, color: const Color(0xFF8B5E3C)),
),
],
),
],
),
const SizedBox(height: 16),
_buildVerseText(
'1 Corinthians 11:3',
'“The head of every man is Christ, the head of a wife is her husband, and the head of Christ is God.',
_loading ? 'Loading...' : (_scriptures['1 Corinthians 11:3'] ?? 'Verse not found.'),
'Supports family structure under Christs authority.',
),
const SizedBox(height: 16),
const Divider(height: 1, color: Color(0xFFE0C097)),
const SizedBox(height: 16),
_buildVerseText(
'1 Tim 3:45, 12 & Titus 1:6',
'1 Timothy 3:45, 12',
timothyText,
'Qualifications for church elders include managing their own households well.',
),
const SizedBox(height: 16),
_buildVerseText(
'Titus 1:6',
_loading ? 'Loading...' : (_scriptures['Titus 1:6'] ?? 'Verse not found.'),
'Husbands who lead faithfully at home are seen as candidates for formal spiritual leadership.',
),
],
@@ -346,14 +432,18 @@ class _HusbandDevotionalScreenState extends ConsumerState<HusbandDevotionalScree
),
),
const SizedBox(height: 4),
Text(
text,
style: GoogleFonts.lora(
fontSize: 15,
fontStyle: FontStyle.italic,
height: 1.4,
color: const Color(0xFF3E2723),
),
AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: Text(
text,
key: ValueKey(text), // Animate change
style: GoogleFonts.lora(
fontSize: 15,
fontStyle: FontStyle.italic,
height: 1.4,
color: const Color(0xFF3E2723),
),
),
),
const SizedBox(height: 4),
Text(