Files
EM2_ERP/em2rp/lib/views/widgets/common/qr_code_dialog.dart

237 lines
6.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:em2rp/utils/colors.dart';
import 'package:em2rp/services/qr_code_service.dart';
import 'package:printing/printing.dart';
/// Widget réutilisable pour afficher un QR code avec option de téléchargement
/// Utilisable pour équipements, containers, et autres entités
class QRCodeDialog<T> extends StatelessWidget {
final T item;
final String Function(T) getId;
final String Function(T) getTitle;
final List<Widget> Function(T)? buildSubtitle;
const QRCodeDialog({
super.key,
required this.item,
required this.getId,
required this.getTitle,
this.buildSubtitle,
});
@override
Widget build(BuildContext context) {
final id = getId(item);
final title = getTitle(item);
return Dialog(
child: Container(
padding: const EdgeInsets.all(24),
constraints: const BoxConstraints(maxWidth: 400),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// En-tête
Row(
children: [
const Icon(Icons.qr_code, color: AppColors.rouge, size: 32),
const SizedBox(width: 12),
Expanded(
child: Text(
'QR Code - $id',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
IconButton(
icon: const Icon(Icons.close),
onPressed: () => Navigator.pop(context),
),
],
),
const SizedBox(height: 24),
// QR Code
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey[300]!),
),
child: QrImageView(
data: id,
version: QrVersions.auto,
size: 250,
backgroundColor: Colors.white,
),
),
const SizedBox(height: 16),
// Informations
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
id,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
const SizedBox(height: 4),
Text(
title,
style: TextStyle(color: Colors.grey[700]),
),
if (buildSubtitle != null) ...[
const SizedBox(height: 4),
...buildSubtitle!(item),
],
],
),
),
const SizedBox(height: 24),
// Bouton télécharger
ElevatedButton.icon(
onPressed: () => _downloadQRCode(context, id),
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.rouge,
minimumSize: const Size(double.infinity, 48),
),
icon: const Icon(Icons.download, color: Colors.white),
label: const Text(
'Télécharger l\'image',
style: TextStyle(color: Colors.white),
),
),
],
),
),
);
}
Future<void> _downloadQRCode(BuildContext context, String id) async {
// Afficher le dialog de chargement
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => Dialog(
child: Container(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(AppColors.rouge),
),
const SizedBox(height: 16),
const Text(
'Génération du QR Code...',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
],
),
),
),
);
try {
// Exécuter la génération dans un isolate séparé
final qrImage = await compute(
_generateQRCodeIsolate,
id,
);
// Fermer le dialog de chargement
if (context.mounted) {
Navigator.pop(context);
}
// Utiliser la bibliothèque printing pour sauvegarder l'image
await Printing.sharePdf(
bytes: qrImage,
filename: 'QRCode_$id.png',
);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Image QR Code téléchargée avec succès'),
backgroundColor: Colors.green,
),
);
}
} catch (e) {
// Fermer le dialog de chargement en cas d'erreur
if (context.mounted) {
Navigator.pop(context);
}
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Erreur lors du téléchargement: $e'),
backgroundColor: Colors.red,
),
);
}
}
}
/// Fonction statique pour exécuter la génération QR code dans un isolate
static Future<Uint8List> _generateQRCodeIsolate(String id) async {
return await QRCodeService.generateQRCode(
id,
size: 1024,
useCache: false,
);
}
/// Factory pour équipement
static QRCodeDialog forEquipment(dynamic equipment) {
return QRCodeDialog(
item: equipment,
getId: (eq) => eq.id,
getTitle: (eq) => '${eq.brand ?? ''} ${eq.model ?? ''}'.trim(),
);
}
/// Factory pour container
static QRCodeDialog forContainer(dynamic container) {
return QRCodeDialog(
item: container,
getId: (c) => c.id,
getTitle: (c) => c.name,
buildSubtitle: (c) {
return [
Text(
_getContainerTypeLabel(c.type),
style: TextStyle(
color: Colors.grey[600],
fontSize: 12,
),
),
];
},
);
}
static String _getContainerTypeLabel(dynamic type) {
// Simple fallback - à améliorer avec import du model
return type.toString().split('.').last;
}
}