import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:real_estate_mobile/core/constants/app_colors.dart'; import 'package:real_estate_mobile/features/profile/presentation/providers/profile_provider.dart'; import 'package:real_estate_mobile/features/profile/presentation/widgets/profile_shared_widgets.dart'; class NotificationsTab extends ConsumerStatefulWidget { const NotificationsTab({super.key}); @override ConsumerState createState() => _NotificationsTabState(); } class _NotificationsTabState extends ConsumerState { final Map> _notificationPrefs = { 'newLeadAlerts': {'email': true, 'inApp': true}, 'messageUpdates': {'email': false, 'inApp': true}, 'urgentRequests': {'email': true, 'inApp': true}, }; String _digestFrequency = 'instant'; bool _notificationsLoaded = false; bool _isLoadingNotifications = false; bool _isSavingNotifications = false; @override void initState() { super.initState(); _loadNotificationPreferences(); } Future _loadNotificationPreferences() async { if (_notificationsLoaded) return; setState(() => _isLoadingNotifications = true); try { final role = ref.read(profileProvider).role; final repo = ref.read(profileRepositoryProvider); final data = await repo.getNotificationPreferences(role); final notifications = data['notifications'] as Map? ?? {}; setState(() { for (final key in ['new_lead_alerts', 'message_updates', 'urgent_requests_tours']) { final mapped = key == 'new_lead_alerts' ? 'newLeadAlerts' : key == 'message_updates' ? 'messageUpdates' : 'urgentRequests'; final vals = notifications[key] as Map?; if (vals != null) { _notificationPrefs[mapped] = { 'email': vals['email'] as bool? ?? false, 'inApp': vals['inApp'] as bool? ?? true, }; } } _digestFrequency = data['digestFrequency'] as String? ?? 'instant'; _isLoadingNotifications = false; _notificationsLoaded = true; }); } catch (_) { setState(() { _isLoadingNotifications = false; _notificationsLoaded = true; }); } } @override Widget build(BuildContext context) { if (_isLoadingNotifications) { return const Center( child: CircularProgressIndicator(color: AppColors.accentOrange)); } return ListView( padding: const EdgeInsets.fromLTRB(27, 10, 27, 30), children: [ const Text( 'Notification Preferences', style: TextStyle( fontFamily: 'Fractul', fontSize: 15, fontWeight: FontWeight.w700, color: AppColors.primaryDark, ), ), const SizedBox(height: 8), const Text( 'Choose what you want to be notified about and how.', style: TextStyle( fontFamily: 'SourceSerif4', fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.primaryDark, ), ), const SizedBox(height: 20), _buildSectionDivider(), const SizedBox(height: 19), _buildNotificationCategory( title: 'New Lead Alerts', description: 'Notifications about new leads and inquiries.', prefKey: 'newLeadAlerts', ), _buildSectionDivider(), const SizedBox(height: 13), _buildNotificationCategory( title: 'Message Updates', description: 'Notices about new messages from clients or other agents.', prefKey: 'messageUpdates', ), _buildSectionDivider(), const SizedBox(height: 16), _buildNotificationCategory( title: 'Urgent Requests & Tours', description: 'Immediate notifications for tour requests and time-sensitive items.', prefKey: 'urgentRequests', ), _buildSectionDivider(), const SizedBox(height: 20), const Text( 'Email Digest Frequency', style: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w700, color: AppColors.primaryDark, ), ), const SizedBox(height: 8), const Text( 'Choose how often you receive non-urgent email summaries', style: TextStyle( fontFamily: 'SourceSerif4', fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.primaryDark, ), ), const SizedBox(height: 16), _buildFrequencySelector(), const SizedBox(height: 40), ProfileActionButtons( onSave: _saveNotificationSettings, onCancel: () => context.go('/home'), isSaving: _isSavingNotifications, ), ], ); } Future _saveNotificationSettings() async { setState(() => _isSavingNotifications = true); try { final role = ref.read(profileProvider).role; final repo = ref.read(profileRepositoryProvider); await repo.updateNotificationPreferences(role, { 'notifications': { 'new_lead_alerts': _notificationPrefs['newLeadAlerts'], 'message_updates': _notificationPrefs['messageUpdates'], 'urgent_requests_tours': _notificationPrefs['urgentRequests'], }, 'digestFrequency': _digestFrequency, }); _showSnackBar('Notification settings saved'); } catch (e) { _showSnackBar('Failed to save: $e', isError: true); } finally { if (mounted) setState(() => _isSavingNotifications = false); } } Widget _buildSectionDivider() { return Divider( color: AppColors.primaryDark.withValues(alpha: 0.15), height: 1, thickness: 1, ); } Widget _buildNotificationCategory({ required String title, required String description, required String prefKey, }) { final prefs = _notificationPrefs[prefKey]!; return Padding( padding: const EdgeInsets.only(bottom: 16), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: const TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w700, color: AppColors.primaryDark, )), const SizedBox(height: 4), Text(description, style: const TextStyle( fontFamily: 'SourceSerif4', fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.primaryDark, )), ], ), ), const SizedBox(width: 20), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildCheckboxRow( label: 'Email', value: prefs['email']!, onChanged: (val) { setState(() { _notificationPrefs[prefKey]!['email'] = val ?? false; }); }, ), const SizedBox(height: 6), _buildCheckboxRow( label: 'In-App', value: prefs['inApp']!, onChanged: (val) { setState(() { _notificationPrefs[prefKey]!['inApp'] = val ?? false; }); }, ), ], ), ], ), ); } Widget _buildCheckboxRow({ required String label, required bool value, required ValueChanged onChanged, }) { return GestureDetector( onTap: () => onChanged(!value), behavior: HitTestBehavior.opaque, child: Row( mainAxisSize: MainAxisSize.min, children: [ SizedBox( width: 18, height: 18, child: Checkbox( value: value, onChanged: onChanged, activeColor: AppColors.primaryDark, checkColor: Colors.white, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, visualDensity: VisualDensity.compact, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(3)), side: BorderSide( color: AppColors.primaryDark.withValues(alpha: 0.4), width: 1, ), ), ), const SizedBox(width: 4), Text(label, style: const TextStyle( fontFamily: 'SourceSerif4', fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.primaryDark, )), ], ), ); } Widget _buildFrequencySelector() { const options = ['instant', 'daily', 'weekly', 'off']; const labels = ['Instant', 'Daily', 'Weekly', 'Off']; return Container( height: 32, width: 278, decoration: BoxDecoration( borderRadius: BorderRadius.circular(7), border: Border.all( color: AppColors.primaryDark.withValues(alpha: 0.15), width: 1, ), ), child: ClipRRect( borderRadius: BorderRadius.circular(6), child: Row( children: List.generate(options.length * 2 - 1, (index) { if (index.isOdd) { return Container( width: 1, height: 32, color: AppColors.primaryDark.withValues(alpha: 0.15), ); } final i = index ~/ 2; final isSelected = _digestFrequency == options[i]; return Expanded( child: GestureDetector( onTap: () => setState(() => _digestFrequency = options[i]), child: Center( child: isSelected ? Container( height: 24, margin: const EdgeInsets.symmetric(horizontal: 3), decoration: BoxDecoration( color: AppColors.accentOrange, borderRadius: BorderRadius.circular(15), ), alignment: Alignment.center, child: Text(labels[i], style: const TextStyle( fontFamily: 'SourceSerif4', fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.primaryDark, height: 1.0, )), ) : Text(labels[i], style: const TextStyle( fontFamily: 'SourceSerif4', fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.primaryDark, height: 1.0, )), ), ), ); }), ), ), ); } void _showSnackBar(String message, {bool isError = false}) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), backgroundColor: isError ? Colors.red : const Color(0xFF638559), ), ); } }