TKK_E32230859/lib/app/services/firestore_service.dart

468 lines
13 KiB
Dart

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import '../models/patient_model.dart';
import '../models/device_model.dart';
import '../models/room_model.dart';
import '../models/notification_model.dart';
import '../models/schedule_model.dart';
import '../models/history_model.dart';
import '../models/user_model.dart';
class FirestoreService {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;
// ==================== USER MANAGEMENT ====================
Future<bool> userExists(String email) async {
try {
final snapshot = await _firestore
.collection('users')
.where('email', isEqualTo: email)
.limit(1)
.get();
return snapshot.docs.isNotEmpty;
} catch (e) {
return false;
}
}
Future<String?> createUser({
required String email,
required String password,
required String name,
required String role,
String? deviceId,
}) async {
final userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
final uid = userCredential.user!.uid;
await _firestore.collection('users').doc(uid).set({
'email': email,
'name': name,
'role': role,
if (deviceId != null) 'device_id': deviceId, // TAMBAH device_id
'created_at': FieldValue.serverTimestamp(),
});
await _auth.signOut();
return uid;
}
Future<void> updateUser({
required String uid,
required String name,
String? email,
String? deviceId,
}) async {
final updateData = {'name': name};
if (email != null) updateData['email'] = email;
if (deviceId != null)
updateData['device_id'] = deviceId; // Support update device_id
await _firestore.collection('users').doc(uid).update(updateData);
}
Future<void> deleteUser(String uid) async {
await _firestore.collection('users').doc(uid).delete();
}
Future<void> deleteUserFromAuth(String email, String password) async {
try {
// Sign in temporary dengan user yang akan dihapus
final userCredential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
// Hapus user dari Authentication
await userCredential.user?.delete();
// Sign out
await _auth.signOut();
} catch (e) {
print('Error deleting user from auth: $e');
// Jika gagal, ignore error (misalnya user sudah tidak ada)
}
}
Future<DocumentSnapshot?> getUserByEmail(String email) async {
try {
final snapshot = await _firestore
.collection('users')
.where('email', isEqualTo: email)
.limit(1)
.get();
return snapshot.docs.isNotEmpty ? snapshot.docs.first : null;
} catch (e) {
return null;
}
}
Future<UserModel?> getUserModelByEmail(String email) async {
try {
final snapshot = await _firestore
.collection('users')
.where('email', isEqualTo: email)
.limit(1)
.get();
return snapshot.docs.isNotEmpty
? UserModel.fromFirestore(snapshot.docs.first)
: null;
} catch (e) {
return null;
}
}
// ==================== DEVICE MANAGEMENT ====================
Future<bool> deviceExists(String deviceId) async {
try {
final doc = await _firestore.collection('devices').doc(deviceId).get();
return doc.exists;
} catch (e) {
return false;
}
}
Future<bool> patientExistsByDevice(String deviceId) async {
try {
final snapshot = await _firestore
.collection('patients')
.where('device_id', isEqualTo: deviceId)
.limit(1)
.get();
return snapshot.docs.isNotEmpty;
} catch (e) {
return false;
}
}
Stream<List<DeviceModel>> getDevicesStream() {
return _firestore
.collection('devices')
.snapshots()
.map(
(snapshot) => snapshot.docs
.map((doc) => DeviceModel.fromFirestore(doc))
.toList(),
);
}
Future<DeviceModel?> getDeviceById(String deviceId) async {
try {
final doc = await _firestore.collection('devices').doc(deviceId).get();
return doc.exists ? DeviceModel.fromFirestore(doc) : null;
} catch (e) {
return null;
}
}
Future<void> createDevice(DeviceModel device) async {
await _firestore
.collection('devices')
.doc(device.idDevices)
.set(device.toFirestore());
}
Future<void> deleteDevice(String deviceId) async {
await _firestore.collection('devices').doc(deviceId).delete();
}
// ==================== PATIENT MANAGEMENT ====================
Stream<List<PatientModel>> getPatientsStream() {
return _firestore
.collection('patients')
.snapshots()
.map(
(snapshot) => snapshot.docs
.map((doc) => PatientModel.fromFirestore(doc))
.toList(),
);
}
Future<PatientModel?> getPatientById(String patientId) async {
try {
final doc = await _firestore.collection('patients').doc(patientId).get();
return doc.exists ? PatientModel.fromFirestore(doc) : null;
} catch (e) {
return null;
}
}
Future<PatientModel?> getPatientByDeviceId(String deviceId) async {
try {
final snapshot = await _firestore
.collection('patients')
.where('device_id', isEqualTo: deviceId)
.limit(1)
.get();
return snapshot.docs.isNotEmpty
? PatientModel.fromFirestore(snapshot.docs.first)
: null;
} catch (e) {
return null;
}
}
Future<void> createPatient(PatientModel patient) async {
await _firestore.collection('patients').add(patient.toFirestore());
}
Future<void> updatePatient(String patientId, PatientModel patient) async {
await _firestore
.collection('patients')
.doc(patientId)
.update(patient.toFirestore());
}
Future<void> deletePatient(String patientId) async {
await _firestore.collection('patients').doc(patientId).delete();
}
// ==================== ROOM MANAGEMENT ====================
Future<bool> roomExists(String roomId) async {
try {
final doc = await _firestore.collection('rooms').doc(roomId).get();
return doc.exists;
} catch (e) {
return false;
}
}
Stream<List<RoomModel>> getRoomsStream() {
return _firestore
.collection('rooms')
.snapshots()
.map(
(snapshot) =>
snapshot.docs.map((doc) => RoomModel.fromFirestore(doc)).toList(),
);
}
Future<RoomModel?> getRoomById(String roomId) async {
try {
final doc = await _firestore.collection('rooms').doc(roomId).get();
return doc.exists ? RoomModel.fromFirestore(doc) : null;
} catch (e) {
return null;
}
}
Future<void> createRoom(RoomModel room) async {
await _firestore.collection('rooms').doc(room.id).set(room.toFirestore());
}
Future<void> deleteRoom(String roomId) async {
await _firestore.collection('rooms').doc(roomId).delete();
}
// ==================== HISTORY MANAGEMENT ====================
Stream<List<HistoryModel>> getDeviceHistoriesStream(String deviceId) {
return _firestore
.collection('histories')
.where('device_id', isEqualTo: deviceId)
.snapshots()
.map((snapshot) {
final histories = snapshot.docs
.map((doc) => HistoryModel.fromFirestore(doc))
.toList();
histories.sort((a, b) => b.timestamp.compareTo(a.timestamp));
return histories;
});
}
Future<List<HistoryModel>> getDeviceHistories(
String deviceId, {
int limit = 100,
}) async {
try {
final snapshot = await _firestore
.collection('histories')
.where('device_id', isEqualTo: deviceId)
.get();
final histories = snapshot.docs
.map((doc) => HistoryModel.fromFirestore(doc))
.toList();
histories.sort((a, b) => b.timestamp.compareTo(a.timestamp));
return histories.take(limit).toList();
} catch (e) {
return [];
}
}
Future<List<HistoryModel>> getDeviceHistoriesInRange(
String deviceId,
DateTime startDate,
DateTime endDate,
) async {
try {
final snapshot = await _firestore
.collection('histories')
.where('device_id', isEqualTo: deviceId)
.where('timestamp', isGreaterThanOrEqualTo: startDate)
.where('timestamp', isLessThanOrEqualTo: endDate)
.get();
final histories = snapshot.docs
.map((doc) => HistoryModel.fromFirestore(doc))
.toList();
histories.sort((a, b) => b.timestamp.compareTo(a.timestamp));
return histories;
} catch (e) {
return [];
}
}
Future<List<HistoryModel>> getDeviceHistoriesToday(String deviceId) async {
final now = DateTime.now();
final startOfDay = DateTime(now.year, now.month, now.day);
final endOfDay = DateTime(now.year, now.month, now.day, 23, 59, 59);
return getDeviceHistoriesInRange(deviceId, startOfDay, endOfDay);
}
Future<void> addHistory(HistoryModel history) async {
await _firestore.collection('histories').add(history.toFirestore());
}
Future<void> deleteOldHistories({int daysToKeep = 30}) async {
final cutoffDate = DateTime.now().subtract(Duration(days: daysToKeep));
final snapshot = await _firestore
.collection('histories')
.where('timestamp', isLessThan: cutoffDate)
.get();
final batch = _firestore.batch();
for (var doc in snapshot.docs) {
batch.delete(doc.reference);
}
await batch.commit();
}
// BARU: Hapus semua histories berdasarkan device_id
Future<void> deleteHistoriesByDevice(String deviceId) async {
final snapshot = await _firestore
.collection('histories')
.where('device_id', isEqualTo: deviceId)
.get();
final batch = _firestore.batch();
for (var doc in snapshot.docs) {
batch.delete(doc.reference);
}
await batch.commit();
}
// ==================== NOTIFICATION MANAGEMENT ====================
Stream<List<NotificationModel>> getNotificationsStream() {
return _firestore
.collection('notifications')
.orderBy('created_at', descending: true)
.snapshots()
.map(
(snapshot) => snapshot.docs
.map((doc) => NotificationModel.fromFirestore(doc))
.toList(),
);
}
Future<void> addNotification(NotificationModel notification) async {
await _firestore
.collection('notifications')
.add(notification.toFirestore());
}
Future<void> markNotificationAsRead(String notificationId) async {
await _firestore.collection('notifications').doc(notificationId).update({
'is_read': true,
});
}
Future<void> deleteNotification(String notificationId) async {
await _firestore.collection('notifications').doc(notificationId).delete();
}
// BARU: Hapus semua notifications berdasarkan device_id
Future<void> deleteNotificationsByDevice(String deviceId) async {
final snapshot = await _firestore
.collection('notifications')
.where('device_id', isEqualTo: deviceId)
.get();
final batch = _firestore.batch();
for (var doc in snapshot.docs) {
batch.delete(doc.reference);
}
await batch.commit();
}
// ==================== SCHEDULE MANAGEMENT ====================
Stream<List<ScheduleModel>> getSchedulesStream({
DateTime? date,
String? timeOfDay,
}) {
Query query = _firestore.collection('schedules');
if (date != null) {
final startOfDay = DateTime(date.year, date.month, date.day);
final endOfDay = DateTime(date.year, date.month, date.day, 23, 59, 59);
query = query
.where('schedule_date', isGreaterThanOrEqualTo: startOfDay)
.where('schedule_date', isLessThanOrEqualTo: endOfDay);
}
if (timeOfDay != null) {
query = query.where('time_of_day', isEqualTo: timeOfDay);
}
return query.snapshots().map(
(snapshot) =>
snapshot.docs.map((doc) => ScheduleModel.fromFirestore(doc)).toList(),
);
}
Future<void> addSchedule(ScheduleModel schedule) async {
await _firestore.collection('schedules').add(schedule.toFirestore());
}
Future<void> updateSchedule(String scheduleId, ScheduleModel schedule) async {
await _firestore
.collection('schedules')
.doc(scheduleId)
.update(schedule.toFirestore());
}
Future<void> deleteSchedule(String scheduleId) async {
await _firestore.collection('schedules').doc(scheduleId).delete();
}
// BARU: Hapus semua schedules berdasarkan device_id
Future<void> deleteSchedulesByDevice(String deviceId) async {
final snapshot = await _firestore
.collection('schedules')
.where('device_id', isEqualTo: deviceId)
.get();
final batch = _firestore.batch();
for (var doc in snapshot.docs) {
batch.delete(doc.reference);
}
await batch.commit();
}
}