TKK_E32230859/lib/app/services/notification_service.dart

262 lines
7.3 KiB
Dart

// lib/app/services/notification_service.dart
import 'package:flutter/material.dart';
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../models/notification_model.dart' as local;
class NotificationService {
static final NotificationService _instance = NotificationService._internal();
factory NotificationService() => _instance;
NotificationService._internal();
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final Map<String, DateTime> _lastNotificationTime = {};
final Duration _notificationCooldown = const Duration(minutes: 5);
Future<void> initialize() async {
await AwesomeNotifications().initialize(null, [
NotificationChannel(
channelKey: 'infus_alert_channel',
channelName: 'Infus Alerts',
channelDescription: 'Alerts for infusion monitoring',
defaultColor: const Color(0xFF9D50DD),
ledColor: Colors.white,
importance: NotificationImportance.High,
channelShowBadge: true,
playSound: true,
enableVibration: true,
),
]);
await _requestPermissions();
_setupNotificationListeners();
}
Future<void> _requestPermissions() async {
await AwesomeNotifications().isNotificationAllowed().then((
isAllowed,
) async {
if (!isAllowed) {
await AwesomeNotifications().requestPermissionToSendNotifications();
}
});
}
void _setupNotificationListeners() {
AwesomeNotifications().setListeners(
onActionReceivedMethod: _onNotificationTapped,
onNotificationCreatedMethod: _onNotificationCreated,
onNotificationDisplayedMethod: _onNotificationDisplayed,
onDismissActionReceivedMethod: _onNotificationDismissed,
);
}
@pragma("vm:entry-point")
static Future<void> _onNotificationCreated(
ReceivedNotification receivedNotification,
) async {
print('Notification created: ${receivedNotification.id}');
}
@pragma("vm:entry-point")
static Future<void> _onNotificationDisplayed(
ReceivedNotification receivedNotification,
) async {
print('Notification displayed: ${receivedNotification.id}');
}
@pragma("vm:entry-point")
static Future<void> _onNotificationTapped(
ReceivedAction receivedAction,
) async {
print('Notification tapped: ${receivedAction.payload}');
}
@pragma("vm:entry-point")
static Future<void> _onNotificationDismissed(
ReceivedAction receivedAction,
) async {
print('Notification dismissed: ${receivedAction.id}');
}
Future<void> showDropRateAlert({
required String patientId,
required String patientName,
required String deviceId,
required String roomName,
}) async {
if (_isInCooldown(deviceId)) {
return;
}
final title = 'Peringatan Infus ⚠️';
final message =
'Infus $patientName di ruang $roomName telah berhenti menetes! Segera lakukan Tindakan!';
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: deviceId.hashCode,
channelKey: 'infus_alert_channel',
title: title,
body: message,
notificationLayout: NotificationLayout.Default,
payload: {
'device_id': deviceId,
'patient_id': patientId,
'patient_name': patientName,
'room_name': roomName,
},
category: NotificationCategory.Alarm,
wakeUpScreen: true,
fullScreenIntent: true,
autoDismissible: false,
backgroundColor: Colors.red,
color: Colors.red,
),
actionButtons: [
NotificationActionButton(
key: 'VIEW',
label: 'Lihat Detail',
actionType: ActionType.Default,
),
NotificationActionButton(
key: 'DISMISS',
label: 'Tutup',
actionType: ActionType.DismissAction,
isDangerousOption: true,
),
],
);
await _saveNotificationToFirestore(
patientId: patientId,
deviceId: deviceId,
title: title,
message: message,
);
_lastNotificationTime[deviceId] = DateTime.now();
print('Notification sent for device: $deviceId');
}
Future<void> showDropRateAlertForPatient({
required String patientId,
required String patientName,
required String deviceId,
required String roomName,
}) async {
if (_isInCooldown(deviceId)) {
return;
}
final title = 'Peringatan Infus ⚠️';
final message =
'Infus $patientName di ruang $roomName telah berhenti menetes! Segera hubungi Perawat!';
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: deviceId.hashCode,
channelKey: 'infus_alert_channel',
title: title,
body: message,
notificationLayout: NotificationLayout.Default,
payload: {
'device_id': deviceId,
'patient_id': patientId,
'patient_name': patientName,
'room_name': roomName,
},
category: NotificationCategory.Alarm,
wakeUpScreen: true,
fullScreenIntent: true,
autoDismissible: false,
backgroundColor: Colors.red,
color: Colors.red,
),
actionButtons: [
NotificationActionButton(
key: 'CALL',
label: 'Hubungi Perawat',
actionType: ActionType.Default,
),
NotificationActionButton(
key: 'DISMISS',
label: 'Tutup',
actionType: ActionType.DismissAction,
isDangerousOption: true,
),
],
);
await _saveNotificationToFirestore(
patientId: patientId,
deviceId: deviceId,
title: title,
message: message,
);
_lastNotificationTime[deviceId] = DateTime.now();
print('Notification sent for patient device: $deviceId');
}
Future<void> _saveNotificationToFirestore({
required String patientId,
required String deviceId,
required String title,
required String message,
}) async {
try {
final notification = local.NotificationModel(
id: '',
patientId: patientId,
deviceId: deviceId,
title: title,
message: message,
isRead: false,
createdAt: DateTime.now(),
);
await _firestore
.collection('notifications')
.add(notification.toFirestore());
print('Notification saved to Firestore');
} catch (e) {
print('Error saving notification to Firestore: $e');
}
}
bool _isInCooldown(String deviceId) {
if (!_lastNotificationTime.containsKey(deviceId)) {
return false;
}
final lastTime = _lastNotificationTime[deviceId]!;
final difference = DateTime.now().difference(lastTime);
return difference < _notificationCooldown;
}
void clearCooldown(String deviceId) {
_lastNotificationTime.remove(deviceId);
}
void clearAllCooldowns() {
_lastNotificationTime.clear();
}
Future<void> cancelNotification(int id) async {
await AwesomeNotifications().cancel(id);
}
Future<void> cancelNotificationByDeviceId(String deviceId) async {
await AwesomeNotifications().cancel(deviceId.hashCode);
}
Future<void> cancelAllNotifications() async {
await AwesomeNotifications().cancelAll();
}
void dispose() {
_lastNotificationTime.clear();
}
}