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:
165
em2rp/lib/providers/container_provider.dart
Normal file
165
em2rp/lib/providers/container_provider.dart
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user