370 lines
14 KiB
Dart
370 lines
14 KiB
Dart
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),
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
}
|