E32221324_Iot_Running/lib/screens/hasil_event_page.dart

214 lines
9.5 KiB
Dart

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'event_result_page.dart'; // Import halaman hasil peserta
class HasilEventPage extends StatelessWidget {
// Warna utama yang terinspirasi dari gambar Anda
final Color primaryBlue = Color(0xFF42A5F5); // Biru muda yang cerah
final Color lightBlue = Color(0xFFBBDEFB); // Biru yang lebih terang untuk background
final Color darkBlue = Color(0xFF1976D2); // Biru yang lebih gelap untuk teks/ikon
@override
Widget build(BuildContext context) {
final eventCollection = FirebaseFirestore.instance.collection('events');
return Scaffold(
backgroundColor: Colors.grey[50], // Background lembut
appBar: AppBar(
title: Text(
'Daftar Hasil Event',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
centerTitle: true,
backgroundColor: primaryBlue, // Warna AppBar
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20), // Sudut melengkung di kiri bawah
bottomRight: Radius.circular(20), // Sudut melengkung di kanan bawah
),
),
iconTheme: IconThemeData(color: Colors.white), // Warna ikon back
elevation: 5, // Tambahkan sedikit bayangan
),
body: StreamBuilder<QuerySnapshot>(
stream: eventCollection.orderBy('created_at', descending: true).snapshots(), // Urutkan terbaru di atas
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator(color: primaryBlue));
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}', style: TextStyle(color: Colors.red)));
}
final docs = snapshot.data!.docs;
if (docs.isEmpty) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.event_note, size: 60, color: Colors.grey[400]),
SizedBox(height: 16),
Text(
"Belum ada event yang tersedia.",
style: TextStyle(fontSize: 18, color: Colors.grey[600]),
),
],
),
);
}
return ListView.builder(
padding: EdgeInsets.all(16.0), // Padding menyeluruh untuk ListView
itemCount: docs.length,
itemBuilder: (context, index) {
final doc = docs[index];
final data = doc.data() as Map<String, dynamic>;
final eventName = data['name'] ?? 'Tanpa Nama';
final totalLaps = data['total_laps'] ?? 0;
final totalDistance = data['total_distance'] ?? 0;
final participantsMap = data['participants'] as Map<String, dynamic>? ?? {}; // Ambil map peserta
// Ambil status permanen dari Firestore
bool isEventFinishedPermanently = data['is_finished_permanently'] ?? false;
bool isEventStartedPermanently = data['is_started_permanently'] ?? false;
String displayEventStatusText;
Color displayEventStatusColor;
if (isEventFinishedPermanently) {
displayEventStatusText = "Selesai"; // Lebih ringkas
displayEventStatusColor = Colors.green.shade700;
} else if (isEventStartedPermanently) {
displayEventStatusText = "Berlangsung"; // Lebih ringkas
displayEventStatusColor = Colors.orange.shade700;
} else {
displayEventStatusText = "Belum Mulai"; // Lebih ringkas
displayEventStatusColor = Colors.red.shade700;
}
return Card(
margin: EdgeInsets.only(bottom: 16), // Spasi antar card
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), // Radius pada Card
),
color: Colors.white, // Warna Card putih
child: InkWell( // Gunakan InkWell untuk efek visual saat ditekan
borderRadius: BorderRadius.circular(12),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => EventResultPage(
eventId: doc.id,
eventName: eventName,
),
),
);
},
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column( // Menggunakan Column untuk menata konten
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row( // Baris untuk Nama Event dan Status
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Text(
eventName,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: darkBlue,
),
overflow: TextOverflow.ellipsis,
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: displayEventStatusColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Text(
displayEventStatusText,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: displayEventStatusColor,
),
),
),
],
),
SizedBox(height: 4),
Text(
"${totalLaps} Putaran | ${(totalDistance / 1000).toStringAsFixed(2)} KM",
style: TextStyle(
fontSize: 14,
color: Colors.grey[700],
),
),
SizedBox(height: 12), // Spasi sebelum daftar peserta
Text(
"Peserta (${participantsMap.length}):",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: darkBlue,
),
),
SizedBox(height: 8),
if (participantsMap.isEmpty)
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
"Belum ada peserta terdaftar.",
style: TextStyle(fontSize: 14, fontStyle: FontStyle.italic, color: Colors.grey[600]),
),
)
else
// List nama peserta
...participantsMap.entries.map((entry) {
final p = entry.value as Map<String, dynamic>;
final name = p['name'] ?? 'Nama tidak ditemukan';
final finished = p['finished'] == true;
final currentLaps = p['laps'] ?? 0;
String statusText = finished ? 'Selesai' : 'Berlangsung ($currentLaps putaran)';
Color statusColor = finished ? Colors.green.shade700 : Colors.orange.shade700;
return Padding(
padding: const EdgeInsets.only(left: 8.0, bottom: 4.0),
child: Row(
children: [
Icon(Icons.person, size: 16, color: Colors.grey[700]), // Ikon orang
SizedBox(width: 8),
Expanded(
child: Text(
name,
style: TextStyle(fontSize: 14, color: Colors.grey[900]),
overflow: TextOverflow.ellipsis,
),
),
Text(
statusText,
style: TextStyle(fontSize: 12, color: statusColor),
),
],
),
);
}).toList(),
],
),
),
),
);
},
);
},
),
);
}
}