import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../widgets/history_grafik_card.dart'; import '../controllers/device_detail_controller.dart'; class DeviceDetailView extends GetView { const DeviceDetailView({super.key}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[50], appBar: AppBar( backgroundColor: Colors.white, elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.black), onPressed: () => Get.back(), ), title: const Text( 'Detail Alat', style: TextStyle( color: Colors.black, fontSize: 18, fontWeight: FontWeight.w600, ), ), actions: [ IconButton( icon: const Icon(Icons.refresh, color: Colors.black), onPressed: controller.refreshData, ), ], ), body: Obx(() { if (controller.isLoading.value) { return const Center( child: CircularProgressIndicator(color: Color(0xFF2196F3)), ); } return RefreshIndicator( onRefresh: controller.refreshData, color: const Color(0xFF2196F3), child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildSection( title: 'Monitoring Infus', child: _buildMonitoringCard(), ), const SizedBox(height: 20), _buildSection( title: 'Kontrol Alat', child: _buildControlCard(), ), const SizedBox(height: 12), // Buzzer card — hanya tampil kalau buzzer aktif Obx(() { if (!controller.isBuzzerActive.value) { return const SizedBox.shrink(); } return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: _buildBuzzerCard(), ); }), const SizedBox(height: 20), _buildSection( title: 'History Data', onSeeAll: controller.navigateToHistory, child: Obx(() { if (controller.chartData.isEmpty) { return _buildEmptyChart(); } return HistoryGrafikCard( dataPoints: controller.chartData.value, ); }), ), const SizedBox(height: 20), ], ), ), ); }), ); } Widget _buildSection({ required String title, required Widget child, VoidCallback? onSeeAll, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(20, 16, 20, 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87, ), ), ], ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: child, ), ], ); } Widget _buildMonitoringCard() { return Obx( () => Container( 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: [ 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: controller.deviceStatus.value == 'connected' ? const Color(0xFF4CAF50) : Colors.red, shape: BoxShape.circle, border: Border.all(color: Colors.white, width: 2), ), ), ), ], ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( controller.dropsPerMinute.value, 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, ), ), ), ], ), const SizedBox(height: 6), Text( 'Last update: ${controller.getLastUpdateText()}', style: TextStyle(fontSize: 11, color: Colors.grey[600]), ), const SizedBox(height: 12), if (controller.patientName.value.isNotEmpty) RichText( text: TextSpan( style: TextStyle(fontSize: 12, color: Colors.grey[700]), children: [ const TextSpan( text: 'Nama Pasien: ', style: TextStyle(fontWeight: FontWeight.w500), ), TextSpan( text: controller.patientName.value, style: const TextStyle( fontWeight: FontWeight.w600, color: Colors.black87, ), ), ], ), ), const SizedBox(height: 8), Wrap( spacing: 8, runSpacing: 6, children: [ if (controller.deviceId != null) _buildBadge( controller.deviceId!, const Color(0xFFE3F2FD), const Color(0xFF2196F3), ), if (controller.roomName.value.isNotEmpty) _buildBadge( controller.roomName.value, Colors.grey[100]!, Colors.grey[700]!, ), _buildBadge( controller.deviceStatus.value == 'connected' ? 'Online' : 'Offline', controller.deviceStatus.value == 'connected' ? const Color(0xFFE8F5E9) : Colors.red[50]!, controller.deviceStatus.value == 'connected' ? const Color(0xFF2E7D32) : Colors.red[700]!, ), ], ), ], ), ), ], ), ), ); } Widget _buildControlCard() { return Obx( () => Container( 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: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: const Color(0xFFE3F2FD), borderRadius: BorderRadius.circular(12), ), child: const Icon( Icons.settings_input_component, size: 28, color: Color(0xFF2196F3), ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Kontrol Servo', style: TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: Colors.black87, ), ), const SizedBox(height: 4), Text( controller.isServoActive.value ? 'Infus sedang mengalir' : 'Infus ditutup', style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), ], ), ), Switch( value: controller.isServoActive.value, onChanged: controller.deviceStatus.value == 'connected' ? controller.toggleServo : null, activeColor: const Color(0xFF2196F3), activeTrackColor: const Color(0xFFBBDEFB), ), ], ), ), ); } /// Card buzzer — muncul saat buzzer_active == true Widget _buildBuzzerCard() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.red[50], borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.red[200]!), boxShadow: [ BoxShadow( color: Colors.red.withOpacity(0.08), blurRadius: 12, offset: const Offset(0, 2), ), ], ), child: Row( children: [ // Icon dengan animasi pulse Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.red[100], borderRadius: BorderRadius.circular(12), ), child: Icon( Icons.notifications_active_rounded, size: 28, color: Colors.red[700], ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Buzzer Aktif', style: TextStyle( fontSize: 15, fontWeight: FontWeight.w700, color: Colors.red[800], ), ), const SizedBox(height: 4), Text( 'Tetesan infus berhenti. Harap periksa pasien.', style: TextStyle( fontSize: 12, color: Colors.red[600], height: 1.4, ), ), ], ), ), const SizedBox(width: 12), // Tombol matikan buzzer ElevatedButton( onPressed: controller.turnOffBuzzer, style: ElevatedButton.styleFrom( backgroundColor: Colors.red[700], foregroundColor: Colors.white, padding: const EdgeInsets.symmetric( horizontal: 14, vertical: 10, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), elevation: 0, ), child: const Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.volume_off_rounded, size: 18), SizedBox(height: 3), Text( 'Matikan', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, ), ), ], ), ), ], ), ); } Widget _buildEmptyChart() { return Container( padding: const EdgeInsets.all(32), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey[200]!), ), child: Center( child: Column( children: [ Icon(Icons.show_chart, size: 48, color: Colors.grey[400]), const SizedBox(height: 12), Text( 'Belum ada data history', style: TextStyle(fontSize: 14, color: Colors.grey[600]), ), ], ), ), ); } 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, ), ), ); } }