import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import '../../../../core/theme/app_theme_extension.dart'; import 'package:flutter_animate/flutter_animate.dart'; import '../../../../core/services/auth_service.dart'; import '../../../../core/services/gamification_service.dart'; import '../../../../core/models/class_stats.dart'; /// Analytics preview section for teacher dashboard class TeacherAnalyticsPreviewWidget extends StatefulWidget { const TeacherAnalyticsPreviewWidget({super.key}); @override State createState() => _TeacherAnalyticsPreviewWidgetState(); } class _TeacherAnalyticsPreviewWidgetState extends State { List _classStats = []; List _topStudents = []; bool _loading = true; @override void initState() { super.initState(); _loadAnalyticsData(); } Future _loadAnalyticsData() async { try { final user = AuthService.currentUser; if (user == null) return; // Obter turmas do professor final classesSnapshot = await FirebaseFirestore.instance .collection('classes') .where('teacherId', isEqualTo: user.uid) .get(); final classStatsList = []; for (final classDoc in classesSnapshot.docs) { final classId = classDoc.id; final stats = await GamificationService.getClassStats(classId); if (stats != null) { classStatsList.add(stats); } } // Obter melhores alunos de todas as turmas final allTopStudents = []; for (final classStats in classStatsList) { final ranking = await GamificationService.getClassRanking(classStats.classId); allTopStudents.addAll(ranking.take(3)); // Top 3 de cada turma } // Ordenar por score e pegar os melhores allTopStudents.sort((a, b) => b.overallScore.compareTo(a.overallScore)); final topStudents = allTopStudents.take(4).toList(); if (mounted) { setState(() { _classStats = classStatsList; _topStudents = topStudents; _loading = false; }); } } catch (e) { print('Error loading analytics data: $e'); if (mounted) { setState(() { _loading = false; }); } } } int get totalStudents => _classStats.fold(0, (sum, stats) => sum + stats.totalStudents); int get activeStudents => _classStats.fold(0, (sum, stats) => sum + stats.activeStudents); double get averageProgress { if (_classStats.isEmpty) return 0.0; final totalProgress = _classStats.fold(0.0, (sum, stats) => sum + stats.averageProgress); return totalProgress / _classStats.length; } int get studentsNeedingSupport => _classStats.fold(0, (sum, stats) => sum + stats.studentsNeedingSupport.length); @override Widget build(BuildContext context) { if (_loading) { return const Center(child: CircularProgressIndicator()); } final user = AuthService.currentUser; final userName = user?.displayName ?? 'Professor'; final userEmail = user?.email ?? ''; return Container( margin: const EdgeInsets.only(top: 24), padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), border: Border.all( color: Theme.of(context).colorScheme.outline.withOpacity(0.2), ), boxShadow: [ BoxShadow( color: Theme.of(context).colorScheme.shadow.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Profile Header Row( children: [ Container( width: 48, height: 48, decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppThemeExtras.of(context).actionCardGradientStart, AppThemeExtras.of(context).actionCardGradientEnd, ], ), borderRadius: BorderRadius.circular(24), ), child: const Icon( Icons.school, color: Colors.white, size: 24, ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( userName, style: TextStyle( color: Theme.of(context).colorScheme.onSurface, fontSize: 18, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 2), SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( userEmail, style: TextStyle( color: Theme.of( context, ).colorScheme.onSurfaceVariant, fontSize: 14, ), ), if (userEmail.length > 20) ...[ const SizedBox(width: 8), Icon( Icons.more_horiz, color: Theme.of( context, ).colorScheme.onSurfaceVariant, size: 16, ), ], ], ), ), ], ), ), ], ), const SizedBox(height: 20), // Quick Stats Row Row( children: [ _buildQuickStat( icon: Icons.check_circle, label: 'Alunos Ativos', value: '$activeStudents/$totalStudents', color: Theme.of(context).colorScheme.primary, ), const SizedBox(width: 12), _buildQuickStat( icon: Icons.warning_amber, label: 'Precisam Apoio', value: '$studentsNeedingSupport', color: Theme.of(context).colorScheme.secondary, ), const SizedBox(width: 12), _buildQuickStat( icon: Icons.emoji_events, label: 'Média Turma', value: '${(averageProgress * 100).toInt()}%', color: Theme.of( context, ).colorScheme.primary.withValues(alpha: 0.8), ), ], ), const SizedBox(height: 20), // Top Performing Students Preview Row( children: [ Icon( Icons.leaderboard, color: Theme.of(context).colorScheme.secondary, size: 20, ), const SizedBox(width: 8), Text( 'Melhores Desempenhos', style: TextStyle( color: Theme.of(context).colorScheme.onSurface, fontSize: 16, fontWeight: FontWeight.bold, ), ), ], ), const SizedBox(height: 12), // Student List Preview ..._topStudents.map((student) { return Padding( padding: const EdgeInsets.only(bottom: 8), child: _buildStudentPerformanceItem( context, student.studentName, student.overallScore.toInt(), _getScoreColor(student.overallScore), ), ); }), const SizedBox(height: 20), // Content Quality Alert Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(12), border: Border.all( color: Theme.of( context, ).colorScheme.outline.withOpacity(0.2), ), ), child: Row( children: [ Icon( Icons.info_outline, color: Theme.of(context).colorScheme.primary, size: 20, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Qualidade do Conteúdo', style: TextStyle( color: Theme.of(context).colorScheme.onSurface, fontSize: 14, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 2), Text( '${_classStats.fold(0, (sum, stats) => sum + stats.totalContent)} conteúdos • $studentsNeedingSupport alunos precisam de apoio', style: TextStyle( color: Theme.of( context, ).colorScheme.onSurfaceVariant, fontSize: 12, ), ), ], ), ), ], ), ), ], ), ) .animate() .slideY( duration: const Duration(milliseconds: 800), curve: Curves.easeOut, ) .then(delay: const Duration(milliseconds: 400)); } Widget _buildQuickStat({ required IconData icon, required String label, required String value, required Color color, }) { return Expanded( child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: color.withOpacity(0.3), width: 1), ), child: Column( children: [ Icon(icon, color: color, size: 20), const SizedBox(height: 6), Text( value, style: TextStyle( color: color, fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 2), Text( label, style: TextStyle(color: color.withOpacity(0.8), fontSize: 10), textAlign: TextAlign.center, maxLines: 3, ), ], ), ), ); } Widget _buildStudentPerformanceItem( BuildContext context, String name, int score, Color color, ) { return Row( children: [ Container( width: 32, height: 32, decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(16), ), child: Center( child: Text( name.split(' ').map((n) => n[0]).take(2).join(), style: TextStyle( color: color, fontSize: 12, fontWeight: FontWeight.bold, ), ), ), ), const SizedBox(width: 12), Expanded( child: Text( name, style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 14, ), ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Text( '$score%', style: TextStyle( color: color, fontSize: 12, fontWeight: FontWeight.bold, ), ), ), ], ); } Color _getScoreColor(double score) { if (score >= 80) return Theme.of(context).colorScheme.tertiary; if (score >= 60) return Theme.of(context).colorScheme.primary; if (score >= 40) return Theme.of(context).colorScheme.secondary; return Theme.of(context).colorScheme.error; } }