placeholders removidos e todos os dados reais colocados, com conquistas e tudo

This commit is contained in:
2026-05-17 17:29:47 +01:00
parent 6ba5c837ce
commit 49a7a6fe02
17 changed files with 4688 additions and 142 deletions

View File

@@ -3,13 +3,75 @@ import 'package:flutter/material.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/user_stats.dart';
import '../../../../core/models/achievement.dart';
/// Profile section with user info and achievements
class ProfileSectionWidget extends StatelessWidget {
class ProfileSectionWidget extends StatefulWidget {
const ProfileSectionWidget({super.key});
@override
State<ProfileSectionWidget> createState() => _ProfileSectionWidgetState();
}
class _ProfileSectionWidgetState extends State<ProfileSectionWidget> {
UserStats? _userStats;
List<Achievement> _recentAchievements = [];
bool _loading = true;
@override
void initState() {
super.initState();
_loadUserData();
}
Future<void> _loadUserData() async {
try {
final user = AuthService.currentUser;
if (user != null) {
final results = await Future.wait([
GamificationService.getUserStats(user.uid),
GamificationService.getAvailableAchievements(),
]);
final stats = results[0] as UserStats?;
final achievements = results[1] as List<Achievement>;
// Obter conquistas desbloqueadas recentemente
final unlockedAchievementIds = stats?.unlockedAchievements
.map((ua) => ua.achievementId)
.toSet() ?? {};
final recentUnlocked = achievements
.where((a) => unlockedAchievementIds.contains(a.id))
.take(4)
.toList();
if (mounted) {
setState(() {
_userStats = stats;
_recentAchievements = recentUnlocked;
_loading = false;
});
}
}
} catch (e) {
print('Error loading user data: $e');
if (mounted) {
setState(() {
_loading = false;
});
}
}
}
@override
Widget build(BuildContext context) {
if (_loading) {
return const Center(child: CircularProgressIndicator());
}
final user = AuthService.currentUser;
final userName = user?.displayName ?? 'Estudante';
final userEmail = user?.email ?? '';
@@ -124,36 +186,55 @@ class ProfileSectionWidget extends StatelessWidget {
),
const SizedBox(height: 12),
// Achievement Badges
Row(
children: [
_buildAchievementBadge(
icon: Icons.local_fire_department,
label: '7 dias',
color: Theme.of(context).colorScheme.secondary,
),
const SizedBox(width: 12),
_buildAchievementBadge(
icon: Icons.school,
label: '3 conceitos',
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(width: 12),
_buildAchievementBadge(
icon: Icons.speed,
label: 'Rápido',
color: Theme.of(
// Achievement List (Teacher-style design)
if (_recentAchievements.isNotEmpty) ...[
..._recentAchievements.map((achievement) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: _buildAchievementItem(
context,
).colorScheme.primary.withOpacity(0.8),
achievement.name,
achievement.points,
_getRarityColor(achievement.rarity),
_getIconData(achievement.icon),
),
);
}),
] else ...[
// Streak item
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: _buildAchievementItem(
context,
'${_userStats?.currentStreak ?? 0} dias seguidos',
(_userStats?.currentStreak ?? 0) * 5,
Theme.of(context).colorScheme.secondary,
Icons.local_fire_department,
),
const SizedBox(width: 12),
_buildAchievementBadge(
icon: Icons.star,
label: '100%',
color: Theme.of(context).colorScheme.tertiary,
),
// Concepts item
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: _buildAchievementItem(
context,
'${_userStats?.masteredConcepts.length ?? 0} conceitos dominados',
(_userStats?.masteredConcepts.length ?? 0) * 10,
Theme.of(context).colorScheme.primary,
Icons.school,
),
],
),
),
if (_userStats != null && _userStats!.totalStudyTime > 0)
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: _buildAchievementItem(
context,
'${(_userStats!.totalStudyTime / 60).toStringAsFixed(1)}h estudadas',
(_userStats!.totalStudyTime ~/ 60) * 3,
Theme.of(context).colorScheme.tertiary,
Icons.schedule,
),
),
],
const SizedBox(height: 20),
// Recent Activity Summary
@@ -183,7 +264,7 @@ class ProfileSectionWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Ótimo progresso!',
_getProgressMessage(),
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontSize: 14,
@@ -192,7 +273,7 @@ class ProfileSectionWidget extends StatelessWidget {
),
const SizedBox(height: 2),
Text(
'Você está 15% acima da média esta semana',
_getProgressComparison(),
style: TextStyle(
color: Theme.of(
context,
@@ -217,32 +298,103 @@ class ProfileSectionWidget extends StatelessWidget {
.then(delay: const Duration(milliseconds: 400));
}
Widget _buildAchievementBadge({
required IconData icon,
required String label,
required Color color,
}) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
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: 16),
const SizedBox(height: 4),
Text(
label,
Widget _buildAchievementItem(
BuildContext context,
String name,
int points,
Color color,
IconData icon,
) {
return Row(
children: [
Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: color.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(16),
),
child: Center(
child: Icon(icon, color: color, size: 16),
),
),
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.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
),
child: Text(
'$points pts',
style: TextStyle(
color: color,
fontSize: 10,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
);
}
IconData _getIconData(String iconName) {
switch (iconName) {
case 'emoji_events': return Icons.emoji_events;
case 'school': return Icons.school;
case 'local_fire_department': return Icons.local_fire_department;
case 'schedule': return Icons.schedule;
case 'trending_up': return Icons.trending_up;
case 'military_tech': return Icons.military_tech;
case 'workspace_premium': return Icons.workspace_premium;
case 'psychology': return Icons.psychology;
case 'lightbulb': return Icons.lightbulb;
case 'star': return Icons.star;
case 'speed': return Icons.speed;
default: return Icons.star;
}
}
Color _getRarityColor(String rarity) {
switch (rarity) {
case 'common': return Colors.grey;
case 'rare': return Colors.blue;
case 'epic': return Colors.purple;
case 'legendary': return Colors.orange;
default: return Colors.grey;
}
}
String _getProgressMessage() {
if (_userStats == null) return 'Continue estudando!';
final streak = _userStats!.currentStreak;
final studyTime = _userStats!.totalStudyTime;
if (streak >= 7) return 'Incrível streak! 🔥';
if (studyTime >= 300) return 'Dedicação exemplar! 📚';
if (streak >= 3) return 'Bom progresso! 📈';
return 'Continue estudando! 💪';
}
String _getProgressComparison() {
if (_userStats == null) return 'Comece sua jornada de estudos';
final weeklyTime = _userStats!.weeklyStudyTime;
final concepts = _userStats!.masteredConcepts.length;
if (weeklyTime >= 180) return 'Você está 15% acima da média esta semana';
if (concepts >= 3) return 'Domine $concepts conceitos esta semana';
if (weeklyTime >= 60) return 'Bom tempo de estudo esta semana';
return 'Continue assim para subir no ranking!';
}
}

View File

@@ -2,30 +2,81 @@ import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../../../../core/services/gamification_service.dart';
import '../../../../core/models/user_stats.dart';
import '../../../../core/services/auth_service.dart';
/// Progress tracking hero section for student dashboard
class ProgressHeroWidget extends StatelessWidget {
class ProgressHeroWidget extends StatefulWidget {
final String userName;
final double overallProgress;
final List<String> masteredConcepts;
final int studyTimeMinutes;
final int streakDays;
const ProgressHeroWidget({
super.key,
required this.userName,
this.overallProgress = 0.65,
this.masteredConcepts = const [
'Fundamentos de Programação',
'Algoritmos Básicos',
'Estruturas de Dados',
],
this.studyTimeMinutes = 245,
this.streakDays = 7,
});
@override
State<ProgressHeroWidget> createState() => _ProgressHeroWidgetState();
}
class _ProgressHeroWidgetState extends State<ProgressHeroWidget> {
@override
Widget build(BuildContext context) {
return FutureBuilder<UserStats?>(
future: _loadUserStats(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return _buildLoadingState();
}
if (snapshot.hasError) {
return _buildErrorState();
}
final userStats = snapshot.data;
return _buildContent(userStats);
},
);
}
Future<UserStats?> _loadUserStats() async {
try {
final user = AuthService.currentUser;
if (user != null) {
return await GamificationService.getUserStats(user.uid);
}
return null;
} catch (e) {
print('Error loading user stats: $e');
return null;
}
}
double _calculateOverallProgress(UserStats? userStats) {
if (userStats == null || userStats.masteredConcepts.isEmpty) {
return 0.0;
}
final totalMastery = userStats.masteredConcepts
.map((c) => c.masteryLevel)
.reduce((a, b) => a + b);
return totalMastery / (userStats.masteredConcepts.length * 100);
}
Widget _buildLoadingState() {
return const Center(child: CircularProgressIndicator());
}
Widget _buildErrorState() {
return const Center(child: Text('Erro ao carregar dados'));
}
Widget _buildContent(UserStats? userStats) {
final streakDays = userStats?.currentStreak ?? 0;
final overallProgress = _calculateOverallProgress(userStats);
final masteredConcepts = userStats?.masteredConcepts.map((c) => c.conceptName).toList() ?? [];
final studyTimeMinutes = userStats?.totalStudyTime ?? 0;
return Container(
margin: const EdgeInsets.only(bottom: 24),
child: Column(
@@ -48,7 +99,7 @@ class ProgressHeroWidget extends StatelessWidget {
),
const SizedBox(height: 4),
Text(
'Continue assim, $userName!',
'Continue assim, ${widget.userName}!',
style: TextStyle(
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 16,

View File

@@ -22,23 +22,34 @@ class QuickAccessWidget extends StatelessWidget {
),
),
const SizedBox(height: 16),
IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
flex: 3,
child: _buildTutorIACard(context),
Column(
children: [
IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
flex: 2,
child: _buildTutorIACard(context),
),
const SizedBox(width: 16),
Expanded(
flex: 2,
child: _buildQuizCard(context),
),
const SizedBox(width: 16),
Expanded(
flex: 2,
child: _buildAchievementsCard(context),
),
],
),
const SizedBox(width: 16),
Expanded(
flex: 2,
child: _buildQuizCard(context),
),
],
),
),
],
),
const SizedBox(height: 16),
_buildQuizManagementCard(context),
const SizedBox(height: 16),
_buildJoinClassCard(context),
],
)
@@ -85,6 +96,42 @@ class QuickAccessWidget extends StatelessWidget {
.then(delay: const Duration(milliseconds: 200));
}
Widget _buildAchievementsCard(BuildContext context) {
final cs = Theme.of(context).colorScheme;
return DashboardActionCardSurface(
title: 'Conquistas',
subtitle: 'Ver medals',
icon: Icons.emoji_events,
minHeight: 150,
iconColor: Colors.amber,
onTap: () => context.go('/student/achievements'),
)
.animate()
.scale(
duration: const Duration(milliseconds: 600),
curve: Curves.elasticOut,
)
.then(delay: const Duration(milliseconds: 200));
}
Widget _buildQuizManagementCard(BuildContext context) {
final cs = Theme.of(context).colorScheme;
return DashboardActionCardSurface(
title: 'Gerenciar Quizzes',
subtitle: 'Ver histórico ou eliminar',
icon: Icons.manage_history,
minHeight: 80,
iconColor: cs.tertiary,
onTap: () => context.go('/quiz-management'),
)
.animate()
.slideY(
duration: const Duration(milliseconds: 800),
curve: Curves.easeOut,
)
.then(delay: const Duration(milliseconds: 200));
}
Widget _buildJoinClassCard(BuildContext context) {
return DashboardActionCard(
title: 'Entrar numa Turma',

View File

@@ -1,15 +1,95 @@
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 StatelessWidget {
class TeacherAnalyticsPreviewWidget extends StatefulWidget {
const TeacherAnalyticsPreviewWidget({super.key});
@override
State<TeacherAnalyticsPreviewWidget> createState() => _TeacherAnalyticsPreviewWidgetState();
}
class _TeacherAnalyticsPreviewWidgetState extends State<TeacherAnalyticsPreviewWidget> {
List<ClassStats> _classStats = [];
List<StudentRanking> _topStudents = [];
bool _loading = true;
@override
void initState() {
super.initState();
_loadAnalyticsData();
}
Future<void> _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 = <ClassStats>[];
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 = <StudentRanking>[];
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 ?? '';
@@ -109,24 +189,24 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
_buildQuickStat(
icon: Icons.check_circle,
label: 'Alunos Ativos',
value: '18/24',
value: '$activeStudents/$totalStudents',
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(width: 12),
_buildQuickStat(
icon: Icons.warning_amber,
label: 'Precisam Apoio',
value: '3',
value: '$studentsNeedingSupport',
color: Theme.of(context).colorScheme.secondary,
),
const SizedBox(width: 12),
_buildQuickStat(
icon: Icons.emoji_events,
label: 'Média Turma',
value: '72%',
value: '${(averageProgress * 100).toInt()}%',
color: Theme.of(
context,
).colorScheme.primary.withOpacity(0.8),
).colorScheme.primary.withValues(alpha: 0.8),
),
],
),
@@ -154,33 +234,17 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
const SizedBox(height: 12),
// Student List Preview
_buildStudentPerformanceItem(
context,
'Ana Silva',
95,
Theme.of(context).colorScheme.tertiary,
),
const SizedBox(height: 8),
_buildStudentPerformanceItem(
context,
'João Costa',
88,
Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 8),
_buildStudentPerformanceItem(
context,
'Maria Santos',
82,
Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 8),
_buildStudentPerformanceItem(
context,
'Pedro Lima',
45,
Theme.of(context).colorScheme.secondary,
),
..._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),
@@ -218,7 +282,7 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
),
const SizedBox(height: 2),
Text(
'12 conteúdos verificados • 2 pendentes de revisão',
'${_classStats.fold(0, (sum, stats) => sum + stats.totalContent)} conteúdos • $studentsNeedingSupport alunos precisam de apoio',
style: TextStyle(
color: Theme.of(
context,
@@ -336,4 +400,11 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
],
);
}
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;
}
}

View File

@@ -1,27 +1,89 @@
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../../../../core/services/gamification_service.dart';
import '../../../../core/models/class_stats.dart';
import '../../../../core/services/auth_service.dart';
/// Hero section for teacher dashboard showing class overview
class TeacherHeroWidget extends StatelessWidget {
class TeacherHeroWidget extends StatefulWidget {
final String userName;
final int totalStudents;
final int activeQuizzes;
final int uploadedContent;
final double classAverageProgress;
const TeacherHeroWidget({
super.key,
required this.userName,
this.totalStudents = 24,
this.activeQuizzes = 3,
this.uploadedContent = 12,
this.classAverageProgress = 0.72,
});
@override
State<TeacherHeroWidget> createState() => _TeacherHeroWidgetState();
}
class _TeacherHeroWidgetState extends State<TeacherHeroWidget> {
List<ClassStats> _classStats = [];
bool _loading = true;
@override
void initState() {
super.initState();
_loadClassStats();
}
Future<void> _loadClassStats() 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 = <ClassStats>[];
for (final classDoc in classesSnapshot.docs) {
final classId = classDoc.id;
final stats = await GamificationService.getClassStats(classId);
if (stats != null) {
classStatsList.add(stats);
}
}
if (mounted) {
setState(() {
_classStats = classStatsList;
_loading = false;
});
}
} catch (e) {
print('Error loading class stats: $e');
if (mounted) {
setState(() {
_loading = false;
});
}
}
}
int get totalStudents => _classStats.fold(0, (sum, stats) => sum + stats.totalStudents);
int get activeQuizzes => _classStats.fold(0, (sum, stats) => sum + stats.activeQuizzes);
int get uploadedContent => _classStats.fold(0, (sum, stats) => sum + stats.totalContent);
double get classAverageProgress {
if (_classStats.isEmpty) return 0.0;
final totalProgress = _classStats.fold(0.0, (sum, stats) => sum + stats.averageProgress);
return totalProgress / _classStats.length;
}
Widget build(BuildContext context) {
if (_loading) {
return Container(
margin: const EdgeInsets.only(bottom: 24),
child: const Center(child: CircularProgressIndicator()),
);
}
return Container(
margin: const EdgeInsets.only(bottom: 24),
child: Column(
@@ -231,26 +293,7 @@ class TeacherHeroWidget extends StatelessWidget {
],
),
const SizedBox(height: 12),
_buildActivityItem(
context,
'15 alunos completaram o quiz de Derivadas',
'Hoje, 14:30',
Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 8),
_buildActivityItem(
context,
'Novo conteúdo: Regra da Cadeia',
'Ontem, 09:15',
Theme.of(context).colorScheme.secondary,
),
const SizedBox(height: 8),
_buildActivityItem(
context,
'3 alunos precisam de apoio em Limites',
'Ontem, 16:45',
Theme.of(context).colorScheme.error,
),
..._buildRecentActivities(),
],
),
)
@@ -302,6 +345,67 @@ class TeacherHeroWidget extends StatelessWidget {
);
}
List<Widget> _buildRecentActivities() {
final activities = <Widget>[];
if (_classStats.isEmpty) {
activities.add(_buildActivityItem(
context,
'Nenhuma atividade recente',
'Comece criando turmas e conteúdos',
Theme.of(context).colorScheme.onSurfaceVariant,
));
return activities;
}
// Adicionar atividades baseadas nas estatísticas das turmas
for (final stats in _classStats.take(3)) {
if (stats.activeQuizzes > 0) {
activities.add(_buildActivityItem(
context,
'${stats.activeQuizzes} quizzes ativos em ${stats.className}',
'Recente',
Theme.of(context).colorScheme.primary,
));
activities.add(const SizedBox(height: 8));
}
if (stats.studentsNeedingSupport.isNotEmpty) {
activities.add(_buildActivityItem(
context,
'${stats.studentsNeedingSupport.length} alunos precisam de apoio em ${stats.className}',
'Ver analytics',
Theme.of(context).colorScheme.error,
));
activities.add(const SizedBox(height: 8));
}
if (stats.totalContent > 0) {
activities.add(_buildActivityItem(
context,
'${stats.totalContent} conteúdos disponíveis em ${stats.className}',
'Atualizado',
Theme.of(context).colorScheme.secondary,
));
activities.add(const SizedBox(height: 8));
}
}
// Remover o último SizedBox se existir
if (activities.isNotEmpty && activities.last is SizedBox) {
activities.removeLast();
}
return activities.isEmpty ? [
_buildActivityItem(
context,
'Nenhuma atividade recente',
'Comece criando turmas e conteúdos',
Theme.of(context).colorScheme.onSurfaceVariant,
)
] : activities;
}
Widget _buildActivityItem(
BuildContext context,
String text,
@@ -333,7 +437,7 @@ class TeacherHeroWidget extends StatelessWidget {
style: TextStyle(
color: Theme.of(
context,
).colorScheme.onSurfaceVariant.withOpacity(0.7),
).colorScheme.onSurfaceVariant.withValues(alpha: 0.7),
fontSize: 12,
),
),