TKK_E32230949/lib/screens/schedule_screen.dart

365 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:intl/intl.dart';
class ScheduleScreen extends StatefulWidget {
const ScheduleScreen({super.key});
@override
State<ScheduleScreen> createState() => _ScheduleScreenState();
}
class _ScheduleScreenState extends State<ScheduleScreen> {
final dateController = TextEditingController();
final timeController = TextEditingController();
final dbRef = FirebaseDatabase.instance.ref("schedules");
final firestore = FirebaseFirestore.instance;
String? editingKey;
/// ================= DATE PICKER =================
Future<void> pickDate() async {
final picked = await showDatePicker(
context: context,
firstDate: DateTime(2024),
lastDate: DateTime(2030),
);
if (picked != null) {
dateController.text =
DateFormat("dd-MM-yyyy").format(picked);
}
}
/// ================= TIME PICKER =================
Future<void> pickTime() async {
final picked = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (picked != null) {
final now = DateTime.now();
final formattedTime = DateFormat("HH:mm").format(
DateTime(
now.year,
now.month,
now.day,
picked.hour,
picked.minute,
),
);
timeController.text = formattedTime;
}
}
/// ================= SAVE =================
Future<void> saveSchedule() async {
final date = dateController.text;
final time = timeController.text;
if (date.isEmpty || time.isEmpty) return;
Map<String, dynamic> data = {
"date": date,
"time": time,
"status": "idle",
"type": "single",
};
if (editingKey == null) {
final newRef = dbRef.push();
await newRef.set(data);
} else {
await dbRef.child(editingKey!).update(data);
editingKey = null;
}
dateController.clear();
timeController.clear();
setState(() {});
}
/// ================= DELETE =================
Future<void> deleteSchedule(String key) async {
await dbRef.child(key).remove();
}
/// ================= EDIT =================
void editSchedule(String key, String date, String time) {
setState(() {
editingKey = key;
dateController.text = date;
timeController.text = time;
});
}
/// ================= START =================
Future<void> startWatering(
String key, String date, String time) async {
await dbRef.child(key).update({"status": "watering"});
final docId = "${date}_$time";
/// START LOG
await firestore.collection("watering_history").doc(docId).set({
"date": date,
"startTime": time,
"endTime": null,
"status": "watering",
"type": "single",
"timestamp": FieldValue.serverTimestamp(),
});
/// simulasi pompa 5 detik
await Future.delayed(const Duration(seconds: 5));
final endTime =
DateFormat("HH:mm").format(DateTime.now());
await firestore
.collection("watering_history")
.doc(docId)
.update({
"endTime": endTime,
"status": "done",
});
await dbRef.child(key).update({"status": "done"});
}
@override
void initState() {
super.initState();
dbRef.onChildChanged.listen((event) async {
final data = event.snapshot.value as Map;
final date = data["date"];
final time = data["time"];
final docId = "${date}_$time";
if (data["status"] == "watering") {
await firestore
.collection("watering_history")
.doc(docId)
.set({
"date": date,
"startTime": time,
"endTime": null,
"status": "watering",
"type": "single",
"timestamp": FieldValue.serverTimestamp(),
});
}
if (data["status"] == "done") {
final endTime =
DateFormat("HH:mm").format(DateTime.now());
await firestore
.collection("watering_history")
.doc(docId)
.update({
"endTime": endTime,
"status": "done",
});
}
});
}
/// ================= UI =================
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFEFF2EF),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
/// HEADER
Row(
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
boxShadow: const [
BoxShadow(
blurRadius: 5,
color: Colors.black12)
],
),
child: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.pop(context),
),
),
const SizedBox(width: 15),
const Text(
"Atur Jadwal Penyiraman",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold),
)
],
),
const SizedBox(height: 20),
/// FORM
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
boxShadow: const [
BoxShadow(
blurRadius: 8,
color: Colors.black12,
offset: Offset(2, 4))
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Tanggal"),
const SizedBox(height: 8),
TextField(
controller: dateController,
readOnly: true,
onTap: pickDate,
decoration: const InputDecoration(
hintText: "Pilih tanggal",
suffixIcon: Icon(Icons.calendar_today),
border: OutlineInputBorder(),
),
),
const SizedBox(height: 12),
const Text("Jam"),
const SizedBox(height: 8),
TextField(
controller: timeController,
readOnly: true,
onTap: pickTime,
decoration: const InputDecoration(
hintText: "Pilih jam",
suffixIcon: Icon(Icons.access_time),
border: OutlineInputBorder(),
),
),
const SizedBox(height: 20),
Center(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor:
const Color(0xFF34A853),
padding: const EdgeInsets.symmetric(
horizontal: 40, vertical: 12),
),
onPressed: saveSchedule,
child: Text(
editingKey == null
? "Simpan"
: "Update"),
),
)
],
),
),
const SizedBox(height: 20),
/// LIST
Expanded(
child: StreamBuilder(
stream: dbRef.onValue,
builder: (context, snapshot) {
if (!snapshot.hasData ||
snapshot.data!.snapshot.value ==
null) {
return const Center(
child: Text("Belum ada jadwal"));
}
Map data =
snapshot.data!.snapshot.value
as Map;
return ListView(
children:
data.entries.map<Widget>((entry) {
final key = entry.key;
final value = entry.value;
return Card(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(20),
),
child: ListTile(
title: Text(
"Jam ${value['time']} WIB"),
subtitle: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(value['date']),
Text(
"Status: ${value['status']}",
style: TextStyle(
color: value['status'] ==
"watering"
? Colors.green
: value['status'] ==
"done"
? Colors.blue
: Colors.grey,
),
)
],
),
trailing: Row(
mainAxisSize:
MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Icons.edit,
color: Colors.orange),
onPressed: () {
editSchedule(
key,
value['date'],
value['time'],
);
},
),
IconButton(
icon: const Icon(Icons.delete,
color: Colors.red),
onPressed: () {
deleteSchedule(key);
},
),
],
),
),
);
}).toList(),
);
},
),
)
],
),
),
),
);
}
}