import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_database/firebase_database.dart'; class DataSiswa extends StatelessWidget { const DataSiswa({super.key}); Future hapusSiswa( String docId, String rfid, String ortuUid, BuildContext context, ) async { try { await FirebaseFirestore.instance .collection('siswa') .doc(docId) .delete(); await FirebaseFirestore.instance .collection('users') .doc(ortuUid) .delete(); await FirebaseDatabase.instance .ref("siswa/$rfid") .remove(); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Data siswa berhasil dihapus'), behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))), ), ); } } catch (e) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text("Error : $e"), behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))), ), ); } } } Widget siswaCard( BuildContext context, String docId, String nama, String kelas, String namaOrtu, String nomorAbsen, String rfid, String ortuUid, ) { return Container( margin: const EdgeInsets.only(left: 24, right: 24, bottom: 20), padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: const Color(0xff0284C7).withOpacity(0.08), blurRadius: 24, spreadRadius: 0, offset: const Offset(0, 12), ), ], ), child: Row( children: [ // Avatar lingkaran dengan warna sesuai tema Container( width: 60, height: 60, decoration: BoxDecoration( shape: BoxShape.circle, color: const Color(0xff0284C7).withOpacity(0.12), boxShadow: [ BoxShadow( color: const Color(0xff0284C7).withOpacity(0.15), blurRadius: 12, spreadRadius: 2, ), ], ), child: const Icon( Icons.person_rounded, color: Color(0xff0284C7), size: 28, ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( nama, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 17, fontWeight: FontWeight.bold, color: Color(0xff12175E), ), ), const SizedBox(height: 6), Text( "Kelas: $kelas", style: TextStyle( fontSize: 14, color: const Color(0xff12175E).withOpacity(0.6), ), ), const SizedBox(height: 4), Text( "Orang Tua: $namaOrtu", style: TextStyle( fontSize: 14, color: const Color(0xff12175E).withOpacity(0.6), ), ), const SizedBox(height: 4), Text( "No. Absen: $nomorAbsen", style: TextStyle( fontSize: 14, color: const Color(0xff12175E).withOpacity(0.6), ), ), const SizedBox(height: 4), Text( "RFID: $rfid", style: TextStyle( fontSize: 14, color: const Color(0xff12175E).withOpacity(0.6), ), ), ], ), ), // Tombol hapus dengan gaya konsisten Container( width: 44, height: 44, decoration: BoxDecoration( color: Colors.red.withOpacity(0.1), borderRadius: BorderRadius.circular(14), ), child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(14), onTap: () { showDialog( context: context, builder: (_) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), title: const Text( "Hapus Data Siswa", style: TextStyle(color: Color(0xff12175E), fontWeight: FontWeight.bold), ), content: Text( "Yakin ingin menghapus data siswa:\n\n$nama ?", style: TextStyle(color: const Color(0xff12175E).withOpacity(0.7)), ), actionsPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text( "Batal", style: TextStyle(color: Colors.grey, fontWeight: FontWeight.w600), ), ), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.red, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), elevation: 2, ), onPressed: () { Navigator.pop(context); hapusSiswa(docId, rfid, ortuUid, context); }, child: const Text( "Hapus", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), ), ), ], ), ); }, child: const Icon( Icons.delete_rounded, color: Colors.red, size: 22, ), ), ), ), ], ), ); } Widget header(BuildContext context) { final screenHeight = MediaQuery.of(context).size.height; return Container( width: double.infinity, height: screenHeight * 0.24, decoration: const BoxDecoration( gradient: LinearGradient( colors: [ Color(0xffE6DFFF), Color(0xffCCBFFF), ], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), borderRadius: BorderRadius.only( bottomLeft: Radius.circular(40), bottomRight: Radius.circular(40), ), boxShadow: [ BoxShadow( color: Color(0xff7F56D9), blurRadius: 24, offset: Offset(0, 8), ), ], ), child: ClipRRect( borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(40), bottomRight: Radius.circular(40), ), child: Stack( children: [ // Ornamen lingkaran Positioned( top: -30, left: -20, child: Container( width: 150, height: 150, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withOpacity(0.15), ), ), ), // Garis gelombang Positioned.fill( child: CustomPaint(painter: HeaderWavePainter()), ), // Pola titik grid Positioned(top: 40, left: 24, child: _buildGridDots()), Positioned(top: 60, right: 60, child: _buildGridDots()), // Konten header Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 20), child: Row( children: [ // Tombol kembali Container( height: 44, width: 44, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(14), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.06), blurRadius: 12, offset: const Offset(0, 4), ) ], ), child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(14), onTap: () => Navigator.pop(context), child: const Icon(Icons.arrow_back_ios_new, color: Color(0xff7F56D9), size: 18), ), ), ), const SizedBox(width: 16), Image.asset( 'lib/assets/sekolah.png', width: 50, height: 50, fit: BoxFit.contain, errorBuilder: (_, __, ___) => const Icon(Icons.school, size: 40, color: Color(0xff7F56D9)), ), const SizedBox(width: 12), const Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Data Siswa", style: TextStyle( color: Color(0xff12175E), fontSize: 22, fontWeight: FontWeight.bold, letterSpacing: -0.5, ), ), SizedBox(height: 4), Text( "Daftar seluruh siswa terdaftar", style: TextStyle( color: Color(0xff12175E), fontSize: 14, fontWeight: FontWeight.w500, height: 0.7, ), ), ], ), ), Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white.withOpacity(0.4), borderRadius: BorderRadius.circular(14), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.04), blurRadius: 8, offset: const Offset(0, 2), ) ], ), child: const Icon( Icons.groups_rounded, color: Color(0xff0284C7), size: 26, ), ), ], ), ), ], ), ), ); } Widget _buildGridDots() { return Opacity( opacity: 0.25, child: Column( children: List.generate(4, (index) => Row( children: List.generate(4, (index) => Container( width: 2.5, height: 2.5, margin: const EdgeInsets.all(2.5), decoration: const BoxDecoration(color: Color(0xff12175E), shape: BoxShape.circle), )), )), ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xffF6F5FB), body: SafeArea( child: Column( children: [ header(context), const SizedBox(height: 20), // Judul bagian Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Row( children: [ Container(width: 24, height: 3, decoration: BoxDecoration(color: const Color(0xff0284C7), borderRadius: BorderRadius.circular(1.5))), const SizedBox(width: 3), Container(width: 3, height: 3, decoration: const BoxDecoration(color: Color(0xff0284C7), shape: BoxShape.circle)), const SizedBox(width: 8), const Text( "DAFTAR SISWA", style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Color(0xff12175E), letterSpacing: 0.5, ), ), ], ), ), const SizedBox(height: 16), Expanded( child: StreamBuilder( stream: FirebaseFirestore.instance.collection('siswa').snapshots(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center( child: CircularProgressIndicator(color: Color(0xff7F56D9)), ); } if (!snapshot.hasData || snapshot.data!.docs.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.person_off_rounded, size: 60, color: const Color(0xff12175E).withOpacity(0.3), ), const SizedBox(height: 16), Text( "Belum ada data siswa", style: TextStyle( fontSize: 16, color: const Color(0xff12175E).withOpacity(0.5), fontWeight: FontWeight.w500, ), ), ], ), ); } final data = snapshot.data!.docs; return ListView.builder( physics: const BouncingScrollPhysics(), padding: const EdgeInsets.only(bottom: 20), itemCount: data.length, itemBuilder: (context, i) { final s = data[i]; final sMap = (s.data() as Map?) ?? {}; final nama = (sMap['nama'] as String?) ?? "Nama Tidak Ada"; final kelas = (sMap['kelas'] as String?) ?? "-"; final namaOrtu = (sMap['nama_orang_tua'] as String?) ?? "-"; final nomorAbsen = (sMap['nomor_absen'] as String?) ?? "-"; final rfid = (sMap['rfid'] as String?) ?? "RFID Tidak Ada"; final ortuUid = sMap['ortu_uid'] as String?; if (ortuUid == null || ortuUid.isEmpty) return const SizedBox(); return siswaCard( context, s.id, nama, kelas, namaOrtu, nomorAbsen, rfid, ortuUid, ); }, ); }, ), ), ], ), ), ); } } // Reusable wave painter (same as dashboard) class HeaderWavePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = Colors.white.withOpacity(0.3) ..style = PaintingStyle.stroke ..strokeWidth = 1.8; final path = Path(); path.moveTo(0, size.height * 0.4); path.quadraticBezierTo(size.width * 0.5, size.height * 0.1, size.width, size.height * 0.3); canvas.drawPath(path, paint); final path2 = Path(); path2.moveTo(0, size.height * 0.6); path2.quadraticBezierTo(size.width * 0.6, size.height * 0.2, size.width, size.height * 0.5); canvas.drawPath(path2, paint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }