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,144 @@
import 'package:flutter/material.dart';
/// Mixin réutilisable pour gérer le mode sélection multiple
/// Utilisable dans equipment_management_page, container_management_page, etc.
mixin SelectionModeMixin<T extends StatefulWidget> on State<T> {
// État du mode sélection
bool _isSelectionMode = false;
final Set<String> _selectedIds = {};
// Getters
bool get isSelectionMode => _isSelectionMode;
Set<String> get selectedIds => _selectedIds;
int get selectedCount => _selectedIds.length;
bool get hasSelection => _selectedIds.isNotEmpty;
/// Active/désactive le mode sélection
void toggleSelectionMode() {
setState(() {
_isSelectionMode = !_isSelectionMode;
if (!_isSelectionMode) {
_selectedIds.clear();
}
});
}
/// Active le mode sélection
void enableSelectionMode() {
if (!_isSelectionMode) {
setState(() {
_isSelectionMode = true;
});
}
}
/// Désactive le mode sélection et efface la sélection
void disableSelectionMode() {
if (_isSelectionMode) {
setState(() {
_isSelectionMode = false;
_selectedIds.clear();
});
}
}
/// Toggle la sélection d'un item
void toggleItemSelection(String id) {
setState(() {
if (_selectedIds.contains(id)) {
_selectedIds.remove(id);
} else {
_selectedIds.add(id);
}
});
}
/// Sélectionne un item
void selectItem(String id) {
setState(() {
_selectedIds.add(id);
});
}
/// Désélectionne un item
void deselectItem(String id) {
setState(() {
_selectedIds.remove(id);
});
}
/// Vérifie si un item est sélectionné
bool isItemSelected(String id) {
return _selectedIds.contains(id);
}
/// Sélectionne tous les items
void selectAll(List<String> ids) {
setState(() {
_selectedIds.addAll(ids);
});
}
/// Efface la sélection
void clearSelection() {
setState(() {
_selectedIds.clear();
});
}
/// Sélectionne/désélectionne tous les items
void toggleSelectAll(List<String> ids) {
setState(() {
if (_selectedIds.length == ids.length) {
// Tout est sélectionné, on désélectionne tout
_selectedIds.clear();
} else {
// Sélectionner tout
_selectedIds.addAll(ids);
}
});
}
/// Widget pour afficher le nombre d'éléments sélectionnés
Widget buildSelectionCounter({
required Color backgroundColor,
required Color textColor,
String? customText,
}) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(16),
),
child: Text(
customText ?? '$selectedCount sélectionné${selectedCount > 1 ? 's' : ''}',
style: TextStyle(
color: textColor,
fontWeight: FontWeight.bold,
),
),
);
}
/// AppBar pour le mode sélection
PreferredSizeWidget buildSelectionAppBar({
required String title,
required List<Widget> actions,
Color? backgroundColor,
}) {
return AppBar(
backgroundColor: backgroundColor,
leading: IconButton(
icon: const Icon(Icons.close, color: Colors.white),
onPressed: disableSelectionMode,
),
title: Text(
'$selectedCount $title sélectionné${selectedCount > 1 ? 's' : ''}',
style: const TextStyle(color: Colors.white),
),
actions: actions,
);
}
}