486 lines
16 KiB
Dart
486 lines
16 KiB
Dart
import 'package:firebase_auth/firebase_auth.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:firebase_database/firebase_database.dart';
|
|
import 'bottom_navigation.dart';
|
|
|
|
class AturJadwal2Screen extends StatefulWidget {
|
|
const AturJadwal2Screen({super.key});
|
|
|
|
@override
|
|
State<AturJadwal2Screen> createState() => _AturJadwal2ScreenState();
|
|
}
|
|
|
|
class _AturJadwal2ScreenState extends State<AturJadwal2Screen> {
|
|
final _namaObatController = TextEditingController();
|
|
final _jumlahObatController = TextEditingController();
|
|
|
|
bool isJamManual = true;
|
|
int dosisCount = 1;
|
|
List<TimeOfDay> manualTimes = [];
|
|
List<TimeOfDay> dosisTimes = [
|
|
TimeOfDay(hour: 6, minute: 0),
|
|
TimeOfDay(hour: 14, minute: 0),
|
|
TimeOfDay(hour: 22, minute: 0),
|
|
TimeOfDay(hour: 0, minute: 0),
|
|
];
|
|
|
|
final dbRef = FirebaseDatabase.instance.ref();
|
|
|
|
bool _isFirstEntry =
|
|
true; // Untuk cek apakah jadwal pertama sudah ada obat dan jumlah
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_checkExistingObatJumlah();
|
|
}
|
|
|
|
Future<void> _checkExistingObatJumlah() async {
|
|
try {
|
|
final obatSnap = await dbRef.child("jadwal/kotak2/obat2").get();
|
|
final jumlahSnap = await dbRef.child("jadwal/kotak2/jumlahObat").get();
|
|
|
|
if (obatSnap.exists &&
|
|
obatSnap.value != null &&
|
|
obatSnap.value.toString().trim().isNotEmpty &&
|
|
jumlahSnap.exists &&
|
|
jumlahSnap.value != null &&
|
|
jumlahSnap.value.toString().trim().isNotEmpty) {
|
|
// Jika data ada, artinya jadwal pertama sudah ada obat dan jumlah obat
|
|
setState(() {
|
|
_isFirstEntry = false;
|
|
// Set controller agar user tetap melihat data yang sudah ada (optional)
|
|
_namaObatController.text = obatSnap.value.toString();
|
|
_jumlahObatController.text = jumlahSnap.value.toString();
|
|
});
|
|
}
|
|
} catch (e) {
|
|
print('Error checking existing obat/jumlah: $e');
|
|
}
|
|
}
|
|
|
|
void simpanData() async {
|
|
final user = FirebaseAuth.instance.currentUser;
|
|
if (user == null) return;
|
|
|
|
final namaObat = _namaObatController.text.trim();
|
|
final jumlahObatText = _jumlahObatController.text.trim();
|
|
|
|
if (_isFirstEntry) {
|
|
if (namaObat.isEmpty || jumlahObatText.isEmpty) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text(
|
|
"Lengkapi data nama obat dan jumlah obat terlebih dahulu",
|
|
),
|
|
),
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (int.tryParse(jumlahObatText) == null) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text("Jumlah obat harus berupa angka")),
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
final int inputJumlahObat = int.tryParse(jumlahObatText) ?? 0;
|
|
final times =
|
|
isJamManual ? manualTimes : dosisTimes.take(dosisCount).toList();
|
|
final DatabaseReference kotakRef = dbRef.child("jadwal/kotak2");
|
|
|
|
try {
|
|
final snapshot = await kotakRef.get();
|
|
int index = 0;
|
|
final existingTimes = <String>[];
|
|
|
|
for (final child in snapshot.children) {
|
|
if (child.key != 'jumlahObat' &&
|
|
child.key != 'obat2' &&
|
|
child.key != 'userId') {
|
|
index++;
|
|
final jam = child.child('jam').value;
|
|
final menit = child.child('menit').value;
|
|
if (jam != null && menit != null) {
|
|
existingTimes.add('$jam:$menit');
|
|
}
|
|
}
|
|
}
|
|
|
|
if (index + times.length > 4) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('Maksimal 4 jadwal diperbolehkan')),
|
|
);
|
|
return;
|
|
}
|
|
|
|
int existingJumlahObat = 0;
|
|
final jumlahSnap = snapshot.child('jumlahObat');
|
|
if (jumlahSnap.exists && jumlahSnap.value != null) {
|
|
existingJumlahObat =
|
|
(jumlahSnap.value is int)
|
|
? jumlahSnap.value as int
|
|
: int.tryParse(jumlahSnap.value.toString()) ?? 0;
|
|
}
|
|
|
|
int totalJumlahObat =
|
|
_isFirstEntry ? inputJumlahObat : existingJumlahObat;
|
|
|
|
if (_isFirstEntry && totalJumlahObat > 15) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('Jumlah obat maksimal 15')),
|
|
);
|
|
return;
|
|
}
|
|
|
|
for (final time in times) {
|
|
final newTime = "${time.hour}:${time.minute}";
|
|
if (existingTimes.contains(newTime)) {
|
|
ScaffoldMessenger.of(
|
|
context,
|
|
).showSnackBar(const SnackBar(content: Text('Jadwal ini sudah ada')));
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Simpan data utama (hanya sekali)
|
|
if (_isFirstEntry) {
|
|
await kotakRef.child('obat2').set(namaObat);
|
|
await kotakRef.child('jumlahObat').set(inputJumlahObat);
|
|
await kotakRef.child('userId').set(user.uid); // dipindah ke sini
|
|
}
|
|
|
|
// Simpan jadwal jam dan menit saja
|
|
for (final time in times) {
|
|
await kotakRef.child('$index').set({
|
|
'jam': time.hour,
|
|
'menit': time.minute,
|
|
});
|
|
index++;
|
|
}
|
|
|
|
ScaffoldMessenger.of(
|
|
context,
|
|
).showSnackBar(const SnackBar(content: Text('Jadwal berhasil disimpan')));
|
|
Navigator.pop(context);
|
|
} catch (e) {
|
|
print('Gagal menyimpan data: $e');
|
|
ScaffoldMessenger.of(
|
|
context,
|
|
).showSnackBar(const SnackBar(content: Text('Gagal menyimpan jadwal')));
|
|
}
|
|
}
|
|
|
|
Future<void> pilihJamManual() async {
|
|
if (manualTimes.length >= 4) return;
|
|
|
|
TimeOfDay? picked = await showTimePicker(
|
|
context: context,
|
|
initialTime: TimeOfDay.now(),
|
|
);
|
|
if (picked != null) {
|
|
setState(() {
|
|
manualTimes.add(picked);
|
|
});
|
|
}
|
|
}
|
|
|
|
Future<void> ubahJamDosis(int index) async {
|
|
TimeOfDay? picked = await showTimePicker(
|
|
context: context,
|
|
initialTime: dosisTimes[index],
|
|
);
|
|
if (picked != null) {
|
|
setState(() {
|
|
dosisTimes[index] = picked;
|
|
});
|
|
}
|
|
}
|
|
|
|
Widget buildInputField(
|
|
String label,
|
|
TextEditingController controller, {
|
|
bool isNumber = false,
|
|
}) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(label),
|
|
SizedBox(height: 6),
|
|
TextField(
|
|
controller: controller,
|
|
keyboardType: isNumber ? TextInputType.number : TextInputType.text,
|
|
decoration: InputDecoration(
|
|
border: OutlineInputBorder(),
|
|
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
|
),
|
|
),
|
|
SizedBox(height: 12),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget buildManualTimePicker() {
|
|
return Column(
|
|
children: [
|
|
for (int i = 0; i < manualTimes.length; i++)
|
|
ListTile(
|
|
title: Text(manualTimes[i].format(context)),
|
|
trailing: IconButton(
|
|
icon: Icon(Icons.delete),
|
|
onPressed: () => setState(() => manualTimes.removeAt(i)),
|
|
),
|
|
),
|
|
if (manualTimes.length < 4)
|
|
ElevatedButton(onPressed: pilihJamManual, child: Text('Tambah Jam')),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget buildDosisTimePicker() {
|
|
return Column(
|
|
children: [
|
|
Wrap(
|
|
spacing: 10,
|
|
children:
|
|
[1, 2, 3, 4].map((e) {
|
|
return ChoiceChip(
|
|
label: Text('Obat ${e}x1'),
|
|
selected: dosisCount == e,
|
|
onSelected: (_) => setState(() => dosisCount = e),
|
|
);
|
|
}).toList(),
|
|
),
|
|
for (int i = 0; i < dosisCount; i++)
|
|
ListTile(
|
|
title: Text(dosisTimes[i].format(context)),
|
|
trailing: IconButton(
|
|
icon: Icon(Icons.edit),
|
|
onPressed: () => ubahJamDosis(i),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Color(0xFF3FA535),
|
|
body: Column(
|
|
children: [
|
|
SafeArea(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
|
child: Row(
|
|
children: [
|
|
IconButton(
|
|
icon: Icon(Icons.arrow_back, color: Colors.white),
|
|
onPressed: () => Navigator.pop(context),
|
|
),
|
|
SizedBox(width: 8),
|
|
Text(
|
|
"Atur Jadwal Obat",
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
child: Container(
|
|
width: double.infinity,
|
|
padding: EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.only(
|
|
topLeft: Radius.circular(30),
|
|
topRight: Radius.circular(30),
|
|
),
|
|
),
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
if (_isFirstEntry) ...[
|
|
buildInputField("Masukan Nama Obat", _namaObatController),
|
|
buildInputField(
|
|
"Masukan Jumlah Obat (Maksimal 15 Obat)",
|
|
_jumlahObatController,
|
|
isNumber: true,
|
|
),
|
|
] else ...[
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
child: Text(
|
|
"Nama obat dan jumlah obat sudah ada. Tidak perlu mengisi ulang.",
|
|
style: TextStyle(
|
|
color: const Color.fromARGB(255, 245, 5, 13),
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
buildInputField(
|
|
"Nama Obat",
|
|
_namaObatController..text = _namaObatController.text,
|
|
isNumber: false,
|
|
),
|
|
buildInputField(
|
|
"Jumlah Obat",
|
|
_jumlahObatController
|
|
..text = _jumlahObatController.text,
|
|
isNumber: true,
|
|
),
|
|
],
|
|
SizedBox(height: 10),
|
|
Text(
|
|
"Pilih Aturan Jam:",
|
|
style: TextStyle(fontWeight: FontWeight.bold),
|
|
),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: ElevatedButton(
|
|
onPressed: () => setState(() => isJamManual = true),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor:
|
|
isJamManual ? Colors.green : Colors.white,
|
|
foregroundColor:
|
|
isJamManual ? Colors.white : Colors.green,
|
|
side: BorderSide(color: Colors.green),
|
|
),
|
|
child: Text("Jam Manual"),
|
|
),
|
|
),
|
|
SizedBox(width: 8),
|
|
Expanded(
|
|
child: ElevatedButton(
|
|
onPressed:
|
|
() => setState(() => isJamManual = false),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor:
|
|
!isJamManual ? Colors.green : Colors.white,
|
|
foregroundColor:
|
|
!isJamManual ? Colors.white : Colors.green,
|
|
side: BorderSide(color: Colors.green),
|
|
),
|
|
child: Text("Jam Dosis"),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 16),
|
|
isJamManual
|
|
? buildManualTimePicker()
|
|
: buildDosisTimePicker(),
|
|
SizedBox(height: 20),
|
|
Center(
|
|
child: ElevatedButton(
|
|
onPressed: simpanData,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.green,
|
|
),
|
|
child: const Text(
|
|
"Simpan",
|
|
style: TextStyle(
|
|
color: Color.fromARGB(255, 255, 255, 255),
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
bottomNavigationBar: BottomNavigationBar(
|
|
currentIndex: 0, // sesuaikan dengan index aktif halaman sekarang
|
|
type: BottomNavigationBarType.fixed,
|
|
selectedItemColor: const Color(0xFF3FA535),
|
|
unselectedItemColor: Colors.grey.shade600,
|
|
showUnselectedLabels: true,
|
|
selectedLabelStyle: const TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14,
|
|
),
|
|
unselectedLabelStyle: const TextStyle(
|
|
fontWeight: FontWeight.normal,
|
|
fontSize: 12,
|
|
),
|
|
elevation: 8,
|
|
backgroundColor: Colors.white,
|
|
iconSize: 28,
|
|
onTap: (index) {
|
|
switch (index) {
|
|
case 0:
|
|
Navigator.pushReplacement(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (_) => MainNavigation(currentIndex: 0),
|
|
),
|
|
);
|
|
break;
|
|
case 1:
|
|
Navigator.pushReplacement(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (_) => MainNavigation(currentIndex: 1),
|
|
),
|
|
);
|
|
break;
|
|
case 2:
|
|
Navigator.pushReplacement(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (_) => MainNavigation(currentIndex: 2),
|
|
),
|
|
);
|
|
break;
|
|
case 3:
|
|
Navigator.pushReplacement(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (_) => MainNavigation(currentIndex: 3),
|
|
),
|
|
);
|
|
break;
|
|
}
|
|
},
|
|
items: const [
|
|
BottomNavigationBarItem(
|
|
icon: Icon(Icons.home_outlined),
|
|
activeIcon: Icon(Icons.home),
|
|
label: 'Home',
|
|
),
|
|
BottomNavigationBarItem(
|
|
icon: Icon(Icons.history_outlined),
|
|
activeIcon: Icon(Icons.history),
|
|
label: 'History',
|
|
),
|
|
BottomNavigationBarItem(
|
|
icon: Icon(Icons.notifications_outlined),
|
|
activeIcon: Icon(Icons.notifications),
|
|
label: 'Notification',
|
|
),
|
|
BottomNavigationBarItem(
|
|
icon: Icon(Icons.person_outline),
|
|
activeIcon: Icon(Icons.person),
|
|
label: 'Account',
|
|
),
|
|
],
|
|
),
|
|
|
|
//bottomNavigationBar: MainNavigation(currentIndex: ),
|
|
);
|
|
}
|
|
}
|