import 'package:flutter/material.dart'; import 'package:firebase_database/firebase_database.dart'; class NotifikasiPage extends StatefulWidget { const NotifikasiPage({super.key}); @override State createState() => _NotifikasiPageState(); } class _NotifikasiPageState extends State { 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, ), ), ], ), ), ), ], ), ); } }