feat: Gestion complète des containers et refactorisation du matériel
Ajout de la gestion des containers (création, édition, suppression, affichage des détails).
Introduction d'un système de génération de QR codes unifié et d'un mode de sélection multiple.
**Features:**
- **Gestion des Containers :**
    - Nouvelle page de gestion des containers (`container_management_page.dart`) avec recherche et filtres.
    - Formulaire de création/édition de containers (`container_form_page.dart`) avec génération d'ID automatique.
    - Page de détails d'un container (`container_detail_page.dart`) affichant son contenu et ses caractéristiques.
    - Ajout des routes et du provider (`ContainerProvider`) nécessaires.
- **Modèle de Données :**
    - Ajout du `ContainerModel` pour représenter les boîtes, flight cases, etc.
    - Le modèle `EquipmentModel` a été enrichi avec des caractéristiques physiques (poids, dimensions).
- **QR Codes :**
    - Nouveau service unifié (`UnifiedPDFGeneratorService`) pour générer des PDFs de QR codes pour n'importe quelle entité.
    - Services `PDFGeneratorService` et `ContainerPDFGeneratorService` transformés en wrappers pour maintenir la compatibilité.
    - Amélioration de la performance de la génération de QR codes en masse.
- **Interface Utilisateur (UI/UX) :**
    - Nouvelle page de détails pour le matériel (`equipment_detail_page.dart`).
    - Ajout d'un `SelectionModeMixin` pour gérer la sélection multiple dans les pages de gestion.
    - Dialogues réutilisables pour l'affichage de QR codes (`QRCodeDialog`) et la sélection de format d'impression (`QRCodeFormatSelectorDialog`).
    - Ajout d'un bouton "Gérer les boîtes" sur la page de gestion du matériel.
**Refactorisation :**
- L' `IdGenerator` a été déplacé dans le répertoire `utils` et étendu pour gérer les containers.
- Mise à jour de nombreuses dépendances `pubspec.yaml` vers des versions plus récentes.
- Séparation de la logique d'affichage des containers et du matériel dans des widgets dédiés (`ContainerHeaderCard`, `EquipmentParentContainers`, etc.).
			
			
This commit is contained in:
		| @@ -0,0 +1,177 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:em2rp/utils/colors.dart'; | ||||
| import 'package:em2rp/models/container_model.dart'; | ||||
| import 'package:em2rp/providers/container_provider.dart'; | ||||
|  | ||||
| /// Widget pour afficher les containers parents d'un équipement | ||||
| class EquipmentParentContainers extends StatefulWidget { | ||||
|   final List<String> parentBoxIds; | ||||
|  | ||||
|   const EquipmentParentContainers({ | ||||
|     super.key, | ||||
|     required this.parentBoxIds, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   State<EquipmentParentContainers> createState() => _EquipmentParentContainersState(); | ||||
| } | ||||
|  | ||||
| class _EquipmentParentContainersState extends State<EquipmentParentContainers> { | ||||
|   List<ContainerModel> _containers = []; | ||||
|   bool _isLoading = true; | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     _loadContainers(); | ||||
|   } | ||||
|  | ||||
|   Future<void> _loadContainers() async { | ||||
|     if (widget.parentBoxIds.isEmpty) { | ||||
|       setState(() { | ||||
|         _isLoading = false; | ||||
|       }); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     setState(() { | ||||
|       _isLoading = true; | ||||
|     }); | ||||
|  | ||||
|     try { | ||||
|       final containerProvider = context.read<ContainerProvider>(); | ||||
|       final List<ContainerModel> containers = []; | ||||
|  | ||||
|       for (final boxId in widget.parentBoxIds) { | ||||
|         final container = await containerProvider.getContainerById(boxId); | ||||
|         if (container != null) { | ||||
|           containers.add(container); | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       setState(() { | ||||
|         _containers = containers; | ||||
|         _isLoading = false; | ||||
|       }); | ||||
|     } catch (e) { | ||||
|       setState(() { | ||||
|         _isLoading = false; | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     if (widget.parentBoxIds.isEmpty) { | ||||
|       return const SizedBox.shrink(); | ||||
|     } | ||||
|  | ||||
|     return Card( | ||||
|       elevation: 2, | ||||
|       child: Padding( | ||||
|         padding: const EdgeInsets.all(20), | ||||
|         child: Column( | ||||
|           crossAxisAlignment: CrossAxisAlignment.start, | ||||
|           children: [ | ||||
|             Row( | ||||
|               children: [ | ||||
|                 const Icon(Icons.inventory_2, color: AppColors.rouge, size: 20), | ||||
|                 const SizedBox(width: 8), | ||||
|                 const Text( | ||||
|                   'Containers', | ||||
|                   style: TextStyle( | ||||
|                     fontSize: 18, | ||||
|                     fontWeight: FontWeight.bold, | ||||
|                   ), | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|             const Divider(height: 24), | ||||
|             if (_isLoading) | ||||
|               const Center( | ||||
|                 child: Padding( | ||||
|                   padding: EdgeInsets.all(16.0), | ||||
|                   child: CircularProgressIndicator(), | ||||
|                 ), | ||||
|               ) | ||||
|             else if (_containers.isEmpty) | ||||
|               const Center( | ||||
|                 child: Padding( | ||||
|                   padding: EdgeInsets.all(16.0), | ||||
|                   child: Text( | ||||
|                     'Cet équipement n\'est dans aucun container', | ||||
|                     style: TextStyle(color: Colors.grey), | ||||
|                   ), | ||||
|                 ), | ||||
|               ) | ||||
|             else | ||||
|               ListView.separated( | ||||
|                 shrinkWrap: true, | ||||
|                 physics: const NeverScrollableScrollPhysics(), | ||||
|                 itemCount: _containers.length, | ||||
|                 separatorBuilder: (context, index) => const Divider(height: 1), | ||||
|                 itemBuilder: (context, index) { | ||||
|                   final container = _containers[index]; | ||||
|                   return _buildContainerTile(container); | ||||
|                 }, | ||||
|               ), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildContainerTile(ContainerModel container) { | ||||
|     return ListTile( | ||||
|       contentPadding: const EdgeInsets.symmetric(vertical: 8), | ||||
|       leading: Icon( | ||||
|         _getTypeIcon(container.type), | ||||
|         color: AppColors.rouge, | ||||
|         size: 32, | ||||
|       ), | ||||
|       title: Text( | ||||
|         container.id, | ||||
|         style: const TextStyle(fontWeight: FontWeight.bold), | ||||
|       ), | ||||
|       subtitle: Column( | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|         children: [ | ||||
|           Text(container.name), | ||||
|           const SizedBox(height: 4), | ||||
|           Text( | ||||
|             containerTypeLabel(container.type), | ||||
|             style: TextStyle( | ||||
|               fontSize: 12, | ||||
|               color: Colors.grey.shade600, | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|       trailing: const Icon(Icons.chevron_right), | ||||
|       onTap: () { | ||||
|         Navigator.pushNamed( | ||||
|           context, | ||||
|           '/container_detail', | ||||
|           arguments: container, | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   IconData _getTypeIcon(ContainerType type) { | ||||
|     switch (type) { | ||||
|       case ContainerType.flightCase: | ||||
|         return Icons.work; | ||||
|       case ContainerType.pelicase: | ||||
|         return Icons.work_outline; | ||||
|       case ContainerType.bag: | ||||
|         return Icons.shopping_bag; | ||||
|       case ContainerType.openCrate: | ||||
|         return Icons.inventory_2; | ||||
|       case ContainerType.toolbox: | ||||
|         return Icons.handyman; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 ElPoyo
					ElPoyo