import 'package:flutter/material.dart'; import 'dart:io'; /// Page Mon Profil - UnionFlow Mobile /// /// Page complète de gestion du profil utilisateur avec informations personnelles, /// préférences, sécurité, et paramètres avancés. class ProfilePage extends StatefulWidget { const ProfilePage({super.key}); @override State createState() => _ProfilePageState(); } class _ProfilePageState extends State with TickerProviderStateMixin { late TabController _tabController; final _formKey = GlobalKey(); // Contrôleurs pour les champs de texte final _firstNameController = TextEditingController(); final _lastNameController = TextEditingController(); final _emailController = TextEditingController(); final _phoneController = TextEditingController(); final _addressController = TextEditingController(); final _cityController = TextEditingController(); final _postalCodeController = TextEditingController(); final _bioController = TextEditingController(); // État du profil File? _profileImage; bool _isEditing = false; bool _isLoading = false; String _selectedLanguage = 'Français'; String _selectedTheme = 'Système'; bool _biometricEnabled = false; bool _twoFactorEnabled = false; final List _languages = ['Français', 'English', 'Español', 'Deutsch']; final List _themes = ['Système', 'Clair', 'Sombre']; @override void initState() { super.initState(); _tabController = TabController(length: 4, vsync: this); _loadUserProfile(); } @override void dispose() { _tabController.dispose(); _firstNameController.dispose(); _lastNameController.dispose(); _emailController.dispose(); _phoneController.dispose(); _addressController.dispose(); _cityController.dispose(); _postalCodeController.dispose(); _bioController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF8F9FA), body: Column( children: [ // Header harmonisé _buildHeader(), // Onglets _buildTabBar(), // Contenu des onglets Expanded( child: TabBarView( controller: _tabController, children: [ _buildPersonalInfoTab(), _buildPreferencesTab(), _buildSecurityTab(), _buildAdvancedTab(), ], ), ), ], ), ); } /// Header harmonisé avec photo de profil Widget _buildHeader() { return Container( margin: const EdgeInsets.all(12), padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFF6C5CE7), Color(0xFF5A4FCF)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: const Color(0xFF6C5CE7).withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 8), ), ], ), child: Column( children: [ Row( children: [ // Photo de profil Stack( children: [ Container( width: 80, height: 80, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: Colors.white, width: 3, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: ClipOval( child: _profileImage != null ? Image.file( _profileImage!, fit: BoxFit.cover, ) : Container( color: Colors.white.withOpacity(0.2), child: const Icon( Icons.person, size: 40, color: Colors.white, ), ), ), ), Positioned( bottom: 0, right: 0, child: InkWell( onTap: _pickProfileImage, child: Container( padding: const EdgeInsets.all(6), decoration: const BoxDecoration( color: Colors.white, shape: BoxShape.circle, ), child: const Icon( Icons.camera_alt, size: 16, color: Color(0xFF6C5CE7), ), ), ), ), ], ), const SizedBox(width: 16), // Informations utilisateur Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${_firstNameController.text} ${_lastNameController.text}', style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 4), Text( _emailController.text.isNotEmpty ? _emailController.text : 'utilisateur@unionflow.com', style: TextStyle( fontSize: 14, color: Colors.white.withOpacity(0.8), ), ), const SizedBox(height: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(12), ), child: const Text( 'Membre actif', style: TextStyle( fontSize: 12, color: Colors.white, fontWeight: FontWeight.w600, ), ), ), ], ), ), ], ), const SizedBox(height: 16), // Statistiques rapides Row( children: [ Expanded( child: _buildStatCard('Depuis', '2 ans', Icons.calendar_today), ), const SizedBox(width: 12), Expanded( child: _buildStatCard('Événements', '24', Icons.event), ), const SizedBox(width: 12), Expanded( child: _buildStatCard('Organisations', '3', Icons.business), ), ], ), ], ), ); } /// Carte de statistique Widget _buildStatCard(String label, String value, IconData icon) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white.withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: Column( children: [ Icon( icon, color: Colors.white, size: 20, ), const SizedBox(height: 4), Text( value, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white, ), ), Text( label, style: TextStyle( fontSize: 10, color: Colors.white.withOpacity(0.8), ), ), ], ), ); } /// Barre d'onglets Widget _buildTabBar() { return Container( margin: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: TabBar( controller: _tabController, labelColor: const Color(0xFF6C5CE7), unselectedLabelColor: Colors.grey[600], indicatorColor: const Color(0xFF6C5CE7), indicatorWeight: 3, indicatorSize: TabBarIndicatorSize.tab, labelStyle: const TextStyle( fontWeight: FontWeight.w600, fontSize: 11, ), unselectedLabelStyle: const TextStyle( fontWeight: FontWeight.normal, fontSize: 11, ), tabs: const [ Tab( icon: Icon(Icons.person, size: 18), text: 'Personnel', ), Tab( icon: Icon(Icons.settings, size: 18), text: 'Préférences', ), Tab( icon: Icon(Icons.security, size: 18), text: 'Sécurité', ), Tab( icon: Icon(Icons.tune, size: 18), text: 'Avancé', ), ], ), ); } /// Onglet informations personnelles Widget _buildPersonalInfoTab() { return SingleChildScrollView( padding: const EdgeInsets.all(12), child: Column( children: [ const SizedBox(height: 16), // Section informations de base _buildInfoSection( 'Informations personnelles', 'Vos données personnelles et de contact', Icons.person, [ Row( children: [ Expanded( child: _buildTextField( controller: _firstNameController, label: 'Prénom', icon: Icons.person_outline, enabled: _isEditing, ), ), const SizedBox(width: 12), Expanded( child: _buildTextField( controller: _lastNameController, label: 'Nom', icon: Icons.person_outline, enabled: _isEditing, ), ), ], ), _buildTextField( controller: _emailController, label: 'Email', icon: Icons.email_outlined, enabled: _isEditing, keyboardType: TextInputType.emailAddress, ), _buildTextField( controller: _phoneController, label: 'Téléphone', icon: Icons.phone_outlined, enabled: _isEditing, keyboardType: TextInputType.phone, ), ], ), const SizedBox(height: 16), // Section adresse _buildInfoSection( 'Adresse', 'Votre adresse de résidence', Icons.location_on, [ _buildTextField( controller: _addressController, label: 'Adresse', icon: Icons.home_outlined, enabled: _isEditing, maxLines: 2, ), Row( children: [ Expanded( flex: 2, child: _buildTextField( controller: _cityController, label: 'Ville', icon: Icons.location_city_outlined, enabled: _isEditing, ), ), const SizedBox(width: 12), Expanded( child: _buildTextField( controller: _postalCodeController, label: 'Code postal', icon: Icons.markunread_mailbox_outlined, enabled: _isEditing, keyboardType: TextInputType.number, ), ), ], ), ], ), const SizedBox(height: 16), // Section biographie _buildInfoSection( 'À propos de moi', 'Partagez quelques mots sur vous', Icons.info, [ _buildTextField( controller: _bioController, label: 'Biographie', icon: Icons.edit_outlined, enabled: _isEditing, maxLines: 4, hintText: 'Parlez-nous de vous, vos intérêts, votre parcours...', ), ], ), const SizedBox(height: 16), // Boutons d'action _buildActionButtons(), const SizedBox(height: 80), ], ), ); } /// Section d'informations Widget _buildInfoSection( String title, String subtitle, IconData icon, List children, ) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( icon, color: Colors.grey[600], size: 20, ), const SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.grey[800], ), ), Text( subtitle, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ), ), ], ), const SizedBox(height: 16), ...children.map((child) => Padding( padding: const EdgeInsets.only(bottom: 12), child: child, )), ], ), ); } /// Champ de texte personnalisé Widget _buildTextField({ required TextEditingController controller, required String label, required IconData icon, bool enabled = true, TextInputType? keyboardType, int maxLines = 1, String? hintText, }) { return TextFormField( controller: controller, enabled: enabled, keyboardType: keyboardType, maxLines: maxLines, decoration: InputDecoration( labelText: label, hintText: hintText, prefixIcon: Icon(icon, color: enabled ? const Color(0xFF6C5CE7) : Colors.grey), filled: true, fillColor: enabled ? Colors.grey[50] : Colors.grey[100], border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey[300]!), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey[300]!), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFF6C5CE7), width: 2), ), disabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey[300]!), ), labelStyle: TextStyle( color: enabled ? Colors.grey[700] : Colors.grey[500], ), ), validator: (value) { if (label == 'Email' && value != null && value.isNotEmpty) { if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) { return 'Email invalide'; } } return null; }, ); } /// Boutons d'action Widget _buildActionButtons() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Row( children: [ if (_isEditing) ...[ Expanded( child: ElevatedButton.icon( onPressed: _isLoading ? null : _cancelEditing, style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[100], foregroundColor: Colors.grey[700], elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), ), icon: const Icon(Icons.cancel, size: 18), label: const Text('Annuler'), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton.icon( onPressed: _isLoading ? null : _saveProfile, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF6C5CE7), foregroundColor: Colors.white, elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), ), icon: _isLoading ? const SizedBox( width: 18, height: 18, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ) : const Icon(Icons.save, size: 18), label: Text(_isLoading ? 'Sauvegarde...' : 'Sauvegarder'), ), ), ] else ...[ Expanded( child: ElevatedButton.icon( onPressed: _startEditing, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF6C5CE7), foregroundColor: Colors.white, elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), ), icon: const Icon(Icons.edit, size: 18), label: const Text('Modifier le profil'), ), ), ], ], ), ); } /// Onglet préférences Widget _buildPreferencesTab() { return SingleChildScrollView( padding: const EdgeInsets.all(12), child: Column( children: [ const SizedBox(height: 16), // Langue et région _buildPreferenceSection( 'Langue et région', 'Personnaliser l\'affichage', Icons.language, [ _buildDropdownPreference( 'Langue', 'Choisir la langue de l\'interface', _selectedLanguage, _languages, (value) => setState(() => _selectedLanguage = value!), ), _buildDropdownPreference( 'Thème', 'Apparence de l\'application', _selectedTheme, _themes, (value) => setState(() => _selectedTheme = value!), ), ], ), const SizedBox(height: 16), // Notifications _buildPreferenceSection( 'Notifications', 'Gérer vos alertes', Icons.notifications, [ _buildSwitchPreference( 'Notifications push', 'Recevoir des notifications sur cet appareil', true, (value) => _showSuccessSnackBar('Préférence mise à jour'), ), _buildSwitchPreference( 'Notifications email', 'Recevoir des emails de notification', false, (value) => _showSuccessSnackBar('Préférence mise à jour'), ), _buildSwitchPreference( 'Sons et vibrations', 'Alertes sonores et vibrations', true, (value) => _showSuccessSnackBar('Préférence mise à jour'), ), ], ), const SizedBox(height: 16), // Confidentialité _buildPreferenceSection( 'Confidentialité', 'Contrôler vos données', Icons.privacy_tip, [ _buildSwitchPreference( 'Profil public', 'Permettre aux autres de voir votre profil', false, (value) => _showSuccessSnackBar('Préférence mise à jour'), ), _buildSwitchPreference( 'Partage de données', 'Partager des données anonymes pour améliorer l\'app', true, (value) => _showSuccessSnackBar('Préférence mise à jour'), ), ], ), const SizedBox(height: 80), ], ), ); } /// Onglet sécurité Widget _buildSecurityTab() { return SingleChildScrollView( padding: const EdgeInsets.all(12), child: Column( children: [ const SizedBox(height: 16), // Authentification _buildSecuritySection( 'Authentification', 'Sécuriser votre compte', Icons.security, [ _buildSecurityItem( 'Changer le mot de passe', 'Dernière modification il y a 3 mois', Icons.lock_outline, () => _showChangePasswordDialog(), ), _buildSwitchPreference( 'Authentification biométrique', 'Utiliser l\'empreinte digitale ou Face ID', _biometricEnabled, (value) { setState(() => _biometricEnabled = value); _showSuccessSnackBar('Authentification biométrique ${value ? 'activée' : 'désactivée'}'); }, ), _buildSwitchPreference( 'Authentification à deux facteurs', 'Sécurité renforcée avec SMS ou app', _twoFactorEnabled, (value) { setState(() => _twoFactorEnabled = value); if (value) { _showTwoFactorSetupDialog(); } else { _showSuccessSnackBar('Authentification à deux facteurs désactivée'); } }, ), ], ), const SizedBox(height: 16), // Sessions actives _buildSecuritySection( 'Sessions actives', 'Gérer vos connexions', Icons.devices, [ _buildSessionItem( 'Cet appareil', 'Android • Maintenant', Icons.smartphone, true, ), _buildSessionItem( 'Navigateur Web', 'Chrome • Il y a 2 heures', Icons.web, false, ), ], ), const SizedBox(height: 16), // Actions de sécurité _buildSecuritySection( 'Actions de sécurité', 'Gérer votre compte', Icons.warning, [ _buildActionItem( 'Télécharger mes données', 'Exporter toutes vos données personnelles', Icons.download, const Color(0xFF0984E3), () => _exportUserData(), ), _buildActionItem( 'Déconnecter tous les appareils', 'Fermer toutes les sessions actives', Icons.logout, const Color(0xFFE17055), () => _logoutAllDevices(), ), _buildActionItem( 'Supprimer mon compte', 'Action irréversible - toutes les données seront perdues', Icons.delete_forever, Colors.red, () => _showDeleteAccountDialog(), ), ], ), const SizedBox(height: 80), ], ), ); } /// Onglet avancé Widget _buildAdvancedTab() { return SingleChildScrollView( padding: const EdgeInsets.all(12), child: Column( children: [ const SizedBox(height: 16), // Données et stockage _buildAdvancedSection( 'Données et stockage', 'Gérer l\'utilisation des données', Icons.storage, [ _buildStorageItem('Cache de l\'application', '45 MB', () => _clearCache()), _buildStorageItem('Images téléchargées', '128 MB', () => _clearImages()), _buildStorageItem('Données hors ligne', '12 MB', () => _clearOfflineData()), ], ), const SizedBox(height: 16), // Développeur _buildAdvancedSection( 'Options développeur', 'Paramètres avancés', Icons.code, [ _buildSwitchPreference( 'Mode développeur', 'Afficher les options de débogage', false, (value) => _showSuccessSnackBar('Mode développeur ${value ? 'activé' : 'désactivé'}'), ), _buildSwitchPreference( 'Logs détaillés', 'Enregistrer plus d\'informations de débogage', false, (value) => _showSuccessSnackBar('Logs détaillés ${value ? 'activés' : 'désactivés'}'), ), ], ), const SizedBox(height: 16), // Informations système _buildAdvancedSection( 'Informations système', 'Détails techniques', Icons.info, [ _buildInfoItem('Version de l\'app', '2.1.0 (Build 42)'), _buildInfoItem('Version Flutter', '3.16.0'), _buildInfoItem('Plateforme', 'Android 13'), _buildInfoItem('ID de l\'appareil', 'R58R34HT85V'), ], ), const SizedBox(height: 80), ], ), ); } // ==================== MÉTHODES DE CONSTRUCTION DES COMPOSANTS ==================== /// Section de préférence Widget _buildPreferenceSection( String title, String subtitle, IconData icon, List children, ) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(icon, color: Colors.grey[600], size: 20), const SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.grey[800], ), ), Text( subtitle, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ), ), ], ), const SizedBox(height: 16), ...children.map((child) => Padding( padding: const EdgeInsets.only(bottom: 12), child: child, )), ], ), ); } /// Section de sécurité Widget _buildSecuritySection( String title, String subtitle, IconData icon, List children, ) { return _buildPreferenceSection(title, subtitle, icon, children); } /// Section avancée Widget _buildAdvancedSection( String title, String subtitle, IconData icon, List children, ) { return _buildPreferenceSection(title, subtitle, icon, children); } /// Préférence avec dropdown Widget _buildDropdownPreference( String title, String subtitle, String value, List options, Function(String?) onChanged, ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), const SizedBox(height: 4), Text( subtitle, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), const SizedBox(height: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey[300]!), ), child: DropdownButtonHideUnderline( child: DropdownButton( value: value, isExpanded: true, onChanged: onChanged, items: options.map((option) { return DropdownMenuItem( value: option, child: Text(option), ); }).toList(), ), ), ), ], ); } /// Préférence avec switch Widget _buildSwitchPreference( String title, String subtitle, bool value, Function(bool) onChanged, ) { return Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), Text( subtitle, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ), ), Switch( value: value, onChanged: onChanged, activeColor: const Color(0xFF6C5CE7), ), ], ); } /// Élément de sécurité Widget _buildSecurityItem( String title, String subtitle, IconData icon, VoidCallback onTap, ) { return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Icon(icon, color: const Color(0xFF6C5CE7), size: 20), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), Text( subtitle, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ), ), Icon(Icons.arrow_forward_ios, color: Colors.grey[400], size: 16), ], ), ), ); } /// Élément de session Widget _buildSessionItem( String title, String subtitle, IconData icon, bool isCurrentDevice, ) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: isCurrentDevice ? const Color(0xFF6C5CE7).withOpacity(0.1) : Colors.grey[50], borderRadius: BorderRadius.circular(12), border: isCurrentDevice ? Border.all(color: const Color(0xFF6C5CE7).withOpacity(0.3)) : null, ), child: Row( children: [ Icon( icon, color: isCurrentDevice ? const Color(0xFF6C5CE7) : Colors.grey[600], size: 20, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), if (isCurrentDevice) ...[ const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: const Color(0xFF6C5CE7), borderRadius: BorderRadius.circular(8), ), child: const Text( 'Actuel', style: TextStyle( fontSize: 10, color: Colors.white, fontWeight: FontWeight.w600, ), ), ), ], ], ), Text( subtitle, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ), ), if (!isCurrentDevice) IconButton( onPressed: () => _terminateSession(title), icon: const Icon(Icons.close, color: Colors.red, size: 18), tooltip: 'Terminer la session', ), ], ), ); } /// Élément d'action Widget _buildActionItem( String title, String subtitle, IconData icon, Color color, VoidCallback onTap, ) { return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: color.withOpacity(0.05), borderRadius: BorderRadius.circular(12), border: Border.all(color: color.withOpacity(0.1)), ), child: Row( children: [ Icon(icon, color: color, size: 20), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: color, ), ), Text( subtitle, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ), ), Icon(Icons.arrow_forward_ios, color: Colors.grey[400], size: 16), ], ), ), ); } /// Élément de stockage Widget _buildStorageItem(String title, String size, VoidCallback onTap) { return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Icon(Icons.folder, color: Colors.grey[600], size: 20), const SizedBox(width: 12), Expanded( child: Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), ), Text( size, style: TextStyle( fontSize: 12, color: Colors.grey[600], fontWeight: FontWeight.w600, ), ), const SizedBox(width: 8), Icon(Icons.clear, color: Colors.grey[400], size: 16), ], ), ), ); } /// Élément d'information Widget _buildInfoItem(String title, String value) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Expanded( child: Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), ), Text( value, style: TextStyle( fontSize: 12, color: Colors.grey[600], fontWeight: FontWeight.w600, ), ), ], ), ); } // ==================== MÉTHODES D'ACTION ==================== /// Charger le profil utilisateur void _loadUserProfile() { // Simuler le chargement des données _firstNameController.text = 'Jean'; _lastNameController.text = 'Dupont'; _emailController.text = 'jean.dupont@unionflow.com'; _phoneController.text = '+33 6 12 34 56 78'; _addressController.text = '123 Rue de la République'; _cityController.text = 'Paris'; _postalCodeController.text = '75001'; _bioController.text = 'Membre actif du syndicat depuis 2 ans, passionné par les droits des travailleurs et l\'amélioration des conditions de travail.'; } /// Commencer l'édition void _startEditing() { setState(() { _isEditing = true; }); } /// Annuler l'édition void _cancelEditing() { setState(() { _isEditing = false; }); _loadUserProfile(); // Recharger les données originales } /// Sauvegarder le profil Future _saveProfile() async { if (!_formKey.currentState!.validate()) return; setState(() { _isLoading = true; }); // Simuler la sauvegarde await Future.delayed(const Duration(seconds: 2)); setState(() { _isLoading = false; _isEditing = false; }); _showSuccessSnackBar('Profil mis à jour avec succès'); } /// Choisir une image de profil Future _pickProfileImage() async { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Changer la photo de profil'), content: const Text('Cette fonctionnalité sera bientôt disponible !'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Fermer'), ), ], ), ); } /// Terminer une session void _terminateSession(String deviceName) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Terminer la session'), content: Text('Êtes-vous sûr de vouloir terminer la session sur "$deviceName" ?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Annuler'), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); _showSuccessSnackBar('Session terminée sur $deviceName'); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.red, foregroundColor: Colors.white, ), child: const Text('Terminer'), ), ], ), ); } /// Dialogue de changement de mot de passe void _showChangePasswordDialog() { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Changer le mot de passe'), content: const Column( mainAxisSize: MainAxisSize.min, children: [ TextField( obscureText: true, decoration: InputDecoration( labelText: 'Mot de passe actuel', border: OutlineInputBorder(), ), ), SizedBox(height: 16), TextField( obscureText: true, decoration: InputDecoration( labelText: 'Nouveau mot de passe', border: OutlineInputBorder(), ), ), SizedBox(height: 16), TextField( obscureText: true, decoration: InputDecoration( labelText: 'Confirmer le nouveau mot de passe', border: OutlineInputBorder(), ), ), ], ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Annuler'), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); _showSuccessSnackBar('Mot de passe modifié avec succès'); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF6C5CE7), foregroundColor: Colors.white, ), child: const Text('Modifier'), ), ], ), ); } /// Configuration de l'authentification à deux facteurs void _showTwoFactorSetupDialog() { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Authentification à deux facteurs'), content: const Text( 'L\'authentification à deux facteurs ajoute une couche de sécurité supplémentaire à votre compte. ' 'Vous recevrez un code par SMS ou via une application d\'authentification.', ), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); setState(() => _twoFactorEnabled = false); }, child: const Text('Annuler'), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); _showSuccessSnackBar('Authentification à deux facteurs configurée'); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF6C5CE7), foregroundColor: Colors.white, ), child: const Text('Configurer'), ), ], ), ); } /// Exporter les données utilisateur void _exportUserData() { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Télécharger mes données'), content: const Text( 'Nous allons préparer un fichier contenant toutes vos données personnelles. ' 'Vous recevrez un email avec le lien de téléchargement dans les 24 heures.', ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Annuler'), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); _showSuccessSnackBar('Demande d\'export envoyée. Vous recevrez un email.'); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF0984E3), foregroundColor: Colors.white, ), child: const Text('Demander l\'export'), ), ], ), ); } /// Déconnecter tous les appareils void _logoutAllDevices() { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Déconnecter tous les appareils'), content: const Text( 'Cette action fermera toutes vos sessions actives sur tous les appareils. ' 'Vous devrez vous reconnecter partout.', ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Annuler'), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); _showSuccessSnackBar('Toutes les sessions ont été fermées'); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFE17055), foregroundColor: Colors.white, ), child: const Text('Déconnecter tout'), ), ], ), ); } /// Dialogue de suppression de compte void _showDeleteAccountDialog() { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Supprimer mon compte'), content: const Text( 'ATTENTION : Cette action est irréversible !\n\n' 'Toutes vos données seront définitivement supprimées :\n' '• Profil et informations personnelles\n' '• Historique des événements\n' '• Participations aux organisations\n' '• Tous les paramètres et préférences', ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Annuler'), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); _showFinalDeleteConfirmation(); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.red, foregroundColor: Colors.white, ), child: const Text('Continuer'), ), ], ), ); } /// Confirmation finale de suppression void _showFinalDeleteConfirmation() { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Confirmation finale'), content: const Column( mainAxisSize: MainAxisSize.min, children: [ Text('Tapez "SUPPRIMER" pour confirmer :'), SizedBox(height: 16), TextField( decoration: InputDecoration( border: OutlineInputBorder(), hintText: 'SUPPRIMER', ), ), ], ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Annuler'), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); _showErrorSnackBar('Fonctionnalité désactivée pour la démo'); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.red, foregroundColor: Colors.white, ), child: const Text('SUPPRIMER DÉFINITIVEMENT'), ), ], ), ); } /// Vider le cache void _clearCache() { _showSuccessSnackBar('Cache vidé (45 MB libérés)'); } /// Vider les images void _clearImages() { _showSuccessSnackBar('Images supprimées (128 MB libérés)'); } /// Vider les données hors ligne void _clearOfflineData() { _showSuccessSnackBar('Données hors ligne supprimées (12 MB libérés)'); } /// Afficher un message de succès void _showSuccessSnackBar(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), backgroundColor: const Color(0xFF00B894), behavior: SnackBarBehavior.floating, ), ); } /// Afficher un message d'erreur void _showErrorSnackBar(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), backgroundColor: const Color(0xFFE74C3C), behavior: SnackBarBehavior.floating, ), ); } }