TKK_E32222650/lib/app/modules/dashboard/views/dashboard_view.dart

498 lines
19 KiB
Dart

import 'package:allium_dry/app/modules/pageslider/views/pageslider_view.dart';
import 'package:allium_dry/app/modules/pageslider1/views/pageslider1_view.dart';
import 'package:allium_dry/app/modules/pageslider2/views/pageslider2_view.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:carousel_slider/carousel_slider.dart';
import '../controllers/dashboard_controller.dart';
import 'package:firebase_database/firebase_database.dart';
class DashboardView extends StatelessWidget {
final DashboardController controller = Get.put(
DashboardController(),
); // Inisialisasi controller
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('AlliumDry'),
actions: [
Obx(
() => Row(
children: [
Icon(
Icons.circle,
color: controller.isOnline.value ? Colors.green : Colors.red,
size: 12,
),
const SizedBox(width: 4),
Text(
controller.isOnline.value ? 'Online' : 'Offline',
style: TextStyle(
color:
controller.isOnline.value ? Colors.green : Colors.red,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 12),
],
),
),
],
),
body: Obx(
() => SingleChildScrollView(
child: Column(
children: [
Material(
elevation: 4,
child: Container(height: 1, color: Colors.transparent),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Carousel Slider
CarouselSlider(
options: CarouselOptions(
height: 200,
enlargeCenterPage: true,
autoPlay: true,
autoPlayInterval: Duration(seconds: 3),
autoPlayAnimationDuration: Duration(milliseconds: 800),
viewportFraction: 1.0,
),
items: [
GestureDetector(
onTap: () {
Get.to(() => PagesliderView());
},
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 5.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
image: AssetImage('assets/image/slider1.png'),
fit: BoxFit.cover,
),
),
),
),
GestureDetector(
onTap: () {
Get.to(() => Pageslider1View());
},
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 5.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
image: AssetImage('assets/image/slider2.png'),
fit: BoxFit.cover,
),
),
),
),
GestureDetector(
onTap: () {
Get.to(() => Pageslider2View());
},
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 5.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
image: AssetImage('assets/image/slider3.png'),
fit: BoxFit.cover,
),
),
),
),
],
),
SizedBox(height: 20),
Text(
'Suhu Terkini',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Card(
elevation: 2,
margin: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
leading: Icon(Icons.thermostat, color: Colors.red),
title: Obx(
() => Text(
'${controller.suhuTerkini.value.toStringAsFixed(1)} °C',
style: TextStyle(fontSize: 16),
),
),
),
),
// Status Pengeringan
SizedBox(height: 20),
Text(
'Status Pengeringan',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
InkWell(
onTap:
controller.statusPengeringan.value ==
"Pengeringan Sedang Berjalan"
? () {
_showStatusDialog(context);
}
: null,
splashColor: Colors.blue.withAlpha(30),
highlightColor: Colors.blue.withAlpha(30),
child: Card(
elevation: 2,
margin: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
leading: Icon(Icons.timelapse, color: Colors.green),
title: Text(
controller.statusPengeringan.value,
style: TextStyle(fontSize: 16),
),
subtitle: Text(
controller.isTimerRunning.value
? 'Waktu yang tersisa: ${controller.waktuTersisa.value ~/ 60} menit ${controller.waktuTersisa.value % 60} detik'
: '',
style: TextStyle(fontSize: 14, color: Colors.grey),
),
),
),
),
// Tombol Aksi: Riwayat & Pengaturan (1 baris modern)
// Tombol Aksi: Riwayat & Pengaturan (Soft Style)
SizedBox(height: 20),
Row(
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: () {
_showRiwayatDialog(context);
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFFFFE0B2), // Soft orange
foregroundColor: Colors.black87,
elevation: 2,
// ignore: deprecated_member_use
shadowColor: Colors.orangeAccent.withOpacity(0.3),
padding: EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
icon: Icon(Icons.history),
label: Text(
'Riwayat',
style: TextStyle(fontSize: 16),
),
),
),
SizedBox(width: 12),
Expanded(
child: ElevatedButton.icon(
onPressed: () {
_showSettingsDialog(context);
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFFBBDEFB), // Soft blue
foregroundColor: Colors.black87,
elevation: 2,
// ignore: deprecated_member_use
shadowColor: Colors.blueAccent.withOpacity(0.3),
padding: EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
icon: Icon(Icons.settings),
label: Text(
'Pengaturan',
style: TextStyle(fontSize: 16),
),
),
),
],
),
],
),
),
],
),
),
),
);
}
// Fungsi untuk menampilkan dialog status pengeringan
void _showStatusDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Pengeringan'),
content: Text('Apa yang ingin Anda lakukan dengan pengeringan ini?'),
actions: [
TextButton(
onPressed: () {
controller.startTimer(); // Lanjutkan
Navigator.of(context).pop();
},
child: Text('Lanjutkan Pengeringan'),
),
TextButton(
onPressed: () async {
await FirebaseDatabase.instance.ref("control").set({
"stop": true,
});
controller.stopTimer(); // Hentikan
Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Pengeringan dihentikan.")),
);
},
child: Text('Hentikan Pengeringan'),
),
],
);
},
);
}
// riwayat
void _showRiwayatDialog(BuildContext context) {
controller.riwayatFirebase();
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Riwayat Pengeringan'),
content: SizedBox(
width: double.maxFinite,
height: 300,
child: Obx(() {
if (controller.riwayatList.isEmpty) {
return Center(child: Text('Belum ada riwayat.'));
}
return Scrollbar(
child: ListView.builder(
itemCount: controller.riwayatList.length,
itemBuilder: (context, index) {
final item = controller.riwayatList[index];
return ListTile(
leading: Icon(Icons.history),
title: Text('Tanggal: ${item['waktu']}'),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Durasi: ${item['durasi']} menit'),
Text('Status: ${item['status']}'),
],
),
);
},
),
);
}),
),
actions: [
// Icon tong sampah hanya muncul jika ada riwayat
Obx(() {
if (controller.riwayatList.isNotEmpty) {
return IconButton(
icon: Icon(Icons.delete, color: Colors.red),
tooltip: 'Hapus Semua Riwayat',
onPressed: () {
FirebaseDatabase.instance.ref("Riwayat").remove();
controller.riwayatList.clear();
Navigator.of(context).pop();
},
);
} else {
return SizedBox.shrink();
}
}),
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('Tutup'),
),
],
);
},
);
}
// Dialog pengaturan suhu dan waktu
void _showSettingsDialog(BuildContext context) {
RxBool isAuto = true.obs; // Menambahkan mode otomatis/manual
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text('Pengaturan Suhu dan Waktu'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Mode Otomatis / Manual
Obx(
() => Row(
children: [
Text('Mode Otomatis'),
Switch(
value: isAuto.value,
onChanged: (val) {
isAuto.value = val;
if (val) {
controller.waktu.value = controller
.hitungWaktuDariSuhu(controller.suhu.value);
}
},
),
],
),
),
// Pengaturan Suhu
Text('Suhu (°C):'),
Obx(
() => Slider(
value: controller.suhu.value,
min: 35,
max: 100,
divisions: 65,
label: '${controller.suhu.value.round()}°C',
onChanged: (value) {
controller.suhu.value = value;
if (isAuto.value) {
controller.waktu.value = controller
.hitungWaktuDariSuhu(value);
}
},
),
),
Obx(() => Text('Suhu: ${controller.suhu.value.round()} °C')),
// Pengaturan Waktu (tampil hanya jika manual)
Obx(
() =>
!isAuto.value
? Column(
children: [
SizedBox(height: 20),
Text('Waktu (Menit):'),
Slider(
value: controller.waktu.value.toDouble(),
min: 0,
max: 540,
divisions: 540,
label: controller.waktu.value.toString(),
onChanged: (value) {
controller.waktu.value = value.toInt();
},
),
Text('Waktu: ${controller.waktu.value} menit'),
],
)
: Text(
'Waktu dihitung otomatis: ${controller.waktu.value} menit',
),
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('Batal'),
),
TextButton(
onPressed: () async {
if (!controller.isOnline.value) {
showDialog(
context: context,
builder:
(context) => AlertDialog(
title: Text('Peringatan'),
content: Text('Mesin sedang offline'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('OK'),
),
],
),
);
return;
}
if (controller.isTimerRunning.value) {
showDialog(
context: context,
builder:
(context) => AlertDialog(
title: Text('Peringatan'),
content: Text(
'Proses pengeringan sedang berjalan.',
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('OK'),
),
],
),
);
} else {
// Simpan ke Firebase
final suhu = controller.suhu.value.round();
final waktu =
controller.waktu.value; // dari menit ke detik
await FirebaseDatabase.instance.ref("control").set({
"start": true,
"target_temp": suhu,
"duration": waktu,
});
controller.saveSettings(
suhu.toDouble(),
controller.waktu.value,
);
Navigator.of(context).pop();
// Opsional: SnackBar konfirmasi
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
"Pengeringan dimulai dengan suhu $suhu°C dan durasi ${controller.waktu.value} menit",
),
),
);
}
},
child: Text('Start'),
),
],
);
},
);
},
);
}
}