import 'package:flutter/material.dart'; import 'package:em2rp/models/alert_model.dart'; // import 'package:timeago/timeago.dart' as timeago; // TODO: Ajouter dépendance dans pubspec.yaml /// Widget pour afficher une alerte individuelle class AlertItem extends StatelessWidget { final AlertModel alert; final VoidCallback? onTap; final VoidCallback? onMarkAsRead; final VoidCallback? onDelete; const AlertItem({ super.key, required this.alert, this.onTap, this.onMarkAsRead, this.onDelete, }); @override Widget build(BuildContext context) { return Dismissible( key: Key(alert.id), background: _buildSwipeBackground( Colors.blue, Icons.check, Alignment.centerLeft, ), secondaryBackground: _buildSwipeBackground( Colors.red, Icons.delete, Alignment.centerRight, ), confirmDismiss: (direction) async { if (direction == DismissDirection.startToEnd) { // Swipe vers la droite = marquer comme lu onMarkAsRead?.call(); return false; // Ne pas supprimer le widget } else { // Swipe vers la gauche = supprimer return await _confirmDelete(context); } }, child: Card( margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), color: alert.isRead ? Colors.white : Colors.blue.shade50, elevation: alert.isRead ? 1 : 2, child: ListTile( leading: _buildIcon(), title: Text( alert.message, style: TextStyle( fontWeight: alert.isRead ? FontWeight.normal : FontWeight.bold, fontSize: 14, ), ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 4), Text( _formatDate(alert.createdAt), style: TextStyle( fontSize: 12, color: Colors.grey.shade600, ), ), if (alert.isResolved) ...[ const SizedBox(height: 4), Row( children: [ Icon(Icons.check_circle, size: 14, color: Colors.green), const SizedBox(width: 4), Text( 'Résolu', style: TextStyle( fontSize: 12, color: Colors.green, fontWeight: FontWeight.w600, ), ), ], ), ], ], ), trailing: !alert.isRead ? Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: _getSeverityColor(alert.severity), borderRadius: BorderRadius.circular(12), ), child: Text( 'Nouveau', style: TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold, ), ), ) : null, onTap: onTap, ), ), ); } Widget _buildSwipeBackground(Color color, IconData icon, Alignment alignment) { return Container( color: color, alignment: alignment, padding: const EdgeInsets.symmetric(horizontal: 20), child: Icon(icon, color: Colors.white, size: 28), ); } Widget _buildIcon() { IconData iconData; Color iconColor; switch (alert.type) { case AlertType.eventCreated: case AlertType.eventModified: case AlertType.eventAssigned: iconData = Icons.event; iconColor = Colors.blue; break; case AlertType.workforceAdded: iconData = Icons.group_add; iconColor = Colors.green; break; case AlertType.eventCancelled: iconData = Icons.event_busy; iconColor = Colors.red; break; case AlertType.maintenanceDue: case AlertType.maintenanceReminder: iconData = Icons.build; iconColor = Colors.orange; break; case AlertType.lost: iconData = Icons.error; iconColor = Colors.red; break; case AlertType.equipmentMissing: iconData = Icons.warning; iconColor = Colors.orange; break; case AlertType.lowStock: iconData = Icons.inventory_2; iconColor = Colors.orange; break; case AlertType.conflict: iconData = Icons.error_outline; iconColor = Colors.red; break; case AlertType.quantityMismatch: iconData = Icons.compare_arrows; iconColor = Colors.orange; break; case AlertType.damaged: iconData = Icons.broken_image; iconColor = Colors.red; break; } return Container( width: 40, height: 40, decoration: BoxDecoration( color: iconColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), child: Icon(iconData, color: iconColor, size: 24), ); } Color _getSeverityColor(AlertSeverity severity) { switch (severity) { case AlertSeverity.info: return Colors.blue; case AlertSeverity.warning: return Colors.orange; case AlertSeverity.critical: return Colors.red; } } String _formatDate(DateTime date) { // TODO: Utiliser timeago une fois la dépendance ajoutée final now = DateTime.now(); final difference = now.difference(date); if (difference.inSeconds < 60) { return 'À l\'instant'; } else if (difference.inMinutes < 60) { return 'Il y a ${difference.inMinutes} min'; } else if (difference.inHours < 24) { return 'Il y a ${difference.inHours}h'; } else if (difference.inDays < 7) { return 'Il y a ${difference.inDays}j'; } else { return '${date.day}/${date.month}/${date.year}'; } } Future _confirmDelete(BuildContext context) async { return await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Supprimer l\'alerte ?'), content: const Text('Cette action est irréversible.'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('Annuler'), ), TextButton( onPressed: () { Navigator.of(context).pop(true); onDelete?.call(); }, style: TextButton.styleFrom(foregroundColor: Colors.red), child: const Text('Supprimer'), ), ], ), ) ?? false; } }