import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'auth/login_screen.dart'; // Pastikan path ini benar import 'create_event_page.dart'; // Pastikan path ini benar import 'event_detail_page.dart'; // Pastikan path ini benar import 'hasil_event_page.dart'; // Pastikan path ini benar class SuperUserDashboard extends StatefulWidget { @override State createState() => _SuperUserDashboardState(); } class _SuperUserDashboardState extends State { // 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 Future _refresh() async { // Memaksa rebuild StreamBuilder saat refresh setState(() {}); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, // Background lembut body: RefreshIndicator( // RefreshIndicator di sini untuk keseluruhan body onRefresh: _refresh, color: primaryBlue, // Warna indicator refresh child: CustomScrollView( // Pastikan physics di CustomScrollView agar bisa di-scroll physics: const AlwaysScrollableScrollPhysics(), slivers: [ SliverAppBar( expandedHeight: 200.0, // Tinggi appBar saat expanded floating: false, pinned: true, // AppBar tetap terlihat saat scroll shape: RoundedRectangleBorder( borderRadius: BorderRadius.only( bottomLeft: Radius.circular(20), // Sudut melengkung di kiri bawah bottomRight: Radius.circular(20), // Sudut melengkung di kanan bawah ), ), backgroundColor: primaryBlue, // Set warna dasar AppBar (penting untuk transisi) flexibleSpace: FlexibleSpaceBar( centerTitle: true, titlePadding: EdgeInsets.only(bottom: 16.0, left: 16.0, right: 16.0), // Untuk membuat "Dashboard Event" dan logo terlihat melengkung, // kita bisa membungkus konten background FlexibleSpaceBar // dengan ClipRRect dan Container tambahan. background: ClipRRect( // <<< Tambahkan ClipRRect di sini borderRadius: BorderRadius.only( bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20), ), child: Container( // <<< Tambahkan Container di sini decoration: BoxDecoration( gradient: LinearGradient( // Tetap gunakan gradient untuk warna colors: [primaryBlue, darkBlue], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), // Hapus borderRadius di sini karena sudah ada di ClipRRect ), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox(height: 20), // Spasi untuk logo Image.asset( 'images/run.png', // Pastikan path logo benar height: 80, ), // Jika Anda ingin teks 'Dashboard Event' juga terlihat di expanded state, // dan melengkung bersama background, Anda bisa menambahkannya di sini. // Namun, secara default, title FlexibleSpaceBar akan bergerak. // Untuk membuat teks title 'tetap' dengan background yang melengkung, // Anda mungkin perlu menempatkan teks di dalam Column ini juga, // dan menghapus properti 'title' dari FlexibleSpaceBar. // Untuk saat ini, kita biarkan 'title' seperti adanya untuk animasi. // Jika Anda ingin title statis di dalam background melengkung, beritahu saya. ], ), ), ), ), title: Text( // Ini adalah title yang akan bergerak saat scroll 'Dashboard Event', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white, ), textAlign: TextAlign.center, ), ), actions: [ IconButton( icon: Icon(Icons.logout, color: Colors.white), tooltip: 'Logout', onPressed: () async { final shouldLogout = await showDialog( context: context, builder: (context) => AlertDialog( title: Text('Konfirmasi Logout'), content: Text('Apakah Anda yakin ingin keluar dari akun Super User?'), actions: [ TextButton(onPressed: () => Navigator.pop(context, false), child: Text('Batal')), TextButton( onPressed: () async { await FirebaseAuth.instance.signOut(); Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (_) => const LoginScreen()), (route) => false, ); }, child: Text('Logout', style: TextStyle(color: Colors.red))), ], ), ); }, ), ], ), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Card( elevation: 4, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), color: Colors.white, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ // Teks "Aksi Cepat" sudah dihapus dari sini sesuai permintaan sebelumnya _buildActionButton( context, icon: Icons.add_circle_outline, label: 'Buat Event Baru', onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (_) => CreateEventPage())); }, color: primaryBlue, ), SizedBox(height: 12), _buildActionButton( context, icon: Icons.bar_chart, label: 'Lihat Hasil Event', onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (_) => HasilEventPage())); }, color: Colors.green.shade600, // Warna hijau yang bagus ), ], ), ), ), SizedBox(height: 24), Text( 'Daftar Event', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: darkBlue, ), ), SizedBox(height: 1), ], ), ), ), StreamBuilder( stream: FirebaseFirestore.instance .collection('events') .orderBy('created_at', descending: true) // Urutkan terbaru di atas .snapshots(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return SliverFillRemaining( child: Center(child: CircularProgressIndicator(color: primaryBlue))); } if (snapshot.hasError) { return SliverFillRemaining( child: Center(child: Text('Error: ${snapshot.error}', style: TextStyle(color: Colors.red)))); } if (!snapshot.hasData || snapshot.data!.docs.isEmpty) { return SliverFillRemaining(child: Center(child: Text('Belum ada event yang dibuat.'))); } final events = snapshot.data!.docs; return SliverList( delegate: SliverChildBuilderDelegate( (context, index) { final data = events[index].data() as Map; final docId = events[index].id; final eventName = data['name'] ?? 'Tanpa Nama Event'; final totalLaps = data['total_laps'] ?? 0; final totalDistance = data['total_distance'] ?? 0; final createdAt = data['created_at'] is Timestamp ? (data['created_at'] as Timestamp).toDate() : null; final isStartedPermanently = data['is_started_permanently'] ?? false; final isFinishedPermanently = data['is_finished_permanently'] ?? false; String statusText; Color statusColor; if (isFinishedPermanently) { statusText = 'Selesai'; statusColor = Colors.green.shade700; } else if (isStartedPermanently) { statusText = 'Sedang Berlangsung'; statusColor = Colors.orange.shade700; } else { statusText = 'Belum Dimulai'; statusColor = darkBlue; } return Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), child: Card( elevation: 5, color: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), clipBehavior: Clip.antiAlias, child: InkWell( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (_) => EventDetailPage( eventId: docId, eventName: eventName, ), ), ); }, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( eventName, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: darkBlue, ), ), SizedBox(height: 8), Row( children: [ Icon(Icons.flag_outlined, size: 18, color: Colors.grey[700]), SizedBox(width: 8), Text( '$totalLaps Putaran (${(totalDistance / 1000).toStringAsFixed(2)} KM)', // Format KM dengan 2 desimal style: TextStyle(fontSize: 14, color: Colors.grey[700]), ), ], ), SizedBox(height: 4), Row( children: [ Icon(Icons.event, size: 18, color: Colors.grey[700]), SizedBox(width: 8), Text( createdAt != null ? '${createdAt.day}/${createdAt.month}/${createdAt.year}' : 'Tanggal tidak diketahui', style: TextStyle(fontSize: 14, color: Colors.grey[700]), ), ], ), SizedBox(height: 8), Align( alignment: Alignment.bottomRight, child: Chip( label: Text( statusText, style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), ), backgroundColor: statusColor, padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), shape: StadiumBorder(), ), ), ], ), ), ), ), ); }, childCount: events.length, ), ); }, ), ], ), ), ); } // Helper method untuk membuat tombol aksi yang konsisten Widget _buildActionButton( BuildContext context, { required IconData icon, required String label, required VoidCallback onPressed, required Color color, }) { return SizedBox( width: double.infinity, // Membuat tombol full width child: ElevatedButton.icon( onPressed: onPressed, icon: Icon(icon, color: Colors.white), label: Text( label, style: TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.bold), ), style: ElevatedButton.styleFrom( backgroundColor: color, padding: EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 5, ), ), ); } }