color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold, ), ), ), ], ), ); } Widget _buildEquipmentCard(EquipmentModel equipment, {Key? key}) { final isSelected = _selectedItems.containsKey(equipment.id); final isConsumable = equipment.category == EquipmentCategory.consumable || equipment.category == EquipmentCategory.cable; final availableQty = _availableQuantities[equipment.id]; final selectedItem = _selectedItems[equipment.id]; final hasConflict = _conflictingEquipmentIds.contains(equipment.id); // CORRECTION ICI ! final conflictDetails = _getConflictDetailsFor(equipment.id); // Bloquer la sélection si en conflit et non forcé final canSelect = !hasConflict || isSelected; return RepaintBoundary( key: key, child: Card( margin: const EdgeInsets.only(bottom: 12), elevation: isSelected ? 4 : 1, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: isSelected ? const BorderSide(color: AppColors.rouge, width: 2) : hasConflict ? BorderSide(color: Colors.orange.shade300, width: 1) : BorderSide.none, ), child: InkWell( onTap: canSelect ? () => _toggleSelection( equipment.id, equipment.id, SelectionType.equipment, maxQuantity: availableQty, ) : null, borderRadius: BorderRadius.circular(8), child: Container( decoration: hasConflict && !isSelected ? BoxDecoration( color: Colors.orange.shade50, borderRadius: BorderRadius.circular(8), ) : null, child: Padding( padding: const EdgeInsets.all(16), child: Column( children: [ Row( children: [ // Checkbox Checkbox( value: isSelected, onChanged: canSelect ? (value) => _toggleSelection( equipment.id, equipment.id, SelectionType.equipment, maxQuantity: availableQty, ) : null, activeColor: AppColors.rouge, ), const SizedBox(width: 12), // Icône equipment.category.getIcon(size: 32, color: equipment.category.color), const SizedBox(width: 16), // Infos Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( equipment.id, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), ), if (hasConflict) Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.orange.shade700, borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.warning, size: 14, color: Colors.white), const SizedBox(width: 4), Text( 'Déjà utilisé', style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold, ), ), ], ), ), ], ), if (equipment.brand != null || equipment.model != null) Text( '${equipment.brand ?? ''} ${equipment.model ?? ''}'.trim(), style: TextStyle( color: Colors.grey.shade700, fontSize: 14, ), ), // Affichage des boîtes parentes if (_getParentContainers(equipment.id).isNotEmpty) Padding( padding: const EdgeInsets.only(top: 4), child: Wrap( spacing: 4, runSpacing: 4, children: _getParentContainers(equipment.id).map((container) { return Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: Colors.blue.shade50, border: Border.all(color: Colors.blue.shade300), borderRadius: BorderRadius.circular(10), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.inventory, size: 12, color: Colors.blue.shade700), const SizedBox(width: 4), Text( container.name, style: TextStyle( fontSize: 10, color: Colors.blue.shade700, fontWeight: FontWeight.w500, ), ), ], ), ); }).toList(), ), ), if (isConsumable) Padding( padding: const EdgeInsets.only(top: 4), child: _buildQuantityInfo(equipment), ), ], ), ), // Sélecteur de quantité pour consommables (toujours affiché) if (isConsumable && availableQty != null) _buildQuantitySelector( equipment.id, selectedItem ?? SelectedItem( id: equipment.id, name: equipment.id, type: SelectionType.equipment, quantity: 0, // Quantité 0 si non sélectionné ), availableQty, isSelected: isSelected, // Passer l'état de sélection ), ], ), // Affichage des conflits if (hasConflict) Container( margin: const EdgeInsets.only(top: 12), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.orange.shade100, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.orange.shade300), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.info_outline, size: 16, color: Colors.orange.shade900), const SizedBox(width: 6), Text( 'Utilisé sur ${conflictDetails.length} événement(s) :', style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.orange.shade900, ), ), ], ), const SizedBox(height: 6), ...conflictDetails.take(2).map((detail) { final eventName = detail['eventName'] as String? ?? 'Événement inconnu'; final viaContainer = detail['viaContainer'] as String?; final viaContainerName = detail['viaContainerName'] as String?; return Padding( padding: const EdgeInsets.only(left: 22, top: 4), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '• $eventName', style: TextStyle( fontSize: 11, color: Colors.orange.shade800, ), ), if (viaContainer != null) Padding( padding: const EdgeInsets.only(left: 8), child: Text( 'via ${viaContainerName ?? viaContainer}', style: TextStyle( fontSize: 10, color: Colors.grey.shade600, fontStyle: FontStyle.italic, ), ), ), ], ), ); }), if (conflictDetails.length > 2) Padding( padding: const EdgeInsets.only(left: 22, top: 4), child: Text( '... et ${conflictDetails.length - 2} autre(s)', style: TextStyle( fontSize: 11, color: Colors.orange.shade800, fontStyle: FontStyle.italic, ), ), ), if (!isSelected) Padding( padding: const EdgeInsets.only(top: 8), child: TextButton.icon( onPressed: () => _toggleSelection( equipment.id, equipment.id, SelectionType.equipment, maxQuantity: availableQty, force: true, ), icon: const Icon(Icons.warning, size: 16), label: const Text('Forcer quand même', style: TextStyle(fontSize: 12)), style: TextButton.styleFrom( foregroundColor: Colors.orange.shade900, padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), ), ), ), ], ), ), ], ), ), ), ), ); } /// Widget pour le sélecteur de quantité /// Si isSelected = false, le premier clic sur + sélectionne l'item avec quantité 1 Widget _buildQuantitySelector( String equipmentId, SelectedItem selectedItem, int maxQuantity, { required bool isSelected, }) { final displayQuantity = isSelected ? selectedItem.quantity : 0;