// lib/app/widgets/notification_card.dart import 'package:flutter/material.dart'; import '../modules/notification/controllers/notification_controller.dart'; class NotificationCard extends StatelessWidget { final NotificationItem notification; final VoidCallback onDismissed; final VoidCallback? onTap; const NotificationCard({ super.key, required this.notification, required this.onDismissed, this.onTap, }); @override Widget build(BuildContext context) { final bool isRead = notification.isRead; final Color primaryColor = isRead ? Colors.grey : const Color(0xFF0091EA); final Color dangerColor = isRead ? Colors.grey : const Color(0xFFE57373); final Color successColor = isRead ? Colors.grey : const Color(0xFF4CAF50); return Dismissible( key: Key(notification.id), direction: DismissDirection.horizontal, onDismissed: (_) => onDismissed(), background: _buildDismissBackground(Alignment.centerLeft), secondaryBackground: _buildDismissBackground(Alignment.centerRight), child: InkWell( onTap: isRead ? null : onTap, child: Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: isRead ? Colors.grey[50] : Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all( color: isRead ? Colors.grey[300]! : primaryColor.withOpacity(0.3), width: isRead ? 1 : 2, ), boxShadow: isRead ? null : [ BoxShadow( color: primaryColor.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ /// ICON Container( width: 40, height: 40, decoration: BoxDecoration( color: isRead ? Colors.grey[200] : const Color(0xFFFFEBEE), borderRadius: BorderRadius.circular(10), ), child: Icon( Icons.warning_rounded, color: dangerColor, size: 24, ), ), const SizedBox(width: 12), /// CONTENT Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /// TITLE + TIME Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( notification.title, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: isRead ? Colors.grey[700] : Colors.black, ), ), ), const SizedBox(width: 8), Text( _formatTime(notification.time), style: TextStyle( fontSize: 11, color: Colors.grey[500], ), ), ], ), const SizedBox(height: 6), /// MESSAGE Text( notification.message, style: TextStyle( fontSize: 13, color: isRead ? Colors.grey[600] : Colors.grey[700], height: 1.4, ), ), const SizedBox(height: 10), /// ROOM + DEVICE Row( children: [ _buildBadge( text: notification.room, bgColor: isRead ? Colors.grey[200]! : const Color(0xFFE3F2FD), textColor: isRead ? Colors.grey : const Color(0xFF2196F3), ), const SizedBox(width: 8), _buildDeviceBadge( notification.deviceId, dotColor: successColor, isRead: isRead, ), ], ), const SizedBox(height: 6), /// PATIENT NAME Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6, ), decoration: BoxDecoration( color: isRead ? Colors.grey[200] : const Color(0xFFE8F5E9), borderRadius: BorderRadius.circular(8), ), child: Text( notification.patientName, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: isRead ? Colors.grey : const Color(0xFF2E7D32), ), ), ), ], ), ), ], ), ), ), ); } /// DISMISS BACKGROUND Widget _buildDismissBackground(Alignment alignment) { return Container( margin: const EdgeInsets.only(bottom: 12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), ), alignment: alignment, padding: const EdgeInsets.symmetric(horizontal: 20), ); } /// BADGE Widget _buildBadge({ required String text, required Color bgColor, required Color textColor, }) { return Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), decoration: BoxDecoration( color: bgColor, borderRadius: BorderRadius.circular(6), ), child: Text( text, style: TextStyle( fontSize: 11, color: textColor, fontWeight: FontWeight.w600, ), ), ); } /// DEVICE BADGE Widget _buildDeviceBadge( String deviceId, { required Color dotColor, required bool isRead, }) { return Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), decoration: BoxDecoration( color: Colors.grey[100], borderRadius: BorderRadius.circular(6), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 6, height: 6, decoration: BoxDecoration( color: dotColor, shape: BoxShape.circle, ), ), const SizedBox(width: 6), Text( deviceId, style: TextStyle( fontSize: 11, color: isRead ? Colors.grey : Colors.grey[700], fontWeight: FontWeight.w600, ), ), ], ), ); } /// TIME FORMAT String _formatTime(DateTime time) { final diff = DateTime.now().difference(time); if (diff.inMinutes < 60) { return '${diff.inMinutes} min ago'; } else if (diff.inHours < 24) { return '${diff.inHours} h ago'; } else { return '${diff.inDays} d ago'; } } }