Implement husband-wife connection dialogue and theme support for learn articles
This commit is contained in:
369
lib/screens/husband/husband_devotional_screen.dart
Normal file
369
lib/screens/husband/husband_devotional_screen.dart
Normal file
@@ -0,0 +1,369 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import '../../models/user_profile.dart';
|
||||
import '../../models/teaching_plan.dart';
|
||||
import '../../providers/user_provider.dart';
|
||||
import '../../theme/app_theme.dart';
|
||||
|
||||
class HusbandDevotionalScreen extends ConsumerStatefulWidget {
|
||||
const HusbandDevotionalScreen({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<HusbandDevotionalScreen> createState() => _HusbandDevotionalScreenState();
|
||||
}
|
||||
|
||||
class _HusbandDevotionalScreenState extends ConsumerState<HusbandDevotionalScreen> {
|
||||
|
||||
void _showAddTeachingDialog([TeachingPlan? existingPlan]) {
|
||||
final titleController = TextEditingController(text: existingPlan?.topic);
|
||||
final scriptureController = TextEditingController(text: existingPlan?.scriptureReference);
|
||||
final notesController = TextEditingController(text: existingPlan?.notes);
|
||||
DateTime selectedDate = existingPlan?.date ?? DateTime.now();
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => StatefulBuilder(
|
||||
builder: (context, setState) => AlertDialog(
|
||||
title: Text(existingPlan == null ? 'Plan Teaching' : 'Edit Plan'),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
controller: titleController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Topic / Theme',
|
||||
hintText: 'e.g., Patience, Prayer, Grace',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
TextField(
|
||||
controller: scriptureController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Scripture Reference',
|
||||
hintText: 'e.g., Eph 5:25',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
TextField(
|
||||
controller: notesController,
|
||||
maxLines: 3,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Notes / Key Points',
|
||||
hintText: 'What do you want to share?',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Text('Date: ${DateFormat.yMMMd().format(selectedDate)}'),
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: selectedDate,
|
||||
firstDate: DateTime.now(),
|
||||
lastDate: DateTime.now().add(const Duration(days: 365)),
|
||||
);
|
||||
if (picked != null) {
|
||||
setState(() => selectedDate = picked);
|
||||
}
|
||||
},
|
||||
child: const Text('Change'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (titleController.text.isEmpty) return;
|
||||
|
||||
final user = ref.read(userProfileProvider);
|
||||
if (user == null) return;
|
||||
|
||||
TeachingPlan newPlan;
|
||||
if (existingPlan != null) {
|
||||
newPlan = existingPlan.copyWith(
|
||||
topic: titleController.text,
|
||||
scriptureReference: scriptureController.text,
|
||||
notes: notesController.text,
|
||||
date: selectedDate,
|
||||
);
|
||||
} else {
|
||||
newPlan = TeachingPlan.create(
|
||||
topic: titleController.text,
|
||||
scriptureReference: scriptureController.text,
|
||||
notes: notesController.text,
|
||||
date: selectedDate,
|
||||
);
|
||||
}
|
||||
|
||||
List<TeachingPlan> updatedList = List.from(user.teachingPlans ?? []);
|
||||
if (existingPlan != null) {
|
||||
final index = updatedList.indexWhere((p) => p.id == existingPlan.id);
|
||||
if (index != -1) updatedList[index] = newPlan;
|
||||
} else {
|
||||
updatedList.add(newPlan);
|
||||
}
|
||||
|
||||
await ref.read(userProfileProvider.notifier).updateProfile(
|
||||
user.copyWith(teachingPlans: updatedList),
|
||||
);
|
||||
|
||||
if (mounted) Navigator.pop(context);
|
||||
},
|
||||
child: const Text('Save'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _deletePlan(TeachingPlan plan) async {
|
||||
final user = ref.read(userProfileProvider);
|
||||
if (user == null || user.teachingPlans == null) return;
|
||||
|
||||
final updatedList = user.teachingPlans!.where((p) => p.id != plan.id).toList();
|
||||
await ref.read(userProfileProvider.notifier).updateProfile(
|
||||
user.copyWith(teachingPlans: updatedList),
|
||||
);
|
||||
}
|
||||
|
||||
void _toggleComplete(TeachingPlan plan) async {
|
||||
final user = ref.read(userProfileProvider);
|
||||
if (user == null || user.teachingPlans == null) return;
|
||||
|
||||
final updatedList = user.teachingPlans!.map((p) {
|
||||
if (p.id == plan.id) return p.copyWith(isCompleted: !p.isCompleted);
|
||||
return p;
|
||||
}).toList();
|
||||
|
||||
await ref.read(userProfileProvider.notifier).updateProfile(
|
||||
user.copyWith(teachingPlans: updatedList),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final user = ref.watch(userProfileProvider);
|
||||
final upcomingPlans = user?.teachingPlans ?? [];
|
||||
upcomingPlans.sort((a,b) => a.date.compareTo(b.date));
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Spiritual Leadership'),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Informational Card (Headship)
|
||||
_buildHeadshipCard(),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Teaching Plans',
|
||||
style: GoogleFonts.outfit(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColors.navyBlue,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => _showAddTeachingDialog(),
|
||||
icon: const Icon(Icons.add_circle, color: AppColors.navyBlue, size: 28),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
if (upcomingPlans.isEmpty)
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(color: Colors.grey.withOpacity(0.2)),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
const Icon(Icons.edit_note, size: 48, color: Colors.grey),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'No teachings planned yet.',
|
||||
style: GoogleFonts.outfit(color: AppColors.warmGray),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => _showAddTeachingDialog(),
|
||||
child: const Text('Plan one now'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
else
|
||||
ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: upcomingPlans.length,
|
||||
separatorBuilder: (ctx, i) => const SizedBox(height: 12),
|
||||
itemBuilder: (ctx, index) {
|
||||
final plan = upcomingPlans[index];
|
||||
return Dismissible(
|
||||
key: Key(plan.id),
|
||||
direction: DismissDirection.endToStart,
|
||||
background: Container(
|
||||
alignment: Alignment.centerRight,
|
||||
padding: const EdgeInsets.only(right: 20),
|
||||
color: Colors.red.withOpacity(0.8),
|
||||
child: const Icon(Icons.delete, color: Colors.white),
|
||||
),
|
||||
onDismissed: (_) => _deletePlan(plan),
|
||||
child: Card(
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
child: ListTile(
|
||||
onTap: () => _showAddTeachingDialog(plan),
|
||||
leading: IconButton(
|
||||
icon: Icon(
|
||||
plan.isCompleted ? Icons.check_circle : Icons.circle_outlined,
|
||||
color: plan.isCompleted ? Colors.green : Colors.grey
|
||||
),
|
||||
onPressed: () => _toggleComplete(plan),
|
||||
),
|
||||
title: Text(
|
||||
plan.topic,
|
||||
style: GoogleFonts.outfit(
|
||||
fontWeight: FontWeight.w600,
|
||||
decoration: plan.isCompleted ? TextDecoration.lineThrough : null,
|
||||
),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (plan.scriptureReference.isNotEmpty)
|
||||
Text(plan.scriptureReference, style: const TextStyle(fontWeight: FontWeight.w500)),
|
||||
if (plan.notes.isNotEmpty)
|
||||
Text(
|
||||
plan.notes,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
DateFormat.yMMMd().format(plan.date),
|
||||
style: TextStyle(fontSize: 11, color: Colors.grey[600]),
|
||||
),
|
||||
],
|
||||
),
|
||||
isThreeLine: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
const SizedBox(height: 40),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHeadshipCard() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFFDF8F0), // Warm tone
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(color: const Color(0xFFE0C097)),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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.”',
|
||||
'Supports family structure under Christ’s authority.',
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Divider(height: 1, color: Color(0xFFE0C097)),
|
||||
const SizedBox(height: 16),
|
||||
_buildVerseText(
|
||||
'1 Tim 3:4–5, 12 & Titus 1:6',
|
||||
'Qualifications for church elders include managing their own households well.',
|
||||
'Husbands who lead faithfully at home are seen as candidates for formal spiritual leadership.',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVerseText(String ref, String text, String context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
ref,
|
||||
style: GoogleFonts.outfit(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: const Color(0xFF8B5E3C),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
text,
|
||||
style: GoogleFonts.lora(
|
||||
fontSize: 15,
|
||||
fontStyle: FontStyle.italic,
|
||||
height: 1.4,
|
||||
color: const Color(0xFF3E2723),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
context,
|
||||
style: GoogleFonts.outfit(
|
||||
fontSize: 12,
|
||||
color: const Color(0xFF6D4C41),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user