diff --git a/lib/features/dashboard/presentation/pages/teacher_dashboard_page.dart b/lib/features/dashboard/presentation/pages/teacher_dashboard_page.dart index f70b53a..b0c75d1 100644 --- a/lib/features/dashboard/presentation/pages/teacher_dashboard_page.dart +++ b/lib/features/dashboard/presentation/pages/teacher_dashboard_page.dart @@ -10,6 +10,14 @@ import '../widgets/teacher_classes_list_widget.dart'; class TeacherDashboardPage extends StatefulWidget { const TeacherDashboardPage({super.key}); + /// Clear the cached user name (call when name is updated in settings) + static void clearCachedUserName() { + _cachedUserName = null; + } + + /// Cached user name to prevent flickering + static String? _cachedUserName; + @override State createState() => _TeacherDashboardPageState(); } @@ -20,7 +28,12 @@ class _TeacherDashboardPageState extends State { @override void initState() { super.initState(); - _checkRoleAndLoadData(); + // Use cached name if available, otherwise load data + if (TeacherDashboardPage._cachedUserName != null) { + _userName = TeacherDashboardPage._cachedUserName!; + } else { + _checkRoleAndLoadData(); + } } Future _checkRoleAndLoadData() async { @@ -70,6 +83,7 @@ class _TeacherDashboardPageState extends State { print('DEBUG: Final displayName to use: "$displayName"'); setState(() { _userName = displayName; + TeacherDashboardPage._cachedUserName = displayName; }); } } diff --git a/lib/features/quiz/presentation/pages/teacher_quiz_page.dart b/lib/features/quiz/presentation/pages/teacher_quiz_page.dart index 5b6e719..671fb4b 100644 --- a/lib/features/quiz/presentation/pages/teacher_quiz_page.dart +++ b/lib/features/quiz/presentation/pages/teacher_quiz_page.dart @@ -212,6 +212,173 @@ class _TeacherQuizPageState extends State return mathKeywords.any((keyword) => combinedText.contains(keyword)); } + void _showQuizCreationOptions(Map material) { + final cs = Theme.of(context).colorScheme; + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => Container( + decoration: BoxDecoration( + color: cs.surface, + borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), + ), + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Handle bar + Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: cs.onSurfaceVariant.withValues(alpha: 0.3), + borderRadius: BorderRadius.circular(2), + ), + ), + ), + const SizedBox(height: 24), + Text( + 'Criar Quiz', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: cs.onSurface, + ), + ), + const SizedBox(height: 8), + Text( + 'Escolhe como queres criar o quiz para este material:', + style: TextStyle( + fontSize: 14, + color: cs.onSurfaceVariant, + ), + ), + const SizedBox(height: 24), + // Option 1: AI + _buildOptionCard( + context: context, + icon: Icons.auto_awesome, + title: 'Gerar com IA', + subtitle: 'O AI analisa o material e cria perguntas automaticamente', + color: cs.primary, + onTap: () { + Navigator.pop(context); + _generateQuiz(material); + }, + ), + const SizedBox(height: 12), + // Option 2: Manual + _buildOptionCard( + context: context, + icon: Icons.edit_note, + title: 'Criar Manualmente', + subtitle: 'Cria as perguntas e respostas do zero', + color: cs.secondary, + onTap: () { + Navigator.pop(context); + _createManualQuiz(material); + }, + ), + const SizedBox(height: 24), + ], + ), + ), + ); + } + + Widget _buildOptionCard({ + required BuildContext context, + required IconData icon, + required String title, + required String subtitle, + required Color color, + required VoidCallback onTap, + }) { + final cs = Theme.of(context).colorScheme; + return Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(16), + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(16), + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + border: Border.all(color: color.withValues(alpha: 0.3)), + borderRadius: BorderRadius.circular(16), + color: color.withValues(alpha: 0.05), + ), + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: color.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Icon(icon, color: color, size: 28), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: cs.onSurface, + ), + ), + const SizedBox(height: 4), + Text( + subtitle, + style: TextStyle( + fontSize: 13, + color: cs.onSurfaceVariant, + ), + ), + ], + ), + ), + Icon( + Icons.arrow_forward_ios, + color: color, + size: 16, + ), + ], + ), + ), + ), + ); + } + + Future _createManualQuiz(Map material) async { + final matName = material['name'] ?? 'Material'; + final matId = material['id']!; + + // Abrir editor com lista vazia de perguntas + if (mounted) { + final published = await Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => _QuizEditorPage( + materialName: matName, + materialId: matId, + questions: const [], // Lista vazia para criação manual + availableClasses: _teacherClasses, + ), + ), + ); + if (published == true) { + await _loadHistory(); + } + } + } + Future _generateQuiz(Map material) async { setState(() => _generatingForId = material['id']); try { @@ -390,7 +557,7 @@ class _TeacherQuizPageState extends State return _MaterialCard( name: name, isGenerating: isGenerating, - onTap: isGenerating ? null : () => _generateQuiz(mat), + onTap: isGenerating ? null : () => _showQuizCreationOptions(mat), cs: cs, ); },