TKK_E32230332/lib/pages/riwayat_page.dart

265 lines
9.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:intl/intl.dart';
class RiwayatPage extends StatelessWidget {
final String uid;
const RiwayatPage({super.key, required this.uid});
// THEME
static const Color primaryColor = Color(0xff4E7C34);
static const Color secondaryColor = Color(0xff6A994E);
static const Color backgroundColor = Color(0xffFFF8E8);
Future<void> _resetRiwayat(BuildContext context) async {
final confirm = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
title: const Text("Konfirmasi"),
content: const Text("Yakin ingin menghapus semua riwayat?"),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text("Batal"),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text("Hapus", style: TextStyle(color: Colors.red)),
),
],
),
);
if (confirm == true) {
await FirebaseDatabase.instance.ref("history/$uid").remove();
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Riwayat berhasil dihapus"),
backgroundColor: primaryColor,
),
);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
title: const Text("Riwayat Nilai"),
centerTitle: true,
backgroundColor: primaryColor,
foregroundColor: Colors.white,
elevation: 2,
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.all(16),
child: Container(
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [primaryColor, secondaryColor],
),
borderRadius: BorderRadius.circular(14),
),
child: ElevatedButton.icon(
onPressed: () => _resetRiwayat(context),
icon: const Icon(Icons.delete, color: Colors.white),
label: const Text(
"Hapus Semua Riwayat",
style: TextStyle(color: Colors.white),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
),
),
),
body: StreamBuilder<DatabaseEvent>(
stream: FirebaseDatabase.instance.ref("history/$uid").onValue,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (!snapshot.hasData || snapshot.data!.snapshot.value == null) {
return const Center(child: Text("Belum ada riwayat"));
}
final raw = snapshot.data!.snapshot.value;
if (raw is! Map) {
return const Center(child: Text("Format data tidak sesuai"));
}
final data = Map<String, dynamic>.from(raw);
final entries = data.entries.toList();
// Sorting berdasarkan timestamp terbaru
entries.sort((a, b) {
final aTime = a.value['timestamp'] ?? 0;
final bTime = b.value['timestamp'] ?? 0;
return (bTime as int).compareTo(aTime as int);
});
// Ambil nama pemilik kartu sekali (fallback ke UID)
return FutureBuilder<DataSnapshot>(
future: FirebaseDatabase.instance.ref('cards/$uid').get(),
builder: (context, cardSnap) {
String cardName = uid.toUpperCase();
if (cardSnap.hasData && cardSnap.data!.value != null) {
final val = cardSnap.data!.value;
if (val is Map) {
final card = Map<String, dynamic>.from(val);
cardName = (card['name'] ?? cardName).toString();
}
}
return Column(
children: [
// CARD HEADER (INFO USER)
Container(
width: double.infinity,
margin: const EdgeInsets.fromLTRB(16, 16, 16, 8),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 8,
),
],
),
child: Row(
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: primaryColor,
borderRadius: BorderRadius.circular(12),
),
child: const Icon(Icons.person, color: Colors.white),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
cardName,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: primaryColor,
),
),
const SizedBox(height: 6),
const Text(
'Riwayat Aktivitas Quiz',
style: TextStyle(color: Colors.black54),
),
],
),
),
],
),
),
// LIST RIWAYAT NILAI
Expanded(
child: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: entries.length,
itemBuilder: (context, index) {
final item = Map<String, dynamic>.from(
entries[index].value as Map,
);
final nilai = item['nilai'] ?? 0;
final time = item['timestamp'];
if (time == null || time is! int) {
return const SizedBox();
}
final date = DateTime.fromMillisecondsSinceEpoch(time);
final formatted = DateFormat(
'dd MMM yyyy, HH:mm',
).format(date);
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Nilai: $nilai",
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
formatted,
style: const TextStyle(
color: Colors.black54,
),
),
],
),
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: secondaryColor.withOpacity(0.15),
borderRadius: BorderRadius.circular(10),
),
child: const Icon(
Icons.history,
color: primaryColor,
),
),
],
),
);
},
),
),
],
);
},
);
},
),
);
}
}