Modificação nos modos, correção de textos cortados
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import '../../../../core/services/auth_service.dart';
|
||||
import '../../../../core/theme/app_theme_extension.dart';
|
||||
import '../widgets/progress_hero_widget.dart';
|
||||
import '../widgets/quick_access_widget.dart';
|
||||
import '../widgets/student_classes_list_widget.dart';
|
||||
@@ -83,19 +84,17 @@ class _StudentDashboardPageState extends State<StudentDashboardPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeExtras = AppThemeExtras.of(context);
|
||||
final headerColor = themeExtras.dashboardHeaderTextColor;
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Theme.of(context).colorScheme.primary,
|
||||
Theme.of(context).colorScheme.primary.withOpacity(0.8),
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
Theme.of(context).colorScheme.background,
|
||||
],
|
||||
stops: [0.0, 0.2, 0.6, 1.0],
|
||||
colors: themeExtras.dashboardBackgroundGradient,
|
||||
stops: themeExtras.dashboardGradientStops,
|
||||
),
|
||||
),
|
||||
child: SafeArea(
|
||||
@@ -114,17 +113,17 @@ class _StudentDashboardPageState extends State<StudentDashboardPage> {
|
||||
children: [
|
||||
Text(
|
||||
'Bem-vindo, $_userName!',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
style: TextStyle(
|
||||
color: headerColor,
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
const Text(
|
||||
Text(
|
||||
'Seu progresso de estudos',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
color: headerColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
@@ -133,7 +132,7 @@ class _StudentDashboardPageState extends State<StudentDashboardPage> {
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.logout, color: Colors.white),
|
||||
icon: Icon(Icons.logout, color: headerColor),
|
||||
onPressed: () async {
|
||||
await AuthService.signOut();
|
||||
if (mounted) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import '../../../../core/services/auth_service.dart';
|
||||
import '../../../../core/theme/app_theme_extension.dart';
|
||||
import '../widgets/teacher_hero_widget.dart';
|
||||
import '../widgets/teacher_quick_actions_widget.dart';
|
||||
import '../widgets/teacher_classes_list_widget.dart';
|
||||
@@ -79,19 +80,17 @@ class _TeacherDashboardPageState extends State<TeacherDashboardPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeExtras = AppThemeExtras.of(context);
|
||||
final headerColor = themeExtras.dashboardHeaderTextColor;
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Theme.of(context).colorScheme.primary,
|
||||
Theme.of(context).colorScheme.primary.withOpacity(0.8),
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
Theme.of(context).colorScheme.background,
|
||||
],
|
||||
stops: [0.0, 0.2, 0.6, 1.0],
|
||||
colors: themeExtras.dashboardBackgroundGradient,
|
||||
stops: themeExtras.dashboardGradientStops,
|
||||
),
|
||||
),
|
||||
child: SafeArea(
|
||||
@@ -110,17 +109,17 @@ class _TeacherDashboardPageState extends State<TeacherDashboardPage> {
|
||||
children: [
|
||||
Text(
|
||||
'Bem-vindo, $_userName!',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
style: TextStyle(
|
||||
color: headerColor,
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
const Text(
|
||||
Text(
|
||||
'Painel de Gestão de Conteúdo',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
color: headerColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
@@ -129,7 +128,7 @@ class _TeacherDashboardPageState extends State<TeacherDashboardPage> {
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.logout, color: Colors.white),
|
||||
icon: Icon(Icons.logout, color: headerColor),
|
||||
onPressed: () async {
|
||||
await AuthService.signOut();
|
||||
if (mounted) {
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../core/theme/app_theme_extension.dart';
|
||||
|
||||
/// Layout variant for dashboard quick-action cards.
|
||||
enum DashboardActionCardLayout { vertical, horizontal }
|
||||
|
||||
/// Reusable action card with flexible height and wrapping subtitles.
|
||||
class DashboardActionCard extends StatelessWidget {
|
||||
const DashboardActionCard({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.icon,
|
||||
required this.onTap,
|
||||
this.layout = DashboardActionCardLayout.vertical,
|
||||
this.minHeight = 150,
|
||||
this.useGradient = false,
|
||||
this.badge,
|
||||
this.iconSize = 24,
|
||||
this.iconPadding = 10,
|
||||
this.titleFontSize,
|
||||
this.subtitleFontSize,
|
||||
this.padding,
|
||||
this.leadingIcon,
|
||||
this.onTapDisabled,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final IconData icon;
|
||||
final VoidCallback? onTap;
|
||||
final bool? onTapDisabled;
|
||||
final DashboardActionCardLayout layout;
|
||||
final double minHeight;
|
||||
final bool useGradient;
|
||||
final String? badge;
|
||||
final double iconSize;
|
||||
final double iconPadding;
|
||||
final double? titleFontSize;
|
||||
final double? subtitleFontSize;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
final Widget? leadingIcon;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
final extras = AppThemeExtras.of(context);
|
||||
final isHorizontal = layout == DashboardActionCardLayout.horizontal;
|
||||
final effectivePadding =
|
||||
padding ?? EdgeInsets.all(isHorizontal ? 16 : (useGradient ? 20 : 14));
|
||||
|
||||
final decoration = BoxDecoration(
|
||||
gradient: useGradient
|
||||
? LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
extras.actionCardGradientStart,
|
||||
extras.actionCardGradientEnd,
|
||||
],
|
||||
)
|
||||
: null,
|
||||
color: useGradient ? null : cs.surface,
|
||||
borderRadius: BorderRadius.circular(minHeight <= 110 ? 12 : 16),
|
||||
border: useGradient
|
||||
? null
|
||||
: Border.all(color: cs.outline.withOpacity(0.2), width: 1),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: (useGradient ? cs.primary : cs.shadow).withOpacity(
|
||||
useGradient ? 0.3 : 0.05,
|
||||
),
|
||||
blurRadius: useGradient ? 15 : 10,
|
||||
offset: Offset(0, useGradient ? 8 : 4),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final titleColor = useGradient ? Colors.white : cs.onSurface;
|
||||
final subtitleColor =
|
||||
useGradient ? Colors.white : cs.onSurfaceVariant;
|
||||
final iconBgColor = useGradient
|
||||
? Colors.white.withOpacity(0.2)
|
||||
: cs.primary.withOpacity(0.1);
|
||||
final iconColor = useGradient ? Colors.white : cs.primary;
|
||||
|
||||
final effectiveMinHeight = minHeight > 0 ? minHeight : null;
|
||||
|
||||
return ConstrainedBox(
|
||||
constraints: effectiveMinHeight != null
|
||||
? BoxConstraints(minHeight: effectiveMinHeight)
|
||||
: const BoxConstraints(),
|
||||
child: Container(
|
||||
decoration: decoration,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(minHeight <= 110 ? 12 : 16),
|
||||
onTap: onTapDisabled == true ? null : onTap,
|
||||
child: Padding(
|
||||
padding: effectivePadding,
|
||||
child: isHorizontal
|
||||
? _buildHorizontalContent(
|
||||
context,
|
||||
titleColor,
|
||||
subtitleColor,
|
||||
iconBgColor,
|
||||
iconColor,
|
||||
)
|
||||
: _buildVerticalContent(
|
||||
context,
|
||||
titleColor,
|
||||
subtitleColor,
|
||||
iconBgColor,
|
||||
iconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHorizontalContent(
|
||||
BuildContext context,
|
||||
Color titleColor,
|
||||
Color subtitleColor,
|
||||
Color iconBgColor,
|
||||
Color iconColor,
|
||||
) {
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
_iconBox(iconBgColor, iconColor),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: _titleSubtitleColumn(
|
||||
titleColor,
|
||||
subtitleColor,
|
||||
titleSize: titleFontSize ?? 16,
|
||||
subtitleSize: subtitleFontSize ?? 13,
|
||||
),
|
||||
),
|
||||
Icon(Icons.arrow_forward_ios, color: cs.primary, size: 16),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVerticalContent(
|
||||
BuildContext context,
|
||||
Color titleColor,
|
||||
Color subtitleColor,
|
||||
Color iconBgColor,
|
||||
Color iconColor,
|
||||
) {
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
final isCompact = minHeight <= 130;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
leadingIcon ?? _iconBox(iconBgColor, iconColor),
|
||||
if (badge != null) ...[
|
||||
const Spacer(),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: isCompact ? 6 : 10,
|
||||
vertical: isCompact ? 3 : 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: cs.secondary,
|
||||
borderRadius: BorderRadius.circular(isCompact ? 10 : 12),
|
||||
),
|
||||
child: Text(
|
||||
badge!,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: isCompact ? 9 : 10,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
SizedBox(height: isCompact ? 8 : 12),
|
||||
_titleSubtitleColumn(
|
||||
titleColor,
|
||||
subtitleColor,
|
||||
titleSize: titleFontSize ?? (useGradient ? 18 : 16),
|
||||
subtitleSize: subtitleFontSize ?? (isCompact ? 11 : 12),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _iconBox(Color bgColor, Color iconColor) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(iconPadding),
|
||||
decoration: BoxDecoration(
|
||||
color: bgColor,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(icon, color: iconColor, size: iconSize),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _titleSubtitleColumn(
|
||||
Color titleColor,
|
||||
Color subtitleColor, {
|
||||
required double titleSize,
|
||||
required double subtitleSize,
|
||||
}) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
color: titleColor,
|
||||
fontSize: titleSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 1.2,
|
||||
),
|
||||
),
|
||||
if (subtitle.isNotEmpty) ...[
|
||||
SizedBox(height: subtitleSize >= 13 ? 4 : 2),
|
||||
Text(
|
||||
subtitle,
|
||||
style: TextStyle(
|
||||
color: subtitleColor,
|
||||
fontSize: subtitleSize,
|
||||
height: 1.25,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Surface-styled vertical card (Quiz, Criar Turma, etc.).
|
||||
class DashboardActionCardSurface extends StatelessWidget {
|
||||
const DashboardActionCardSurface({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.icon,
|
||||
required this.onTap,
|
||||
this.minHeight = 150,
|
||||
this.iconColor,
|
||||
this.leadingWidget,
|
||||
this.onTapDisabled,
|
||||
this.titleFontSize = 14,
|
||||
this.subtitleFontSize = 11,
|
||||
this.iconSize = 20,
|
||||
this.padding = const EdgeInsets.all(12),
|
||||
});
|
||||
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final IconData icon;
|
||||
final VoidCallback? onTap;
|
||||
final bool? onTapDisabled;
|
||||
final double minHeight;
|
||||
final Color? iconColor;
|
||||
final Widget? leadingWidget;
|
||||
final double titleFontSize;
|
||||
final double subtitleFontSize;
|
||||
final double iconSize;
|
||||
final EdgeInsetsGeometry padding;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
final effectiveIconColor = iconColor ?? cs.secondary;
|
||||
|
||||
return DashboardActionCard(
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
icon: icon,
|
||||
onTap: onTap,
|
||||
onTapDisabled: onTapDisabled,
|
||||
minHeight: minHeight,
|
||||
useGradient: false,
|
||||
iconSize: iconSize,
|
||||
leadingIcon: leadingWidget ??
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: effectiveIconColor.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(icon, color: effectiveIconColor, size: iconSize),
|
||||
),
|
||||
titleFontSize: titleFontSize,
|
||||
subtitleFontSize: subtitleFontSize,
|
||||
padding: padding,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
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/routing/app_router.dart';
|
||||
@@ -42,10 +44,8 @@ class ProfileSectionWidget extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Theme.of(context).colorScheme.primary,
|
||||
Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withOpacity(0.8),
|
||||
AppThemeExtras.of(context).actionCardGradientStart,
|
||||
AppThemeExtras.of(context).actionCardGradientEnd,
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
|
||||
import '../../../../core/theme/app_theme_extension.dart';
|
||||
|
||||
/// Progress tracking hero section for student dashboard
|
||||
class ProgressHeroWidget extends StatelessWidget {
|
||||
final String userName;
|
||||
@@ -148,8 +150,11 @@ class ProgressHeroWidget extends StatelessWidget {
|
||||
widthFactor: overallProgress,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
colors: [Colors.white, Color(0xFFF8F9FA)],
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppThemeExtras.of(context).heroProgressStart,
|
||||
AppThemeExtras.of(context).heroProgressEnd,
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
|
||||
@@ -2,8 +2,9 @@ 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 'dashboard_action_card.dart';
|
||||
|
||||
/// Quick access cards for Tutor IA and Quiz with fixed overflow
|
||||
/// Quick access cards for Tutor IA and Quiz
|
||||
class QuickAccessWidget extends StatelessWidget {
|
||||
const QuickAccessWidget({super.key});
|
||||
|
||||
@@ -21,18 +22,23 @@ class QuickAccessWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
// Tutor IA Card (Primary)
|
||||
Expanded(flex: 3, child: _buildTutorIACard(context)),
|
||||
const SizedBox(width: 16),
|
||||
// Quiz Card (Secondary)
|
||||
Expanded(flex: 2, child: _buildQuizCard(context)),
|
||||
],
|
||||
IntrinsicHeight(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: _buildTutorIACard(context),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: _buildQuizCard(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
// Join Class Card
|
||||
_buildJoinClassCard(context),
|
||||
],
|
||||
)
|
||||
@@ -45,110 +51,13 @@ class QuickAccessWidget extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _buildTutorIACard(BuildContext context) {
|
||||
return Container(
|
||||
height: 150,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
Theme.of(context).colorScheme.primary,
|
||||
Theme.of(context).colorScheme.primary.withOpacity(0.8),
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(context).colorScheme.primary.withOpacity(0.3),
|
||||
blurRadius: 15,
|
||||
offset: const Offset(0, 8),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () {
|
||||
print('DEBUG: AI Tutor card clicked!');
|
||||
try {
|
||||
context.go('/ai-tutor');
|
||||
print('DEBUG: Navigation to AI Tutor successful');
|
||||
} catch (e) {
|
||||
print('DEBUG: Navigation error: $e');
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(7),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.psychology,
|
||||
color: Colors.white,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: const Text(
|
||||
'NOVO',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Tutor IA',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
//SizedBox(height: 4),
|
||||
Text(
|
||||
'Assistente de estudos',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
height: 1.2,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
return DashboardActionCard(
|
||||
title: 'Tutor IA',
|
||||
subtitle: 'Assistente de estudos',
|
||||
icon: Icons.psychology,
|
||||
useGradient: true,
|
||||
minHeight: 150,
|
||||
onTap: () => context.go('/ai-tutor'),
|
||||
)
|
||||
.animate()
|
||||
.scale(
|
||||
@@ -159,80 +68,14 @@ class QuickAccessWidget extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _buildQuizCard(BuildContext context) {
|
||||
return Container(
|
||||
height: 150,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
|
||||
width: 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () => context.go('/quiz'),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(14),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.secondary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.quiz,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Quiz',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Testa os teus conhecimentos',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
fontSize: 12,
|
||||
height: 1.2,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
return DashboardActionCardSurface(
|
||||
title: 'Quiz',
|
||||
subtitle: 'Testa os teus conhecimentos',
|
||||
icon: Icons.quiz,
|
||||
minHeight: 150,
|
||||
iconColor: cs.secondary,
|
||||
onTap: () => context.go('/quiz'),
|
||||
)
|
||||
.animate()
|
||||
.scale(
|
||||
@@ -243,90 +86,18 @@ class QuickAccessWidget extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _buildJoinClassCard(BuildContext context) {
|
||||
return Container(
|
||||
height: 86,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
|
||||
width: 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => const JoinClassPage()),
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.group_add,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Entrar numa Turma',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Junta-te a uma turma com o código',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
size: 16,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
return DashboardActionCard(
|
||||
title: 'Entrar numa Turma',
|
||||
subtitle: 'Junta-te a uma turma com o código',
|
||||
icon: Icons.group_add,
|
||||
layout: DashboardActionCardLayout.horizontal,
|
||||
minHeight: 0,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => const JoinClassPage()),
|
||||
);
|
||||
},
|
||||
)
|
||||
.animate()
|
||||
.scale(
|
||||
|
||||
@@ -107,7 +107,7 @@ class StudentClassesListWidget extends StatelessWidget {
|
||||
if (!snapshot.hasData || !snapshot.data!.exists) {
|
||||
return Container(
|
||||
width: 200,
|
||||
height: 150,
|
||||
constraints: const BoxConstraints(minHeight: 150),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
@@ -135,7 +135,7 @@ class StudentClassesListWidget extends StatelessWidget {
|
||||
|
||||
return Container(
|
||||
width: 200,
|
||||
height: 150,
|
||||
constraints: const BoxConstraints(minHeight: 150),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
@@ -172,7 +172,7 @@ class StudentClassesListWidget extends StatelessWidget {
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
maxLines: 1,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
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';
|
||||
|
||||
@@ -41,10 +43,8 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Theme.of(context).colorScheme.primary,
|
||||
Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withOpacity(0.8),
|
||||
AppThemeExtras.of(context).actionCardGradientStart,
|
||||
AppThemeExtras.of(context).actionCardGradientEnd,
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
@@ -288,8 +288,7 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
|
||||
label,
|
||||
style: TextStyle(color: color.withOpacity(0.8), fontSize: 10),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 3,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -112,7 +112,7 @@ class TeacherClassesListWidget extends StatelessWidget {
|
||||
},
|
||||
child: Container(
|
||||
width: 200,
|
||||
height: 150,
|
||||
constraints: const BoxConstraints(minHeight: 150),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
@@ -149,7 +149,7 @@ class TeacherClassesListWidget extends StatelessWidget {
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
maxLines: 1,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
|
||||
import '../../../../core/theme/app_theme_extension.dart';
|
||||
|
||||
/// Hero section for teacher dashboard showing class overview
|
||||
class TeacherHeroWidget extends StatelessWidget {
|
||||
final String userName;
|
||||
@@ -34,8 +36,6 @@ class TeacherHeroWidget extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
'Visão Geral da Turma',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
fontSize: 20,
|
||||
@@ -45,8 +45,6 @@ class TeacherHeroWidget extends StatelessWidget {
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Acompanhe o progresso dos seus alunos',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
fontSize: 13,
|
||||
@@ -148,8 +146,11 @@ class TeacherHeroWidget extends StatelessWidget {
|
||||
widthFactor: classAverageProgress,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
colors: [Colors.white, Color(0xFFF8F9FA)],
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppThemeExtras.of(context).heroProgressStart,
|
||||
AppThemeExtras.of(context).heroProgressEnd,
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../../../core/services/auth_service.dart';
|
||||
import '../../../../features/materials/presentation/pages/teacher_materials_page.dart';
|
||||
import 'dashboard_action_card.dart';
|
||||
|
||||
/// Quick access cards for teacher actions
|
||||
class TeacherQuickActionsWidget extends StatefulWidget {
|
||||
@@ -20,8 +21,25 @@ class TeacherQuickActionsWidget extends StatefulWidget {
|
||||
class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
|
||||
bool _isCreatingClass = false;
|
||||
|
||||
/// Mesmas dimensões dos cards em "As Minhas Turmas".
|
||||
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 = [
|
||||
_buildUploadContentCard(context),
|
||||
_buildCreateClassCard(context),
|
||||
_buildCreateQuizCard(context),
|
||||
_buildViewAnalyticsCard(context),
|
||||
];
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -33,29 +51,20 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Primary Actions Row
|
||||
Row(
|
||||
children: [
|
||||
// Upload Content Card (Primary)
|
||||
Expanded(flex: 2, child: _buildUploadContentCard(context)),
|
||||
const SizedBox(width: 16),
|
||||
// Create Class Card
|
||||
Expanded(flex: 2, child: _buildCreateClassCard(context)),
|
||||
const SizedBox(width: 16),
|
||||
// Create Quiz Card (Secondary)
|
||||
Expanded(flex: 2, child: _buildCreateQuizCard(context)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Secondary Actions Row
|
||||
Row(
|
||||
children: [
|
||||
// View Analytics Card
|
||||
Expanded(child: _buildViewAnalyticsCard(context)),
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
height: _scrollRowHeight,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
clipBehavior: Clip.none,
|
||||
padding: const EdgeInsets.only(right: 16),
|
||||
itemCount: cards.length,
|
||||
separatorBuilder: (_, __) => const SizedBox(width: 12),
|
||||
itemBuilder: (context, index) => SizedBox(
|
||||
width: _scrollCardWidth,
|
||||
child: cards[index],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -70,284 +79,77 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
|
||||
Widget _buildUploadContentCard(BuildContext context) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child:
|
||||
Container(
|
||||
height: 150,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
Theme.of(context).colorScheme.primary,
|
||||
Theme.of(context).colorScheme.primary.withOpacity(0.8),
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withOpacity(0.3),
|
||||
blurRadius: 15,
|
||||
offset: const Offset(0, 8),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => const TeacherMaterialsPage(),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.upload_file,
|
||||
color: Colors.white,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 6,
|
||||
vertical: 3,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.secondary,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: const Text(
|
||||
'NOVO',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 9,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: const [
|
||||
Text(
|
||||
'Upload Conteúdo',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
'PDFs, textos, imagens',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 11,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.animate()
|
||||
.scale(
|
||||
duration: const Duration(milliseconds: 600),
|
||||
curve: Curves.elasticOut,
|
||||
)
|
||||
.then(delay: const Duration(milliseconds: 100)),
|
||||
child: DashboardActionCard(
|
||||
title: 'Upload Conteúdo',
|
||||
subtitle: 'PDFs, textos, imagens',
|
||||
icon: Icons.upload_file,
|
||||
useGradient: true,
|
||||
minHeight: _cardMinHeight,
|
||||
iconSize: _iconSize,
|
||||
iconPadding: _iconPadding,
|
||||
titleFontSize: _titleFontSize,
|
||||
subtitleFontSize: _subtitleFontSize,
|
||||
padding: _cardPadding,
|
||||
onTap: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => const TeacherMaterialsPage(),
|
||||
),
|
||||
),
|
||||
)
|
||||
.animate()
|
||||
.scale(
|
||||
duration: const Duration(milliseconds: 600),
|
||||
curve: Curves.elasticOut,
|
||||
)
|
||||
.then(delay: const Duration(milliseconds: 100)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCreateQuizCard(BuildContext context) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child:
|
||||
Container(
|
||||
height: 150,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.outline.withOpacity(0.2),
|
||||
width: 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.shadow.withOpacity(0.05),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () => context.go('/teacher/quiz/create'),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.secondary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.quiz,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Criar Quiz',
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
'Avaliações interativas',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
fontSize: 11,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.animate()
|
||||
.scale(
|
||||
duration: const Duration(milliseconds: 600),
|
||||
curve: Curves.elasticOut,
|
||||
)
|
||||
.then(delay: const Duration(milliseconds: 200)),
|
||||
child: DashboardActionCardSurface(
|
||||
title: 'Criar Quiz',
|
||||
subtitle: 'Avaliações interativas',
|
||||
icon: Icons.quiz,
|
||||
minHeight: _cardMinHeight,
|
||||
titleFontSize: _titleFontSize,
|
||||
subtitleFontSize: _subtitleFontSize,
|
||||
iconSize: _iconSize,
|
||||
padding: _cardPadding,
|
||||
onTap: () => context.go('/teacher/quiz/create'),
|
||||
)
|
||||
.animate()
|
||||
.scale(
|
||||
duration: const Duration(milliseconds: 600),
|
||||
curve: Curves.elasticOut,
|
||||
)
|
||||
.then(delay: const Duration(milliseconds: 200)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildViewAnalyticsCard(BuildContext context) {
|
||||
return Container(
|
||||
height: 120,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
|
||||
width: 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () => context.go('/teacher/analytics'),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withOpacity(0.8),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.analytics,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Analytics',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'Desempenho da turma',
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
fontSize: 11,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
return DashboardActionCardSurface(
|
||||
title: 'Analytics',
|
||||
subtitle: 'Desempenho da turma',
|
||||
icon: Icons.analytics,
|
||||
minHeight: _cardMinHeight,
|
||||
titleFontSize: _titleFontSize,
|
||||
subtitleFontSize: _subtitleFontSize,
|
||||
iconSize: _iconSize,
|
||||
padding: _cardPadding,
|
||||
iconColor: cs.primary,
|
||||
leadingWidget: Container(
|
||||
padding: const EdgeInsets.all(_iconPadding),
|
||||
decoration: BoxDecoration(
|
||||
color: cs.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(Icons.analytics, color: cs.primary, size: _iconSize),
|
||||
),
|
||||
onTap: () => context.go('/teacher/analytics'),
|
||||
)
|
||||
.animate()
|
||||
.scale(
|
||||
@@ -358,110 +160,45 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
|
||||
}
|
||||
|
||||
Widget _buildCreateClassCard(BuildContext context) {
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child:
|
||||
Container(
|
||||
height: 150,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.outline.withOpacity(0.2),
|
||||
width: 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.shadow.withOpacity(0.05),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: _isCreatingClass
|
||||
? null
|
||||
: () => _showCreateClassDialog(context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: _isCreatingClass
|
||||
? SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.primary,
|
||||
),
|
||||
)
|
||||
: Icon(
|
||||
Icons.school,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.primary,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Criar Turma',
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
'Gerar código de acesso',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
fontSize: 11,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
child: DashboardActionCardSurface(
|
||||
title: 'Criar Turma',
|
||||
subtitle: 'Gerar código de acesso',
|
||||
icon: Icons.school,
|
||||
minHeight: _cardMinHeight,
|
||||
titleFontSize: _titleFontSize,
|
||||
subtitleFontSize: _subtitleFontSize,
|
||||
iconSize: _iconSize,
|
||||
padding: _cardPadding,
|
||||
iconColor: cs.primary,
|
||||
onTapDisabled: _isCreatingClass,
|
||||
onTap: () => _showCreateClassDialog(context),
|
||||
leadingWidget: Container(
|
||||
padding: const EdgeInsets.all(_iconPadding),
|
||||
decoration: BoxDecoration(
|
||||
color: cs.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: _isCreatingClass
|
||||
? SizedBox(
|
||||
width: _iconSize,
|
||||
height: _iconSize,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: cs.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.animate()
|
||||
.scale(
|
||||
duration: const Duration(milliseconds: 600),
|
||||
curve: Curves.elasticOut,
|
||||
)
|
||||
.then(delay: const Duration(milliseconds: 150)),
|
||||
)
|
||||
: Icon(Icons.school, color: cs.primary, size: _iconSize),
|
||||
),
|
||||
)
|
||||
.animate()
|
||||
.scale(
|
||||
duration: const Duration(milliseconds: 600),
|
||||
curve: Curves.elasticOut,
|
||||
)
|
||||
.then(delay: const Duration(milliseconds: 150)),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user