import 'package:flutter/material.dart'; import 'settings_page.dart'; import 'package:firebase_database/firebase_database.dart'; class JadwalPage extends StatefulWidget { const JadwalPage({super.key}); @override State createState() => _JadwalPageState(); } class _JadwalPageState extends State { final tanggalController = TextEditingController(); final jamController = TextEditingController(); final dbRef = FirebaseDatabase.instance.ref("jadwal"); @override void initState() { super.initState(); dbRef.onValue.listen((event) { final data = event.snapshot.value; if (data != null) { Map map = data as Map; List> temp = []; map.forEach((key, value) { temp.add({ "key": key, "waktu": value["waktu"] ?? "", "jam": value["jam"] ?? "", "tanggal": value["tanggal"] ?? "", "status": value["status"] ?? "idle", }); }); setState(() { jadwalList = temp; }); } }); } DateTime? startDate; DateTime? endDate; String? selectedWaktu; List> jadwalList = []; int? editIndex; // 🔥 PILIH TANGGAL Future pilihTanggal() async { final result = await showDialog( context: context, builder: (_) => AlertDialog( title: const Text("Pilih Mode"), content: const Text("Pilih 1 hari atau rentang tanggal"), actions: [ TextButton( onPressed: () => Navigator.pop(context, "single"), child: const Text("1 Hari"), ), TextButton( onPressed: () => Navigator.pop(context, "range"), child: const Text("Rentang"), ), ], ), ); if (result == "single") { DateTime? picked = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime(2020), lastDate: DateTime(2100), ); if (picked != null) { setState(() { startDate = picked; endDate = null; tanggalController.text = "${picked.day}-${picked.month}-${picked.year}"; }); } } if (result == "range") { DateTimeRange? picked = await showDateRangePicker( context: context, firstDate: DateTime(2020), lastDate: DateTime(2100), ); if (picked != null) { setState(() { startDate = picked.start; endDate = picked.end; tanggalController.text = "${picked.start.day}-${picked.start.month}-${picked.start.year} s/d ${picked.end.day}-${picked.end.month}-${picked.end.year}"; }); } } } Future kirimKeFirebase() async { if (startDate == null) return null; DatabaseReference newRef = dbRef.push(); String tanggal; // 🔥 kalau range if (endDate != null) { tanggal = "${startDate!.day}-${startDate!.month}-${startDate!.year} s/d ${endDate!.day}-${endDate!.month}-${endDate!.year}"; } // 🔥 kalau single else { tanggal = "${startDate!.day}-${startDate!.month}-${startDate!.year}"; } await newRef.set({ "tanggal": tanggal, "jam": jamController.text, "waktu": selectedWaktu, }); return newRef.key; } // 🔥 PILIH JAM Future pilihJam() async { TimeOfDay? picked = await showTimePicker( context: context, initialTime: TimeOfDay.now(), ); if (picked != null) { setState(() { jamController.text = "${picked.hour.toString().padLeft(2, '0')}:${picked.minute.toString().padLeft(2, '0')} WIB"; }); } } // 🔥 SIMPAN DATA void simpanData() async { if (selectedWaktu == null || jamController.text.isEmpty || tanggalController.text.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("Isi semua data dulu")), ); return; } // 🔥 MODE EDIT if (editIndex != null) { String key = jadwalList[editIndex!]["key"] ?? ""; if (key.isNotEmpty) { await dbRef.child(key).update({ "tanggal": tanggalController.text, "jam": jamController.text, "waktu": selectedWaktu, "status": "idle", // 🔥 TAMBAHAN }); } ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("Jadwal berhasil diupdate")), ); } // 🔥 MODE TAMBAH else { DatabaseReference newRef = dbRef.push(); await newRef.set({ "tanggal": tanggalController.text, "jam": jamController.text, "waktu": selectedWaktu, "status": "idle", // reset ulang }); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("Jadwal berhasil ditambah")), ); } // reset form selectedWaktu = null; jamController.clear(); tanggalController.clear(); } // 🔥 EDIT DATA void editData(int index) { setState(() { selectedWaktu = jadwalList[index]["waktu"]; jamController.text = jadwalList[index]["jam"]!; tanggalController.text = jadwalList[index]["tanggal"]!; editIndex = index; }); } // 🔥 DELETE DATA void deleteData(int index) async { String key = jadwalList[index]["key"] ?? ""; if (key.isNotEmpty) { await dbRef.child(key).remove(); } setState(() { jadwalList.removeAt(index); }); } Color getStatusColor(String? status) { switch (status) { case "running": return Colors.orange; case "done": return Colors.green; default: return Colors.grey; } } @override void dispose() { tanggalController.dispose(); jamController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFE6E7A3), body: SafeArea( child: Column( children: [ // 🔶 HEADER Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 15), child: Row( children: [ GestureDetector( onTap: () => Navigator.pop(context), child: const CircleAvatar( backgroundColor: Colors.white, child: Icon(Icons.arrow_back), ), ), const SizedBox(width: 10), const Expanded( child: Text( "Atur Jadwal Pakan", textAlign: TextAlign.center, style: TextStyle(fontWeight: FontWeight.bold), ), ), IconButton( icon: const Icon(Icons.settings), onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (_) => SettingsPage()), ); }, ), ], ), ), // 🔻 CONTENT Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( children: [ // 🔶 FORM INPUT Container( padding: const EdgeInsets.all(15), decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(20), ), child: Column( children: [ const Text("Tanggal/Hari"), const SizedBox(height: 10), TextField( controller: tanggalController, readOnly: true, onTap: pilihTanggal, decoration: InputDecoration( hintText: "Pilih tanggal", suffixIcon: const Icon(Icons.calendar_today), filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), ), ), const SizedBox(height: 15), const Text("Jam"), const SizedBox(height: 10), Row( children: [ Expanded( child: DropdownButtonFormField( value: selectedWaktu, hint: const Text("Pagi / Sore"), items: ["Pagi", "Sore"].map((e) { return DropdownMenuItem( value: e, child: Text(e), ); }).toList(), onChanged: (value) { setState(() { selectedWaktu = value; }); }, decoration: InputDecoration( filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), ), ), ), const SizedBox(width: 10), Expanded( child: TextField( controller: jamController, readOnly: true, onTap: pilihJam, decoration: InputDecoration( hintText: "Pilih Jam", suffixIcon: const Icon(Icons.access_time), filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), ), ), ), ], ), const SizedBox(height: 20), ElevatedButton( onPressed: simpanData, child: Text(editIndex != null ? "Update" : "Simpan"), ) ], ), ), const SizedBox(height: 20), // 🔥 LIST HASIL if (jadwalList.isNotEmpty) Column( children: List.generate(jadwalList.length, (index) { final data = jadwalList[index]; return Container( margin: const EdgeInsets.only(bottom: 15), padding: const EdgeInsets.all(15), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: Colors.green.withOpacity(0.3), blurRadius: 8, ) ], ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(data["waktu"]!, style: const TextStyle( fontWeight: FontWeight.bold)), const SizedBox(height: 5), Text("Jam ${data["jam"]}"), const SizedBox(height: 5), Text( data["tanggal"]!, style: const TextStyle( fontSize: 10, color: Colors.grey), ), const SizedBox(height: 5), // 🔥 STATUS Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: getStatusColor(data["status"]), borderRadius: BorderRadius.circular(10), ), child: SizedBox( width: 220, child: Text( data["status"] ?? "idle", softWrap: true, style: const TextStyle( color: Colors.white, fontSize: 12, ), ), ), ), ], ), ), Row( children: [ // EDIT IconButton( icon: const Icon(Icons.edit), onPressed: () => editData(index), ), // DELETE IconButton( icon: const Icon(Icons.delete, color: Colors.red), onPressed: () => deleteData(index), ), ], ) ], ), ); }), ) ], ), ), ), ], ), ), ); } }