TKK_E32230949/lib/screens/dashboard.dart

319 lines
9.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'schedule_screen.dart';
class Dashboard extends StatefulWidget {
const Dashboard({super.key});
@override
State<Dashboard> createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
final DatabaseReference dbRef =
FirebaseDatabase.instance.ref();
double humidity = 0;
bool pumpOn = false;
bool scheduleWatering = false;
@override
void initState() {
super.initState();
/// LISTEN KELEMBAPAN
dbRef.child("sht/humidity").onValue.listen((event) {
final value = event.snapshot.value;
if (value != null) {
setState(() {
humidity = double.parse(value.toString());
});
}
});
/// LISTEN STATUS POMPA MANUAL
dbRef.child("pump/status").onValue.listen((event) {
final value = event.snapshot.value;
if (value != null) {
setState(() {
pumpOn = value as bool;
});
}
});
/// LISTEN STATUS SCHEDULE
dbRef.child("schedules").onValue.listen((event) {
final data = event.snapshot.value;
bool watering = false;
if (data != null) {
Map schedules = data as Map;
for (var item in schedules.values) {
if (item["status"] == "watering") {
watering = true;
break;
}
}
}
setState(() {
scheduleWatering = watering;
});
});
}
/// TOGGLE POMPA KE DATABASE
Future<void> togglePump() async {
bool newStatus = !pumpOn;
setState(() {
pumpOn = newStatus;
});
await dbRef.child("pump/status").set(newStatus);
}
@override
Widget build(BuildContext context) {
bool finalPumpStatus = pumpOn || scheduleWatering;
return SafeArea(
child: Column(
children: [
/// ================= HEADER =================
Container(
width: double.infinity,
padding: const EdgeInsets.all(20),
decoration: const BoxDecoration(
color: Color(0xFF34C759),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
),
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(20),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Menu Utama",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold),
),
const SizedBox(height: 15),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const ScheduleScreen()),
);
},
child: Column(
children: const [
CircleAvatar(
radius: 20,
backgroundColor: Colors.white,
child: Icon(Icons.assignment, size: 20),
),
SizedBox(height: 5),
Text(
"Jadwal\nPenyiraman",
textAlign: TextAlign.center,
)
],
),
)
],
),
),
),
/// ================= CONTENT =================
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.only(bottom: 120),
child: Column(
children: [
const SizedBox(height: 20),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
"Update Hari Ini!!",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold),
),
),
),
const SizedBox(height: 15),
/// KELEMBAPAN REALTIME
_infoCard(
title: "Kelembapan",
trailing: "${humidity.toStringAsFixed(2)} %",
color: Colors.green,
),
const SizedBox(height: 15),
/// STATUS POMPA
Container(
margin:
const EdgeInsets.symmetric(horizontal: 20),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(15),
boxShadow: const [
BoxShadow(
color: Colors.black26,
blurRadius: 4,
offset: Offset(0, 3),
)
],
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
const Text(
"Status Pompa",
style: TextStyle(
fontSize: 16,
fontWeight:
FontWeight.bold),
),
Container(
padding:
const EdgeInsets.symmetric(
horizontal: 14,
vertical: 6),
decoration: BoxDecoration(
color: finalPumpStatus
? Colors.green
: Colors.red,
borderRadius:
BorderRadius.circular(8),
),
child: Text(
finalPumpStatus ? "ON" : "OFF",
style: const TextStyle(
color: Colors.white,
fontWeight:
FontWeight.bold),
),
),
],
),
const Divider(height: 25),
const Text(
"Menyalakan Pompa Manual",
style: TextStyle(
fontSize: 16,
fontWeight:
FontWeight.bold),
),
const SizedBox(height: 20),
Center(
child: GestureDetector(
onTap: togglePump,
child: Container(
width: 90,
height: 90,
decoration: BoxDecoration(
color: pumpOn
? Colors.green
: Colors.red,
shape: BoxShape.circle,
),
child: Center(
child: Text(
pumpOn ? "ON" : "OFF",
style:
const TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight:
FontWeight.bold,
),
),
),
),
),
)
],
),
),
],
),
),
)
],
),
);
}
Widget _infoCard({
required String title,
required String trailing,
required Color color,
}) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 20),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(15),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold)),
Container(
padding:
const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6),
decoration: BoxDecoration(
color: color,
borderRadius:
BorderRadius.circular(8),
),
child: Text(trailing,
style: const TextStyle(
color: Colors.white,
fontWeight:
FontWeight.bold)),
)
],
),
);
}
}