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 { final ref = FirebaseDatabase.instance.ref("histori"); List> 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.from(event.snapshot.value as Map); final List> temp = []; data.forEach((key, value) { if (value is Map) { final log = Map.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']), ), ), ); }, ), ); } }