Implement husband-wife connection dialogue and theme support for learn articles

This commit is contained in:
2026-01-05 17:09:15 -06:00
parent 02d25d0cc7
commit 96655f9a74
36 changed files with 3849 additions and 819 deletions

View File

@@ -5,9 +5,16 @@ import 'package:collection/collection.dart';
import '../../models/cycle_entry.dart';
import '../../providers/user_provider.dart';
class CycleHistoryScreen extends ConsumerWidget {
class CycleHistoryScreen extends ConsumerStatefulWidget {
const CycleHistoryScreen({super.key});
@override
ConsumerState<CycleHistoryScreen> createState() => _CycleHistoryScreenState();
}
class _CycleHistoryScreenState extends ConsumerState<CycleHistoryScreen> {
bool _isUnlocked = false;
void _showDeleteAllDialog(BuildContext context, WidgetRef ref) {
showDialog(
context: context,
@@ -42,9 +49,85 @@ class CycleHistoryScreen extends ConsumerWidget {
);
}
Future<void> _authenticate() async {
final user = ref.read(userProfileProvider);
if (user?.privacyPin == null) return;
final controller = TextEditingController();
final pin = await showDialog<String>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Enter PIN'),
content: TextField(
controller: controller,
keyboardType: TextInputType.number,
obscureText: true,
maxLength: 4,
style: const TextStyle(fontSize: 24, letterSpacing: 8),
textAlign: TextAlign.center,
decoration: const InputDecoration(
hintText: '....',
border: OutlineInputBorder(),
),
autofocus: true,
),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text('Cancel')),
ElevatedButton(
onPressed: () => Navigator.pop(context, controller.text),
child: const Text('Unlock'),
),
],
),
);
if (pin == user!.privacyPin) {
setState(() {
_isUnlocked = true;
});
} else if (pin != null) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Incorrect PIN')),
);
}
}
}
@override
Widget build(BuildContext context, WidgetRef ref) {
Widget build(BuildContext context) {
final entries = ref.watch(cycleEntriesProvider);
final user = ref.watch(userProfileProvider);
// Privacy Check
final isProtected = user?.isHistoryProtected ?? false;
final hasPin = user?.privacyPin != null && user!.privacyPin!.isNotEmpty;
final isLocked = isProtected && hasPin && !_isUnlocked;
if (isLocked) {
return Scaffold(
appBar: AppBar(title: const Text('Cycle History')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.lock_outline, size: 64, color: Colors.grey),
const SizedBox(height: 16),
const Text(
'History is Protected',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 24),
ElevatedButton.icon(
onPressed: _authenticate,
icon: const Icon(Icons.key),
label: const Text('Enter PIN to View'),
),
],
),
),
);
}
final groupedEntries = groupBy(
entries,