import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../core/di/injection.dart'; import '../../../../core/models/membre_model.dart'; import '../../../../shared/theme/app_theme.dart'; import '../bloc/membres_bloc.dart'; import '../bloc/membres_event.dart'; import '../bloc/membres_state.dart'; /// Dialog de confirmation de suppression/désactivation d'un membre class MembreDeleteDialog extends StatefulWidget { const MembreDeleteDialog({ super.key, required this.membre, }); final MembreModel membre; @override State createState() => _MembreDeleteDialogState(); } class _MembreDeleteDialogState extends State { late MembresBloc _membresBloc; bool _isLoading = false; bool _softDelete = true; // Par défaut, désactivation plutôt que suppression bool _hasActiveCotisations = false; bool _hasUnpaidCotisations = false; int _totalCotisations = 0; double _unpaidAmount = 0.0; @override void initState() { super.initState(); _membresBloc = getIt(); _checkMemberDependencies(); } void _checkMemberDependencies() { // TODO: Implémenter la vérification des dépendances via le repository // Pour l'instant, simulation avec des données fictives setState(() { _hasActiveCotisations = true; _hasUnpaidCotisations = true; _totalCotisations = 5; _unpaidAmount = 75000.0; }); } @override Widget build(BuildContext context) { return BlocProvider.value( value: _membresBloc, child: BlocConsumer( listener: (context, state) { if (state is MembreDeleted) { setState(() { _isLoading = false; }); Navigator.of(context).pop(true); } else if (state is MembreUpdated) { setState(() { _isLoading = false; }); Navigator.of(context).pop(true); } else if (state is MembresError) { setState(() { _isLoading = false; }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(state.message), backgroundColor: AppTheme.errorColor, ), ); } }, builder: (context, state) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), title: Row( children: [ Icon( _softDelete ? Icons.person_off : Icons.delete_forever, color: _softDelete ? AppTheme.warningColor : AppTheme.errorColor, ), const SizedBox(width: 12), Expanded( child: Text( _softDelete ? 'Désactiver le membre' : 'Supprimer le membre', style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w600, ), ), ), ], ), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Informations du membre _buildMemberInfo(), const SizedBox(height: 20), // Vérifications des dépendances if (_hasActiveCotisations || _hasUnpaidCotisations) _buildDependenciesWarning(), const SizedBox(height: 16), // Options de suppression _buildDeleteOptions(), const SizedBox(height: 20), // Message de confirmation _buildConfirmationMessage(), ], ), ), actions: [ TextButton( onPressed: _isLoading ? null : () => Navigator.of(context).pop(false), child: const Text('Annuler'), ), ElevatedButton( onPressed: _isLoading ? null : _handleDelete, style: ElevatedButton.styleFrom( backgroundColor: _softDelete ? AppTheme.warningColor : AppTheme.errorColor, foregroundColor: Colors.white, ), child: _isLoading ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ) : Text(_softDelete ? 'Désactiver' : 'Supprimer'), ), ], ); }, ), ); } Widget _buildMemberInfo() { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppTheme.backgroundLight, borderRadius: BorderRadius.circular(8), border: Border.all(color: AppTheme.borderColor), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ CircleAvatar( backgroundColor: AppTheme.primaryColor, child: Text( '${widget.membre.prenom[0]}${widget.membre.nom[0]}', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${widget.membre.prenom} ${widget.membre.nom}', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), ), Text( widget.membre.numeroMembre, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary, ), ), ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: widget.membre.actif ? AppTheme.successColor : AppTheme.errorColor, borderRadius: BorderRadius.circular(12), ), child: Text( widget.membre.actif ? 'Actif' : 'Inactif', style: const TextStyle( fontSize: 10, color: Colors.white, fontWeight: FontWeight.w500, ), ), ), ], ), const SizedBox(height: 8), Text( widget.membre.email, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary, ), ), ], ), ); } Widget _buildDependenciesWarning() { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppTheme.warningColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), border: Border.all(color: AppTheme.warningColor.withOpacity(0.3)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( Icons.warning_amber, color: AppTheme.warningColor, size: 20, ), const SizedBox(width: 8), const Text( 'Attention - Dépendances détectées', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: AppTheme.warningColor, ), ), ], ), const SizedBox(height: 8), if (_hasActiveCotisations) ...[ Text( '• $_totalCotisations cotisations associées à ce membre', style: const TextStyle(fontSize: 12, color: AppTheme.textSecondary), ), ], if (_hasUnpaidCotisations) ...[ Text( '• ${_unpaidAmount.toStringAsFixed(0)} XOF de cotisations impayées', style: const TextStyle(fontSize: 12, color: AppTheme.textSecondary), ), ], const SizedBox(height: 8), const Text( 'La désactivation est recommandée pour préserver l\'historique.', style: TextStyle( fontSize: 11, color: AppTheme.textSecondary, fontStyle: FontStyle.italic, ), ), ], ), ); } Widget _buildDeleteOptions() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Options de suppression :', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), ), const SizedBox(height: 12), // Option désactivation InkWell( onTap: () { setState(() { _softDelete = true; }); }, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: _softDelete ? AppTheme.warningColor.withOpacity(0.1) : Colors.transparent, borderRadius: BorderRadius.circular(8), border: Border.all( color: _softDelete ? AppTheme.warningColor : AppTheme.borderColor, width: _softDelete ? 2 : 1, ), ), child: Row( children: [ Radio( value: true, groupValue: _softDelete, onChanged: (value) { setState(() { _softDelete = value!; }); }, activeColor: AppTheme.warningColor, ), const SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Désactiver le membre (Recommandé)', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppTheme.textPrimary, ), ), const SizedBox(height: 4), const Text( 'Le membre sera marqué comme inactif mais ses données et historique seront préservés.', style: TextStyle( fontSize: 11, color: AppTheme.textSecondary, ), ), ], ), ), ], ), ), ), const SizedBox(height: 8), // Option suppression définitive InkWell( onTap: () { setState(() { _softDelete = false; }); }, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: !_softDelete ? AppTheme.errorColor.withOpacity(0.1) : Colors.transparent, borderRadius: BorderRadius.circular(8), border: Border.all( color: !_softDelete ? AppTheme.errorColor : AppTheme.borderColor, width: !_softDelete ? 2 : 1, ), ), child: Row( children: [ Radio( value: false, groupValue: _softDelete, onChanged: (value) { setState(() { _softDelete = value!; }); }, activeColor: AppTheme.errorColor, ), const SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Supprimer définitivement', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppTheme.textPrimary, ), ), const SizedBox(height: 4), const Text( 'ATTENTION : Cette action est irréversible. Toutes les données du membre seront perdues.', style: TextStyle( fontSize: 11, color: AppTheme.errorColor, fontWeight: FontWeight.w500, ), ), ], ), ), ], ), ), ), ], ); } Widget _buildConfirmationMessage() { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: _softDelete ? AppTheme.warningColor.withOpacity(0.1) : AppTheme.errorColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), border: Border.all( color: _softDelete ? AppTheme.warningColor.withOpacity(0.3) : AppTheme.errorColor.withOpacity(0.3), ), ), child: Text( _softDelete ? 'Le membre "${widget.membre.prenom} ${widget.membre.nom}" sera désactivé et ne pourra plus accéder aux services, mais son historique sera préservé.' : 'Le membre "${widget.membre.prenom} ${widget.membre.nom}" sera définitivement supprimé avec toutes ses données. Cette action ne peut pas être annulée.', style: TextStyle( fontSize: 12, color: _softDelete ? AppTheme.warningColor : AppTheme.errorColor, fontWeight: FontWeight.w500, ), ), ); } void _handleDelete() { setState(() { _isLoading = true; }); if (_softDelete) { // Désactivation du membre final membreDesactive = widget.membre.copyWith( actif: false, version: widget.membre.version + 1, dateModification: DateTime.now(), ); final memberId = widget.membre.id; if (memberId != null && memberId.isNotEmpty) { _membresBloc.add(UpdateMembre(memberId, membreDesactive)); } else { setState(() { _isLoading = false; }); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Erreur : ID du membre manquant'), backgroundColor: AppTheme.errorColor, ), ); } } else { // Suppression définitive final memberId = widget.membre.id; if (memberId != null && memberId.isNotEmpty) { _membresBloc.add(DeleteMembre(memberId)); } else { setState(() { _isLoading = false; }); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Erreur : ID du membre manquant'), backgroundColor: AppTheme.errorColor, ), ); } } } }