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:
ElPoyo
2025-10-29 10:57:42 +01:00
parent ae3a1b7227
commit 3fab69cb00
31 changed files with 6540 additions and 656 deletions

View File

@@ -0,0 +1,165 @@
import 'package:flutter/foundation.dart';
import 'package:em2rp/models/container_model.dart';
import 'package:em2rp/models/equipment_model.dart';
import 'package:em2rp/services/container_service.dart';
class ContainerProvider with ChangeNotifier {
final ContainerService _containerService = ContainerService();
ContainerType? _selectedType;
EquipmentStatus? _selectedStatus;
String _searchQuery = '';
ContainerType? get selectedType => _selectedType;
EquipmentStatus? get selectedStatus => _selectedStatus;
String get searchQuery => _searchQuery;
/// Stream des containers avec filtres appliqués
Stream<List<ContainerModel>> get containersStream {
return _containerService.getContainers(
type: _selectedType,
status: _selectedStatus,
searchQuery: _searchQuery,
);
}
/// Définir le type sélectionné
void setSelectedType(ContainerType? type) {
_selectedType = type;
notifyListeners();
}
/// Définir le statut sélectionné
void setSelectedStatus(EquipmentStatus? status) {
_selectedStatus = status;
notifyListeners();
}
/// Définir la requête de recherche
void setSearchQuery(String query) {
_searchQuery = query;
notifyListeners();
}
/// Créer un nouveau container
Future<void> createContainer(ContainerModel container) async {
await _containerService.createContainer(container);
notifyListeners();
}
/// Mettre à jour un container
Future<void> updateContainer(String id, Map<String, dynamic> data) async {
await _containerService.updateContainer(id, data);
notifyListeners();
}
/// Supprimer un container
Future<void> deleteContainer(String id) async {
await _containerService.deleteContainer(id);
notifyListeners();
}
/// Récupérer un container par ID
Future<ContainerModel?> getContainerById(String id) async {
return await _containerService.getContainerById(id);
}
/// Ajouter un équipement à un container
Future<Map<String, dynamic>> addEquipmentToContainer({
required String containerId,
required String equipmentId,
String? userId,
}) async {
final result = await _containerService.addEquipmentToContainer(
containerId: containerId,
equipmentId: equipmentId,
userId: userId,
);
notifyListeners();
return result;
}
/// Retirer un équipement d'un container
Future<void> removeEquipmentFromContainer({
required String containerId,
required String equipmentId,
String? userId,
}) async {
await _containerService.removeEquipmentFromContainer(
containerId: containerId,
equipmentId: equipmentId,
userId: userId,
);
notifyListeners();
}
/// Vérifier la disponibilité d'un container
Future<Map<String, dynamic>> checkContainerAvailability({
required String containerId,
required DateTime startDate,
required DateTime endDate,
String? excludeEventId,
}) async {
return await _containerService.checkContainerAvailability(
containerId: containerId,
startDate: startDate,
endDate: endDate,
excludeEventId: excludeEventId,
);
}
/// Récupérer les équipements d'un container
Future<List<EquipmentModel>> getContainerEquipment(String containerId) async {
return await _containerService.getContainerEquipment(containerId);
}
/// Trouver tous les containers contenant un équipement
Future<List<ContainerModel>> findContainersWithEquipment(String equipmentId) async {
return await _containerService.findContainersWithEquipment(equipmentId);
}
/// Vérifier si un ID existe
Future<bool> checkContainerIdExists(String id) async {
return await _containerService.checkContainerIdExists(id);
}
/// Générer un ID unique pour un container
/// Format: BOX_{TYPE}_{NAME}_{NUMBER}
static String generateContainerId({
required ContainerType type,
required String name,
int? number,
}) {
// Obtenir le type en majuscules
final typeStr = containerTypeToString(type);
// Nettoyer le nom (enlever espaces, caractères spéciaux)
final cleanName = name
.replaceAll(' ', '_')
.replaceAll(RegExp(r'[^a-zA-Z0-9_-]'), '')
.toUpperCase();
if (number != null) {
return 'BOX_${typeStr}_${cleanName}_#$number';
}
return 'BOX_${typeStr}_$cleanName';
}
/// Assurer l'unicité d'un ID de container
static Future<String> ensureUniqueContainerId(
String baseId,
ContainerService service,
) async {
String uniqueId = baseId;
int counter = 1;
while (await service.checkContainerIdExists(uniqueId)) {
uniqueId = '${baseId}_$counter';
counter++;
}
return uniqueId;
}
}