import 'package:flutter/material.dart'; import '../modules/home/controllers/home_controller.dart'; class MonitoringCard extends StatelessWidget { final InfusMonitoring monitoring; final VoidCallback? onTap; const MonitoringCard({ super.key, required this.monitoring, this.onTap, }); @override Widget build(BuildContext context) { final isConnected = monitoring.deviceStatus == 'connected'; return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(16), child: Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.grey[200]!), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.08), blurRadius: 12, offset: const Offset(0, 2), ), ], ), child: Row( children: [ _buildIcon(isConnected), const SizedBox(width: 16), Expanded(child: _buildContent(isConnected)), ], ), ), ); } Widget _buildIcon(bool isConnected) { return Stack( children: [ Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: const Color(0xFFE3F2FD), borderRadius: BorderRadius.circular(14), ), child: const Icon( Icons.water_drop_outlined, size: 32, color: Color(0xFF2196F3), ), ), Positioned( right: 0, top: 0, child: Container( width: 12, height: 12, decoration: BoxDecoration( color: isConnected ? const Color(0xFF4CAF50) : Colors.red, shape: BoxShape.circle, border: Border.all(color: Colors.white, width: 2), ), ), ), ], ); } Widget _buildContent(bool isConnected) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildDropRate(), const SizedBox(height: 6), _buildLastUpdate(), const SizedBox(height: 12), _buildPatientInfo(), const SizedBox(height: 8), _buildBadges(isConnected), ], ); } Widget _buildDropRate() { return Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( monitoring.dropsPerMinute.replaceAll(' tpm', ''), style: const TextStyle( fontSize: 22, fontWeight: FontWeight.bold, color: Color(0xFF2196F3), height: 1, ), ), const SizedBox(width: 6), const Padding( padding: EdgeInsets.only(bottom: 2), child: Text( 'tetes per menit', style: TextStyle( fontSize: 12, color: Colors.black54, fontWeight: FontWeight.w500, ), ), ), ], ); } Widget _buildLastUpdate() { return Text( 'Last update: ${_getLastUpdateText(monitoring.lastUpdate)}', style: TextStyle(fontSize: 11, color: Colors.grey[600]), ); } Widget _buildPatientInfo() { return RichText( text: TextSpan( style: TextStyle(fontSize: 12, color: Colors.grey[700]), children: [ const TextSpan( text: 'Nama Pasien: ', style: TextStyle(fontWeight: FontWeight.w500), ), TextSpan( text: monitoring.patientName, style: const TextStyle( fontWeight: FontWeight.w600, color: Colors.black87, ), ), ], ), ); } Widget _buildBadges(bool isConnected) { return Wrap( spacing: 8, runSpacing: 6, children: [ _buildBadge( monitoring.deviceId, const Color(0xFFE3F2FD), const Color(0xFF2196F3), ), _buildBadge( monitoring.room, Colors.grey[100]!, Colors.grey[700]!, ), _buildBadge( isConnected ? 'Online' : 'Offline', isConnected ? const Color(0xFFE8F5E9) : Colors.red[50]!, isConnected ? const Color(0xFF2E7D32) : Colors.red[700]!, ), ], ); } Widget _buildBadge(String text, Color bgColor, 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, fontWeight: FontWeight.w600, color: textColor, ), ), ); } String _getLastUpdateText(DateTime lastUpdate) { final diff = DateTime.now().difference(lastUpdate); if (diff.inMinutes < 60) return '${diff.inMinutes}m ago'; if (diff.inHours < 24) return '${diff.inHours}h ago'; return '${diff.inDays}d ago'; } }