Files
LearnIT/lib/features/analytics/presentation/widgets/class_analytics_card.dart

318 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import '../../../../core/models/class_stats.dart';
import '../../../../core/theme/app_theme_extension.dart';
/// Card displaying analytics for a specific class
class ClassAnalyticsCard extends StatelessWidget {
final ClassStats classStats;
final VoidCallback onTap;
const ClassAnalyticsCard({
super.key,
required this.classStats,
required this.onTap,
});
@override
Widget build(BuildContext context) {
final cs = Theme.of(context).colorScheme;
return Container(
margin: const EdgeInsets.only(bottom: 16),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(20),
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
cs.primary.withValues(alpha: 0.9),
cs.primary.withValues(alpha: 0.7),
],
),
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: cs.shadow.withValues(alpha: 0.1),
blurRadius: 20,
offset: const Offset(0, 10),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Header
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
classStats.className,
style: const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
'${classStats.activeStudents} de ${classStats.totalStudents} alunos ativos',
style: TextStyle(
color: Colors.white.withValues(alpha: 0.8),
fontSize: 14,
),
),
],
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(16),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.trending_up, color: Colors.white, size: 16),
const SizedBox(width: 4),
Text(
'${(classStats.averageProgress * 100).toInt()}%',
style: const TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
),
const SizedBox(height: 20),
// Progress Bar
Container(
height: 8,
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.3),
borderRadius: BorderRadius.circular(4),
),
child: FractionallySizedBox(
alignment: Alignment.centerLeft,
widthFactor: classStats.averageProgress.clamp(0.0, 1.0),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
AppThemeExtras.of(context).heroProgressStart,
AppThemeExtras.of(context).heroProgressEnd,
],
),
borderRadius: BorderRadius.circular(4),
),
),
),
),
const SizedBox(height: 20),
// Stats Grid
Row(
children: [
Expanded(
child: _buildStatCard(
icon: Icons.quiz,
value: '${classStats.activeQuizzes}',
label: 'Quizzes Ativos',
context: context,
),
),
const SizedBox(width: 12),
Expanded(
child: _buildStatCard(
icon: Icons.description,
value: '${classStats.totalContent}',
label: 'Conteúdos',
context: context,
),
),
const SizedBox(width: 12),
Expanded(
child: _buildStatCard(
icon: Icons.warning,
value: '${classStats.studentsNeedingSupport.length}',
label: 'Precisam Apoio',
context: context,
isWarning: classStats.studentsNeedingSupport.isNotEmpty,
),
),
],
),
// Students needing support preview
if (classStats.studentsNeedingSupport.isNotEmpty) ...[
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.priority_high,
color: Colors.orange.withValues(alpha: 0.8),
size: 16,
),
const SizedBox(width: 6),
Text(
'Alunos que precisam de atenção:',
style: TextStyle(
color: Colors.white.withValues(alpha: 0.9),
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 8),
...classStats.studentsNeedingSupport.take(3).map((student) => Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Row(
children: [
Container(
width: 6,
height: 6,
decoration: const BoxDecoration(
color: Colors.orange,
shape: BoxShape.circle,
),
),
const SizedBox(width: 8),
Expanded(
child: Text(
student.studentName,
style: TextStyle(
color: Colors.white.withValues(alpha: 0.8),
fontSize: 11,
),
),
),
Text(
'${student.averageScore.toInt()}%',
style: TextStyle(
color: Colors.white.withValues(alpha: 0.8),
fontSize: 11,
fontWeight: FontWeight.bold,
),
),
],
),
)),
if (classStats.studentsNeedingSupport.length > 3)
Text(
'+${classStats.studentsNeedingSupport.length - 3} alunos',
style: TextStyle(
color: Colors.white.withValues(alpha: 0.6),
fontSize: 10,
),
),
],
),
),
],
// Click indicator
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Ver ranking detalhado',
style: TextStyle(
color: Colors.white.withValues(alpha: 0.8),
fontSize: 12,
),
),
const SizedBox(width: 4),
Icon(
Icons.arrow_forward,
color: Colors.white.withValues(alpha: 0.8),
size: 12,
),
],
),
],
),
),
),
),
).animate().scale(duration: 600.ms, curve: Curves.elasticOut);
}
Widget _buildStatCard({
required IconData icon,
required String value,
required String label,
required BuildContext context,
bool isWarning = false,
}) {
final cs = Theme.of(context).colorScheme;
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: Colors.white.withValues(alpha: 0.3),
width: 1,
),
),
child: Column(
children: [
Icon(
icon,
color: isWarning ? Colors.orange : Colors.white,
size: 20,
),
const SizedBox(height: 6),
Text(
value,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 2),
Text(
label,
style: TextStyle(
color: Colors.white.withValues(alpha: 0.8),
fontSize: 10,
),
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
);
}
}