150 lines
6.6 KiB
Dart
150 lines
6.6 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
import '../models/sensor_data.dart';
|
|
|
|
class HistoryPage extends StatelessWidget {
|
|
const HistoryPage({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final collectionRef = FirebaseFirestore.instance
|
|
.collection('rtdb_data')
|
|
.orderBy('createdAt', descending: true);
|
|
|
|
return Scaffold(
|
|
backgroundColor: Colors.blueGrey.shade50,
|
|
appBar: AppBar(
|
|
title: const Text('Riwayat Sensor'),
|
|
backgroundColor: Colors.blue.shade800,
|
|
foregroundColor: Colors.white,
|
|
),
|
|
body: StreamBuilder<QuerySnapshot>(
|
|
stream: collectionRef.snapshots(),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) {
|
|
return Center(child: Text('Error: ${snapshot.error}'));
|
|
}
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
|
|
final docs = snapshot.data?.docs ?? [];
|
|
if (docs.isEmpty) {
|
|
return const Center(child: Text('Belum ada data'));
|
|
}
|
|
|
|
return SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
padding: const EdgeInsets.all(12),
|
|
child: SingleChildScrollView(
|
|
scrollDirection: Axis.vertical,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
DataTable(
|
|
headingRowColor: MaterialStateColor.resolveWith(
|
|
(_) => Colors.blue.shade700),
|
|
headingTextStyle: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.white,
|
|
fontSize: 12,
|
|
),
|
|
columnSpacing: 12,
|
|
dataRowMinHeight: 32,
|
|
dataRowMaxHeight: 40,
|
|
dataTextStyle: TextStyle(fontSize: 12,
|
|
color: Colors.blueGrey.shade800
|
|
),
|
|
columns: const [
|
|
DataColumn(label: Text('Elemen')),
|
|
DataColumn(label: Text('Suhu'), numeric: true),
|
|
DataColumn(label: Text('Suhu Min'), numeric: true),
|
|
DataColumn(label: Text('Suhu Maks'), numeric: true),
|
|
DataColumn(label: Text('Timer'), numeric: true),
|
|
DataColumn(label: Text('Kadar Air'), numeric: true),
|
|
DataColumn(label: Text('Waktu')),
|
|
DataColumn(label: Text('Aksi')),
|
|
],
|
|
rows: docs.map((doc) {
|
|
final data = doc.data()! as Map<String, dynamic>;
|
|
final Timestamp ts = data['createdAt'] as Timestamp;
|
|
final DateTime dateTime = ts.toDate();
|
|
final String formattedDate = DateFormat('EEEE, dd MMMM yyyy', 'id_ID').format(dateTime);
|
|
final String formattedTimeOnly = DateFormat('HH:mm:ss').format(dateTime);
|
|
final String displayTime = '$formattedDate\n$formattedTimeOnly';
|
|
|
|
final sensor = SensorData(
|
|
elemen: data['elemen'] ?? '-',
|
|
manualButton: data['manualButton'] ?? false,
|
|
manualMode: data['manualMode'] ?? false,
|
|
suhu: (data['suhu'] as num?)?.toDouble() ?? 0,
|
|
suhuMaks: (data['suhuMaks'] as num?)?.toInt() ?? 0,
|
|
suhuMin: (data['suhuMin'] as num?)?.toInt() ?? 0,
|
|
timer: data['timer'] ?? 0,
|
|
kadarAir: (data['kadarAir'] as num?)?.toDouble() ?? 0,
|
|
);
|
|
|
|
return DataRow(
|
|
color: MaterialStateColor.resolveWith((states) =>
|
|
docs.indexOf(doc) % 2 == 0
|
|
? Colors.white
|
|
: Colors.blueGrey.shade100),
|
|
cells: [
|
|
DataCell(Text(sensor.elemen)),
|
|
DataCell(Text('${sensor.suhu}°C')),
|
|
DataCell(Text('${sensor.suhuMin}°C')),
|
|
DataCell(Text('${sensor.suhuMaks}°C')),
|
|
DataCell(Text('${sensor.timer} detik')),
|
|
DataCell(Text('${sensor.kadarAir} %')),
|
|
DataCell(Text(displayTime)),
|
|
DataCell(
|
|
IconButton(
|
|
icon: const Icon(Icons.delete,
|
|
color: Colors.redAccent),
|
|
onPressed: () async {
|
|
final ok = await showDialog<bool>(
|
|
context: context,
|
|
builder: (_) => AlertDialog(
|
|
title: const Text('Hapus Data'),
|
|
content: const Text(
|
|
'Yakin ingin menghapus entri ini?'),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () =>
|
|
Navigator.pop(context, false),
|
|
child: const Text('Batal'),
|
|
),
|
|
TextButton(
|
|
onPressed: () =>
|
|
Navigator.pop(context, true),
|
|
child: const Text('Hapus'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
if (ok == true) {
|
|
await doc.reference.delete();
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text('Data berhasil dihapus')),
|
|
);
|
|
}
|
|
},
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}).toList(),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|