import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:go_router/go_router.dart'; import '../../../classes/presentation/pages/join_class_page.dart'; import '../../../materials/presentation/pages/content_management_page.dart'; import 'dashboard_action_card.dart'; /// Quick access cards for Student Dashboard with horizontal scrollable row class QuickAccessWidget extends StatelessWidget { const QuickAccessWidget({super.key}); /// Mesmas dimensões dos cards em "Ações Rápidas" do professor. static const double _scrollCardWidth = 200; static const double _scrollRowHeight = 150; static const double _cardMinHeight = 150; static const EdgeInsets _cardPadding = EdgeInsets.all(16); static const double _titleFontSize = 16; static const double _subtitleFontSize = 13; static const double _iconSize = 24; static const double _iconPadding = 10; @override Widget build(BuildContext context) { final cards = [ _buildTutorIACard(context), _buildContentManagementCard(context), _buildQuizCard(context), _buildAchievementsCard(context), ]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ InkWell( onTap: () => _showQuickAccessList(context), borderRadius: BorderRadius.circular(8), child: Padding( padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( 'Acesso Rápido', style: TextStyle( color: Theme.of(context).colorScheme.onSurface, fontSize: 20, fontWeight: FontWeight.bold, ), ), const SizedBox(width: 8), Icon( Icons.expand_more, color: Theme.of(context).colorScheme.onSurfaceVariant, size: 20, ), ], ), ), ), const SizedBox(height: 12), IntrinsicHeight( child: SingleChildScrollView( scrollDirection: Axis.horizontal, clipBehavior: Clip.none, padding: const EdgeInsets.only(right: 16), child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ SizedBox(width: _scrollCardWidth, child: cards[0]), const SizedBox(width: 12), SizedBox(width: _scrollCardWidth, child: cards[1]), const SizedBox(width: 12), SizedBox(width: _scrollCardWidth, child: cards[2]), const SizedBox(width: 12), SizedBox(width: _scrollCardWidth, child: cards[3]), ], ), ), ), const SizedBox(height: 16), // Entrar numa Disciplina (full width) _buildJoinClassCard(context), ], ) .animate() .fadeIn( duration: const Duration(milliseconds: 300), curve: Curves.easeOut, ) .then(delay: const Duration(milliseconds: 100)); } Widget _buildTutorIACard(BuildContext context) { return ClipRRect( borderRadius: BorderRadius.circular(16), child: DashboardActionCard( title: 'Tutor IA', subtitle: 'Assistente de estudos', icon: Icons.psychology, useGradient: true, minHeight: _cardMinHeight, iconSize: _iconSize, iconPadding: _iconPadding, titleFontSize: _titleFontSize, subtitleFontSize: _subtitleFontSize, padding: _cardPadding, leadingIcon: Container( width: 44, height: 44, decoration: BoxDecoration( color: const Color(0xFFF9EEE8), borderRadius: BorderRadius.circular(10), ), child: Padding( padding: const EdgeInsets.all(8), child: Image.asset( 'assets/images/epvc.png', fit: BoxFit.contain, ), ), ), onTap: () => context.go('/ai-tutor'), ) .animate() .fadeIn( duration: const Duration(milliseconds: 300), curve: Curves.easeOut, ) .then(delay: const Duration(milliseconds: 100)), ); } Widget _buildContentManagementCard(BuildContext context) { return ClipRRect( borderRadius: BorderRadius.circular(16), child: DashboardActionCardSurface( title: 'Gerenciamento Conteúdo', subtitle: 'Ver por disciplinas', icon: Icons.folder_open, minHeight: _cardMinHeight, titleFontSize: _titleFontSize, subtitleFontSize: _subtitleFontSize, iconSize: _iconSize, padding: _cardPadding, onTap: () { Navigator.push( context, MaterialPageRoute( builder: (_) => const ContentManagementPage(), ), ); }, ) .animate() .fadeIn( duration: const Duration(milliseconds: 300), curve: Curves.easeOut, ) .then(delay: const Duration(milliseconds: 150)), ); } Widget _buildQuizCard(BuildContext context) { return ClipRRect( borderRadius: BorderRadius.circular(16), child: DashboardActionCardSurface( title: 'Quiz', subtitle: 'Testa os teus conhecimentos', icon: Icons.quiz, minHeight: _cardMinHeight, titleFontSize: _titleFontSize, subtitleFontSize: _subtitleFontSize, iconSize: _iconSize, padding: _cardPadding, onTap: () => context.go('/quiz'), ) .animate() .fadeIn( duration: const Duration(milliseconds: 300), curve: Curves.easeOut, ) .then(delay: const Duration(milliseconds: 150)), ); } Widget _buildAchievementsCard(BuildContext context) { return ClipRRect( borderRadius: BorderRadius.circular(16), child: DashboardActionCardSurface( title: 'Conquistas', subtitle: 'Ver medals', icon: Icons.emoji_events, minHeight: _cardMinHeight, titleFontSize: _titleFontSize, subtitleFontSize: _subtitleFontSize, iconSize: _iconSize, padding: _cardPadding, iconColor: Colors.amber, onTap: () => context.go('/student/achievements'), ) .animate() .fadeIn( duration: const Duration(milliseconds: 300), curve: Curves.easeOut, ) .then(delay: const Duration(milliseconds: 200)), ); } Widget _buildJoinClassCard(BuildContext context) { return DashboardActionCard( title: 'Adicionar uma Disciplina', subtitle: 'Junta-te a uma disciplina com o código', icon: Icons.group_add, layout: DashboardActionCardLayout.horizontal, minHeight: 0, onTap: () { Navigator.push( context, MaterialPageRoute(builder: (_) => const JoinClassPage()), ); }, ) .animate() .fadeIn( duration: const Duration(milliseconds: 300), curve: Curves.easeOut, ) .then(delay: const Duration(milliseconds: 300)); } void _showQuickAccessList(BuildContext context) { final items = [ _QuickAccessItem( title: 'Tutor IA', subtitle: 'Assistente de estudos', icon: Icons.psychology, useGradient: true, useCustomIcon: true, onTap: () { Navigator.pop(context); context.go('/ai-tutor'); }, ), _QuickAccessItem( title: 'Gerenciamento Conteúdo', subtitle: 'Ver por disciplinas', icon: Icons.folder_open, onTap: () { Navigator.pop(context); Navigator.push( context, MaterialPageRoute(builder: (_) => const ContentManagementPage()), ); }, ), _QuickAccessItem( title: 'Quiz', subtitle: 'Testa os teus conhecimentos', icon: Icons.quiz, onTap: () { Navigator.pop(context); context.go('/quiz'); }, ), _QuickAccessItem( title: 'Conquistas', subtitle: 'Ver medals', icon: Icons.emoji_events, iconColor: Colors.amber, onTap: () { Navigator.pop(context); context.go('/student/achievements'); }, ), _QuickAccessItem( title: 'Adicionar uma Disciplina', subtitle: 'Junta-te a uma disciplina com o código', icon: Icons.group_add, onTap: () { Navigator.pop(context); Navigator.push( context, MaterialPageRoute(builder: (_) => const JoinClassPage()), ); }, ), ]; showModalBottomSheet( context: context, isScrollControlled: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (context) => DraggableScrollableSheet( initialChildSize: 0.6, minChildSize: 0.3, maxChildSize: 0.9, expand: false, builder: (context, scrollController) { return Column( children: [ Container( margin: const EdgeInsets.only(top: 8), width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(2), ), ), Padding( padding: const EdgeInsets.all(20), child: Text( 'Acesso Rápido', style: TextStyle( color: Theme.of(context).colorScheme.onSurface, fontSize: 20, fontWeight: FontWeight.bold, ), ), ), Expanded( child: ListView.builder( controller: scrollController, padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: items.length, itemBuilder: (context, index) { final item = items[index]; return Card( margin: const EdgeInsets.only(bottom: 12), elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide( color: Theme.of( context, ).colorScheme.outline.withOpacity(0.2), ), ), child: ListTile( leading: item.useCustomIcon ? Container( width: 44, height: 44, decoration: BoxDecoration( color: const Color(0xFFF9EEE8), borderRadius: BorderRadius.circular(10), ), child: Padding( padding: const EdgeInsets.all(8), child: Image.asset( 'assets/images/epvc.png', fit: BoxFit.contain, ), ), ) : Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: item.useGradient ? Theme.of( context, ).colorScheme.primary.withOpacity(0.1) : (item.iconColor ?? Theme.of( context, ).colorScheme.secondary) .withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: Icon( item.icon, color: item.useGradient ? Theme.of(context).colorScheme.primary : (item.iconColor ?? Theme.of( context, ).colorScheme.secondary), size: 24, ), ), title: Text( item.title, style: TextStyle( fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.onSurface, ), ), subtitle: Text( item.subtitle, style: TextStyle( color: Theme.of( context, ).colorScheme.onSurfaceVariant, fontSize: 13, ), ), trailing: Icon( Icons.arrow_forward_ios, color: Theme.of(context).colorScheme.primary, size: 16, ), onTap: item.onTap, ), ); }, ), ), const SizedBox(height: 20), ], ); }, ), ); } } class _QuickAccessItem { final String title; final String subtitle; final IconData icon; final bool useGradient; final Color? iconColor; final bool useCustomIcon; final VoidCallback onTap; _QuickAccessItem({ required this.title, required this.subtitle, required this.icon, this.useGradient = false, this.iconColor, this.useCustomIcon = false, required this.onTap, }); }