TKK_E32230939/poultryrail/lib/jadwal_page.dart

495 lines
16 KiB
Dart

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<JadwalPage> createState() => _JadwalPageState();
}
class _JadwalPageState extends State<JadwalPage> {
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<Map<String, String>> 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<Map<String, String>> jadwalList = [];
int? editIndex;
// 🔥 PILIH TANGGAL
Future<void> pilihTanggal() async {
final result = await showDialog<String>(
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<String?> 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<void> 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<String>(
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),
),
],
)
],
),
);
}),
)
],
),
),
),
],
),
),
);
}
}