import 'package:flutter/material.dart'; import 'package:em2rp/models/notification_preferences_model.dart'; import 'package:em2rp/providers/local_user_provider.dart'; import 'package:provider/provider.dart'; /// Widget pour afficher et modifier les préférences de notifications class NotificationPreferencesWidget extends StatefulWidget { const NotificationPreferencesWidget({super.key}); @override State createState() => _NotificationPreferencesWidgetState(); } class _NotificationPreferencesWidgetState extends State { // État local pour feedback immédiat NotificationPreferences? _localPrefs; bool _isSaving = false; @override Widget build(BuildContext context) { return Consumer( builder: (context, userProvider, _) { final user = userProvider.currentUser; if (user == null) return const SizedBox.shrink(); // Utiliser les prefs locales si disponibles, sinon les prefs du user final prefs = _localPrefs ?? user.notificationPreferences ?? NotificationPreferences.defaults(); return Card( elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Titre section Row( children: [ Icon(Icons.notifications, color: Theme.of(context).primaryColor), const SizedBox(width: 8), Text( 'Préférences de notifications', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Theme.of(context).primaryColor, ), ), if (_isSaving) ...[ const SizedBox(width: 8), const SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ), ], ], ), const SizedBox(height: 8), Text( 'Choisissez comment vous souhaitez être notifié', style: TextStyle( fontSize: 13, color: Colors.grey.shade600, ), ), const Divider(height: 24), // Canaux de notification Text( 'Canaux de notification', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.grey.shade700, ), ), const SizedBox(height: 8), _buildSwitchTile( context, title: 'Notifications in-app', subtitle: 'Alertes dans l\'application', value: prefs.inAppEnabled, icon: Icons.app_settings_alt, onChanged: (value) => _updatePrefs( context, prefs.copyWith(inAppEnabled: value), ), ), _buildSwitchTile( context, title: 'Notifications email', subtitle: 'Recevoir des emails', value: prefs.emailEnabled, icon: Icons.email, onChanged: (value) => _updatePrefs( context, prefs.copyWith(emailEnabled: value), ), ), _buildSwitchTile( context, title: 'Notifications push', subtitle: 'Notifications navigateur', value: prefs.pushEnabled, icon: Icons.notifications_active, onChanged: (value) => _updatePrefs( context, prefs.copyWith(pushEnabled: value), ), ), const Divider(height: 24), // Types de notifications Text( 'Types de notifications', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.grey.shade700, ), ), const SizedBox(height: 8), _buildSwitchTile( context, title: 'Événements', subtitle: 'Création, modification, assignations', value: prefs.eventsNotifications, icon: Icons.event, onChanged: (value) => _updatePrefs( context, prefs.copyWith(eventsNotifications: value), ), ), _buildSwitchTile( context, title: 'Maintenance', subtitle: 'Rappels de maintenance', value: prefs.maintenanceNotifications, icon: Icons.build, onChanged: (value) => _updatePrefs( context, prefs.copyWith(maintenanceNotifications: value), ), ), _buildSwitchTile( context, title: 'Stock', subtitle: 'Stock faible, quantités', value: prefs.stockNotifications, icon: Icons.inventory_2, onChanged: (value) => _updatePrefs( context, prefs.copyWith(stockNotifications: value), ), ), _buildSwitchTile( context, title: 'Équipement', subtitle: 'Perdu, manquant, conflits', value: prefs.equipmentNotifications, icon: Icons.warning, onChanged: (value) => _updatePrefs( context, prefs.copyWith(equipmentNotifications: value), ), ), ], ), ), ); }, ); } Widget _buildSwitchTile( BuildContext context, { required String title, required String subtitle, required bool value, required IconData icon, required ValueChanged onChanged, }) { return SwitchListTile( secondary: Icon(icon, color: value ? Theme.of(context).primaryColor : Colors.grey), title: Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, ), ), subtitle: Text( subtitle, style: TextStyle( fontSize: 12, color: Colors.grey.shade600, ), ), value: value, onChanged: _isSaving ? null : onChanged, // Désactiver pendant sauvegarde activeColor: Theme.of(context).primaryColor, inactiveThumbColor: Colors.grey.shade400, // Couleur visible quand OFF inactiveTrackColor: Colors.grey.shade300, // Track visible quand OFF contentPadding: EdgeInsets.zero, dense: true, ); } Future _updatePrefs(BuildContext context, NotificationPreferences newPrefs) async { // Mise à jour locale immédiate pour feedback visuel setState(() { _localPrefs = newPrefs; _isSaving = true; }); final userProvider = context.read(); try { await userProvider.updateNotificationPreferences(newPrefs); if (mounted) { setState(() { _isSaving = false; _localPrefs = null; // Revenir aux prefs du provider }); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Préférences enregistrées'), backgroundColor: Colors.green, duration: Duration(seconds: 2), ), ); } } catch (e) { if (mounted) { setState(() { _isSaving = false; _localPrefs = null; // Rollback en cas d'erreur }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur : $e'), backgroundColor: Colors.red, ), ); } } } }