import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'dart:async'; import '../../../services/firestore_service.dart'; import '../../../services/realtime_database_service.dart'; import '../../../models/patient_model.dart'; import '../../../models/room_model.dart'; import '../../../models/realtime_monitoring_model.dart'; import '../../../widgets/app_snackbar.dart'; class InfusMonitoring { final String id; final String patientName; final String deviceId; final String room; final String roomId; final String dropsPerMinute; final DateTime lastUpdate; final String deviceStatus; InfusMonitoring({ required this.id, required this.patientName, required this.deviceId, required this.room, required this.roomId, required this.dropsPerMinute, required this.lastUpdate, required this.deviceStatus, }); } class HomeController extends GetxController { final searchController = TextEditingController(); final FirestoreService _firestoreService = FirestoreService(); final RealtimeDatabaseService _realtimeService = RealtimeDatabaseService(); final currentCarouselIndex = 0.obs; final bannerImages = [ 'assets/images/banner-slider1.png', 'assets/images/banner-slider2.png', ]; final monitoringList = [].obs; final isLoading = true.obs; StreamSubscription? _patientsSubscription; StreamSubscription? _realtimeSubscription; @override void onInit() { super.onInit(); _initializeMonitoring(); } @override void onClose() { searchController.dispose(); _patientsSubscription?.cancel(); _realtimeSubscription?.cancel(); super.onClose(); } void _initializeMonitoring() { isLoading.value = true; _patientsSubscription = _firestoreService.getPatientsStream().listen( (patients) async { _realtimeSubscription = _realtimeService.getAllDevicesStream().listen(( realtimeDevices, ) { _combineMonitoringData(patients, realtimeDevices); }); }, onError: (error) { isLoading.value = false; AppSnackbar.error('Gagal memuat data'); }, ); } void _combineMonitoringData( List patients, List realtimeDevices, ) async { final List combinedData = []; for (var patient in patients) { final realtimeDevice = realtimeDevices.firstWhereOrNull( (device) => device.deviceId == patient.deviceId, ); final roomName = await _getRoomName(patient.roomId); final dropRate = realtimeDevice?.dropRate ?? 0.0; final lastUpdate = realtimeDevice?.lastUpdate ?? DateTime.now(); final deviceStatus = realtimeDevice?.deviceStatus ?? 'disconnected'; combinedData.add( InfusMonitoring( id: patient.id, patientName: patient.namePatient, deviceId: patient.deviceId, room: roomName, roomId: patient.roomId, dropsPerMinute: '${dropRate.toStringAsFixed(0)} tpm', lastUpdate: lastUpdate, deviceStatus: deviceStatus, ), ); } monitoringList.value = combinedData; isLoading.value = false; } Future _getRoomName(String roomId) async { try { final rooms = await _firestoreService.getRoomsStream().first; final room = rooms.firstWhereOrNull( (r) => r.id == roomId || r.roomName.toLowerCase() == roomId.toLowerCase(), ); return room?.roomName ?? roomId; } catch (e) { return roomId; } } Future controlInfusServo( String deviceId, String roomId, bool open, ) async { try { final dbRoomId = roomId.toLowerCase().replaceAll(' ', '_'); await _realtimeService.controlServo(dbRoomId, deviceId, open); AppSnackbar.success(open ? 'Infus dibuka' : 'Infus ditutup'); } catch (e) { AppSnackbar.error('Gagal mengontrol infus'); } } void updateCarouselIndex(int index) { currentCarouselIndex.value = index; } void showLogoutDialog(BuildContext context) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15), ), title: const Text( 'Konfirmasi Logout', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), ), content: const Text( 'Yakin ingin keluar?', style: TextStyle(fontSize: 16), ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), style: TextButton.styleFrom( foregroundColor: Colors.grey[600], padding: const EdgeInsets.symmetric( vertical: 12, horizontal: 20, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: const Text('Batal'), ), ElevatedButton( onPressed: () async { Navigator.of(context).pop(); await FirebaseAuth.instance.signOut(); Get.offAllNamed('/login'); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.red, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric( vertical: 12, horizontal: 20, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: const Text( 'Logout', style: TextStyle(fontWeight: FontWeight.bold), ), ), ], ); }, ); } String getLastUpdateText(DateTime lastUpdate) { final difference = DateTime.now().difference(lastUpdate); if (difference.inMinutes < 60) { return '${difference.inMinutes}m ago'; } else if (difference.inHours < 24) { return '${difference.inHours}h ago'; } else { return '${difference.inDays}d ago'; } } }