Enhance Pad Tracking with new Flow and Supply logic
This commit is contained in:
@@ -4,10 +4,12 @@ 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 '../models/user_profile.dart';
|
||||
import '../providers/user_provider.dart';
|
||||
import '../providers/navigation_provider.dart';
|
||||
import '../screens/log/pad_tracker_screen.dart';
|
||||
import '../services/notification_service.dart';
|
||||
import '../theme/app_theme.dart';
|
||||
|
||||
class QuickLogDialog extends ConsumerStatefulWidget {
|
||||
final String logType;
|
||||
@@ -23,6 +25,8 @@ class _QuickLogDialogState extends ConsumerState<QuickLogDialog> {
|
||||
FlowIntensity? _flowIntensity;
|
||||
MoodLevel? _mood;
|
||||
int? _energyLevel;
|
||||
PadType? _selectedPadType;
|
||||
int _padAbsorbency = 3;
|
||||
|
||||
// Symptoms & Cravings
|
||||
final Map<String, bool> _symptoms = {
|
||||
@@ -274,18 +278,138 @@ class _QuickLogDialogState extends ConsumerState<QuickLogDialog> {
|
||||
}
|
||||
|
||||
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'),
|
||||
final theme = Theme.of(context);
|
||||
// ignore: unused_local_variable
|
||||
final user = ref.watch(userProfileProvider);
|
||||
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Flow Intensity:',
|
||||
style: GoogleFonts.outfit(fontWeight: FontWeight.w600)),
|
||||
const SizedBox(height: 8),
|
||||
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(),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text('Protection Type:',
|
||||
style: GoogleFonts.outfit(fontWeight: FontWeight.w600)),
|
||||
const SizedBox(height: 8),
|
||||
DropdownButtonFormField<PadType>(
|
||||
initialValue: _selectedPadType,
|
||||
decoration: InputDecoration(
|
||||
border:
|
||||
OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
),
|
||||
items: PadType.values.map((type) {
|
||||
return DropdownMenuItem(
|
||||
value: type,
|
||||
child: Text(type.label),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) => setState(() => _selectedPadType = value),
|
||||
hint: const Text('Select type'),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text('Absorbency (1-5):',
|
||||
style: GoogleFonts.outfit(fontWeight: FontWeight.w600)),
|
||||
Slider(
|
||||
value: _padAbsorbency.toDouble(),
|
||||
min: 1,
|
||||
max: 5,
|
||||
divisions: 4,
|
||||
label: _padAbsorbency.toString(),
|
||||
onChanged: (val) => setState(() => _padAbsorbency = val.round()),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
if (_flowIntensity != null && _selectedPadType != null)
|
||||
Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.sageGreen.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(
|
||||
'Estimated duration: ${_calculateRecommendedHours()} hours',
|
||||
style: GoogleFonts.outfit(
|
||||
color: AppColors.sageGreen,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
ref.read(navigationProvider.notifier).setIndex(2);
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => const PadTrackerScreen(),
|
||||
));
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: theme.colorScheme.surfaceContainerHighest,
|
||||
foregroundColor: theme.colorScheme.onSurface,
|
||||
),
|
||||
child: const Text('More Options (Inventory, etc.)'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
int _calculateRecommendedHours() {
|
||||
if (_selectedPadType == null || _flowIntensity == null) return 6;
|
||||
|
||||
final type = _selectedPadType!;
|
||||
if (type == PadType.menstrualCup ||
|
||||
type == PadType.menstrualDisc ||
|
||||
type == PadType.periodUnderwear) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
int baseHours;
|
||||
switch (_flowIntensity!) {
|
||||
case FlowIntensity.heavy:
|
||||
baseHours = (type == PadType.superPad ||
|
||||
type == PadType.overnight ||
|
||||
type == PadType.tamponSuper)
|
||||
? 4
|
||||
: 3;
|
||||
break;
|
||||
case FlowIntensity.medium:
|
||||
baseHours = 6;
|
||||
break;
|
||||
case FlowIntensity.light:
|
||||
baseHours = 8;
|
||||
break;
|
||||
case FlowIntensity.spotting:
|
||||
baseHours = 10;
|
||||
break;
|
||||
case FlowIntensity.none:
|
||||
baseHours = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
return baseHours;
|
||||
}
|
||||
|
||||
Widget _buildPrayerLog() {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -397,8 +521,33 @@ class _QuickLogDialogState extends ConsumerState<QuickLogDialog> {
|
||||
return; // Don't save empty prayer
|
||||
}
|
||||
break;
|
||||
case 'pads':
|
||||
final userProfile = ref.read(userProfileProvider);
|
||||
if (userProfile != null) {
|
||||
final hours = _calculateRecommendedHours();
|
||||
await ref.read(userProfileProvider.notifier).updateProfile(
|
||||
userProfile.copyWith(
|
||||
lastPadChangeTime: DateTime.now(),
|
||||
// Auto-inventory deduction could go here, but omitted for "Quick" simplicity
|
||||
// unless we want to match PadTrackerScreen exactly.
|
||||
),
|
||||
);
|
||||
|
||||
await NotificationService().scheduleNotification(
|
||||
id: 100,
|
||||
title: 'Time to change!',
|
||||
body: 'It\'s been $hours hours since you logged your protection.',
|
||||
scheduledDate: DateTime.now().add(Duration(hours: hours)),
|
||||
);
|
||||
}
|
||||
updatedEntry = entry.copyWith(
|
||||
isPeriodDay: _flowIntensity != FlowIntensity.none &&
|
||||
_flowIntensity != FlowIntensity.spotting,
|
||||
flowIntensity: _flowIntensity,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// pads handled separately
|
||||
// Already handled or invalid
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user