TKK_E32222484/lib/realtime_monitoring.dart

166 lines
5.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:intl/intl.dart';
class RealtimeMonitoring extends StatefulWidget {
const RealtimeMonitoring({super.key});
@override
State<RealtimeMonitoring> createState() => _RealtimeMonitoringState();
}
class _RealtimeMonitoringState extends State<RealtimeMonitoring> {
final DatabaseReference _ref = FirebaseDatabase.instance.ref('monitoring');
Map<dynamic, dynamic> _data = {};
@override
void initState() {
super.initState();
// Mendengarkan perubahan data pada node 'monitoring' di Firebase
_ref.onValue.listen((event) {
final value = event.snapshot.value;
if (value != null && value is Map) {
setState(() {
_data = value;
});
}
});
}
@override
Widget build(BuildContext context) {
// Mengambil data dari _data map, dengan nilai default jika null
final suhu = _data['suhu_udara']?.toStringAsFixed(1) ?? '-';
final ph = _data['ph']?.toStringAsFixed(2) ?? '-';
final tds = _data['tds']?.toString() ?? '-';
final timestamp = _data['timestamp'];
String timeString = '-';
if (timestamp != null && timestamp is int) {
// Mengonversi Unix timestamp ke format tanggal dan waktu yang mudah dibaca
final time = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
timeString = DateFormat('dd MMM yyyy HH:mm:ss').format(time);
}
// Status perangkat
final fanStatus = (_data['fan'] ?? false) ? 'ON' : 'OFF';
final pompaUtamaStatus = (_data['pompa'] ?? false) ? 'ON' : 'OFF';
final pompaAbMixStatus = (_data['pompa_abmix'] ?? false) ? 'ON' : 'OFF';
final abmixHabisStatus = (_data['abmix_habis'] ?? false) ? 'YA' : 'TIDAK';
return Scaffold(
appBar: AppBar(title: const Text('Realtime Data'), centerTitle: true),
body: SingleChildScrollView(
// <--- PERBAIKAN: Tambahkan SingleChildScrollView di sini
padding: const EdgeInsets.all(16.0),
child: Card(
elevation: 6,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment.stretch, // Agar tabel mengisi lebar
children: [
const Text(
"📊 Data Realtime Monitoring",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.green,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
// Tabel untuk menampilkan data
Table(
columnWidths: const {
0: FlexColumnWidth(1.5), // Label
1: FlexColumnWidth(2.5), // Value
},
border: TableBorder.all(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(10),
width: 1.0,
),
children: [
_buildTableRow('Waktu Update', timeString),
_buildTableRow('Suhu Udara', '$suhu °C'),
_buildTableRow('TDS', '$tds ppm'),
_buildTableRow('pH', ph),
_buildTableRow(
'Kipas',
fanStatus,
statusColor: fanStatus == 'ON'
? Colors.green
: Colors.red,
),
_buildTableRow(
'Pompa Utama',
pompaUtamaStatus,
statusColor: pompaUtamaStatus == 'ON'
? Colors.green
: Colors.red,
),
_buildTableRow(
'Pompa AB Mix',
pompaAbMixStatus,
statusColor: pompaAbMixStatus == 'ON'
? Colors.green
: Colors.red,
),
_buildTableRow(
'AB Mix Habis',
abmixHabisStatus,
statusColor: abmixHabisStatus == 'YA'
? Colors.red
: Colors.green,
),
],
),
const SizedBox(height: 20),
Text(
"Data diperbarui secara otomatis dari ESP32.",
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
textAlign: TextAlign.center,
),
],
),
),
),
),
);
}
// Fungsi pembantu untuk membuat baris tabel
TableRow _buildTableRow(String label, String value, {Color? statusColor}) {
return TableRow(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
label,
style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 16),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
value,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color:
statusColor ?? Colors.black, // Gunakan warna status jika ada
),
textAlign: TextAlign.right, // Rata kanan untuk nilai
),
),
],
);
}
}