import 'package:flutter/material.dart'; import 'package:em2rp/services/event_availability_service.dart'; import 'package:em2rp/utils/colors.dart'; import 'package:intl/intl.dart'; /// Dialog affichant les conflits de disponibilité du matériel class EquipmentConflictDialog extends StatefulWidget { final Map> conflicts; const EquipmentConflictDialog({ super.key, required this.conflicts, }); @override State createState() => _EquipmentConflictDialogState(); } class _EquipmentConflictDialogState extends State { final Set _removedEquipmentIds = {}; int get totalConflicts => widget.conflicts.values.fold(0, (sum, list) => sum + list.length); int get remainingConflicts => widget.conflicts.entries .where((entry) => !_removedEquipmentIds.contains(entry.key)) .fold(0, (sum, entry) => sum + entry.value.length); @override Widget build(BuildContext context) { final dateFormat = DateFormat('dd/MM/yyyy'); return Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), child: Container( constraints: const BoxConstraints(maxWidth: 700, maxHeight: 700), padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ // En-tête avec icône warning Row( children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.orange.shade100, shape: BoxShape.circle, ), child: Icon( Icons.warning_amber_rounded, size: 32, color: Colors.orange.shade700, ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Conflits de disponibilité détectés', style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Text( '$remainingConflicts conflit(s) sur $totalConflicts équipement(s)', style: TextStyle( fontSize: 14, color: Colors.grey.shade700, ), ), ], ), ), IconButton( icon: const Icon(Icons.close), onPressed: () => Navigator.of(context).pop('cancel'), ), ], ), const SizedBox(height: 16), const Divider(), const SizedBox(height: 8), // Liste des conflits Flexible( child: ListView.builder( shrinkWrap: true, itemCount: widget.conflicts.length, itemBuilder: (context, index) { final entry = widget.conflicts.entries.elementAt(index); final equipmentId = entry.key; final conflictsList = entry.value; final isRemoved = _removedEquipmentIds.contains(equipmentId); if (conflictsList.isEmpty) return const SizedBox.shrink(); final firstConflict = conflictsList.first; return Opacity( opacity: isRemoved ? 0.4 : 1.0, child: Card( margin: const EdgeInsets.only(bottom: 12), elevation: isRemoved ? 0 : 2, color: isRemoved ? Colors.grey.shade200 : null, child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Nom de l'équipement Row( children: [ Icon( Icons.inventory_2, color: isRemoved ? Colors.grey : AppColors.rouge, size: 20, ), const SizedBox(width: 8), Expanded( child: Text( firstConflict.equipmentName, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, decoration: isRemoved ? TextDecoration.lineThrough : null, ), ), ), if (isRemoved) Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: Colors.grey, borderRadius: BorderRadius.circular(12), ), child: const Text( 'RETIRÉ', style: TextStyle( color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold, ), ), ), ], ), const SizedBox(height: 12), // Liste des événements en conflit ...conflictsList.map((conflict) { return Padding( padding: const EdgeInsets.only(bottom: 8, left: 28), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( Icons.event, size: 16, color: Colors.grey.shade600, ), const SizedBox(width: 6), Expanded( child: Text( conflict.conflictingEvent.name, style: TextStyle( fontWeight: FontWeight.w500, color: Colors.grey.shade800, ), ), ), ], ), const SizedBox(height: 4), Padding( padding: const EdgeInsets.only(left: 22), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${dateFormat.format(conflict.conflictingEvent.startDateTime)} → ${dateFormat.format(conflict.conflictingEvent.endDateTime)}', style: TextStyle( fontSize: 13, color: Colors.grey.shade600, ), ), Text( 'Chevauchement : ${conflict.overlapDays} jour(s)', style: TextStyle( fontSize: 12, color: Colors.orange.shade700, fontWeight: FontWeight.w500, ), ), ], ), ), ], ), ); }).toList(), // Boutons d'action par équipement if (!isRemoved) Padding( padding: const EdgeInsets.only(top: 8), child: Row( children: [ const Spacer(), OutlinedButton.icon( onPressed: () { setState(() { _removedEquipmentIds.add(equipmentId); }); }, icon: const Icon(Icons.remove_circle_outline, size: 16), label: const Text('Retirer'), style: OutlinedButton.styleFrom( foregroundColor: Colors.red, side: const BorderSide(color: Colors.red), ), ), ], ), ), ], ), ), ), ); }, ), ), const SizedBox(height: 16), const Divider(), const SizedBox(height: 16), // Boutons d'action globaux Row( children: [ Expanded( child: OutlinedButton( onPressed: () => Navigator.of(context).pop('cancel'), style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 14), ), child: const Text('Annuler tout'), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton( onPressed: remainingConflicts == 0 ? () => Navigator.of(context).pop('force_removed') : () => Navigator.of(context).pop('force_all'), style: ElevatedButton.styleFrom( backgroundColor: remainingConflicts == 0 ? Colors.green : Colors.orange, padding: const EdgeInsets.symmetric(vertical: 14), ), child: Text( remainingConflicts == 0 ? 'Valider sans les retirés' : 'Forcer malgré les conflits', style: const TextStyle(color: Colors.white), ), ), ), ], ), ], ), ), ); } }