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.).
111 lines
3.1 KiB
Dart
111 lines
3.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:em2rp/utils/colors.dart';
|
|
import 'package:em2rp/models/equipment_model.dart';
|
|
|
|
/// Widget pour afficher un équipement dans la liste d'un container
|
|
class ContainerEquipmentTile extends StatelessWidget {
|
|
final EquipmentModel equipment;
|
|
final VoidCallback onView;
|
|
final VoidCallback onRemove;
|
|
|
|
const ContainerEquipmentTile({
|
|
super.key,
|
|
required this.equipment,
|
|
required this.onView,
|
|
required this.onRemove,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ListTile(
|
|
contentPadding: const EdgeInsets.symmetric(vertical: 8),
|
|
leading: CircleAvatar(
|
|
backgroundColor: AppColors.rouge.withOpacity(0.1),
|
|
child: const Icon(Icons.inventory_2, color: AppColors.rouge),
|
|
),
|
|
title: Text(
|
|
equipment.id,
|
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
|
),
|
|
subtitle: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
if (equipment.brand != null || equipment.model != null)
|
|
Text('${equipment.brand ?? ''} ${equipment.model ?? ''}'),
|
|
const SizedBox(height: 4),
|
|
Row(
|
|
children: [
|
|
_buildSmallBadge(
|
|
_getCategoryLabel(equipment.category),
|
|
Colors.blue,
|
|
),
|
|
const SizedBox(width: 8),
|
|
if (equipment.weight != null)
|
|
_buildSmallBadge(
|
|
'${equipment.weight} kg',
|
|
Colors.grey,
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
trailing: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
IconButton(
|
|
icon: const Icon(Icons.visibility, size: 20),
|
|
tooltip: 'Voir détails',
|
|
onPressed: onView,
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.remove_circle, color: Colors.red, size: 20),
|
|
tooltip: 'Retirer',
|
|
onPressed: onRemove,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSmallBadge(String label, Color color) {
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: color.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: color.withOpacity(0.3)),
|
|
),
|
|
child: Text(
|
|
label,
|
|
style: TextStyle(
|
|
fontSize: 11,
|
|
color: color,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
String _getCategoryLabel(EquipmentCategory category) {
|
|
switch (category) {
|
|
case EquipmentCategory.lighting:
|
|
return 'Lumière';
|
|
case EquipmentCategory.sound:
|
|
return 'Son';
|
|
case EquipmentCategory.video:
|
|
return 'Vidéo';
|
|
case EquipmentCategory.effect:
|
|
return 'Effets';
|
|
case EquipmentCategory.structure:
|
|
return 'Structure';
|
|
case EquipmentCategory.consumable:
|
|
return 'Consommable';
|
|
case EquipmentCategory.cable:
|
|
return 'Câble';
|
|
case EquipmentCategory.other:
|
|
return 'Autre';
|
|
}
|
|
}
|
|
}
|
|
|