TKK_E32230859/lib/app/modules/home/controllers/home_controller.dart

219 lines
6.3 KiB
Dart

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 = <InfusMonitoring>[].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<PatientModel> patients,
List<RealtimeMonitoringModel> realtimeDevices,
) async {
final List<InfusMonitoring> 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<String> _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<void> 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';
}
}
}