TKK_E32222484/lib/histori_page.dart

221 lines
7.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:intl/intl.dart'; // Pastikan ini ada untuk DateFormat
class HistoriPage extends StatefulWidget {
const HistoriPage({super.key});
@override
_HistoriPageState createState() => _HistoriPageState();
}
class _HistoriPageState extends State<HistoriPage> {
final ref = FirebaseDatabase.instance.ref("histori");
List<Map<String, dynamic>> logs = [];
@override
void initState() {
super.initState();
// Mendengarkan perubahan data pada node 'histori' di Firebase
ref.onValue.listen(
(event) {
if (event.snapshot.value != null && event.snapshot.value is Map) {
final data = Map<String, dynamic>.from(event.snapshot.value as Map);
final List<Map<String, dynamic>> temp = [];
data.forEach((key, value) {
if (value is Map) {
final log = Map<String, dynamic>.from(value);
log['key'] = key; // Simpan key Firebase
// --- PERBAIKAN PENTING: Parsing Timestamp ---
String timestampStr = log['timestamp']?.toString() ?? '';
DateTime logDateTime;
try {
// Coba parsing sebagai int (Unix timestamp dari Arduino)
int unixTimestamp = int.parse(timestampStr);
logDateTime = DateTime.fromMillisecondsSinceEpoch(
unixTimestamp * 1000,
);
} catch (e) {
// Jika parsing sebagai int gagal, coba parsing sebagai formatted string (dari log manual Flutter)
try {
logDateTime = DateFormat(
'yyyy-MM-dd HH:mm:ss',
).parse(timestampStr);
} catch (e) {
// Fallback jika keduanya gagal, gunakan waktu saat ini atau nilai default
logDateTime = DateTime.now();
print(
'Error parsing timestamp: $timestampStr. Using current time. Error: $e',
);
}
}
log['parsedTimestamp'] =
logDateTime; // Simpan DateTime yang sudah di-parse untuk pengurutan
temp.add(log);
}
});
// Urutkan berdasarkan 'parsedTimestamp' (DateTime) secara menurun (terbaru di atas)
temp.sort((a, b) {
final DateTime tsA = a['parsedTimestamp'];
final DateTime tsB = b['parsedTimestamp'];
return tsB.compareTo(tsA); // Urutkan dari yang terbaru ke terlama
});
setState(() {
logs = temp; // Perbarui state dengan data yang sudah diurutkan
});
} else {
// Jika snapshot.value null atau bukan Map (misal node dihapus/kosong)
setState(() {
logs = [];
});
}
},
onError: (error) {
// Penanganan error untuk listener Firebase
print("Error listening to Firebase history: $error");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("❌ Gagal memuat histori: $error")),
);
},
);
}
// Fungsi untuk menghapus satu entri histori
void _hapusHistori(String key) {
ref
.child(key)
.remove()
.then((_) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("✅ Histori berhasil dihapus")),
);
})
.catchError((e) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text("❌ Gagal hapus histori: $e")));
});
}
// Fungsi konfirmasi untuk menghapus semua histori
void _konfirmasiHapusHistori() {
if (logs.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Tidak ada histori untuk dihapus.")),
);
return;
}
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text("Hapus Semua Histori"),
content: const Text("Apakah kamu yakin ingin menghapus semua histori?"),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx),
child: const Text("Batal"),
),
TextButton(
onPressed: () {
ref
.remove()
.then((_) {
Navigator.pop(ctx);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("✅ Semua histori dihapus")),
);
})
.catchError((e) {
Navigator.pop(ctx);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("❌ Gagal hapus histori: $e")),
);
});
},
child: const Text("Hapus", style: TextStyle(color: Colors.red)),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Histori Aktivitas"),
actions: [
IconButton(
icon: const Icon(Icons.delete, color: Colors.redAccent),
onPressed: _konfirmasiHapusHistori,
),
],
),
body: logs.isEmpty
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.history, size: 60, color: Colors.grey[400]),
const SizedBox(height: 10),
const Text(
"Belum ada aktivitas.",
style: TextStyle(fontSize: 16, color: Colors.grey),
),
],
),
)
: ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: logs.length,
separatorBuilder: (_, __) => const SizedBox(height: 4),
itemBuilder: (_, i) {
final log = logs[i];
// Menggunakan 'parsedTimestamp' untuk tampilan
final DateTime displayTimestamp =
log['parsedTimestamp'] as DateTime;
final String formattedTimestamp = DateFormat(
'dd MMM yyyy HH:mm:ss',
).format(displayTimestamp);
return Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
child: ListTile(
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
leading: const Icon(Icons.access_time, color: Colors.blue),
title: Text(
log["aksi"] ?? "-",
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 15,
),
),
subtitle: Text(
formattedTimestamp, // Tampilkan timestamp yang sudah diformat
style: TextStyle(fontSize: 12, color: Colors.grey[700]),
),
trailing: IconButton(
icon: const Icon(Icons.delete, color: Colors.red),
onPressed: () => _hapusHistori(log['key']),
),
),
);
},
),
);
}
}