TKK_E32230939/poultryrail/lib/notifikasi_page.dart

458 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
class NotifikasiPage extends StatefulWidget {
const NotifikasiPage({super.key});
@override
State<NotifikasiPage> createState() => _NotifikasiPageState();
}
class _NotifikasiPageState extends State<NotifikasiPage> {
final dbRef = FirebaseDatabase.instance.ref("sensor");
double jarak = 0;
double berat1 = 0;
double berat2 = 0;
final statusRef = FirebaseDatabase.instance.ref("status");
int lastHeartbeat = 0;
DateTime lastHeartbeatTime = DateTime.now();
bool perangkatOffline = false;
@override
void initState() {
super.initState();
dbRef.onValue.listen((event) {
final data = event.snapshot.value as Map?;
if (data != null) {
double newJarak =
(data['jarak'] ?? 0).toDouble();
double newBerat1 =
(data['berat1'] ?? 0).toDouble();
double newBerat2 =
(data['berat2'] ?? 0).toDouble();
setState(() {
jarak = newJarak;
berat1 = newBerat1;
berat2 = newBerat2;
});
}
statusRef.child("heartbeat").onValue.listen((event) {
int heartbeat = 0;
if (event.snapshot.value != null) {
heartbeat = (event.snapshot.value as num).toInt();
}
if (heartbeat != lastHeartbeat) {
lastHeartbeat = heartbeat;
setState(() {
lastHeartbeatTime = DateTime.now();
perangkatOffline = false;
});
}
});
// cek setiap detik
Stream.periodic(
const Duration(seconds: 1),
).listen((_) {
int selisih = DateTime.now()
.difference(lastHeartbeatTime)
.inSeconds;
if (mounted) {
setState(() {
perangkatOffline = selisih >= 15;
});
}
});
});
}
@override
Widget build(BuildContext context) {
// 🔥 HITUNG PERSEN PENAMPUNG
double persen = ((12 - jarak) / 8) * 100;
if (persen < 0) persen = 0;
if (persen > 100) persen = 100;
// 🔥 DETEKSI PAKAN BERHASIL
bool pakanBerhasil =
berat1 > 0 || berat2 > 0;
return Scaffold(
backgroundColor: const Color(0xFFE0E0E0),
appBar: AppBar(
backgroundColor: const Color(0xFFFFC107),
elevation: 0,
title: const Text(
"Notifikasi",
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
iconTheme: const IconThemeData(
color: Colors.black,
),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
if (perangkatOffline)
Container(
margin: const EdgeInsets.only(bottom: 15),
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 5,
)
],
),
child: Row(
children: [
const CircleAvatar(
backgroundColor: Colors.orange,
child: Icon(
Icons.wifi_off,
color: Colors.white,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Perangkat Offline",
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 5),
Text(
"Jaringan lemah atau perangkat tidak terhubung.",
style: TextStyle(
color: Colors.grey[700],
),
),
],
),
),
],
),
),
// 🔔 PAKAN HAMPIR HABIS
// 🔔 PAKAN FULL
if (persen >= 100)
Container(
margin: const EdgeInsets.only(
bottom: 15,
),
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black
.withOpacity(0.1),
blurRadius: 5,
)
],
),
child: Row(
children: [
const CircleAvatar(
backgroundColor: Colors.green,
child: Icon(
Icons.inventory,
color: Colors.white,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const Text(
"Pakan Full",
style: TextStyle(
fontWeight:
FontWeight.bold,
),
),
const SizedBox(height: 5),
Text(
"Wadah penampung pakan penuh.",
style: TextStyle(
color: Colors.grey[700],
),
),
],
),
),
],
),
),
if (persen <= 25)
Container(
margin: const EdgeInsets.only(
bottom: 15,
),
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black
.withOpacity(0.1),
blurRadius: 5,
)
],
),
child: Row(
children: [
const CircleAvatar(
backgroundColor: Colors.red,
child: Icon(
Icons.warning,
color: Colors.white,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const Text(
"Pakan Hampir Habis",
style: TextStyle(
fontWeight:
FontWeight.bold,
),
),
const SizedBox(height: 5),
Text(
"Segera isi ulang wadah penampung pakan.",
style: TextStyle(
color:
Colors.grey[700],
),
),
],
),
),
],
),
),
// 🔔 PAKAN HABIS
if (persen <= 0)
Container(
margin: const EdgeInsets.only(
bottom: 15,
),
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black
.withOpacity(0.1),
blurRadius: 5,
)
],
),
child: Row(
children: [
const CircleAvatar(
backgroundColor: Colors.black,
child: Icon(
Icons.error,
color: Colors.white,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const Text(
"Pakan Habis",
style: TextStyle(
fontWeight:
FontWeight.bold,
),
),
const SizedBox(height: 5),
Text(
"Wadah penampung pakan sudah kosong.",
style: TextStyle(
color: Colors.grey[700],
),
),
],
),
),
],
),
),
// 🔔 PEMBERIAN PAKAN BERHASIL
if (pakanBerhasil)
Container(
margin: const EdgeInsets.only(
bottom: 15,
),
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black
.withOpacity(0.1),
blurRadius: 5,
)
],
),
child: Row(
children: [
const CircleAvatar(
backgroundColor:
Colors.green,
child: Icon(
Icons.check,
color: Colors.white,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const Text(
"Pemberian Pakan Berhasil",
style: TextStyle(
fontWeight:
FontWeight.bold,
),
),
const SizedBox(height: 5),
Text(
"Pakan berhasil diberikan ke wadah pakan.",
style: TextStyle(
color:
Colors.grey[700],
),
),
],
),
),
],
),
),
// 🔥 TIDAK ADA NOTIFIKASI
if (persen > 25 &&
!pakanBerhasil)
Center(
child: Padding(
padding:
const EdgeInsets.only(
top: 50,
),
child: Column(
children: [
Icon(
Icons.notifications_off,
size: 80,
color: Colors.grey[400],
),
const SizedBox(height: 10),
Text(
"Belum ada notifikasi",
style: TextStyle(
color: Colors.grey[600],
fontSize: 16,
),
),
],
),
),
),
],
),
);
}
}