import 'package:flutter/material.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_functions/cloud_functions.dart'; import 'login_page.dart'; import 'tambah_user.dart'; import 'tambah_siswa.dart'; class DashboardAdmin extends StatelessWidget { const DashboardAdmin({super.key}); Future logout(BuildContext context) async { await FirebaseAuth.instance.signOut(); if (!context.mounted) return; Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (_) => const LoginPage()), (route) => false, ); } Future hapusUser(String uid) async { await FirebaseFunctions.instance .httpsCallable('deleteUserAndSiswa') .call({'uid': uid}); } void showHapusDialog(BuildContext context, String role) { showDialog( context: context, builder: (_) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), title: Text( 'Hapus Akun ${role.toUpperCase()}', style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 18, color: Color(0xff12175E), ), ), content: Container( width: MediaQuery.of(context).size.width * 0.85, constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.55, ), child: StreamBuilder( stream: FirebaseFirestore.instance .collection('users') .where('role', isEqualTo: role) .snapshots(), builder: (context, snapshot) { if (!snapshot.hasData) { return const Center( child: CircularProgressIndicator(color: Color(0xff7F56D9)), ); } final data = snapshot.data!.docs; if (data.isEmpty) { return const Center( child: Text( 'Tidak ada akun', style: TextStyle(color: Color(0xff12175E), fontSize: 15), ), ); } return ListView.builder( shrinkWrap: true, itemCount: data.length, itemBuilder: (context, index) { final user = data[index].data() as Map; return Container( margin: const EdgeInsets.symmetric(vertical: 6), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: const Color(0xffF6F5FB), borderRadius: BorderRadius.circular(14), ), child: Row( children: [ CircleAvatar( backgroundColor: const Color(0xff7F56D9).withOpacity(0.12), child: const Icon(Icons.person, color: Color(0xff7F56D9)), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( user['nama'] ?? '-', maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( fontWeight: FontWeight.w600, color: Color(0xff12175E), ), ), const SizedBox(height: 2), Text( user['email'] ?? '-', maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 13, color: const Color(0xff12175E).withOpacity(0.6), ), ), ], ), ), IconButton( icon: const Icon(Icons.delete_outline, color: Color(0xffDC2626)), onPressed: () async { await hapusUser(data[index].id); if (!context.mounted) return; Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Akun berhasil dihapus'), behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))), ), ); }, ), ], ), ); }, ); }, ), ), ), ); } Widget menuCard({ required String title, required String subtitle, required IconData icon, required Color startColor, required Color iconBg, required Color btnColor, required VoidCallback onTap, }) { return GestureDetector( onTap: onTap, child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.04), blurRadius: 16, spreadRadius: 1, offset: const Offset(0, 6), ), ], ), child: Stack( children: [ Positioned( top: 0, left: 0, child: CustomPaint( size: const Size(85, 85), painter: CornerCurvePainter(color: startColor), ), ), Positioned( top: 20, right: 20, child: Column( children: List.generate(3, (_) => Row( children: List.generate(3, (_) => Container( width: 3.5, height: 3.5, margin: const EdgeInsets.all(2), decoration: BoxDecoration( color: startColor.withOpacity(0.25), shape: BoxShape.circle, ), )), )), ), ), Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 54, height: 54, decoration: BoxDecoration( color: iconBg, shape: BoxShape.circle, ), child: Icon(icon, size: 26, color: startColor), ), const SizedBox(height: 16), Text( title, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xff12175E), height: 1.2, ), ), const SizedBox(height: 6), Expanded( child: Text( subtitle, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 12, color: const Color(0xff12175E).withOpacity(0.6), height: 1.4, ), ), ), Align( alignment: Alignment.bottomRight, child: Container( width: 36, height: 36, decoration: BoxDecoration( color: btnColor, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: btnColor.withOpacity(0.2), blurRadius: 6, offset: const Offset(0, 2), ), ], ), child: const Icon( Icons.arrow_forward, color: Colors.white, size: 18, ), ), ), ], ), ), ], ), ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xffF8F5FF), body: SingleChildScrollView( physics: const BouncingScrollPhysics(), child: Column( children: [ // ✅ HEADER DENGAN WARNA GRADASI SEPERTI HALAMAN HOME Container( width: double.infinity, decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xffEDE9FF), // Ungu sangat muda Color(0xffDCD4FF), // Ungu lembut Color(0xffCBBEFF), // Ungu sedikit lebih tua ], ), borderRadius: BorderRadius.only( bottomLeft: Radius.circular(36), bottomRight: Radius.circular(36), ), ), child: SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 28), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Baris Logo & Tombol Logout Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Image.asset( 'lib/assets/sekolah.png', width: 56, height: 56, fit: BoxFit.contain, errorBuilder: (_, __, ___) => const Icon( Icons.school, size: 52, color: Color(0xff7F56D9), ), ), const SizedBox(width: 12), const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "TK PGRI", style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Color(0xff12175E), height: 1.1, ), ), Text( "BHAKTI LESTARI", style: TextStyle( fontSize: 15, fontWeight: FontWeight.w500, color: Color(0xff12175E), height: 1.1, ), ), ], ), ], ), ElevatedButton.icon( onPressed: () => logout(context), icon: const Icon(Icons.logout_rounded, size: 16), label: const Text("Logout", style: TextStyle(fontSize: 14)), style: ElevatedButton.styleFrom( backgroundColor: Colors.white, foregroundColor: const Color(0xff7F56D9), elevation: 1, shadowColor: Colors.black.withOpacity(0.08), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), minimumSize: const Size(0, 40), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), ), ], ), const SizedBox(height: 32), // Teks Sambutan const Text( "Selamat Datang 👋", style: TextStyle( fontSize: 16, color: Color(0xff4B39EF), fontWeight: FontWeight.w500, ), ), const SizedBox(height: 8), const Text( "Dashboard Admin", style: TextStyle( fontSize: 32, fontWeight: FontWeight.bold, color: Color(0xff12175E), height: 1.1, ), ), const SizedBox(height: 14), Container( width: 60, height: 4, decoration: BoxDecoration( color: const Color(0xff7F56D9), borderRadius: BorderRadius.circular(2), ), ), const SizedBox(height: 20), const Text( "Kelola akun guru dan orang tua\ndengan mudah, cepat, dan aman.", style: TextStyle( fontSize: 16, color: Color(0xff6B7280), height: 1.5, ), ), ], ), ), ), ), // ✅ BAGIAN MENU Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 28), child: GridView.count( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), crossAxisCount: 2, crossAxisSpacing: 18, mainAxisSpacing: 18, childAspectRatio: 0.82, children: [ menuCard( title: "Tambah Guru", subtitle: "Tambahkan akun guru baru ke dalam sistem.", icon: Icons.person_add_rounded, startColor: const Color(0xff7F56D9), iconBg: const Color(0xffF0EBFF), btnColor: const Color(0xff7F56D9), onTap: () => Navigator.push( context, MaterialPageRoute(builder: (_) => const TambahUser(role: 'guru')), ), ), menuCard( title: "Hapus Akun Guru", subtitle: "Manajemen atau hapus akun guru dari sistem.", icon: Icons.person_remove_rounded, startColor: const Color(0xffF472B6), iconBg: const Color(0xffFEEFF8), btnColor: const Color(0xffF472B6), onTap: () => showHapusDialog(context, 'guru'), ), menuCard( title: "Tambah Orang Tua", subtitle: "Tambahkan akun orang tua baru ke dalam sistem.", icon: Icons.family_restroom_rounded, startColor: const Color(0xff3B82F6), iconBg: const Color(0xffEFF6FF), btnColor: const Color(0xff3B82F6), onTap: () => Navigator.push( context, MaterialPageRoute(builder: (_) => const TambahSiswa()), ), ), menuCard( title: "Hapus Akun Orang Tua", subtitle: "Manajemen atau hapus akun orang tua dari sistem.", icon: Icons.delete_rounded, startColor: const Color(0xffF97316), iconBg: const Color(0xffFFF7ED), btnColor: const Color(0xffF97316), onTap: () => showHapusDialog(context, 'ortu'), ), ], ), ), ], ), ), ); } } class CornerCurvePainter extends CustomPainter { final Color color; CornerCurvePainter({required this.color}); @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = color.withOpacity(0.15) ..style = PaintingStyle.fill; final path = Path(); path.moveTo(0, 0); path.lineTo(size.width, 0); path.quadraticBezierTo(size.width * 0.6, size.height * 0.45, size.width * 0.5, size.height); path.lineTo(0, size.height); path.close(); canvas.drawPath(path, paint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }