1687 lines
50 KiB
Dart
1687 lines
50 KiB
Dart
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<ProfilePage> createState() => _ProfilePageState();
|
|
}
|
|
|
|
class _ProfilePageState extends State<ProfilePage>
|
|
with TickerProviderStateMixin {
|
|
late TabController _tabController;
|
|
final _formKey = GlobalKey<FormState>();
|
|
|
|
// 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<String> _languages = ['Français', 'English', 'Español', 'Deutsch'];
|
|
final List<String> _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<Widget> 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<Color>(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<Widget> 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<Widget> children,
|
|
) {
|
|
return _buildPreferenceSection(title, subtitle, icon, children);
|
|
}
|
|
|
|
/// Section avancée
|
|
Widget _buildAdvancedSection(
|
|
String title,
|
|
String subtitle,
|
|
IconData icon,
|
|
List<Widget> children,
|
|
) {
|
|
return _buildPreferenceSection(title, subtitle, icon, children);
|
|
}
|
|
|
|
/// Préférence avec dropdown
|
|
Widget _buildDropdownPreference(
|
|
String title,
|
|
String subtitle,
|
|
String value,
|
|
List<String> 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<String>(
|
|
value: value,
|
|
isExpanded: true,
|
|
onChanged: onChanged,
|
|
items: options.map((option) {
|
|
return DropdownMenuItem<String>(
|
|
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<void> _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<void> _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,
|
|
),
|
|
);
|
|
}
|
|
}
|