import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:em2rp/models/event_model.dart'; import 'package:em2rp/models/equipment_model.dart'; import 'package:em2rp/providers/event_provider.dart'; import 'package:em2rp/providers/equipment_provider.dart'; import 'package:em2rp/providers/local_user_provider.dart'; import 'package:em2rp/services/event_preparation_service.dart'; import 'package:em2rp/utils/colors.dart'; import 'package:em2rp/views/widgets/nav/custom_app_bar.dart'; import 'package:em2rp/views/widgets/event/equipment_checklist_item.dart'; import 'package:em2rp/views/widgets/event/missing_equipment_dialog.dart'; import 'package:em2rp/views/widgets/event/preparation_success_dialog.dart'; class EventPreparationPage extends StatefulWidget { final String eventId; const EventPreparationPage({ super.key, required this.eventId, }); @override State createState() => _EventPreparationPageState(); } class _EventPreparationPageState extends State { final EventPreparationService _preparationService = EventPreparationService(); EventModel? _event; Map _equipmentMap = {}; Map _returnedQuantities = {}; // Pour les quantités retournées (consommables) bool _isLoading = true; bool _isSaving = false; // Mode déterminé automatiquement bool get _isReturnMode { if (_event == null) return false; // Mode retour si préparation complétée et retour pas encore complété return _event!.preparationStatus == PreparationStatus.completed || _event!.preparationStatus == PreparationStatus.completedWithMissing; } String get _pageTitle => _isReturnMode ? 'Retour matériel' : 'Préparation matériel'; @override void initState() { super.initState(); _loadEventAndEquipment(); } Future _loadEventAndEquipment() async { try { // Charger l'événement final eventProvider = context.read(); final event = await eventProvider.getEvent(widget.eventId); if (event == null) { throw Exception('Événement non trouvé'); } // Charger tous les équipements assignés final equipmentProvider = context.read(); final Map equipmentMap = {}; for (var assignedEq in event.assignedEquipment) { final equipment = await equipmentProvider.getEquipmentById(assignedEq.equipmentId); if (equipment != null) { equipmentMap[assignedEq.equipmentId] = equipment; // Initialiser les quantités retournées pour les consommables if (_isReturnMode && (equipment.category == EquipmentCategory.consumable || equipment.category == EquipmentCategory.cable)) { _returnedQuantities[assignedEq.equipmentId] = assignedEq.returnedQuantity ?? assignedEq.quantity; } } } setState(() { _event = event; _equipmentMap = equipmentMap; _isLoading = false; }); } catch (e) { setState(() => _isLoading = false); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur: $e'), backgroundColor: Colors.red, ), ); } } } Future _toggleEquipmentValidation(String equipmentId, bool isValidated) async { try { if (_isReturnMode) { if (isValidated) { final returnedQty = _returnedQuantities[equipmentId]; await _preparationService.validateEquipmentReturn( widget.eventId, equipmentId, returnedQuantity: returnedQty, ); } } else { await _preparationService.validateEquipmentPreparation(widget.eventId, equipmentId); } // Recharger l'événement await _loadEventAndEquipment(); } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Erreur: $e'), backgroundColor: Colors.red), ); } } } Future _validateAllQuickly() async { setState(() => _isSaving = true); try { if (_isReturnMode) { await _preparationService.validateAllReturn(widget.eventId, _returnedQuantities); } else { await _preparationService.validateAllPreparation(widget.eventId); } // Afficher le dialog de succès avec animation if (mounted) { await showDialog( context: context, barrierDismissible: false, builder: (context) => PreparationSuccessDialog(isReturnMode: _isReturnMode), ); // Retour à la page précédente Navigator.of(context).pop(); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Erreur: $e'), backgroundColor: Colors.red), ); } } finally { setState(() => _isSaving = false); } } Future _validatePreparation() async { if (_event == null) return; // Vérifier quels équipements ne sont pas validés final missingEquipment = []; final missingIds = []; for (var assignedEq in _event!.assignedEquipment) { final isValidated = _isReturnMode ? assignedEq.isReturned : assignedEq.isPrepared; if (!isValidated) { final equipment = _equipmentMap[assignedEq.equipmentId]; if (equipment != null) { missingEquipment.add(equipment); missingIds.add(assignedEq.equipmentId); } } } // Si tout est validé, on finalise directement if (missingEquipment.isEmpty) { await _validateAllQuickly(); return; } // Sinon, afficher le dialog des manquants if (mounted) { final result = await showDialog( context: context, builder: (context) => MissingEquipmentDialog( missingEquipments: missingEquipment, eventId: widget.eventId, isReturnMode: _isReturnMode, ), ); if (result == 'confirm_with_missing') { setState(() => _isSaving = true); try { if (_isReturnMode) { await _preparationService.completeReturnWithMissing(widget.eventId, missingIds); } else { await _preparationService.completePreparationWithMissing(widget.eventId, missingIds); } if (mounted) { await showDialog( context: context, barrierDismissible: false, builder: (context) => PreparationSuccessDialog(isReturnMode: _isReturnMode), ); Navigator.of(context).pop(); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Erreur: $e'), backgroundColor: Colors.red), ); } } finally { setState(() => _isSaving = false); } } else if (result == 'validate_missing') { // Valider tous les manquants setState(() => _isSaving = true); try { for (var equipmentId in missingIds) { await _toggleEquipmentValidation(equipmentId, true); } await _validateAllQuickly(); } finally { setState(() => _isSaving = false); } } } } @override Widget build(BuildContext context) { final userProvider = context.watch(); final userId = userProvider.uid; final hasManagePermission = userProvider.hasPermission('manage_events'); // Vérifier si l'utilisateur fait partie de l'équipe final isInWorkforce = _event?.workforce.any((ref) => ref.id == userId) ?? false; final hasPermission = hasManagePermission || isInWorkforce; if (!hasPermission) { return Scaffold( appBar: const CustomAppBar(title: 'Accès refusé'), body: const Center( child: Text('Vous n\'avez pas les permissions pour accéder à cette page.'), ), ); } return Scaffold( appBar: CustomAppBar(title: _pageTitle), body: _isLoading ? const Center(child: CircularProgressIndicator()) : _event == null ? const Center(child: Text('Événement introuvable')) : Column( children: [ // En-tête avec info de l'événement _buildEventHeader(), // Bouton "Tout confirmer" _buildQuickValidateButton(), // Liste des équipements Expanded(child: _buildEquipmentList()), // Bouton de validation final _buildValidateButton(), ], ), ); } Widget _buildEventHeader() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.rouge.withOpacity(0.1), border: Border( bottom: BorderSide(color: Colors.grey.shade300), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _event!.name, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Text( '${_event!.assignedEquipment.length} équipement(s) assigné(s)', style: TextStyle(color: Colors.grey.shade700), ), ], ), ); } Widget _buildQuickValidateButton() { return Container( padding: const EdgeInsets.all(16), child: ElevatedButton.icon( onPressed: _isSaving ? null : _validateAllQuickly, style: ElevatedButton.styleFrom( backgroundColor: Colors.green, minimumSize: const Size(double.infinity, 50), ), icon: const Icon(Icons.check_circle, color: Colors.white), label: Text( _isReturnMode ? 'Tout confirmer comme retourné' : 'Tout confirmer comme préparé', style: const TextStyle(color: Colors.white, fontSize: 16), ), ), ); } Widget _buildEquipmentList() { return ListView.builder( padding: const EdgeInsets.all(16), itemCount: _event!.assignedEquipment.length, itemBuilder: (context, index) { final assignedEq = _event!.assignedEquipment[index]; final equipment = _equipmentMap[assignedEq.equipmentId]; if (equipment == null) { return const SizedBox.shrink(); } final isValidated = _isReturnMode ? assignedEq.isReturned : assignedEq.isPrepared; return EquipmentChecklistItem( equipment: equipment, isValidated: isValidated, onValidate: (value) => _toggleEquipmentValidation(assignedEq.equipmentId, value), isReturnMode: _isReturnMode, quantity: assignedEq.quantity, returnedQuantity: _returnedQuantities[assignedEq.equipmentId], onReturnedQuantityChanged: _isReturnMode ? (value) { setState(() { _returnedQuantities[assignedEq.equipmentId] = value; }); } : null, ); }, ); } Widget _buildValidateButton() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.3), spreadRadius: 1, blurRadius: 5, offset: const Offset(0, -2), ), ], ), child: ElevatedButton( onPressed: _isSaving ? null : _validatePreparation, style: ElevatedButton.styleFrom( backgroundColor: AppColors.rouge, minimumSize: const Size(double.infinity, 50), ), child: _isSaving ? const CircularProgressIndicator(color: Colors.white) : Text( _isReturnMode ? 'Finaliser le retour' : 'Finaliser la préparation', style: const TextStyle(color: Colors.white, fontSize: 16), ), ), ); } }