import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:uuid/uuid.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../models/cycle_entry.dart'; import '../providers/user_provider.dart'; import '../providers/navigation_provider.dart'; import '../screens/log/pad_tracker_screen.dart'; import '../services/notification_service.dart'; class QuickLogDialog extends ConsumerStatefulWidget { final String logType; const QuickLogDialog({super.key, required this.logType}); @override ConsumerState createState() => _QuickLogDialogState(); } class _QuickLogDialogState extends ConsumerState { // State variables for the dialog FlowIntensity? _flowIntensity; MoodLevel? _mood; int? _energyLevel; // Symptoms & Cravings final Map _symptoms = { 'Headache': false, 'Bloating': false, 'Breast Tenderness': false, 'Fatigue': false, 'Acne': false, 'Back Pain': false, 'Constipation': false, 'Diarrhea': false, 'Insomnia': false, 'Cramps': false, }; final TextEditingController _cravingController = TextEditingController(); final List _cravings = []; List _recentCravings = []; @override void initState() { super.initState(); if (widget.logType == 'cravings') { _loadRecentCravings(); } } @override void dispose() { _cravingController.dispose(); super.dispose(); } Future _loadRecentCravings() async { final prefs = await SharedPreferences.getInstance(); setState(() { _recentCravings = prefs.getStringList('recent_cravings') ?? []; }); } @override Widget build(BuildContext context) { return AlertDialog( title: Text('Quick Log: ${widget.logType.capitalize()}'), content: _buildLogContent(), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel'), ), ElevatedButton( onPressed: _saveLog, child: const Text('Save'), ), TextButton( onPressed: () { Navigator.of(context).pop(); ref.read(navigationProvider.notifier).setIndex(2); }, child: const Text('Full Log'), ) ], ); } Widget _buildLogContent() { switch (widget.logType) { case 'period': return _buildPeriodLog(); case 'mood': return _buildMoodLog(); case 'energy': return _buildEnergyLog(); case 'pads': return _buildPadsLog(); case 'symptoms': return _buildSymptomsLog(); case 'cravings': return _buildCravingsLog(); case 'prayer': return _buildPrayerLog(); default: return const Text('Invalid log type.'); } } Widget _buildSymptomsLog() { return SizedBox( width: double.maxFinite, child: ListView( shrinkWrap: true, children: [ const Text('Select symptoms you are experiencing:'), const SizedBox(height: 16), Wrap( spacing: 8, runSpacing: 8, children: _symptoms.keys.map((symptom) { final isSelected = _symptoms[symptom]!; return ChoiceChip( label: Text(symptom), selected: isSelected, onSelected: (selected) { setState(() { _symptoms[symptom] = selected; }); }, ); }).toList(), ), ], ), ); } Widget _buildCravingsLog() { return SizedBox( width: double.maxFinite, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ TextField( controller: _cravingController, decoration: const InputDecoration( labelText: 'Add a craving', hintText: 'e.g. Chocolate', border: OutlineInputBorder(), ), onSubmitted: (value) { if (value.isNotEmpty) { setState(() { _cravings.add(value.trim()); _cravingController.clear(); }); } }, ), const SizedBox(height: 8), Wrap( spacing: 8, children: _cravings .map((c) => Chip( label: Text(c), onDeleted: () { setState(() => _cravings.remove(c)); }, )) .toList(), ), const SizedBox(height: 16), if (_recentCravings.isNotEmpty) ...[ Text('Recent Cravings:', style: GoogleFonts.outfit( fontSize: 12, fontWeight: FontWeight.bold)), const SizedBox(height: 8), Wrap( spacing: 8, children: _recentCravings .take(5) .map((c) => ActionChip( label: Text(c), onPressed: () { if (!_cravings.contains(c)) { setState(() => _cravings.add(c)); } }, )) .toList(), ), ] ], ), ); } Widget _buildPeriodLog() { return Column( mainAxisSize: MainAxisSize.min, children: [ const Text('Select your flow intensity:'), const SizedBox(height: 16), Wrap( spacing: 8, children: FlowIntensity.values.map((flow) { return ChoiceChip( label: Text(flow.label), selected: _flowIntensity == flow, onSelected: (selected) { if (selected) { setState(() { _flowIntensity = flow; }); } }, ); }).toList(), ), ], ); } Widget _buildMoodLog() { return Column( mainAxisSize: MainAxisSize.min, children: [ const Text('Select your mood:'), const SizedBox(height: 16), Wrap( spacing: 8, children: MoodLevel.values.map((mood) { return ChoiceChip( label: Text(mood.label), selected: _mood == mood, onSelected: (selected) { if (selected) { setState(() { _mood = mood; }); } }, ); }).toList(), ), ], ); } Widget _buildEnergyLog() { return Column( mainAxisSize: MainAxisSize.min, children: [ const Text('Select your energy level:'), const SizedBox(height: 16), Slider( value: (_energyLevel ?? 3).toDouble(), min: 1, max: 5, divisions: 4, label: (_energyLevel ?? 3).toString(), onChanged: (value) { setState(() { _energyLevel = value.round(); }); }, ), ], ); } Widget _buildPadsLog() { // This can be a simple button to navigate to the PadTrackerScreen return ElevatedButton( onPressed: () { Navigator.of(context).pop(); Navigator.of(context).push(MaterialPageRoute( builder: (context) => const PadTrackerScreen(), )); }, child: const Text('Track Pad Change'), ); } Widget _buildPrayerLog() { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Enter your prayer request or gratitude:'), const SizedBox(height: 16), TextField( controller: _cravingController, // Reusing controller for simplicity, or create _prayerController maxLines: 4, decoration: const InputDecoration( hintText: 'I am thankful for...', border: OutlineInputBorder(), ), ), ], ); } Future _saveLog() async { // Handle text input for cravings if user didn't hit enter if (widget.logType == 'cravings' && _cravingController.text.isNotEmpty) { _cravings.add(_cravingController.text.trim()); } final cycleNotifier = ref.read(cycleEntriesProvider.notifier); final today = DateTime.now(); final entries = ref.read(cycleEntriesProvider); final entry = entries.firstWhere( (e) => DateUtils.isSameDay(e.date, today), orElse: () => CycleEntry( id: const Uuid().v4(), date: today, createdAt: today, updatedAt: today), ); CycleEntry updatedEntry = entry; switch (widget.logType) { case 'period': updatedEntry = entry.copyWith( isPeriodDay: true, flowIntensity: _flowIntensity, ); break; case 'mood': updatedEntry = entry.copyWith(mood: _mood); break; case 'energy': updatedEntry = entry.copyWith(energyLevel: _energyLevel); break; case 'symptoms': updatedEntry = entry.copyWith( hasHeadache: _symptoms['Headache'], hasBloating: _symptoms['Bloating'], hasBreastTenderness: _symptoms['Breast Tenderness'], hasFatigue: _symptoms['Fatigue'], hasAcne: _symptoms['Acne'], hasLowerBackPain: _symptoms['Back Pain'], hasConstipation: _symptoms['Constipation'], hasDiarrhea: _symptoms['Diarrhea'], hasInsomnia: _symptoms['Insomnia'], crampIntensity: _symptoms['Cramps'] == true ? 2 : 0, // Default to mild cramps if just toggled ); // Trigger notification if any symptom is selected final user = ref.read(userProfileProvider); if (_symptoms.values.any((selected) => selected == true)) { final selectedSymptom = _symptoms.entries .firstWhere((element) => element.value == true) .key; NotificationService().showSymptomNotification( senderName: user?.name ?? 'Wife', symptom: selectedSymptom, ); } break; case 'cravings': final currentCravings = entry.cravings ?? []; final newCravings = {...currentCravings, ..._cravings}.toList(); updatedEntry = entry.copyWith(cravings: newCravings); // Update History final prefs = await SharedPreferences.getInstance(); final history = prefs.getStringList('recent_cravings') ?? []; final updatedHistory = {..._cravings, ...history}.take(20).toList(); await prefs.setStringList('recent_cravings', updatedHistory); await prefs.setStringList('recent_cravings', updatedHistory); break; case 'prayer': final currentPrayer = entry.prayerRequest ?? ''; final newPrayer = _cravingController.text.trim(); // Using reused controller if (newPrayer.isNotEmpty) { updatedEntry = entry.copyWith( prayerRequest: currentPrayer.isEmpty ? newPrayer : '$currentPrayer\n$newPrayer'); // Trigger notification final user = ref.read(userProfileProvider); NotificationService().showPrayerRequestNotification( senderName: user?.name ?? 'Wife', ); } else { return; // Don't save empty prayer } break; default: // pads handled separately return; } if (entries.any((e) => e.id == entry.id)) { cycleNotifier.updateEntry(updatedEntry); } else { cycleNotifier.addEntry(updatedEntry); } if (mounted) { Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Entry saved!')), ); } } } extension StringExtension on String { String capitalize() { return "${this[0].toUpperCase()}${substring(1)}"; } }