fix: Amélioration de l'expérience utilisateur lors de la génération de QR codes
Cette mise à jour améliore la génération de QR codes pour les équipements et les containers en ajoutant un retour visuel à l'utilisateur et une gestion des erreurs plus robuste. **Changements :** - **Ajout d'un indicateur de chargement :** Un `CircularProgressIndicator` est désormais affiché pendant que les données des équipements ou des containers sélectionnés sont récupérées, informant l'utilisateur qu'une opération est en cours. - **Gestion des erreurs :** Un bloc `try...catch` a été ajouté autour de la logique de génération dans les pages de gestion des équipements (`EquipmentManagementPage`) et des containers (`ContainerManagementPage`). - **Affichage des erreurs :** En cas d'échec, le chargement est stoppé et une `SnackBar` rouge apparaît pour notifier l'utilisateur de l'erreur, améliorant ainsi la robustesse de la fonctionnalité.
This commit is contained in:
@@ -473,49 +473,81 @@ class _ContainerManagementPageState extends State<ContainerManagementPage>
|
|||||||
Future<void> _generateQRCodesForSelected() async {
|
Future<void> _generateQRCodesForSelected() async {
|
||||||
if (!hasSelection) return;
|
if (!hasSelection) return;
|
||||||
|
|
||||||
// Récupérer les containers sélectionnés
|
// Afficher un indicateur de chargement
|
||||||
final containerProvider = context.read<ContainerProvider>();
|
showDialog(
|
||||||
final List<ContainerModel> selectedContainers = [];
|
context: context,
|
||||||
final Map<String, List<EquipmentModel>> containerEquipmentMap = {};
|
barrierDismissible: false,
|
||||||
|
builder: (context) => const Center(
|
||||||
|
child: CircularProgressIndicator(color: AppColors.rouge),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
for (final id in selectedIds) {
|
try {
|
||||||
final container = await containerProvider.getContainerById(id);
|
// Récupérer les containers sélectionnés
|
||||||
if (container != null) {
|
final containerProvider = context.read<ContainerProvider>();
|
||||||
selectedContainers.add(container);
|
final List<ContainerModel> selectedContainers = [];
|
||||||
// Charger les équipements pour ce container
|
final Map<String, List<EquipmentModel>> containerEquipmentMap = {};
|
||||||
final equipment = await containerProvider.getContainerEquipment(id);
|
|
||||||
containerEquipmentMap[id] = equipment;
|
for (final id in selectedIds) {
|
||||||
|
final container = await containerProvider.getContainerById(id);
|
||||||
|
if (container != null) {
|
||||||
|
selectedContainers.add(container);
|
||||||
|
// Charger les équipements pour ce container
|
||||||
|
final equipment = await containerProvider.getContainerEquipment(id);
|
||||||
|
containerEquipmentMap[id] = equipment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedContainers.isEmpty) {
|
// Fermer l'indicateur de chargement
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
Navigator.of(context).pop();
|
||||||
const SnackBar(content: Text('Aucun container trouvé')),
|
}
|
||||||
|
|
||||||
|
if (selectedContainers.isEmpty) {
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(content: Text('Aucun container trouvé')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Afficher le dialogue de sélection de format avec le widget générique
|
||||||
|
if (mounted) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => QRCodeFormatSelectorDialog<ContainerModel>(
|
||||||
|
itemList: selectedContainers,
|
||||||
|
getId: (c) => c.id,
|
||||||
|
getTitle: (c) => c.name,
|
||||||
|
getDetails: (ContainerModel c) {
|
||||||
|
final equipment = containerEquipmentMap[c.id] ?? <EquipmentModel>[];
|
||||||
|
return [
|
||||||
|
'Contenu (${equipment.length}):',
|
||||||
|
...equipment.take(5).map((eq) => '- ${eq.id}'),
|
||||||
|
if (equipment.length > 5) '... +${equipment.length - 5}',
|
||||||
|
];
|
||||||
|
},
|
||||||
|
dialogTitle: 'Générer ${selectedContainers.length} QR Code(s)',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
} catch (e) {
|
||||||
}
|
// Fermer l'indicateur si une erreur survient
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
|
||||||
// Afficher le dialogue de sélection de format avec le widget générique
|
DebugLog.error('[ContainerManagementPage] Error generating QR codes', e);
|
||||||
if (mounted) {
|
|
||||||
showDialog(
|
if (mounted) {
|
||||||
context: context,
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
builder: (context) => QRCodeFormatSelectorDialog<ContainerModel>(
|
SnackBar(
|
||||||
itemList: selectedContainers,
|
content: Text('Erreur lors de la génération : ${e.toString()}'),
|
||||||
getId: (c) => c.id,
|
backgroundColor: Colors.red,
|
||||||
getTitle: (c) => c.name,
|
),
|
||||||
getDetails: (ContainerModel c) {
|
);
|
||||||
final equipment = containerEquipmentMap[c.id] ?? <EquipmentModel>[];
|
}
|
||||||
return [
|
|
||||||
'Contenu (${equipment.length}):',
|
|
||||||
...equipment.take(5).map((eq) => '- ${eq.id}'),
|
|
||||||
if (equipment.length > 5) '... +${equipment.length - 5}',
|
|
||||||
];
|
|
||||||
},
|
|
||||||
dialogTitle: 'Générer ${selectedContainers.length} QR Code(s)',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -791,39 +791,75 @@ class _EquipmentManagementPageState extends State<EquipmentManagementPage>
|
|||||||
void _generateQRCodesForSelected() async {
|
void _generateQRCodesForSelected() async {
|
||||||
if (!hasSelection) return;
|
if (!hasSelection) return;
|
||||||
|
|
||||||
// Récupérer les équipements sélectionnés
|
// Afficher un indicateur de chargement
|
||||||
final provider = context.read<EquipmentProvider>();
|
showDialog(
|
||||||
final List<EquipmentModel> selectedEquipment = [];
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) => const Center(
|
||||||
|
child: CircularProgressIndicator(color: AppColors.rouge),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
// On doit récupérer les équipements depuis le stream
|
try {
|
||||||
await for (final equipmentList in provider.equipmentStream.take(1)) {
|
// Récupérer les équipements sélectionnés
|
||||||
for (final equipment in equipmentList) {
|
final provider = context.read<EquipmentProvider>();
|
||||||
if (isItemSelected(equipment.id)) {
|
final List<EquipmentModel> selectedEquipment = [];
|
||||||
selectedEquipment.add(equipment);
|
|
||||||
|
// On doit récupérer les équipements depuis le stream
|
||||||
|
await for (final equipmentList in provider.equipmentStream.take(1)) {
|
||||||
|
for (final equipment in equipmentList) {
|
||||||
|
if (isItemSelected(equipment.id)) {
|
||||||
|
selectedEquipment.add(equipment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fermer l'indicateur de chargement
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedEquipment.isEmpty) return;
|
||||||
|
|
||||||
|
if (selectedEquipment.length == 1) {
|
||||||
|
// Un seul équipement : afficher le dialogue simple
|
||||||
|
if (mounted) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => QRCodeDialog.forEquipment(selectedEquipment.first),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Plusieurs équipements : afficher le sélecteur de format
|
||||||
|
if (mounted) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => QRCodeFormatSelectorDialog<EquipmentModel>(
|
||||||
|
itemList: selectedEquipment,
|
||||||
|
getId: (eq) => eq.id,
|
||||||
|
getTitle: (eq) => '${eq.brand ?? ''} ${eq.model ?? ''}'.trim(),
|
||||||
|
dialogTitle: 'Générer ${selectedEquipment.length} QR Code(s)',
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
} catch (e) {
|
||||||
}
|
// Fermer l'indicateur si une erreur survient
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedEquipment.isEmpty) return;
|
DebugLog.error('[EquipmentManagementPage] Error generating QR codes', e);
|
||||||
|
|
||||||
if (selectedEquipment.length == 1) {
|
if (mounted) {
|
||||||
// Un seul équipement : afficher le dialogue simple
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
showDialog(
|
SnackBar(
|
||||||
context: context,
|
content: Text('Erreur lors de la génération : ${e.toString()}'),
|
||||||
builder: (context) => QRCodeDialog.forEquipment(selectedEquipment.first),
|
backgroundColor: Colors.red,
|
||||||
);
|
),
|
||||||
} else {
|
);
|
||||||
// Plusieurs équipements : afficher le sélecteur de format
|
}
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => QRCodeFormatSelectorDialog<EquipmentModel>(
|
|
||||||
itemList: selectedEquipment,
|
|
||||||
getId: (eq) => eq.id,
|
|
||||||
getTitle: (eq) => '${eq.brand ?? ''} ${eq.model ?? ''}'.trim(),
|
|
||||||
dialogTitle: 'Générer ${selectedEquipment.length} QR Code(s)',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user