// ignore_for_file: must_be_immutable import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:ui/routes/app_routes.dart'; import 'package:ui/views/siswa/controllers/siswa_controller.dart'; class ProfileSiswa extends StatelessWidget { ProfileSiswa({super.key}); SiswaController siswaC = Get.find(); @override Widget build(BuildContext context) { siswaC.getAnalysis(); final size = MediaQuery.of(context).size; final isTablet = size.width > 600; return Scaffold( backgroundColor: const Color(0xFFF8FAFC), appBar: AppBar( title: const Text( 'Profil Siswa', style: TextStyle( fontWeight: FontWeight.w700, fontSize: 20, color: Colors.white, fontFamily: 'Poppins', ), ), centerTitle: true, elevation: 0, backgroundColor: Colors.transparent, flexibleSpace: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFF667EEA), Color(0xFF764BA2), ], ), ), ), leading: IconButton( icon: const Icon(Icons.arrow_back_ios, color: Colors.white), onPressed: () => Get.back(), ), ), body: RefreshIndicator( onRefresh: () async { await siswaC.getAnalysis(); }, child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), child: Column( children: [ // Header profil dengan gradient _buildProfileHeader(isTablet), // Konten utama Padding( padding: EdgeInsets.symmetric( horizontal: isTablet ? size.width * 0.1 : 20, vertical: 20), child: Column( children: [ // Card untuk konten analisis _buildAnalysisCard(context, isTablet), SizedBox(height: isTablet ? 32 : 24), // Tombol-tombol aksi _buildActionButtons(context, isTablet), ], ), ), ], ), ), ), ); } Widget _buildProfileHeader(bool isTablet) { return Container( padding: EdgeInsets.symmetric( vertical: isTablet ? 40 : 30, horizontal: isTablet ? 40 : 20), decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFF667EEA), Color(0xFF764BA2), ], ), borderRadius: BorderRadius.only( bottomLeft: Radius.circular(30), bottomRight: Radius.circular(30), ), boxShadow: [ BoxShadow( color: Color(0xFF667EEA), blurRadius: 20, offset: Offset(0, 10), ), ], ), child: Obx( () => Column( children: [ // Avatar dengan animasi Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: Colors.white, width: 3, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 15, offset: const Offset(0, 8), ), ], ), child: CircleAvatar( radius: isTablet ? 70 : 60, backgroundColor: Colors.white, child: Icon( Icons.person, size: isTablet ? 70 : 60, color: const Color(0xFF667EEA), ), ), ), const SizedBox(height: 20), Text( siswaC.dataUser['user']['nama'], style: TextStyle( fontSize: isTablet ? 28 : 24, fontWeight: FontWeight.w700, color: Colors.white, fontFamily: 'Poppins', ), textAlign: TextAlign.center, ), const SizedBox(height: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(20), border: Border.all( color: Colors.white.withOpacity(0.3), width: 1, ), ), child: Text( 'Kelas ${siswaC.dataUser['user']['kelas']}', style: TextStyle( fontSize: isTablet ? 18 : 16, color: Colors.white, fontWeight: FontWeight.w600, fontFamily: 'Poppins', ), ), ), const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(10), ), child: const Icon( Icons.email_outlined, color: Colors.white, size: 18, ), ), const SizedBox(width: 12), Text( siswaC.dataUser['user']['user']['email'].toString(), style: TextStyle( fontSize: isTablet ? 16 : 14, color: Colors.white, fontWeight: FontWeight.w500, fontFamily: 'Poppins', ), ), ], ), ], ), ), ); } Widget _buildAnalysisCard(BuildContext context, bool isTablet) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.1), blurRadius: 20, offset: const Offset(0, 10), ), ], ), child: Padding( padding: EdgeInsets.all(isTablet ? 24 : 20), child: Obx( () { if (siswaC.isLoadingAnalysis.value) { return Container( height: 200, alignment: Alignment.center, child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.1), blurRadius: 20, offset: const Offset(0, 10), ), ], ), child: const CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( Color(0xFF6366F1), ), strokeWidth: 3, ), ), const SizedBox(height: 20), const Text( 'Memuat data analisis...', style: TextStyle( color: Colors.grey, fontSize: 16, fontFamily: 'Poppins', ), ) ], ), ); } var kelebihan = siswaC.dataAnalysis['kelebihan']; var kekurangan = siswaC.dataAnalysis['kekurangan']; return Column( children: [ if (siswaC.kelebihanIsEmpty.value) const SizedBox() else Column(children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: const Color(0xFF10B981).withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: const Icon( Icons.quiz, color: Color(0xFF10B981), size: 24, ), ), const SizedBox(width: 12), const Text( 'Rata rata Kuis', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: Colors.black87, fontFamily: 'Poppins', ), ), ], ), const SizedBox(height: 16), ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: siswaC.dataAnalysis['kelebihan'].length, itemBuilder: (context, index) { return AnimatedProgressItem( title: kelebihan[index]['mapel'], percentage: kelebihan[index]['persentase'], color: const Color(0xFF10B981), isTablet: isTablet, animationDelay: (index * 200), ); }, ), ]), if (siswaC.kekuranganIsEmpty.value) const SizedBox() else Column(children: [ const SizedBox(height: 24), Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: const Color(0xFFEF4444).withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: const Icon( Icons.trending_down, color: Color(0xFFEF4444), size: 24, ), ), const SizedBox(width: 12), const Text( 'Perlu Perbaikan', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: Colors.black87, fontFamily: 'Poppins', ), ), ], ), const SizedBox(height: 16), ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: siswaC.dataAnalysis['kekurangan'].length, itemBuilder: (context, index) { return AnimatedProgressItem( title: kekurangan[index]['mapel'], percentage: kekurangan[index]['persentase'], color: const Color(0xFFEF4444), isTablet: isTablet, animationDelay: (index * 200) + 500, ); }, ), ]), if (siswaC.kelebihanIsEmpty.value && siswaC.kekuranganIsEmpty.value) Container( padding: const EdgeInsets.all(40), child: Column( children: [ Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: const Color(0xFF6366F1).withOpacity(0.1), borderRadius: BorderRadius.circular(20), ), child: const Icon( Icons.analytics_outlined, size: 60, color: Color(0xFF6366F1), ), ), const SizedBox(height: 20), const Text( 'Belum ada data analisis', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: Colors.grey, fontFamily: 'Poppins', ), ), const SizedBox(height: 8), const Text( 'Data akan muncul setelah mengerjakan kuis', style: TextStyle( fontSize: 14, color: Colors.grey, fontFamily: 'Poppins', ), textAlign: TextAlign.center, ), ], ), ), ], ); }, ), ), ); } Widget _buildActionButtons(BuildContext context, bool isTablet) { return Column( children: [ // Tombol Ubah Password GestureDetector( onTap: () { Get.toNamed(AppRoutes.ubahPassord); }, child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 18), decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFF6366F1), Color(0xFF8B5CF6)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: const Color(0xFF6366F1).withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 10), ), ], ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(10), ), child: const Icon( Icons.lock_reset, color: Colors.white, size: 20, ), ), const SizedBox(width: 12), Text( 'Ubah Password', style: TextStyle( fontSize: isTablet ? 18 : 16, fontWeight: FontWeight.w600, color: Colors.white, fontFamily: 'Poppins', ), ), ], ), ), ), SizedBox(height: isTablet ? 20 : 16), // Tombol Logout GestureDetector( onTap: () { showDialog( context: context, builder: (ctx) => AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), ), title: const Text( 'Konfirmasi Logout', style: TextStyle( fontWeight: FontWeight.w600, fontFamily: 'Poppins', ), ), content: const Text( 'Apakah Anda yakin ingin logout?', style: TextStyle( fontFamily: 'Poppins', ), ), actions: [ TextButton( onPressed: () { Navigator.of(ctx).pop(); }, child: const Text( 'Batal', style: TextStyle( color: Colors.grey, fontFamily: 'Poppins', ), ), ), ElevatedButton( onPressed: () { siswaC.logout(role: "siswa"); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFEF4444), foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15), ), ), child: const Text( 'Logout', style: TextStyle( fontFamily: 'Poppins', ), ), ), ], ), ); }, child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 18), decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFFEF4444), Color(0xFFDC2626)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: const Color(0xFFEF4444).withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 10), ), ], ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(10), ), child: const Icon( Icons.logout, color: Colors.white, size: 20, ), ), const SizedBox(width: 12), Text( 'Logout', style: TextStyle( fontSize: isTablet ? 18 : 16, fontWeight: FontWeight.w600, color: Colors.white, fontFamily: 'Poppins', ), ), ], ), ), ), ], ); } } // Widget untuk progress item dengan animasi class AnimatedProgressItem extends StatefulWidget { final String title; final int percentage; final Color color; final bool isTablet; final int animationDelay; const AnimatedProgressItem({ super.key, required this.title, required this.percentage, required this.color, required this.isTablet, this.animationDelay = 0, }); @override State createState() => _AnimatedProgressItemState(); } class _AnimatedProgressItemState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 1000), vsync: this, ); _animation = Tween(begin: 0, end: widget.percentage / 100) .animate(CurvedAnimation( parent: _controller, curve: Curves.easeOutQuart, )); // Tunda animasi sesuai dengan delay yang diberikan Future.delayed(Duration(milliseconds: widget.animationDelay), () { if (mounted) { _controller.forward(); } }); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final textStyle = TextStyle( fontSize: widget.isTablet ? 16 : 14, fontWeight: FontWeight.w500, color: Colors.black87, fontFamily: 'Poppins', ); return Container( margin: const EdgeInsets.only(bottom: 16), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.grey.shade50, borderRadius: BorderRadius.circular(15), border: Border.all( color: widget.color.withOpacity(0.1), width: 1, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( widget.title, style: textStyle.copyWith( fontWeight: FontWeight.w600, ), ), ), AnimatedBuilder( animation: _animation, builder: (context, child) { return Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6, ), decoration: BoxDecoration( color: widget.color.withOpacity(0.1), borderRadius: BorderRadius.circular(20), ), child: Text( '${(_animation.value * 100).toInt()}%', style: textStyle.copyWith( color: widget.color, fontWeight: FontWeight.w700, fontSize: 12, ), ), ); }, ), ], ), const SizedBox(height: 12), AnimatedBuilder( animation: _animation, builder: (context, child) { return ClipRRect( borderRadius: BorderRadius.circular(10), child: LinearProgressIndicator( value: _animation.value, backgroundColor: widget.color.withOpacity(0.1), color: widget.color, minHeight: widget.isTablet ? 12 : 10, ), ); }, ), ], ), ); } }