TKK_E32230332/lib/pages/rfid/nilai_praktik.dart

354 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
class CardDetailPage extends StatefulWidget {
final String uid;
final String name;
const CardDetailPage({super.key, required this.uid, required this.name});
@override
State<CardDetailPage> createState() => _CardDetailPageState();
}
class _CardDetailPageState extends State<CardDetailPage> {
// 🎨 THEME WARNA GLOBAL
static const Color primaryColor = Color(0xff4E7C34);
static const Color secondaryColor = Color(0xff6A994E);
static const Color backgroundColor = Color(0xffFFF8E8);
final List<String> steps = [
'Membaca doa wudhu',
'Berkumur-kumur',
'Membersihkan hidung',
'Membasuh muka',
'Membasuh tangan kanan & kiri',
'Mengusap kepala',
'Mengusap telinga',
'Membasuh kaki kanan & kiri',
];
final Map<String, bool?> values = {};
int lastSavedScore = -1;
@override
void initState() {
super.initState();
for (final step in steps) {
values[step] = null;
}
FirebaseDatabase.instance.ref("hasil/${widget.uid}").onValue.listen((
event,
) {
final data = event.snapshot.value as Map?;
if (data != null) {
for (int i = 0; i < steps.length; i++) {
values[steps[i]] = data["step${i + 1}"];
}
setState(() {});
int correct = values.values.where((v) => v == true).length;
int total = values.length;
int newScore = ((correct / total) * 100).round();
if (newScore != lastSavedScore) {
lastSavedScore = newScore;
FirebaseDatabase.instance.ref("cards/${widget.uid}").update({
"nilai": newScore,
});
FirebaseDatabase.instance.ref("history/${widget.uid}").push().set({
"nilai": newScore,
"timestamp": DateTime.now().millisecondsSinceEpoch,
});
}
}
});
}
Future<void> _resetData() async {
final confirm = await showDialog(
context: context,
builder: (context) => AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
title: const Text("Reset Data"),
content: const Text("Yakin ingin mengulang penilaian dari awal?"),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text("Batal"),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text("Reset", style: TextStyle(color: Colors.red)),
),
],
),
);
if (confirm == true) {
await FirebaseDatabase.instance.ref("hasil/${widget.uid}").remove();
await FirebaseDatabase.instance.ref("cards/${widget.uid}").update({
"nilai": 0,
});
setState(() {
for (final step in steps) {
values[step] = null;
}
lastSavedScore = -1;
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Data berhasil direset"),
backgroundColor: primaryColor,
),
);
}
}
int get correctCount => values.values.where((v) => v == true).length;
int get wrongCount => values.values.where((v) => v == false).length;
int get score {
final total = values.length;
if (total == 0) return 0;
return ((correctCount / total) * 100).round();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
// 🔥 APPBAR
appBar: AppBar(
title: const Text("Nilai Praktik Wudhu"),
backgroundColor: primaryColor,
foregroundColor: Colors.white,
centerTitle: true,
),
// 🔽 RESET BUTTON
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: _resetData,
icon: const Icon(Icons.refresh, color: Colors.white),
label: const Text(
"Reset Penilaian",
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: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
child: Column(
children: [
// 🔥 HEADER
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [backgroundColor, secondaryColor.withOpacity(0.2)],
),
borderRadius: BorderRadius.circular(16),
),
child: Row(
children: [
Container(
width: 50,
height: 50,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: primaryColor,
),
child: const Icon(Icons.person, color: Colors.white),
),
const SizedBox(width: 12),
Expanded(
child: Text(
widget.name,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: primaryColor,
),
),
),
],
),
),
const SizedBox(height: 20),
// 🔥 LIST STEP
Expanded(
child: ListView.separated(
itemCount: steps.length,
separatorBuilder: (_, __) => const SizedBox(height: 12),
itemBuilder: (context, index) {
final step = steps[index];
final value = values[step];
final statusText = value == null
? 'Belum'
: value
? 'Benar'
: 'Salah';
final statusColor = value == null
? Colors.black54
: value
? primaryColor
: Colors.red;
final icon = value == null
? Icons.circle_outlined
: value
? Icons.check_circle
: Icons.cancel;
final iconColor = value == null
? Colors.black26
: value
? primaryColor
: Colors.red;
final iconBg = value == null
? const Color(0xffe5e7eb)
: value
? const Color(0xffdff5e1)
: const Color(0xffffe2e2);
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 14,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Row(
children: [
Container(
width: 32,
height: 32,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: iconBg,
),
child: Icon(icon, color: iconColor, size: 18),
),
const SizedBox(width: 12),
Expanded(
child: Text(
step,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
),
),
),
Text(
statusText,
style: TextStyle(
fontWeight: FontWeight.bold,
color: statusColor,
),
),
],
),
);
},
),
),
const SizedBox(height: 16),
// 🔥 SCORE CARD
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [primaryColor, secondaryColor],
),
borderRadius: BorderRadius.circular(16),
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Benar',
style: TextStyle(color: Colors.white70),
),
Text(
'$correctCount',
style: const TextStyle(color: Colors.white),
),
],
),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Salah',
style: TextStyle(color: Colors.white70),
),
Text(
'$wrongCount',
style: const TextStyle(color: Colors.white),
),
],
),
const SizedBox(height: 16),
const Divider(color: Colors.white24),
const SizedBox(height: 16),
Text(
'Nilai: $score',
style: const TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
),
),
);
}
}