/// Page dédiée aux paramètres de confidentialité /// Gestion du profil public, partage de données, et suppression de compte library privacy_settings_page; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../../../shared/design_system/unionflow_design_system.dart'; class PrivacySettingsPage extends StatefulWidget { const PrivacySettingsPage({super.key}); @override State createState() => _PrivacySettingsPageState(); } class _PrivacySettingsPageState extends State { bool _profilePublic = false; bool _shareAnalytics = true; bool _showOnlineStatus = true; bool _allowSearchByEmail = true; static const String _keyProfilePublic = 'profile_public'; static const String _keyShareAnalytics = 'share_analytics'; static const String _keyShowOnlineStatus = 'show_online_status'; static const String _keyAllowSearchByEmail = 'allow_search_by_email'; @override void initState() { super.initState(); _loadPreferences(); } Future _loadPreferences() async { final prefs = await SharedPreferences.getInstance(); if (mounted) { setState(() { _profilePublic = prefs.getBool(_keyProfilePublic) ?? false; _shareAnalytics = prefs.getBool(_keyShareAnalytics) ?? true; _showOnlineStatus = prefs.getBool(_keyShowOnlineStatus) ?? true; _allowSearchByEmail = prefs.getBool(_keyAllowSearchByEmail) ?? true; }); } } Future _savePreference(String key, bool value) async { final prefs = await SharedPreferences.getInstance(); await prefs.setBool(key, value); } void _showSnackBar(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), backgroundColor: const Color(0xFF00B894), behavior: SnackBarBehavior.floating, ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF8F9FA), body: Column( children: [ _buildHeader(), Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(12), child: Column( children: [ const SizedBox(height: 16), _buildVisibilitySection(), const SizedBox(height: 16), _buildDataSection(), const SizedBox(height: 16), _buildDangerSection(), const SizedBox(height: 80), ], ), ), ), ], ), ); } Widget _buildHeader() { return Container( margin: const EdgeInsets.all(SpacingTokens.lg), padding: const EdgeInsets.all(SpacingTokens.xxl), decoration: BoxDecoration( gradient: const LinearGradient( colors: ColorTokens.primaryGradient, begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(SpacingTokens.xl), boxShadow: [ BoxShadow( color: ColorTokens.primary.withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 8), ), ], ), child: SafeArea( bottom: false, child: Row( children: [ IconButton( onPressed: () => Navigator.of(context).pop(), icon: const Icon(Icons.arrow_back, color: Colors.white), ), Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(12), ), child: const Icon(Icons.privacy_tip, color: Colors.white, size: 24), ), const SizedBox(width: 16), const Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Confidentialité', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white, ), ), Text( 'Contrôler la visibilité de vos données', style: TextStyle( fontSize: 14, color: Colors.white70, ), ), ], ), ), ], ), ), ); } Widget _buildVisibilitySection() { return _buildSection( 'Visibilité du profil', 'Qui peut voir vos informations', Icons.visibility, [ _buildSwitchTile( 'Profil public', 'Permettre aux autres membres de voir votre profil', _profilePublic, (value) async { setState(() => _profilePublic = value); await _savePreference(_keyProfilePublic, value); _showSnackBar(value ? 'Profil public activé' : 'Profil public désactivé'); }, ), _buildSwitchTile( 'Statut en ligne', 'Afficher quand vous êtes connecté', _showOnlineStatus, (value) async { setState(() => _showOnlineStatus = value); await _savePreference(_keyShowOnlineStatus, value); _showSnackBar(value ? 'Statut en ligne visible' : 'Statut en ligne masqué'); }, ), _buildSwitchTile( 'Recherche par email', 'Permettre de vous trouver via votre adresse email', _allowSearchByEmail, (value) async { setState(() => _allowSearchByEmail = value); await _savePreference(_keyAllowSearchByEmail, value); _showSnackBar(value ? 'Recherche par email activée' : 'Recherche par email désactivée'); }, ), ], ); } Widget _buildDataSection() { return _buildSection( 'Données et analyses', 'Utilisation de vos données', Icons.analytics, [ _buildSwitchTile( 'Partage de données anonymes', 'Aider à améliorer l\'application avec des statistiques d\'usage anonymisées', _shareAnalytics, (value) async { setState(() => _shareAnalytics = value); await _savePreference(_keyShareAnalytics, value); _showSnackBar(value ? 'Partage de données activé' : 'Partage de données désactivé'); }, ), ], ); } Widget _buildDangerSection() { return _buildSection( 'Zone sensible', 'Actions irréversibles', Icons.warning_amber, [ InkWell( onTap: _showDeleteAccountDialog, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.red.withOpacity(0.05), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.red.withOpacity(0.2)), ), child: Row( children: [ const Icon(Icons.delete_forever, color: Colors.red, size: 20), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Supprimer mon compte', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.red, ), ), Text( 'Supprimer définitivement toutes vos données', style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), ], ), ), Icon(Icons.arrow_forward_ios, color: Colors.grey[400], size: 16), ], ), ), ), ], ); } void _showDeleteAccountDialog() { showDialog( context: context, builder: (context) => AlertDialog( title: const Row( children: [ Icon(Icons.warning, color: Colors.red), SizedBox(width: 8), Text('Supprimer le compte'), ], ), content: const Text( 'Cette action est irréversible. Toutes vos données seront supprimées définitivement.\n\n' 'Pour confirmer, veuillez contacter l\'administrateur de votre organisation.', ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Annuler'), ), ElevatedButton( onPressed: () async { Navigator.of(context).pop(); final uri = Uri.parse('mailto:support@unionflow.com?subject=Demande de suppression de compte'); if (await canLaunchUrl(uri)) { await launchUrl(uri, mode: LaunchMode.externalApplication); } }, style: ElevatedButton.styleFrom(backgroundColor: Colors.red), child: const Text('Contacter l\'administrateur', style: TextStyle(color: Colors.white)), ), ], ), ); } Widget _buildSection(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, )), ], ), ); } Widget _buildSwitchTile( String title, String subtitle, bool value, ValueChanged onChanged, ) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), ), child: Row( children: [ const Icon(Icons.toggle_on, color: ColorTokens.primary, 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]), ), ], ), ), Switch( value: value, onChanged: onChanged, activeTrackColor: ColorTokens.primary, thumbColor: WidgetStateProperty.resolveWith((states) => states.contains(WidgetState.selected) ? Colors.white : null), ), ], ), ); } }