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 createState() => _ScheduleScreenState(); } class _ScheduleScreenState extends State { final dateController = TextEditingController(); final timeController = TextEditingController(); final dbRef = FirebaseDatabase.instance.ref("schedules"); final firestore = FirebaseFirestore.instance; String? editingKey; /// ================= DATE PICKER ================= Future 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 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 saveSchedule() async { final date = dateController.text; final time = timeController.text; if (date.isEmpty || time.isEmpty) return; Map 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 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 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((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(), ); }, ), ) ], ), ), ), ); } }