From 62b9a107bc3298432183ebfd88463d9bfac3d6f2 Mon Sep 17 00:00:00 2001 From: 240405 <240405@epvc.pt> Date: Thu, 14 May 2026 22:07:03 +0100 Subject: [PATCH] =?UTF-8?q?-=20Dark=20/=20light=20mode=20a=20funcionar=20n?= =?UTF-8?q?o=20lado=20do=20aluno=20-=20Atualiza=C3=A7=C3=A3o=20dos=20fiche?= =?UTF-8?q?iros=20markdown.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/CHANGELOG.md | 23 + docs/FRONTEND_MVP_TASKS.md | 20 +- docs/PROJECT_PROGRESS.md | 39 +- lib/core/providers/theme_provider.dart | 20 +- lib/core/theme/app_colors.dart | 97 +- lib/core/theme/app_theme.dart | 261 ++++-- .../pages/tutor_chat_page_simple.dart | 114 ++- .../auth/presentation/pages/login_page.dart | 714 ++++++++------- .../pages/role_selection_page.dart | 17 +- .../auth/presentation/pages/signup_page.dart | 739 ++++++++------- .../pages/student_dashboard_page.dart | 10 +- .../pages/teacher_dashboard_page.dart | 10 +- .../widgets/profile_section_widget.dart | 83 +- .../widgets/progress_hero_widget.dart | 172 ++-- .../widgets/quick_access_widget.dart | 79 +- .../widgets/student_classes_list_widget.dart | 46 +- .../teacher_analytics_preview_widget.dart | 425 +++++---- .../widgets/teacher_classes_list_widget.dart | 36 +- .../widgets/teacher_hero_widget.dart | 177 ++-- .../widgets/teacher_quick_actions_widget.dart | 846 +++++++++--------- .../presentation/pages/profile_page.dart | 25 +- .../presentation/pages/quiz_list_page.dart | 35 +- .../quiz/presentation/pages/quiz_page.dart | 26 +- .../presentation/pages/help_page.dart | 113 ++- .../presentation/pages/profile_edit_page.dart | 62 +- .../presentation/pages/settings_page.dart | 94 +- .../presentation/pages/splash_page.dart | 66 +- .../presentation/pages/tutor_chat_page.dart | 35 +- .../presentation/pages/loading_page.dart | 16 +- .../presentation/pages/not_found_page.dart | 21 +- 30 files changed, 2582 insertions(+), 1839 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3cfadad..50c5cc4 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -87,6 +87,29 @@ - Loading state with CircularProgressIndicator ### Fixed +- **Settings Profile Card UI** - Fixed white background and duplicate email display + - Background now uses Theme.of(context).colorScheme.surface instead of hardcoded white + - User info displays displayName (bold, larger) on top, email (smaller) below + - File: lib/features/settings/presentation/pages/profile_edit_page.dart + +- **Signup Page Input Field Theming** - Fixed dark backgrounds in light mode + - Input fields now use conditional background based on theme brightness + - Light mode: surface color, Dark mode: surfaceContainerHighest + - Applied to name, email, and password fields + - File: lib/features/auth/presentation/pages/signup_page.dart + +- **Dashboard Progress Container Theming** - Fixed dark background in light mode + - "Ótimo progresso!" container now uses conditional background + - Light mode: surface color, Dark mode: surfaceContainerHighest + - File: lib/features/dashboard/presentation/widgets/profile_section_widget.dart + +- **Authentication Navigation** - Enhanced back button behavior + - Removed AppBar from login and signup pages + - Added PopScope for Android back button navigation to role-selection + - Added custom positioned back button with aesthetic design + - Positioned at top: 50 to avoid notification bar overlap + - Files: lib/features/auth/presentation/pages/login_page.dart, signup_page.dart + - **Unified Quick Action Cards Text Style** - "Upload Conteúdo" and "Criar Quiz" cards now match "Criar Turma" text alignment - All cards use `Column` with `crossAxisAlignment: CrossAxisAlignment.start` for text section diff --git a/docs/FRONTEND_MVP_TASKS.md b/docs/FRONTEND_MVP_TASKS.md index 3e90c8b..c7183eb 100644 --- a/docs/FRONTEND_MVP_TASKS.md +++ b/docs/FRONTEND_MVP_TASKS.md @@ -496,14 +496,20 @@ class FirebaseConstants { **Dependencies**: Task 1.4 #### Subtasks: -- [ ] Implement Firebase Auth service -- [ ] Create user models and entities -- [ ] Build authentication repository -- [ ] Implement sign in use case -- [ ] Implement sign up use case +- [x] Implement Firebase Auth service +- [x] Create user models and entities +- [x] Build authentication repository +- [x] Implement sign in use case +- [x] Implement sign up use case - [ ] Implement password reset -- [ ] Create authentication providers -- [ ] Build login/signup screens +- [x] Create authentication providers +- [x] Build login/signup screens (with navigation improvements and theme fixes) + +**Recent Updates:** +- ✅ Enhanced authentication navigation with PopScope for Android back button support +- ✅ Removed AppBar and added custom positioned back button with aesthetic design +- ✅ Fixed theme consistency in signup page input fields (light/dark mode) +- ✅ Navigation flow complete: back button navigates to role-selection #### Implementation: diff --git a/docs/PROJECT_PROGRESS.md b/docs/PROJECT_PROGRESS.md index bde61d4..36e248c 100644 --- a/docs/PROJECT_PROGRESS.md +++ b/docs/PROJECT_PROGRESS.md @@ -28,7 +28,7 @@ This document tracks the overall progress of the AI Study Assistant project deve - ✅ **Foundation:** 100% Complete -- ✅ **UI/UX:** 90% Complete +- ✅ **UI/UX:** 95% Complete - ✅ **Internationalization:** 100% Complete @@ -66,7 +66,7 @@ This document tracks the overall progress of the AI Study Assistant project deve - [x] Splash screen with animations -- [x] Login page with improved design +- [x] Login page with improved design and navigation - [x] Role selection page (student/teacher) @@ -76,7 +76,7 @@ This document tracks the overall progress of the AI Study Assistant project deve - [x] Dark/light theme support -- [ ] Signup page (needs update) +- [x] Signup page (updated with theme fixes) - [x] Dashboard pages (fixed overflow issue) @@ -355,11 +355,9 @@ This document tracks the overall progress of the AI Study Assistant project deve -### **Minor Issues (1)** +### **Minor Issues (0)** -- [ ] Signup page needs design update - -- [ ] Some animations could be optimized +- None currently @@ -419,6 +417,31 @@ This document tracks the overall progress of the AI Study Assistant project deve ### **Last 24 Hours:** +- ✅ **Fixed Settings Profile Card UI** - profile_edit_page.dart + - Background: Changed from hardcoded white to Theme.of(context).colorScheme.surface + - User info: Fixed duplicate email display, now shows displayName (bold, fontSize 16) on top and email (fontSize 14) below + - Shadow: Updated to use Theme.of(context).colorScheme.shadow.withOpacity(0.1) + +- ✅ **Fixed Signup Page Input Fields** - signup_page.dart + - Background: Changed to conditional based on brightness + - Light mode: Theme.of(context).colorScheme.surface + - Dark mode: Theme.of(context).colorScheme.surfaceContainerHighest + - Applied to name, email, and password fields (lines 259-265, 316-322, 386-392) + +- ✅ **Fixed Dashboard Progress Container** - profile_section_widget.dart + - "Ótimo progresso!" container background changed to conditional + - Light mode: Theme.of(context).colorScheme.surface + - Dark mode: Theme.of(context).colorScheme.surfaceContainerHighest + +- ✅ **Enhanced Authentication Navigation** - login_page.dart & signup_page.dart + - Removed AppBar from both pages + - Added PopScope with canPop: false and onPopInvokedWithResult to navigate to '/role-selection' + - Added custom positioned back button (top: 50, left: 16) with: + - Semi-transparent container (colorScheme.surface.withOpacity(0.8)) + - Rounded corners (12px) + - Subtle shadow (colorScheme.shadow.withOpacity(0.1), blurRadius: 8) + - Positioned below notification bar to avoid overlap + - ✅ **Teacher Materials Upload Page** - Nova tela dedicada para professores enviarem materiais para a IA - Ficheiro: `lib/features/materials/presentation/pages/teacher_materials_page.dart` - **FASE 1**: Criar tela com AppBar "Materiais da Turma" e design consistente @@ -712,7 +735,7 @@ This document tracks the overall progress of the AI Study Assistant project deve -**📊 Last Updated: 2024-05-06 21:43** +**📊 Last Updated: 2026-05-14 21:04** **🔄 Auto-Update: Enabled** diff --git a/lib/core/providers/theme_provider.dart b/lib/core/providers/theme_provider.dart index 115212f..9eab61f 100644 --- a/lib/core/providers/theme_provider.dart +++ b/lib/core/providers/theme_provider.dart @@ -25,22 +25,16 @@ class ThemeNotifier extends StateNotifier { /// Change theme mode Future setThemeMode(ThemeMode themeMode) async { - // For now, only allow light mode - // Future: Allow dark mode when available - if (themeMode == ThemeMode.light || ThemeService.isDarkModeAvailable()) { - state = themeMode; - await ThemeService.setThemeMode(themeMode); - } + state = themeMode; + await ThemeService.setThemeMode(themeMode); } - /// Toggle between light and dark mode (for future use) + /// Toggle between light and dark mode Future toggleTheme() async { - if (ThemeService.isDarkModeAvailable()) { - final newTheme = state == ThemeMode.light - ? ThemeMode.dark - : ThemeMode.light; - await setThemeMode(newTheme); - } + final newTheme = state == ThemeMode.light + ? ThemeMode.dark + : ThemeMode.light; + await setThemeMode(newTheme); } /// Reset to default theme diff --git a/lib/core/theme/app_colors.dart b/lib/core/theme/app_colors.dart index cb0bf1e..c98b34a 100644 --- a/lib/core/theme/app_colors.dart +++ b/lib/core/theme/app_colors.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -/// EPVC School Color Palette - New Color Scheme +/// EPVC School Color Palette - New Color Scheme with Light/Dark Mode Support class AppColors { - // Primary Brand Colors + // Primary Brand Colors (same for both modes) static const Color primaryTeal = Color( 0xFF82C9BD, ); // Main teal color - PRIMARY @@ -10,17 +10,30 @@ class AppColors { 0xFFF68D2D, ); // Accent orange - SECONDARY - // Gradient Colors + // Gradient Colors (same for both modes) static const Color gradientStart = Color(0xFF82C9BD); // Teal gradient start static const Color gradientEnd = Color( 0xFF6AB8A8, ); // Darker teal gradient end - // Secondary Colors + // Secondary Colors (same for both modes) static const Color secondaryTeal = Color(0xFF6AB8A8); // Darker teal static const Color accentTeal = Color(0xFF5AA69A); // Lighter teal accent static const Color lightOrange = Color(0xFFF7A960); // Lighter orange + // Status Colors (same for both modes) + static const Color success = Color(0xFF10B981); // Green for success + static const Color warning = Color(0xFFF59E0B); // Amber for warnings + static const Color error = Color(0xFFEF4444); // Red for errors + static const Color info = Color(0xFF3B82F6); // Blue for info + + // Legacy compatibility (for existing code) + @deprecated + static const Color primaryBlue = primaryTeal; // Map old primaryBlue to new primaryTeal +} + +/// Light Mode Colors +class LightColors { // Neutral Colors static const Color background = Color(0xFFF8F9FA); // Light gray background static const Color surface = Color(0xFFFFFFFF); // White surfaces @@ -31,38 +44,68 @@ class AppColors { static const Color textSecondary = Color(0xFF6B7280); // Secondary text static const Color textHint = Color(0xFF9CA3AF); // Hint text - // Status Colors - static const Color success = Color(0xFF10B981); // Green for success - static const Color warning = Color(0xFFF59E0B); // Amber for warnings - static const Color error = Color(0xFFEF4444); // Red for errors - static const Color info = Color(0xFF3B82F6); // Blue for info - // Interactive Colors - static const Color buttonPrimary = Color(0xFF82C9BD); // Primary button (teal) - static const Color buttonAccent = Color(0xFFF68D2D); // Accent button (orange) + static const Color buttonPrimary = + AppColors.primaryTeal; // Primary button (teal) + static const Color buttonAccent = + AppColors.primaryOrange; // Accent button (orange) static const Color buttonSecondary = Color(0xFFE5E7EB); // Secondary button - static const Color iconActive = Color(0xFF82C9BD); // Active icons (teal) + static const Color iconActive = AppColors.primaryTeal; // Active icons (teal) static const Color iconInactive = Color(0xFF9CA3AF); // Inactive icons // Chat Specific Colors - static const Color chatBubbleStudent = Color( - 0xFF82C9BD, - ); // Student messages (teal) + static const Color chatBubbleStudent = + AppColors.primaryTeal; // Student messages (teal) static const Color chatBubbleAI = Color(0xFFF3F4F6); // AI messages static const Color chatInputBackground = Color( 0xFFF8F9FA, ); // Input background - static const Color chatSendButton = Color(0xFF82C9BD); // Send button (teal) + static const Color chatSendButton = + AppColors.primaryTeal; // Send button (teal) - // Dark Mode Colors - static const Color darkBackground = Color(0xFF1F2937); // Dark background - static const Color darkSurface = Color(0xFF374151); // Dark surface - static const Color darkTextPrimary = Color(0xFFF9FAFB); // Dark primary text - static const Color darkTextSecondary = Color( - 0xFFD1D5DB, - ); // Dark secondary text + // Border Colors + static const Color border = Color(0xFFE2E8F0); // Border color + static const Color divider = Color(0xFFE5E7EB); // Divider color - // Legacy compatibility (for existing code) - @deprecated - static const Color primaryBlue = primaryTeal; // Map old primaryBlue to new primaryTeal + // Overlay Colors + static const Color overlay = Color(0x80000000); // Overlay color +} + +/// Dark Mode Colors +class DarkColors { + // Neutral Colors + static const Color background = Color(0xFF1F2937); // Dark background + static const Color surface = Color(0xFF374151); // Dark surface + static const Color cardBackground = Color(0xFF374151); // Dark cards + + // Text Colors + static const Color textPrimary = Color(0xFFF9FAFB); // Dark primary text + static const Color textSecondary = Color(0xFFD1D5DB); // Dark secondary text + static const Color textHint = Color(0xFF9CA3AF); // Hint text + + // Interactive Colors + static const Color buttonPrimary = + AppColors.primaryTeal; // Primary button (teal) + static const Color buttonAccent = + AppColors.primaryOrange; // Accent button (orange) + static const Color buttonSecondary = Color(0xFF4B5563); // Secondary button + static const Color iconActive = AppColors.primaryTeal; // Active icons (teal) + static const Color iconInactive = Color(0xFF6B7280); // Inactive icons + + // Chat Specific Colors + static const Color chatBubbleStudent = + AppColors.primaryTeal; // Student messages (teal) + static const Color chatBubbleAI = Color(0xFF4B5563); // AI messages (darker) + static const Color chatInputBackground = Color( + 0xFF374151, + ); // Input background + static const Color chatSendButton = + AppColors.primaryTeal; // Send button (teal) + + // Border Colors + static const Color border = Color(0xFF4B5563); // Border color + static const Color divider = Color(0xFF4B5563); // Divider color + + // Overlay Colors + static const Color overlay = Color(0x80000000); // Overlay color } diff --git a/lib/core/theme/app_theme.dart b/lib/core/theme/app_theme.dart index b9bd464..a4456a8 100644 --- a/lib/core/theme/app_theme.dart +++ b/lib/core/theme/app_theme.dart @@ -9,24 +9,24 @@ class AppTheme { useMaterial3: true, brightness: Brightness.light, colorScheme: ColorScheme.fromSeed( - seedColor: AppColors.primaryBlue, + seedColor: AppColors.primaryTeal, brightness: Brightness.light, - primary: AppColors.primaryBlue, - secondary: AppColors.primaryTeal, - surface: AppColors.surface, - background: AppColors.background, + primary: AppColors.primaryTeal, + secondary: AppColors.primaryOrange, + surface: LightColors.surface, + background: LightColors.background, error: AppColors.error, ), // App Bar Theme appBarTheme: const AppBarTheme( - backgroundColor: AppColors.surface, - foregroundColor: AppColors.textPrimary, + backgroundColor: LightColors.surface, + foregroundColor: LightColors.textPrimary, elevation: 0, centerTitle: true, systemOverlayStyle: SystemUiOverlayStyle.dark, titleTextStyle: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 18, fontWeight: FontWeight.w600, ), @@ -34,7 +34,7 @@ class AppTheme { // Card Theme cardTheme: CardThemeData( - color: AppColors.cardBackground, + color: LightColors.cardBackground, elevation: 2, shadowColor: Colors.black.withOpacity(0.08), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), @@ -44,10 +44,10 @@ class AppTheme { // Elevated Button Theme elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( - backgroundColor: AppColors.buttonPrimary, + backgroundColor: LightColors.buttonPrimary, foregroundColor: Colors.white, elevation: 2, - shadowColor: AppColors.primaryBlue.withOpacity(0.3), + shadowColor: AppColors.primaryTeal.withOpacity(0.3), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), @@ -59,8 +59,8 @@ class AppTheme { // Outlined Button Theme outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( - foregroundColor: AppColors.primaryBlue, - side: BorderSide(color: AppColors.primaryBlue.withOpacity(0.3)), + foregroundColor: AppColors.primaryTeal, + side: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), @@ -72,7 +72,7 @@ class AppTheme { // Text Button Theme textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom( - foregroundColor: AppColors.primaryBlue, + foregroundColor: AppColors.primaryTeal, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), @@ -82,18 +82,18 @@ class AppTheme { // Input Field Theme inputDecorationTheme: InputDecorationTheme( filled: true, - fillColor: AppColors.surface, + fillColor: LightColors.surface, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), - borderSide: BorderSide(color: AppColors.primaryBlue.withOpacity(0.3)), + borderSide: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), - borderSide: BorderSide(color: AppColors.primaryBlue.withOpacity(0.3)), + borderSide: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.primaryBlue, width: 2), + borderSide: const BorderSide(color: AppColors.primaryTeal, width: 2), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), @@ -103,9 +103,9 @@ class AppTheme { horizontal: 16, vertical: 12, ), - hintStyle: const TextStyle(color: AppColors.textHint, fontSize: 14), + hintStyle: const TextStyle(color: LightColors.textHint, fontSize: 14), labelStyle: const TextStyle( - color: AppColors.textSecondary, + color: LightColors.textSecondary, fontSize: 14, fontWeight: FontWeight.w500, ), @@ -113,85 +113,85 @@ class AppTheme { // Text Field Theme textSelectionTheme: TextSelectionThemeData( - cursorColor: AppColors.primaryBlue, - selectionColor: AppColors.primaryBlue.withOpacity(0.3), - selectionHandleColor: AppColors.primaryBlue, + cursorColor: AppColors.primaryTeal, + selectionColor: AppColors.primaryTeal.withOpacity(0.3), + selectionHandleColor: AppColors.primaryTeal, ), // Text Theme textTheme: const TextTheme( displayLarge: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 32, fontWeight: FontWeight.bold, ), displayMedium: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 28, fontWeight: FontWeight.bold, ), displaySmall: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 24, fontWeight: FontWeight.bold, ), headlineLarge: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 22, fontWeight: FontWeight.w600, ), headlineMedium: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 20, fontWeight: FontWeight.w600, ), headlineSmall: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 18, fontWeight: FontWeight.w600, ), titleLarge: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 16, fontWeight: FontWeight.w600, ), titleMedium: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 14, fontWeight: FontWeight.w600, ), titleSmall: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 12, fontWeight: FontWeight.w600, ), bodyLarge: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 16, fontWeight: FontWeight.normal, ), bodyMedium: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 14, fontWeight: FontWeight.normal, ), bodySmall: TextStyle( - color: AppColors.textSecondary, + color: LightColors.textSecondary, fontSize: 12, fontWeight: FontWeight.normal, ), labelLarge: TextStyle( - color: AppColors.textPrimary, + color: LightColors.textPrimary, fontSize: 14, fontWeight: FontWeight.w500, ), labelMedium: TextStyle( - color: AppColors.textSecondary, + color: LightColors.textSecondary, fontSize: 12, fontWeight: FontWeight.w500, ), labelSmall: TextStyle( - color: AppColors.textHint, + color: LightColors.textHint, fontSize: 10, fontWeight: FontWeight.w500, ), @@ -199,9 +199,9 @@ class AppTheme { // Bottom Navigation Bar Theme bottomNavigationBarTheme: const BottomNavigationBarThemeData( - backgroundColor: AppColors.surface, - selectedItemColor: AppColors.primaryBlue, - unselectedItemColor: AppColors.iconInactive, + backgroundColor: LightColors.surface, + selectedItemColor: AppColors.primaryTeal, + unselectedItemColor: LightColors.iconInactive, type: BottomNavigationBarType.fixed, elevation: 8, selectedLabelStyle: TextStyle( @@ -216,7 +216,7 @@ class AppTheme { // Floating Action Button Theme floatingActionButtonTheme: FloatingActionButtonThemeData( - backgroundColor: AppColors.primaryBlue, + backgroundColor: AppColors.primaryTeal, foregroundColor: Colors.white, elevation: 4, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), @@ -224,28 +224,28 @@ class AppTheme { // Divider Theme dividerTheme: const DividerThemeData( - color: AppColors.buttonSecondary, + color: LightColors.divider, thickness: 1, space: 1, ), // Icon Theme - iconTheme: const IconThemeData(color: AppColors.iconActive, size: 24), + iconTheme: const IconThemeData(color: LightColors.iconActive, size: 24), // Progress Indicator Theme progressIndicatorTheme: const ProgressIndicatorThemeData( - color: AppColors.primaryBlue, - linearTrackColor: AppColors.buttonSecondary, - circularTrackColor: AppColors.buttonSecondary, + color: AppColors.primaryTeal, + linearTrackColor: LightColors.buttonSecondary, + circularTrackColor: LightColors.buttonSecondary, ), // Chip Theme chipTheme: ChipThemeData( - backgroundColor: AppColors.buttonSecondary, - selectedColor: AppColors.primaryBlue.withOpacity(0.1), - disabledColor: AppColors.buttonSecondary.withOpacity(0.5), - labelStyle: const TextStyle(color: AppColors.textPrimary), - secondaryLabelStyle: const TextStyle(color: AppColors.textPrimary), + backgroundColor: LightColors.buttonSecondary, + selectedColor: AppColors.primaryTeal.withOpacity(0.1), + disabledColor: LightColors.buttonSecondary.withOpacity(0.5), + labelStyle: const TextStyle(color: LightColors.textPrimary), + secondaryLabelStyle: const TextStyle(color: LightColors.textPrimary), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), @@ -257,52 +257,90 @@ class AppTheme { useMaterial3: true, brightness: Brightness.dark, colorScheme: ColorScheme.fromSeed( - seedColor: AppColors.primaryBlue, + seedColor: AppColors.primaryTeal, brightness: Brightness.dark, - primary: AppColors.primaryBlue, - secondary: AppColors.primaryTeal, - surface: AppColors.darkSurface, - background: AppColors.darkBackground, + primary: AppColors.primaryTeal, + secondary: AppColors.primaryOrange, + surface: DarkColors.surface, + background: DarkColors.background, error: AppColors.error, ), // Dark mode specific overrides would go here appBarTheme: const AppBarTheme( - backgroundColor: AppColors.darkSurface, - foregroundColor: AppColors.darkTextPrimary, + backgroundColor: DarkColors.surface, + foregroundColor: DarkColors.textPrimary, elevation: 0, centerTitle: true, systemOverlayStyle: SystemUiOverlayStyle.light, titleTextStyle: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 18, fontWeight: FontWeight.w600, ), ), cardTheme: CardThemeData( - color: AppColors.darkSurface, + color: DarkColors.cardBackground, elevation: 2, shadowColor: Colors.black.withOpacity(0.3), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), ), + // Elevated Button Theme for Dark Mode + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + backgroundColor: DarkColors.buttonPrimary, + foregroundColor: Colors.white, + elevation: 2, + shadowColor: AppColors.primaryTeal.withOpacity(0.3), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + textStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600), + ), + ), + + // Outlined Button Theme for Dark Mode + outlinedButtonTheme: OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + foregroundColor: AppColors.primaryTeal, + side: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + textStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600), + ), + ), + + // Text Button Theme for Dark Mode + textButtonTheme: TextButtonThemeData( + style: TextButton.styleFrom( + foregroundColor: AppColors.primaryTeal, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + ), + ), + // Input Field Theme for Dark Mode inputDecorationTheme: InputDecorationTheme( filled: true, - fillColor: AppColors.darkSurface, + fillColor: DarkColors.surface, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), - borderSide: BorderSide(color: AppColors.primaryBlue.withOpacity(0.3)), + borderSide: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), - borderSide: BorderSide(color: AppColors.primaryBlue.withOpacity(0.3)), + borderSide: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.primaryBlue, width: 2), + borderSide: const BorderSide(color: AppColors.primaryTeal, width: 2), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), @@ -313,11 +351,11 @@ class AppTheme { vertical: 12, ), hintStyle: const TextStyle( - color: AppColors.darkTextSecondary, + color: DarkColors.textSecondary, fontSize: 14, ), labelStyle: const TextStyle( - color: AppColors.darkTextSecondary, + color: DarkColors.textSecondary, fontSize: 14, fontWeight: FontWeight.w500, ), @@ -325,88 +363,141 @@ class AppTheme { // Text Field Theme for Dark Mode textSelectionTheme: TextSelectionThemeData( - cursorColor: AppColors.primaryBlue, - selectionColor: AppColors.primaryBlue.withOpacity(0.3), - selectionHandleColor: AppColors.primaryBlue, + cursorColor: AppColors.primaryTeal, + selectionColor: AppColors.primaryTeal.withOpacity(0.3), + selectionHandleColor: AppColors.primaryTeal, ), textTheme: const TextTheme( displayLarge: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 32, fontWeight: FontWeight.bold, ), displayMedium: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 28, fontWeight: FontWeight.bold, ), displaySmall: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 24, fontWeight: FontWeight.bold, ), headlineLarge: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 22, fontWeight: FontWeight.w600, ), headlineMedium: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 20, fontWeight: FontWeight.w600, ), headlineSmall: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 18, fontWeight: FontWeight.w600, ), titleLarge: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 16, fontWeight: FontWeight.w600, ), titleMedium: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 14, fontWeight: FontWeight.w600, ), titleSmall: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 12, fontWeight: FontWeight.w600, ), bodyLarge: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 16, fontWeight: FontWeight.normal, ), bodyMedium: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 14, fontWeight: FontWeight.normal, ), bodySmall: TextStyle( - color: AppColors.darkTextSecondary, + color: DarkColors.textSecondary, fontSize: 12, fontWeight: FontWeight.normal, ), labelLarge: TextStyle( - color: AppColors.darkTextPrimary, + color: DarkColors.textPrimary, fontSize: 14, fontWeight: FontWeight.w500, ), labelMedium: TextStyle( - color: AppColors.darkTextSecondary, + color: DarkColors.textSecondary, fontSize: 12, fontWeight: FontWeight.w500, ), labelSmall: TextStyle( - color: AppColors.darkTextSecondary, + color: DarkColors.textSecondary, fontSize: 10, fontWeight: FontWeight.w500, ), ), + + // Bottom Navigation Bar Theme for Dark Mode + bottomNavigationBarTheme: const BottomNavigationBarThemeData( + backgroundColor: DarkColors.surface, + selectedItemColor: AppColors.primaryTeal, + unselectedItemColor: DarkColors.iconInactive, + type: BottomNavigationBarType.fixed, + elevation: 8, + selectedLabelStyle: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + unselectedLabelStyle: TextStyle( + fontSize: 12, + fontWeight: FontWeight.normal, + ), + ), + + // Floating Action Button Theme for Dark Mode + floatingActionButtonTheme: FloatingActionButtonThemeData( + backgroundColor: AppColors.primaryTeal, + foregroundColor: Colors.white, + elevation: 4, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + ), + + // Divider Theme for Dark Mode + dividerTheme: const DividerThemeData( + color: DarkColors.divider, + thickness: 1, + space: 1, + ), + + // Icon Theme for Dark Mode + iconTheme: const IconThemeData(color: DarkColors.iconActive, size: 24), + + // Progress Indicator Theme for Dark Mode + progressIndicatorTheme: const ProgressIndicatorThemeData( + color: AppColors.primaryTeal, + linearTrackColor: DarkColors.buttonSecondary, + circularTrackColor: DarkColors.buttonSecondary, + ), + + // Chip Theme for Dark Mode + chipTheme: ChipThemeData( + backgroundColor: DarkColors.buttonSecondary, + selectedColor: AppColors.primaryTeal.withOpacity(0.1), + disabledColor: DarkColors.buttonSecondary.withOpacity(0.5), + labelStyle: const TextStyle(color: DarkColors.textPrimary), + secondaryLabelStyle: const TextStyle(color: DarkColors.textPrimary), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), ); } } diff --git a/lib/features/ai_tutor/presentation/pages/tutor_chat_page_simple.dart b/lib/features/ai_tutor/presentation/pages/tutor_chat_page_simple.dart index 34d84da..8ad5353 100644 --- a/lib/features/ai_tutor/presentation/pages/tutor_chat_page_simple.dart +++ b/lib/features/ai_tutor/presentation/pages/tutor_chat_page_simple.dart @@ -48,9 +48,9 @@ class _TutorChatPageSimpleState extends State } }, child: Scaffold( - backgroundColor: const Color(0xFFF8F9FA), + backgroundColor: Theme.of(context).colorScheme.background, appBar: AppBar( - backgroundColor: Colors.white, + backgroundColor: Theme.of(context).colorScheme.surface, elevation: 0, title: Row( children: [ @@ -58,8 +58,11 @@ class _TutorChatPageSimpleState extends State width: 40, height: 40, decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFF82C9BD), Color(0xFF6BA5A0)], + gradient: LinearGradient( + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.primary.withOpacity(0.8), + ], ), borderRadius: BorderRadius.circular(20), ), @@ -74,12 +77,15 @@ class _TutorChatPageSimpleState extends State style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, - color: Colors.grey[800], + color: Theme.of(context).colorScheme.onSurface, ), ), Text( 'Seu tutor educacional inteligente', - style: TextStyle(fontSize: 12, color: Colors.grey[600]), + style: TextStyle( + fontSize: 12, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ], ), @@ -88,7 +94,10 @@ class _TutorChatPageSimpleState extends State actions: [ IconButton( onPressed: _handleLogout, - icon: Icon(Icons.logout, color: Colors.grey[700]), + icon: Icon( + Icons.logout, + color: Theme.of(context).colorScheme.onSurface, + ), tooltip: 'Sair', ), ], @@ -98,14 +107,14 @@ class _TutorChatPageSimpleState extends State // Messages area Expanded( child: Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Color(0xFFF8F9FA), - Color(0xFFE8F0FE), - Color(0xFFF8F9FA), + Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.primary.withOpacity(0.05), + Theme.of(context).colorScheme.background, ], ), ), @@ -163,15 +172,24 @@ class _TutorChatPageSimpleState extends State padding: const EdgeInsets.all(16.0), decoration: BoxDecoration( gradient: isUser - ? const LinearGradient( - colors: [Color(0xFF82C9BD), Color(0xFF6BA5A0)], + ? LinearGradient( + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of( + context, + ).colorScheme.primary.withOpacity(0.8), + ], begin: Alignment.topLeft, end: Alignment.bottomRight, ) : LinearGradient( colors: [ - Colors.white.withOpacity(0.95), - Colors.white.withOpacity(0.9), + Theme.of( + context, + ).colorScheme.surface.withOpacity(0.95), + Theme.of( + context, + ).colorScheme.surface.withOpacity(0.9), ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -208,24 +226,32 @@ class _TutorChatPageSimpleState extends State data: content, styleSheet: MarkdownStyleSheet( p: TextStyle( - color: const Color(0xFF2D3748), + color: Theme.of( + context, + ).colorScheme.onSurface, fontSize: 16, height: 1.4, ), strong: TextStyle( - color: const Color(0xFF2D3748), + color: Theme.of( + context, + ).colorScheme.onSurface, fontSize: 16, fontWeight: FontWeight.bold, height: 1.4, ), em: TextStyle( - color: const Color(0xFF2D3748), + color: Theme.of( + context, + ).colorScheme.onSurface, fontSize: 16, fontStyle: FontStyle.italic, height: 1.4, ), listBullet: TextStyle( - color: const Color(0xFF2D3748), + color: Theme.of( + context, + ).colorScheme.onSurface, fontSize: 16, height: 1.4, ), @@ -247,7 +273,10 @@ class _TutorChatPageSimpleState extends State ), child: Text( _formatTimestamp(timestamp), - style: TextStyle(fontSize: 11, color: Colors.grey[600]), + style: TextStyle( + fontSize: 11, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ), ], @@ -267,13 +296,16 @@ class _TutorChatPageSimpleState extends State width: 36, height: 36, decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFF82C9BD), Color(0xFF6BA5A0)], + gradient: LinearGradient( + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.primary.withOpacity(0.8), + ], ), borderRadius: BorderRadius.circular(18), boxShadow: [ BoxShadow( - color: const Color(0xFF82C9BD).withOpacity(0.3), + color: Theme.of(context).colorScheme.primary.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 2), ), @@ -295,7 +327,7 @@ class _TutorChatPageSimpleState extends State bottom: bottomPadding + 16.0, // Add system navigation bar padding ), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.95), + color: Theme.of(context).colorScheme.surface.withOpacity(0.95), borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), boxShadow: [ BoxShadow( @@ -308,8 +340,11 @@ class _TutorChatPageSimpleState extends State child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), - color: Colors.white, - border: Border.all(color: const Color(0xFFE2E8F0), width: 1), + color: Theme.of(context).colorScheme.surface, + border: Border.all( + color: Theme.of(context).colorScheme.outline.withOpacity(0.5), + width: 1, + ), ), child: Row( children: [ @@ -317,9 +352,9 @@ class _TutorChatPageSimpleState extends State Expanded( child: TextField( controller: _messageController, - style: const TextStyle( + style: TextStyle( fontSize: 16, - color: Color(0xFF1A1A1A), // Dark text for visibility + color: Theme.of(context).colorScheme.onSurface, fontWeight: FontWeight.w500, ), decoration: InputDecoration( @@ -330,7 +365,7 @@ class _TutorChatPageSimpleState extends State ), hintText: 'Faz a tua pergunta!', hintStyle: TextStyle( - color: Colors.grey[400], + color: Theme.of(context).colorScheme.onSurfaceVariant, fontWeight: FontWeight.w400, fontSize: 16, ), @@ -351,20 +386,27 @@ class _TutorChatPageSimpleState extends State height: 44, decoration: BoxDecoration( gradient: _messageController.text.isNotEmpty - ? const LinearGradient( - colors: [Color(0xFF82C9BD), Color(0xFF6BA5A0)], + ? LinearGradient( + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of( + context, + ).colorScheme.primary.withOpacity(0.8), + ], begin: Alignment.topLeft, end: Alignment.bottomRight, ) : null, color: _messageController.text.isNotEmpty ? null - : Colors.grey[300], + : Theme.of(context).colorScheme.outline.withOpacity(0.3), borderRadius: BorderRadius.circular(22), boxShadow: _messageController.text.isNotEmpty ? [ BoxShadow( - color: const Color(0xFF82C9BD).withOpacity(0.3), + color: Theme.of( + context, + ).colorScheme.primary.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 2), ), @@ -398,7 +440,8 @@ class _TutorChatPageSimpleState extends State void _addWelcomeMessage() { final welcomeMessage = { - 'content': '''**Olá! Sou o GOAT, o teu Assistente IA oficial do Teach it.** 🐐 + 'content': + '''**Olá! Sou o GOAT, o teu Assistente IA oficial do Teach it.** 🐐 Estou aqui para te ajudar a aprender de forma confiante e motivadora! @@ -465,7 +508,8 @@ Envia-me a tua pergunta sobre qualquer assunto educacional e vou usar o material } catch (e) { // Fallback to error message if API fails Logger.error('RAG AI Service error: $e'); - final aiResponse = 'Desculpe, ocorreu um erro ao processar a pergunta. Tente novamente.'; + final aiResponse = + 'Desculpe, ocorreu um erro ao processar a pergunta. Tente novamente.'; setState(() { _messages.add({ diff --git a/lib/features/auth/presentation/pages/login_page.dart b/lib/features/auth/presentation/pages/login_page.dart index ce0d0e0..0dddb17 100644 --- a/lib/features/auth/presentation/pages/login_page.dart +++ b/lib/features/auth/presentation/pages/login_page.dart @@ -70,7 +70,9 @@ class _LoginPageState extends State { ); print('DEBUG: Login Firebase bem-sucedido'); - print('DEBUG: Role selecionado na tela anterior: ${widget.selectedRole}'); + print( + 'DEBUG: Role selecionado na tela anterior: ${widget.selectedRole}', + ); // Ler role na Firestore final uid = result?.user?.uid; @@ -81,7 +83,9 @@ class _LoginPageState extends State { // Validar se o role selecionado corresponde ao role real final selectedRole = widget.selectedRole; - if (selectedRole != null && actualRole != null && selectedRole != actualRole) { + if (selectedRole != null && + actualRole != null && + selectedRole != actualRole) { // Role não corresponde - mostrar erro setState(() { _isLoading = false; @@ -89,11 +93,14 @@ class _LoginPageState extends State { String errorMessage; if (selectedRole == 'teacher' && actualRole == 'student') { - errorMessage = 'Este email está registado como Aluno. Não pode aceder à área de Professores.'; + errorMessage = + 'Este email está registado como Aluno. Não pode aceder à área de Professores.'; } else if (selectedRole == 'student' && actualRole == 'teacher') { - errorMessage = 'Este email está registado como Professor. Não pode aceder à área de Alunos.'; + errorMessage = + 'Este email está registado como Professor. Não pode aceder à área de Alunos.'; } else { - errorMessage = 'O tipo de utilizador selecionado não corresponde ao perfil registado.'; + errorMessage = + 'O tipo de utilizador selecionado não corresponde ao perfil registado.'; } _showRoleErrorDialog('Acesso Negado', errorMessage); @@ -151,14 +158,14 @@ class _LoginPageState extends State { return AlertDialog( title: Text( title, - style: const TextStyle( - color: Color(0xFF2D3748), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, fontWeight: FontWeight.bold, ), ), content: Text( message, - style: const TextStyle(color: Color(0xFF2D3748)), + style: TextStyle(color: Theme.of(context).colorScheme.onSurface), ), actions: [ TextButton( @@ -167,9 +174,9 @@ class _LoginPageState extends State { // Fazer logout para limpar a sessão AuthService.signOut(); }, - child: const Text( + child: Text( 'Voltar', - style: TextStyle(color: Color(0xFF82C9BD)), + style: TextStyle(color: Theme.of(context).colorScheme.primary), ), ), ], @@ -180,304 +187,403 @@ class _LoginPageState extends State { @override Widget build(BuildContext context) { - return Scaffold( - body: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Color(0xFFF8F9FA), - Color.fromRGBO(130, 201, 189, 0.1), - Color.fromRGBO(246, 141, 45, 0.05), - Color(0xFFF8F9FA), - ], - ), - ), - child: SafeArea( - child: Center( - child: SingleChildScrollView( - padding: const EdgeInsets.all(24.0), - child: Form( - key: _formKey, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox(height: 60), - - // Logo/Title - Container( - padding: const EdgeInsets.all(20.0), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.9), - borderRadius: BorderRadius.circular(16.0), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 10.0, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - children: [ - Text( - 'EPVC', - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - foreground: Paint() - ..shader = LinearGradient( - colors: [ - const Color(0xFF82C9BD), - const Color(0xFFF68D2D), - ], - ).createShader(Rect.fromLTWH(0, 0, 200, 20)), - ), - ), - const SizedBox(height: 8), - Text( - 'Escola Profissional de Vila do Conde', - style: TextStyle( - fontSize: 14, - color: const Color(0xFF2D3748), - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ).animate().fadeIn( - duration: const Duration(milliseconds: 800), - ), - - const SizedBox(height: 40), - - // Login form - Container( - padding: const EdgeInsets.all(24.0), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.9), - borderRadius: BorderRadius.circular(16.0), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 10.0, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - 'Entrar', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF2D3748), - ), - ), - const SizedBox(height: 24), - - // Email field - TextFormField( - controller: _emailController, - keyboardType: TextInputType.emailAddress, - style: const TextStyle(color: Color(0xFF2D3748)), - decoration: InputDecoration( - labelText: 'Email', - labelStyle: const TextStyle( - color: Color(0xFF2D3748), - ), - hintStyle: const TextStyle( - color: Color(0xFF718096), - ), - prefixIcon: const Icon( - Icons.email, - color: Color(0xFF82C9BD), - ), - border: InputBorder.none, - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - borderSide: const BorderSide( - color: Color(0xFFE2E8F0), - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - borderSide: const BorderSide( - color: Color(0xFF82C9BD), - ), - ), - filled: true, - fillColor: const Color(0xFFF8F9FA), - ), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Email é obrigatório'; - } - if (!value.contains('@')) { - return 'Email inválido'; - } - return null; - }, - ), - const SizedBox(height: 16), - - // Password field - TextFormField( - controller: _passwordController, - obscureText: _obscurePassword, - style: const TextStyle(color: Color(0xFF2D3748)), - decoration: InputDecoration( - labelText: 'Palavra-passe', - labelStyle: const TextStyle( - color: Color(0xFF2D3748), - ), - hintStyle: const TextStyle( - color: Color(0xFF718096), - ), - prefixIcon: const Icon( - Icons.lock, - color: Color(0xFF82C9BD), - ), - suffixIcon: IconButton( - icon: Icon( - _obscurePassword - ? Icons.visibility - : Icons.visibility_off, - color: const Color(0xFF82C9BD), - ), - onPressed: () { - setState(() { - _obscurePassword = !_obscurePassword; - }); - }, - ), - border: InputBorder.none, - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - borderSide: const BorderSide( - color: Color(0xFFE2E8F0), - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - borderSide: const BorderSide( - color: Color(0xFF82C9BD), - ), - ), - filled: true, - fillColor: const Color(0xFFF8F9FA), - ), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Palavra-passe é obrigatória'; - } - if (value.length < 6) { - return 'Palavra-passe muito curta'; - } - return null; - }, - ), - const SizedBox(height: 12), - - // Remember me checkbox - Row( - children: [ - Checkbox( - value: _rememberMe, - onChanged: (bool? value) { - setState(() { - _rememberMe = value ?? false; - }); - }, - activeColor: const Color(0xFF82C9BD), - checkColor: Colors.white, - ), - GestureDetector( - onTap: () { - setState(() { - _rememberMe = !_rememberMe; - }); - }, - child: Text( - 'Manter sessão iniciada', - style: TextStyle( - color: const Color(0xFF2D3748), - fontSize: 14, - fontWeight: _rememberMe - ? FontWeight.w500 - : FontWeight.normal, - ), - ), - ), - ], - ), - const SizedBox(height: 12), - - // Login button - SizedBox( - height: 50, - child: ElevatedButton( - onPressed: _isLoading ? null : _handleLogin, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF82C9BD), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - ), - child: _isLoading - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: - AlwaysStoppedAnimation( - Colors.white, - ), - ), - ) - : Text( - 'Entrar', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(height: 16), - - // Signup link - GestureDetector( - onTap: () { - context.go('/signup'); - }, - child: Text( - 'Não tem conta? Criar aqui', - style: const TextStyle( - color: Color(0xFF82C9BD), - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - ).animate().fadeIn( - duration: const Duration(milliseconds: 1000), - ), - - const SizedBox(height: 40), + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) { + if (!didPop) { + context.go('/role-selection'); + } + }, + child: Scaffold( + body: Stack( + children: [ + // Main content + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.primary.withOpacity(0.1), + Theme.of(context).colorScheme.secondary.withOpacity(0.05), + Theme.of(context).colorScheme.background, ], ), ), + child: SafeArea( + child: Center( + child: SingleChildScrollView( + padding: const EdgeInsets.all(24.0), + child: Form( + key: _formKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 60), + + // Logo/Title + Container( + padding: const EdgeInsets.all(20.0), + decoration: BoxDecoration( + color: Theme.of( + context, + ).colorScheme.surface.withOpacity(0.9), + borderRadius: BorderRadius.circular(16.0), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 10.0, + offset: const Offset(0, 4), + ), + ], + ), + child: Column( + children: [ + Text( + 'EPVC', + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.bold, + foreground: Paint() + ..shader = + LinearGradient( + colors: [ + Theme.of( + context, + ).colorScheme.primary, + Theme.of( + context, + ).colorScheme.secondary, + ], + ).createShader( + Rect.fromLTWH(0, 0, 200, 20), + ), + ), + ), + const SizedBox(height: 8), + Text( + 'Escola Profissional de Vila do Conde', + style: TextStyle( + fontSize: 14, + color: Theme.of( + context, + ).colorScheme.onSurface, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ).animate().fadeIn( + duration: const Duration(milliseconds: 800), + ), + + const SizedBox(height: 40), + + // Login form + Container( + padding: const EdgeInsets.all(24.0), + decoration: BoxDecoration( + color: Theme.of( + context, + ).colorScheme.surface.withOpacity(0.9), + borderRadius: BorderRadius.circular(16.0), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 10.0, + offset: const Offset(0, 4), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + 'Entrar', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + ), + const SizedBox(height: 24), + + // Email field + TextFormField( + controller: _emailController, + keyboardType: TextInputType.emailAddress, + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + decoration: InputDecoration( + labelText: 'Email', + labelStyle: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + hintStyle: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + ), + prefixIcon: Icon( + Icons.email, + color: Theme.of( + context, + ).colorScheme.primary, + ), + border: InputBorder.none, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.5), + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Theme.of( + context, + ).colorScheme.primary, + ), + ), + filled: true, + fillColor: Theme.of( + context, + ).colorScheme.surface, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Email é obrigatório'; + } + if (!value.contains('@')) { + return 'Email inválido'; + } + return null; + }, + ), + const SizedBox(height: 16), + + // Password field + TextFormField( + controller: _passwordController, + obscureText: _obscurePassword, + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + decoration: InputDecoration( + labelText: 'Palavra-passe', + labelStyle: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + hintStyle: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + ), + prefixIcon: Icon( + Icons.lock, + color: Theme.of( + context, + ).colorScheme.primary, + ), + suffixIcon: IconButton( + icon: Icon( + _obscurePassword + ? Icons.visibility + : Icons.visibility_off, + color: Theme.of( + context, + ).colorScheme.primary, + ), + onPressed: () { + setState(() { + _obscurePassword = !_obscurePassword; + }); + }, + ), + border: InputBorder.none, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.5), + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Theme.of( + context, + ).colorScheme.primary, + ), + ), + filled: true, + fillColor: Theme.of( + context, + ).colorScheme.surface, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Palavra-passe é obrigatória'; + } + if (value.length < 6) { + return 'Palavra-passe muito curta'; + } + return null; + }, + ), + const SizedBox(height: 12), + + // Remember me checkbox + Row( + children: [ + Checkbox( + value: _rememberMe, + onChanged: (bool? value) { + setState(() { + _rememberMe = value ?? false; + }); + }, + activeColor: Theme.of( + context, + ).colorScheme.primary, + checkColor: Colors.white, + ), + GestureDetector( + onTap: () { + setState(() { + _rememberMe = !_rememberMe; + }); + }, + child: Text( + 'Manter sessão iniciada', + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + fontSize: 14, + fontWeight: _rememberMe + ? FontWeight.w500 + : FontWeight.normal, + ), + ), + ), + ], + ), + const SizedBox(height: 12), + + // Login button + SizedBox( + height: 50, + child: ElevatedButton( + onPressed: _isLoading ? null : _handleLogin, + style: ElevatedButton.styleFrom( + backgroundColor: Theme.of( + context, + ).colorScheme.primary, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 8.0, + ), + ), + elevation: 2, + ), + child: _isLoading + ? const SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + valueColor: + AlwaysStoppedAnimation( + Colors.white, + ), + ), + ) + : Text( + 'Entrar', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + const SizedBox(height: 16), + + // Signup link + GestureDetector( + onTap: () { + context.go('/signup'); + }, + child: Text( + 'Não tem conta? Criar aqui', + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.primary, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ).animate().fadeIn( + duration: const Duration(milliseconds: 1000), + ), + + const SizedBox(height: 40), + ], + ), + ), + ), + ), + ), ), - ), + // Custom back button + Positioned( + top: 50, + left: 16, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface.withOpacity(0.8), + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Theme.of( + context, + ).colorScheme.shadow.withOpacity(0.1), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: IconButton( + icon: Icon( + Icons.arrow_back, + color: Theme.of(context).colorScheme.onSurface, + ), + onPressed: () => context.go('/role-selection'), + ), + ), + ), + ], ), ), ); diff --git a/lib/features/auth/presentation/pages/role_selection_page.dart b/lib/features/auth/presentation/pages/role_selection_page.dart index f2ec963..ec0bb43 100644 --- a/lib/features/auth/presentation/pages/role_selection_page.dart +++ b/lib/features/auth/presentation/pages/role_selection_page.dart @@ -23,9 +23,10 @@ class _RoleSelectionPageState extends State { begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ - AppColors.background, - AppColors.primaryBlue.withOpacity(0.05), - AppColors.gradientStart.withOpacity(0.1), + Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.primary.withOpacity(0.1), + Theme.of(context).colorScheme.secondary.withOpacity(0.05), + Theme.of(context).colorScheme.background, ], ), ), @@ -92,7 +93,9 @@ class _RoleSelectionPageState extends State { AppLocalizations.of(context)!.appTitle, style: Theme.of(context).textTheme.headlineLarge ?.copyWith( - color: AppColors.textPrimary, + color: Theme.of( + context, + ).colorScheme.onSurface, fontWeight: FontWeight.bold, ), ) @@ -149,7 +152,7 @@ class _RoleSelectionPageState extends State { 'Quem é você?', style: Theme.of(context).textTheme.headlineMedium ?.copyWith( - color: AppColors.textPrimary, + color: Theme.of(context).colorScheme.onSurface, fontWeight: FontWeight.w600, ), ) @@ -351,7 +354,7 @@ class _RoleSelectionPageState extends State { style: Theme.of(context).textTheme.titleLarge?.copyWith( color: isSelected ? Colors.white - : AppColors.textPrimary, + : Theme.of(context).colorScheme.onSurface, fontWeight: FontWeight.w600, ), ), @@ -410,4 +413,4 @@ class _RoleSelectionPageState extends State { context.go('/signup?role=$_selectedRole'); } } -} \ No newline at end of file +} diff --git a/lib/features/auth/presentation/pages/signup_page.dart b/lib/features/auth/presentation/pages/signup_page.dart index 7bb43b6..9586147 100644 --- a/lib/features/auth/presentation/pages/signup_page.dart +++ b/lib/features/auth/presentation/pages/signup_page.dart @@ -101,315 +101,444 @@ class _SignupPageState extends State { @override Widget build(BuildContext context) { - return Scaffold( - body: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Color(0xFFF8F9FA), - Color.fromRGBO(130, 201, 189, 0.1), - Color.fromRGBO(246, 141, 45, 0.05), - Color(0xFFF8F9FA), - ], - ), - ), - child: SafeArea( - child: Center( - child: SingleChildScrollView( - padding: const EdgeInsets.all(24.0), - child: Form( - key: _formKey, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox(height: 60), - - // Logo/Title - Container( - padding: const EdgeInsets.all(20.0), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.9), - borderRadius: BorderRadius.circular(16.0), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 10.0, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - children: [ - Text( - 'EPVC', - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - foreground: Paint() - ..shader = LinearGradient( - colors: [ - const Color(0xFF82C9BD), - const Color(0xFFF68D2D), - ], - ).createShader(Rect.fromLTWH(0, 0, 200, 20)), - ), - ), - const SizedBox(height: 8), - Text( - 'Escola Profissional de Vila do Conde', - style: TextStyle( - fontSize: 14, - color: const Color(0xFF2D3748), - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ).animate().fadeIn( - duration: const Duration(milliseconds: 800), - ), - - const SizedBox(height: 40), - - // Signup form - Container( - padding: const EdgeInsets.all(24.0), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.9), - borderRadius: BorderRadius.circular(16.0), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 10.0, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - 'Criar Conta', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF2D3748), - ), - ), - const SizedBox(height: 24), - - // Name field - TextFormField( - controller: _nameController, - keyboardType: TextInputType.name, - style: const TextStyle(color: Color(0xFF2D3748)), - decoration: InputDecoration( - labelText: 'Nome Completo', - labelStyle: const TextStyle( - color: Color(0xFF2D3748), - ), - hintStyle: const TextStyle( - color: Color(0xFF718096), - ), - prefixIcon: const Icon( - Icons.person, - color: Color(0xFF82C9BD), - ), - border: InputBorder.none, - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - borderSide: const BorderSide( - color: Color(0xFFE2E8F0), - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - borderSide: const BorderSide( - color: Color(0xFF82C9BD), - ), - ), - filled: true, - fillColor: const Color(0xFFF8F9FA), - ), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Nome é obrigatório'; - } - if (value.length < 2) { - return 'Nome muito curto'; - } - return null; - }, - ), - const SizedBox(height: 16), - - // Email field - TextFormField( - controller: _emailController, - keyboardType: TextInputType.emailAddress, - style: const TextStyle(color: Color(0xFF2D3748)), - decoration: InputDecoration( - labelText: 'Email', - labelStyle: const TextStyle( - color: Color(0xFF2D3748), - ), - hintStyle: const TextStyle( - color: Color(0xFF718096), - ), - prefixIcon: const Icon( - Icons.email, - color: Color(0xFF82C9BD), - ), - border: InputBorder.none, - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - borderSide: const BorderSide( - color: Color(0xFFE2E8F0), - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - borderSide: const BorderSide( - color: Color(0xFF82C9BD), - ), - ), - filled: true, - fillColor: const Color(0xFFF8F9FA), - ), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Email é obrigatório'; - } - if (!value.contains('@')) { - return 'Email inválido'; - } - return null; - }, - ), - const SizedBox(height: 16), - - // Password field - TextFormField( - controller: _passwordController, - obscureText: _obscurePassword, - style: const TextStyle(color: Color(0xFF2D3748)), - decoration: InputDecoration( - labelText: 'Palavra-passe', - labelStyle: const TextStyle( - color: Color(0xFF2D3748), - ), - hintStyle: const TextStyle( - color: Color(0xFF718096), - ), - prefixIcon: const Icon( - Icons.lock, - color: Color(0xFF82C9BD), - ), - suffixIcon: IconButton( - icon: Icon( - _obscurePassword - ? Icons.visibility - : Icons.visibility_off, - color: const Color(0xFF82C9BD), - ), - onPressed: () { - setState(() { - _obscurePassword = !_obscurePassword; - }); - }, - ), - border: InputBorder.none, - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - borderSide: const BorderSide( - color: Color(0xFFE2E8F0), - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - borderSide: const BorderSide( - color: Color(0xFF82C9BD), - ), - ), - filled: true, - fillColor: const Color(0xFFF8F9FA), - ), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Palavra-passe é obrigatória'; - } - if (value.length < 6) { - return 'Palavra-passe muito curta'; - } - return null; - }, - ), - const SizedBox(height: 24), - - // Signup button - SizedBox( - height: 50, - child: ElevatedButton( - onPressed: _isLoading ? null : _handleSignup, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF82C9BD), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - ), - child: _isLoading - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: - AlwaysStoppedAnimation( - Colors.white, - ), - ), - ) - : Text( - 'Criar Conta', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(height: 16), - - // Login link - GestureDetector( - onTap: () { - context.go('/login?role=$_selectedRole'); - }, - child: Text( - 'Já tem conta? Entrar aqui', - style: const TextStyle( - color: Color(0xFF82C9BD), - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - ).animate().fadeIn( - duration: const Duration(milliseconds: 1000), - ), - - const SizedBox(height: 40), + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) { + if (!didPop) { + context.go('/role-selection'); + } + }, + child: Scaffold( + body: Stack( + children: [ + // Main content + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.primary.withOpacity(0.1), + Theme.of(context).colorScheme.secondary.withOpacity(0.05), + Theme.of(context).colorScheme.background, ], ), ), + child: SafeArea( + child: Center( + child: SingleChildScrollView( + padding: const EdgeInsets.all(24.0), + child: Form( + key: _formKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 60), + + // Logo/Title + Container( + padding: const EdgeInsets.all(20.0), + decoration: BoxDecoration( + color: Theme.of( + context, + ).colorScheme.surface.withOpacity(0.9), + borderRadius: BorderRadius.circular(16.0), + boxShadow: [ + BoxShadow( + color: Theme.of( + context, + ).colorScheme.shadow.withOpacity(0.1), + blurRadius: 10.0, + offset: const Offset(0, 4), + ), + ], + ), + child: Column( + children: [ + Text( + 'EPVC', + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.bold, + foreground: Paint() + ..shader = + LinearGradient( + colors: [ + Theme.of( + context, + ).colorScheme.primary, + Theme.of( + context, + ).colorScheme.secondary, + ], + ).createShader( + Rect.fromLTWH(0, 0, 200, 20), + ), + ), + ), + const SizedBox(height: 8), + Text( + 'Escola Profissional de Vila do Conde', + style: TextStyle( + fontSize: 14, + color: Theme.of( + context, + ).colorScheme.onSurface, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ).animate().fadeIn( + duration: const Duration(milliseconds: 800), + ), + + const SizedBox(height: 40), + + // Signup form + Container( + padding: const EdgeInsets.all(24.0), + decoration: BoxDecoration( + color: Theme.of( + context, + ).colorScheme.surface.withOpacity(0.9), + borderRadius: BorderRadius.circular(16.0), + boxShadow: [ + BoxShadow( + color: Theme.of( + context, + ).colorScheme.shadow.withOpacity(0.1), + blurRadius: 10.0, + offset: const Offset(0, 4), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + 'Criar Conta', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + ), + const SizedBox(height: 24), + + // Name field + TextFormField( + controller: _nameController, + keyboardType: TextInputType.name, + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + decoration: InputDecoration( + labelText: 'Nome Completo', + labelStyle: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + hintStyle: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + ), + prefixIcon: Icon( + Icons.person, + color: Theme.of( + context, + ).colorScheme.primary, + ), + border: InputBorder.none, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.3), + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Theme.of( + context, + ).colorScheme.primary, + ), + ), + filled: true, + fillColor: + Theme.of(context).brightness == + Brightness.dark + ? Theme.of( + context, + ).colorScheme.surfaceContainerHighest + : Theme.of(context).colorScheme.surface, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Nome é obrigatório'; + } + if (value.length < 2) { + return 'Nome muito curto'; + } + return null; + }, + ), + const SizedBox(height: 16), + + // Email field + TextFormField( + controller: _emailController, + keyboardType: TextInputType.emailAddress, + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + decoration: InputDecoration( + labelText: 'Email', + labelStyle: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + hintStyle: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + ), + prefixIcon: Icon( + Icons.email, + color: Theme.of( + context, + ).colorScheme.primary, + ), + border: InputBorder.none, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.3), + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Theme.of( + context, + ).colorScheme.primary, + ), + ), + filled: true, + fillColor: + Theme.of(context).brightness == + Brightness.dark + ? Theme.of( + context, + ).colorScheme.surfaceContainerHighest + : Theme.of(context).colorScheme.surface, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Email é obrigatório'; + } + if (!value.contains('@')) { + return 'Email inválido'; + } + return null; + }, + ), + const SizedBox(height: 16), + + // Password field + TextFormField( + controller: _passwordController, + obscureText: _obscurePassword, + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + decoration: InputDecoration( + labelText: 'Palavra-passe', + labelStyle: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + ), + hintStyle: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + ), + prefixIcon: Icon( + Icons.lock, + color: Theme.of( + context, + ).colorScheme.primary, + ), + suffixIcon: IconButton( + icon: Icon( + _obscurePassword + ? Icons.visibility + : Icons.visibility_off, + color: Theme.of( + context, + ).colorScheme.primary, + ), + onPressed: () { + setState(() { + _obscurePassword = !_obscurePassword; + }); + }, + ), + border: InputBorder.none, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.3), + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Theme.of( + context, + ).colorScheme.primary, + ), + ), + filled: true, + fillColor: + Theme.of(context).brightness == + Brightness.dark + ? Theme.of( + context, + ).colorScheme.surfaceContainerHighest + : Theme.of(context).colorScheme.surface, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Palavra-passe é obrigatória'; + } + if (value.length < 6) { + return 'Palavra-passe muito curta'; + } + return null; + }, + ), + const SizedBox(height: 24), + + // Signup button + SizedBox( + height: 50, + child: ElevatedButton( + onPressed: _isLoading + ? null + : _handleSignup, + style: ElevatedButton.styleFrom( + backgroundColor: Theme.of( + context, + ).colorScheme.primary, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 8.0, + ), + ), + elevation: 2, + ), + child: _isLoading + ? const SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + valueColor: + AlwaysStoppedAnimation( + Colors.white, + ), + ), + ) + : Text( + 'Criar Conta', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + const SizedBox(height: 16), + + // Login link + GestureDetector( + onTap: () { + context.go('/login?role=$_selectedRole'); + }, + child: Text( + 'Já tem conta? Entrar aqui', + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.primary, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ).animate().fadeIn( + duration: const Duration(milliseconds: 1000), + ), + + const SizedBox(height: 40), + ], + ), + ), + ), + ), + ), ), - ), + // Custom back button + Positioned( + top: 50, + left: 16, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface.withOpacity(0.8), + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Theme.of( + context, + ).colorScheme.shadow.withOpacity(0.1), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: IconButton( + icon: Icon( + Icons.arrow_back, + color: Theme.of(context).colorScheme.onSurface, + ), + onPressed: () => context.go('/role-selection'), + ), + ), + ), + ], ), ), ); diff --git a/lib/features/dashboard/presentation/pages/student_dashboard_page.dart b/lib/features/dashboard/presentation/pages/student_dashboard_page.dart index 20c1376..2cc7cf5 100644 --- a/lib/features/dashboard/presentation/pages/student_dashboard_page.dart +++ b/lib/features/dashboard/presentation/pages/student_dashboard_page.dart @@ -76,15 +76,15 @@ class _StudentDashboardPageState extends State { Widget build(BuildContext context) { return Scaffold( body: Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Color(0xFF82C9BD), - Color(0xFF7BA89C), - Color(0xFFF68D2D), - Color(0xFFF8F9FA), + 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], ), diff --git a/lib/features/dashboard/presentation/pages/teacher_dashboard_page.dart b/lib/features/dashboard/presentation/pages/teacher_dashboard_page.dart index 75793bd..18984c0 100644 --- a/lib/features/dashboard/presentation/pages/teacher_dashboard_page.dart +++ b/lib/features/dashboard/presentation/pages/teacher_dashboard_page.dart @@ -71,15 +71,15 @@ class _TeacherDashboardPageState extends State { Widget build(BuildContext context) { return Scaffold( body: Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Color(0xFF82C9BD), - Color(0xFF7BA89C), - Color(0xFFF68D2D), - Color(0xFFF8F9FA), + 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], ), diff --git a/lib/features/dashboard/presentation/widgets/profile_section_widget.dart b/lib/features/dashboard/presentation/widgets/profile_section_widget.dart index ed0edaf..359203c 100644 --- a/lib/features/dashboard/presentation/widgets/profile_section_widget.dart +++ b/lib/features/dashboard/presentation/widgets/profile_section_widget.dart @@ -17,12 +17,14 @@ class ProfileSectionWidget extends StatelessWidget { margin: const EdgeInsets.only(top: 24), padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0)), + border: Border.all( + color: Theme.of(context).colorScheme.outline.withOpacity(0.2), + ), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.05), + color: Theme.of(context).colorScheme.shadow.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), @@ -38,8 +40,13 @@ class ProfileSectionWidget extends StatelessWidget { width: 48, height: 48, decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFF82C9BD), Color(0xFF6BA8A0)], + gradient: LinearGradient( + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of( + context, + ).colorScheme.primary.withOpacity(0.8), + ], ), borderRadius: BorderRadius.circular(24), ), @@ -56,8 +63,8 @@ class ProfileSectionWidget extends StatelessWidget { children: [ Text( userName, - style: const TextStyle( - color: Color(0xFF2D3748), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, fontSize: 18, fontWeight: FontWeight.bold, ), @@ -70,16 +77,20 @@ class ProfileSectionWidget extends StatelessWidget { children: [ Text( userEmail, - style: const TextStyle( - color: Color(0xFF718096), + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, fontSize: 14, ), ), if (userEmail.length > 20) ...[ const SizedBox(width: 8), - const Icon( + Icon( Icons.more_horiz, - color: Color(0xFF718096), + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, size: 16, ), ], @@ -96,12 +107,14 @@ class ProfileSectionWidget extends StatelessWidget { child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: const Color(0xFFF68D2D).withOpacity(0.1), + color: Theme.of( + context, + ).colorScheme.secondary.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), - child: const Icon( + child: Icon( Icons.settings, - color: Color(0xFFF68D2D), + color: Theme.of(context).colorScheme.secondary, size: 20, ), ), @@ -113,16 +126,16 @@ class ProfileSectionWidget extends StatelessWidget { // Achievements Row( children: [ - const Icon( + Icon( Icons.emoji_events, - color: Color(0xFFF68D2D), + color: Theme.of(context).colorScheme.secondary, size: 20, ), const SizedBox(width: 8), - const Text( + Text( 'Conquistas', style: TextStyle( - color: Color(0xFF2D3748), + color: Theme.of(context).colorScheme.onSurface, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -137,25 +150,27 @@ class ProfileSectionWidget extends StatelessWidget { _buildAchievementBadge( icon: Icons.local_fire_department, label: '7 dias', - color: const Color(0xFFF68D2D), + color: Theme.of(context).colorScheme.secondary, ), const SizedBox(width: 12), _buildAchievementBadge( icon: Icons.school, label: '3 conceitos', - color: const Color(0xFF82C9BD), + color: Theme.of(context).colorScheme.primary, ), const SizedBox(width: 12), _buildAchievementBadge( icon: Icons.speed, label: 'Rápido', - color: const Color(0xFF6BA8A0), + color: Theme.of( + context, + ).colorScheme.primary.withOpacity(0.8), ), const SizedBox(width: 12), _buildAchievementBadge( icon: Icons.star, label: '100%', - color: const Color(0xFF4CAF50), + color: Theme.of(context).colorScheme.tertiary, ), ], ), @@ -165,15 +180,21 @@ class ProfileSectionWidget extends StatelessWidget { Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: const Color(0xFFF8F9FA), + color: Theme.of(context).brightness == Brightness.dark + ? Theme.of(context).colorScheme.surfaceContainerHighest + : Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(12), - border: Border.all(color: const Color(0xFFE2E8F0)), + border: Border.all( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.2), + ), ), child: Row( children: [ - const Icon( + Icon( Icons.trending_up, - color: Color(0xFF82C9BD), + color: Theme.of(context).colorScheme.primary, size: 20, ), const SizedBox(width: 12), @@ -181,10 +202,10 @@ class ProfileSectionWidget extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + Text( 'Ótimo progresso!', style: TextStyle( - color: Color(0xFF2D3748), + color: Theme.of(context).colorScheme.onSurface, fontSize: 14, fontWeight: FontWeight.bold, ), @@ -192,8 +213,10 @@ class ProfileSectionWidget extends StatelessWidget { const SizedBox(height: 2), Text( 'Você está 15% acima da média esta semana', - style: const TextStyle( - color: Color(0xFF718096), + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, fontSize: 12, ), ), diff --git a/lib/features/dashboard/presentation/widgets/progress_hero_widget.dart b/lib/features/dashboard/presentation/widgets/progress_hero_widget.dart index a359d4c..4eca529 100644 --- a/lib/features/dashboard/presentation/widgets/progress_hero_widget.dart +++ b/lib/features/dashboard/presentation/widgets/progress_hero_widget.dart @@ -39,7 +39,7 @@ class ProgressHeroWidget extends StatelessWidget { Text( 'Seu Progresso', style: TextStyle( - color: const Color(0xFF2D3748), + color: Theme.of(context).colorScheme.onSurface, fontSize: 24, fontWeight: FontWeight.bold, ), @@ -48,7 +48,7 @@ class ProgressHeroWidget extends StatelessWidget { Text( 'Continue assim, $userName!', style: TextStyle( - color: const Color(0xFF718096), + color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 16, ), ), @@ -56,9 +56,12 @@ class ProgressHeroWidget extends StatelessWidget { ), ), Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), decoration: BoxDecoration( - color: const Color(0xFF82C9BD), + color: Theme.of(context).colorScheme.primary, borderRadius: BorderRadius.circular(20), ), child: Row( @@ -93,8 +96,8 @@ class ProgressHeroWidget extends StatelessWidget { begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ - const Color(0xFF82C9BD), - const Color(0xFF6BA8A0), + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.primary.withOpacity(0.8), ], ), borderRadius: BorderRadius.circular(20), @@ -132,7 +135,7 @@ class ProgressHeroWidget extends StatelessWidget { ], ), const SizedBox(height: 16), - + // Progress Bar Container( height: 12, @@ -186,77 +189,90 @@ class ProgressHeroWidget extends StatelessWidget { // Mastered Concepts Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon( - Icons.school, - color: Color(0xFFF68D2D), - size: 20, + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.2), + ), + boxShadow: [ + BoxShadow( + color: Theme.of( + context, + ).colorScheme.shadow.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 4), ), - const SizedBox(width: 8), - const Text( - 'Conceitos Dominados', - style: TextStyle( - color: Color(0xFF2D3748), - fontSize: 16, - fontWeight: FontWeight.bold, + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + Icons.school, + color: Theme.of(context).colorScheme.secondary, + size: 20, + ), + const SizedBox(width: 8), + Text( + 'Conceitos Dominados', + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 12), + ...masteredConcepts.map( + (concept) => Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Row( + children: [ + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary, + shape: BoxShape.circle, + ), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + concept, + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + fontSize: 14, + ), + ), + ), + Icon( + Icons.check_circle, + color: Theme.of(context).colorScheme.primary, + size: 16, + ), + ], + ), ), ), ], ), - const SizedBox(height: 12), - ...masteredConcepts.map((concept) => Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Row( - children: [ - Container( - width: 8, - height: 8, - decoration: const BoxDecoration( - color: Color(0xFF82C9BD), - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 12), - Expanded( - child: Text( - concept, - style: const TextStyle( - color: Color(0xFF4A5568), - fontSize: 14, - ), - ), - ), - const Icon( - Icons.check_circle, - color: Color(0xFF82C9BD), - size: 16, - ), - ], - ), - )), - ], - ), - ).animate().slideX( - duration: const Duration(milliseconds: 800), - curve: Curves.easeOut, - ).then(delay: const Duration(milliseconds: 200)), + ) + .animate() + .slideX( + duration: const Duration(milliseconds: 800), + curve: Curves.easeOut, + ) + .then(delay: const Duration(milliseconds: 200)), ], ), ); @@ -272,10 +288,7 @@ class ProgressHeroWidget extends StatelessWidget { decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(12), - border: Border.all( - color: Colors.white.withOpacity(0.3), - width: 1, - ), + border: Border.all(color: Colors.white.withOpacity(0.3), width: 1), ), child: Column( children: [ @@ -292,10 +305,7 @@ class ProgressHeroWidget extends StatelessWidget { const SizedBox(height: 4), Text( label, - style: const TextStyle( - color: Colors.white, - fontSize: 12, - ), + style: const TextStyle(color: Colors.white, fontSize: 12), textAlign: TextAlign.center, ), ], diff --git a/lib/features/dashboard/presentation/widgets/quick_access_widget.dart b/lib/features/dashboard/presentation/widgets/quick_access_widget.dart index e01a1d6..e2c4eb7 100644 --- a/lib/features/dashboard/presentation/widgets/quick_access_widget.dart +++ b/lib/features/dashboard/presentation/widgets/quick_access_widget.dart @@ -15,7 +15,7 @@ class QuickAccessWidget extends StatelessWidget { Text( 'Acesso Rápido', style: TextStyle( - color: const Color(0xFF2D3748), + color: Theme.of(context).colorScheme.onSurface, fontSize: 20, fontWeight: FontWeight.bold, ), @@ -48,15 +48,18 @@ class QuickAccessWidget extends StatelessWidget { return Container( height: 150, decoration: BoxDecoration( - gradient: const LinearGradient( + gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, - colors: [Color(0xFF82C9BD), Color(0xFF6BA8A0)], + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.primary.withOpacity(0.8), + ], ), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: const Color(0xFF82C9BD).withOpacity(0.3), + color: Theme.of(context).colorScheme.primary.withOpacity(0.3), blurRadius: 15, offset: const Offset(0, 8), ), @@ -102,7 +105,7 @@ class QuickAccessWidget extends StatelessWidget { vertical: 4, ), decoration: BoxDecoration( - color: const Color(0xFFF68D2D), + color: Theme.of(context).colorScheme.secondary, borderRadius: BorderRadius.circular(12), ), child: const Text( @@ -159,12 +162,15 @@ class QuickAccessWidget extends StatelessWidget { return Container( height: 150, decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0), width: 1), + border: Border.all( + color: Theme.of(context).colorScheme.outline.withOpacity(0.2), + width: 1, + ), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.05), + color: Theme.of(context).colorScheme.shadow.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), @@ -192,34 +198,38 @@ class QuickAccessWidget extends StatelessWidget { Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: const Color(0xFFF68D2D).withOpacity(0.1), + color: Theme.of( + context, + ).colorScheme.secondary.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), - child: const Icon( + child: Icon( Icons.quiz, - color: Color(0xFFF68D2D), + color: Theme.of(context).colorScheme.secondary, size: 24, ), ), const SizedBox(height: 12), - const Column( + Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Quiz', style: TextStyle( - color: Color(0xFF2D3748), + color: Theme.of(context).colorScheme.onSurface, fontSize: 16, fontWeight: FontWeight.bold, ), ), - SizedBox(height: 4), + const SizedBox(height: 4), Text( - 'Teste conhecimentos', + 'Testa os teus conhecimentos', maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle( - color: Color(0xFF718096), + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, fontSize: 12, height: 1.2, ), @@ -242,14 +252,17 @@ class QuickAccessWidget extends StatelessWidget { Widget _buildJoinClassCard(BuildContext context) { return Container( - height: 80, + height: 86, decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0), width: 1), + border: Border.all( + color: Theme.of(context).colorScheme.outline.withOpacity(0.2), + width: 1, + ), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.05), + color: Theme.of(context).colorScheme.shadow.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), @@ -262,9 +275,7 @@ class QuickAccessWidget extends StatelessWidget { onTap: () { Navigator.push( context, - MaterialPageRoute( - builder: (_) => const JoinClassPage(), - ), + MaterialPageRoute(builder: (_) => const JoinClassPage()), ); }, child: Padding( @@ -274,17 +285,19 @@ class QuickAccessWidget extends StatelessWidget { Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: const Color(0xFF82C9BD).withOpacity(0.1), + color: Theme.of( + context, + ).colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), - child: const Icon( + child: Icon( Icons.group_add, - color: Color(0xFF82C9BD), + color: Theme.of(context).colorScheme.primary, size: 24, ), ), const SizedBox(width: 16), - const Expanded( + Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, @@ -292,27 +305,29 @@ class QuickAccessWidget extends StatelessWidget { Text( 'Entrar numa Turma', style: TextStyle( - color: Color(0xFF2D3748), + color: Theme.of(context).colorScheme.onSurface, fontSize: 16, fontWeight: FontWeight.bold, ), ), - SizedBox(height: 4), + const SizedBox(height: 4), Text( 'Junta-te a uma turma com o código', maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( - color: Color(0xFF718096), + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, fontSize: 13, ), ), ], ), ), - const Icon( + Icon( Icons.arrow_forward_ios, - color: Color(0xFF82C9BD), + color: Theme.of(context).colorScheme.primary, size: 16, ), ], diff --git a/lib/features/dashboard/presentation/widgets/student_classes_list_widget.dart b/lib/features/dashboard/presentation/widgets/student_classes_list_widget.dart index 5a73d04..699ec8b 100644 --- a/lib/features/dashboard/presentation/widgets/student_classes_list_widget.dart +++ b/lib/features/dashboard/presentation/widgets/student_classes_list_widget.dart @@ -23,11 +23,11 @@ class StudentClassesListWidget extends StatelessWidget { .snapshots(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { - return const Center( + return Center( child: Padding( - padding: EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16.0), child: CircularProgressIndicator( - color: Color(0xFF82C9BD), + color: Theme.of(context).colorScheme.primary, ), ), ); @@ -44,10 +44,7 @@ class StudentClassesListWidget extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 16.0), child: Text( 'Ainda não entraste em nenhuma turma.', - style: TextStyle( - color: Colors.grey[600], - fontSize: 14, - ), + style: TextStyle(color: Colors.grey[600], fontSize: 14), ), ); } @@ -58,9 +55,9 @@ class StudentClassesListWidget extends StatelessWidget { Text( 'As Minhas Turmas', style: Theme.of(context).textTheme.titleLarge?.copyWith( - color: const Color(0xFF2D3748), - fontWeight: FontWeight.bold, - ), + color: Theme.of(context).colorScheme.onSurface, + fontWeight: FontWeight.bold, + ), ), const SizedBox(height: 16), SizedBox( @@ -102,7 +99,10 @@ class StudentClassesListWidget extends StatelessWidget { } return FutureBuilder( - future: FirebaseFirestore.instance.collection('classes').doc(classId).get(), + future: FirebaseFirestore.instance + .collection('classes') + .doc(classId) + .get(), builder: (context, snapshot) { if (!snapshot.hasData || !snapshot.data!.exists) { return Container( @@ -110,19 +110,19 @@ class StudentClassesListWidget extends StatelessWidget { height: 150, padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.05), + color: Theme.of(context).colorScheme.shadow.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), - child: const Center( + child: Center( child: CircularProgressIndicator( - color: Color(0xFF82C9BD), + color: Theme.of(context).colorScheme.primary, strokeWidth: 2, ), ), @@ -138,11 +138,11 @@ class StudentClassesListWidget extends StatelessWidget { height: 150, padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.05), + color: Theme.of(context).colorScheme.shadow.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), @@ -155,20 +155,20 @@ class StudentClassesListWidget extends StatelessWidget { Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: const Color(0xFF82C9BD).withOpacity(0.1), + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), - child: const Icon( + child: Icon( Icons.school, - color: Color(0xFF82C9BD), + color: Theme.of(context).colorScheme.primary, size: 24, ), ), const SizedBox(height: 12), Text( className, - style: const TextStyle( - color: Color(0xFF2D3748), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -179,7 +179,7 @@ class StudentClassesListWidget extends StatelessWidget { Text( 'Código: $classCode', style: TextStyle( - color: Colors.grey[600], + color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 13, ), ), diff --git a/lib/features/dashboard/presentation/widgets/teacher_analytics_preview_widget.dart b/lib/features/dashboard/presentation/widgets/teacher_analytics_preview_widget.dart index fe24639..1b4bd1c 100644 --- a/lib/features/dashboard/presentation/widgets/teacher_analytics_preview_widget.dart +++ b/lib/features/dashboard/presentation/widgets/teacher_analytics_preview_widget.dart @@ -13,207 +13,248 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget { final userEmail = user?.email ?? ''; return Container( - margin: const EdgeInsets.only(top: 24), - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Profile Header - Row( - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFF82C9BD), Color(0xFF6BA8A0)], - ), - borderRadius: BorderRadius.circular(24), - ), - child: const Icon( - Icons.school, - color: Colors.white, - size: 24, - ), + margin: const EdgeInsets.only(top: 24), + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: Theme.of(context).colorScheme.outline.withOpacity(0.2), + ), + boxShadow: [ + BoxShadow( + color: Theme.of(context).colorScheme.shadow.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 4), ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - userName, - style: const TextStyle( - color: Color(0xFF2D3748), - fontSize: 18, - fontWeight: FontWeight.bold, + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Profile Header + Row( + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of( + context, + ).colorScheme.primary.withOpacity(0.8), + ], ), + borderRadius: BorderRadius.circular(24), ), - const SizedBox(height: 2), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - mainAxisSize: MainAxisSize.min, + child: const Icon( + Icons.school, + color: Colors.white, + size: 24, + ), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + userName, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 2), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + userEmail, + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + fontSize: 14, + ), + ), + if (userEmail.length > 20) ...[ + const SizedBox(width: 8), + Icon( + Icons.more_horiz, + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + size: 16, + ), + ], + ], + ), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: Theme.of( + context, + ).colorScheme.secondary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon( + Icons.settings, + color: Theme.of(context).colorScheme.secondary, + size: 20, + ), + ), + ], + ), + const SizedBox(height: 20), + + // Quick Stats Row + Row( + children: [ + _buildQuickStat( + icon: Icons.check_circle, + label: 'Alunos Ativos', + value: '18/24', + color: Theme.of(context).colorScheme.primary, + ), + const SizedBox(width: 12), + _buildQuickStat( + icon: Icons.warning_amber, + label: 'Precisam Apoio', + value: '3', + color: Theme.of(context).colorScheme.secondary, + ), + const SizedBox(width: 12), + _buildQuickStat( + icon: Icons.emoji_events, + label: 'Média Turma', + value: '72%', + color: Theme.of( + context, + ).colorScheme.primary.withOpacity(0.8), + ), + ], + ), + const SizedBox(height: 20), + + // Top Performing Students Preview + Row( + children: [ + Icon( + Icons.leaderboard, + color: Theme.of(context).colorScheme.secondary, + size: 20, + ), + const SizedBox(width: 8), + Text( + 'Melhores Desempenhos', + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + 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, + ), + + const SizedBox(height: 20), + + // Content Quality Alert + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainerHighest, + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.2), + ), + ), + child: Row( + children: [ + Icon( + Icons.info_outline, + color: Theme.of(context).colorScheme.primary, + size: 20, + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - userEmail, - style: const TextStyle( - color: Color(0xFF718096), + 'Qualidade do Conteúdo', + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, fontSize: 14, + fontWeight: FontWeight.bold, ), ), - if (userEmail.length > 20) ...[ - const SizedBox(width: 8), - const Icon( - Icons.more_horiz, - color: Color(0xFF718096), - size: 16, + const SizedBox(height: 2), + Text( + '12 conteúdos verificados • 2 pendentes de revisão', + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + fontSize: 12, ), - ], + ), ], ), ), ], ), ), - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: const Color(0xFFF68D2D).withOpacity(0.1), - borderRadius: BorderRadius.circular(8), - ), - child: const Icon( - Icons.settings, - color: Color(0xFFF68D2D), - size: 20, - ), - ), ], ), - const SizedBox(height: 20), - - // Quick Stats Row - Row( - children: [ - _buildQuickStat( - icon: Icons.check_circle, - label: 'Alunos Ativos', - value: '18/24', - color: const Color(0xFF82C9BD), - ), - const SizedBox(width: 12), - _buildQuickStat( - icon: Icons.warning_amber, - label: 'Precisam Apoio', - value: '3', - color: const Color(0xFFF68D2D), - ), - const SizedBox(width: 12), - _buildQuickStat( - icon: Icons.emoji_events, - label: 'Média Turma', - value: '72%', - color: const Color(0xFF6BA8A0), - ), - ], - ), - const SizedBox(height: 20), - - // Top Performing Students Preview - Row( - children: [ - const Icon( - Icons.leaderboard, - color: Color(0xFFF68D2D), - size: 20, - ), - const SizedBox(width: 8), - const Text( - 'Melhores Desempenhos', - style: TextStyle( - color: Color(0xFF2D3748), - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 12), - - // Student List Preview - _buildStudentPerformanceItem('Ana Silva', 95, const Color(0xFF4CAF50)), - const SizedBox(height: 8), - _buildStudentPerformanceItem('João Costa', 88, const Color(0xFF82C9BD)), - const SizedBox(height: 8), - _buildStudentPerformanceItem('Maria Santos', 82, const Color(0xFF82C9BD)), - const SizedBox(height: 8), - _buildStudentPerformanceItem('Pedro Lima', 45, const Color(0xFFF68D2D)), - - const SizedBox(height: 20), - - // Content Quality Alert - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFF8F9FA), - borderRadius: BorderRadius.circular(12), - border: Border.all(color: const Color(0xFFE2E8F0)), - ), - child: Row( - children: [ - const Icon( - Icons.info_outline, - color: Color(0xFF82C9BD), - size: 20, - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Qualidade do Conteúdo', - style: TextStyle( - color: Color(0xFF2D3748), - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 2), - Text( - '12 conteúdos verificados • 2 pendentes de revisão', - style: const TextStyle( - color: Color(0xFF718096), - fontSize: 12, - ), - ), - ], - ), - ), - ], - ), - ), - ], - ), - ) - .animate() - .slideY( - duration: const Duration(milliseconds: 800), - curve: Curves.easeOut, - ) - .then(delay: const Duration(milliseconds: 400)); + ) + .animate() + .slideY( + duration: const Duration(milliseconds: 800), + curve: Curves.easeOut, + ) + .then(delay: const Duration(milliseconds: 400)); } Widget _buildQuickStat({ @@ -245,10 +286,7 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget { const SizedBox(height: 2), Text( label, - style: TextStyle( - color: color.withOpacity(0.8), - fontSize: 10, - ), + style: TextStyle(color: color.withOpacity(0.8), fontSize: 10), textAlign: TextAlign.center, ), ], @@ -257,7 +295,12 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget { ); } - Widget _buildStudentPerformanceItem(String name, int score, Color color) { + Widget _buildStudentPerformanceItem( + BuildContext context, + String name, + int score, + Color color, + ) { return Row( children: [ Container( @@ -282,8 +325,8 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget { Expanded( child: Text( name, - style: const TextStyle( - color: Color(0xFF4A5568), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 14, ), ), diff --git a/lib/features/dashboard/presentation/widgets/teacher_classes_list_widget.dart b/lib/features/dashboard/presentation/widgets/teacher_classes_list_widget.dart index 5729a3f..bd3b77c 100644 --- a/lib/features/dashboard/presentation/widgets/teacher_classes_list_widget.dart +++ b/lib/features/dashboard/presentation/widgets/teacher_classes_list_widget.dart @@ -24,11 +24,11 @@ class TeacherClassesListWidget extends StatelessWidget { .snapshots(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { - return const Center( + return Center( child: Padding( - padding: EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16.0), child: CircularProgressIndicator( - color: Color(0xFF82C9BD), + color: Theme.of(context).colorScheme.primary, ), ), ); @@ -46,7 +46,7 @@ class TeacherClassesListWidget extends StatelessWidget { child: Text( 'Ainda não criaste nenhuma turma.', style: TextStyle( - color: Colors.grey[600], + color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 14, ), ), @@ -59,9 +59,9 @@ class TeacherClassesListWidget extends StatelessWidget { Text( 'As Minhas Turmas', style: Theme.of(context).textTheme.titleLarge?.copyWith( - color: const Color(0xFF2D3748), - fontWeight: FontWeight.bold, - ), + color: Theme.of(context).colorScheme.onSurface, + fontWeight: FontWeight.bold, + ), ), const SizedBox(height: 16), SizedBox( @@ -105,10 +105,8 @@ class TeacherClassesListWidget extends StatelessWidget { Navigator.push( context, MaterialPageRoute( - builder: (_) => ClassStudentsPage( - classId: classId, - className: className, - ), + builder: (_) => + ClassStudentsPage(classId: classId, className: className), ), ); }, @@ -117,11 +115,11 @@ class TeacherClassesListWidget extends StatelessWidget { height: 150, padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.05), + color: Theme.of(context).colorScheme.shadow.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), @@ -134,20 +132,20 @@ class TeacherClassesListWidget extends StatelessWidget { Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: const Color(0xFF82C9BD).withOpacity(0.1), + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), - child: const Icon( + child: Icon( Icons.school, - color: Color(0xFF82C9BD), + color: Theme.of(context).colorScheme.primary, size: 24, ), ), const SizedBox(height: 12), Text( className, - style: const TextStyle( - color: Color(0xFF2D3748), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -158,7 +156,7 @@ class TeacherClassesListWidget extends StatelessWidget { Text( 'Código: $classCode', style: TextStyle( - color: Colors.grey[600], + color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 13, ), ), diff --git a/lib/features/dashboard/presentation/widgets/teacher_hero_widget.dart b/lib/features/dashboard/presentation/widgets/teacher_hero_widget.dart index 3711a85..00d9c90 100644 --- a/lib/features/dashboard/presentation/widgets/teacher_hero_widget.dart +++ b/lib/features/dashboard/presentation/widgets/teacher_hero_widget.dart @@ -35,7 +35,7 @@ class TeacherHeroWidget extends StatelessWidget { Text( 'Visão Geral da Turma', style: TextStyle( - color: const Color(0xFF2D3748), + color: Theme.of(context).colorScheme.onSurface, fontSize: 24, fontWeight: FontWeight.bold, ), @@ -44,7 +44,7 @@ class TeacherHeroWidget extends StatelessWidget { Text( 'Acompanhe o progresso dos seus alunos', style: TextStyle( - color: const Color(0xFF718096), + color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 16, ), ), @@ -52,19 +52,18 @@ class TeacherHeroWidget extends StatelessWidget { ), ), Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), decoration: BoxDecoration( - color: const Color(0xFFF68D2D), + color: Theme.of(context).colorScheme.secondary, borderRadius: BorderRadius.circular(20), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ - const Icon( - Icons.people, - color: Colors.white, - size: 16, - ), + const Icon(Icons.people, color: Colors.white, size: 16), const SizedBox(width: 4), Text( '$totalStudents alunos', @@ -89,14 +88,14 @@ class TeacherHeroWidget extends StatelessWidget { begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ - const Color(0xFF82C9BD), - const Color(0xFF6BA8A0), + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.primary.withOpacity(0.8), ], ), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.1), + color: Theme.of(context).colorScheme.shadow.withOpacity(0.1), blurRadius: 20, offset: const Offset(0, 10), ), @@ -128,7 +127,7 @@ class TeacherHeroWidget extends StatelessWidget { ], ), const SizedBox(height: 16), - + // Progress Bar Container( height: 12, @@ -182,64 +181,76 @@ class TeacherHeroWidget extends StatelessWidget { // Recent Activity Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon( - Icons.trending_up, - color: Color(0xFFF68D2D), - size: 20, - ), - const SizedBox(width: 8), - const Text( - 'Atividade Recente', - style: TextStyle( - color: Color(0xFF2D3748), - fontSize: 16, - fontWeight: FontWeight.bold, - ), + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.2), + ), + boxShadow: [ + BoxShadow( + color: Theme.of( + context, + ).colorScheme.shadow.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 4), ), ], ), - const SizedBox(height: 12), - _buildActivityItem( - '15 alunos completaram o quiz de Derivadas', - 'Hoje, 14:30', - const Color(0xFF82C9BD), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + Icons.trending_up, + color: Theme.of(context).colorScheme.secondary, + size: 20, + ), + const SizedBox(width: 8), + Text( + 'Atividade Recente', + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + 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, + ), + ], ), - const SizedBox(height: 8), - _buildActivityItem( - 'Novo conteúdo: Regra da Cadeia', - 'Ontem, 09:15', - const Color(0xFFF68D2D), - ), - const SizedBox(height: 8), - _buildActivityItem( - '3 alunos precisam de apoio em Limites', - 'Ontem, 16:45', - const Color(0xFFE53E3E), - ), - ], - ), - ).animate().slideX( - duration: const Duration(milliseconds: 800), - curve: Curves.easeOut, - ).then(delay: const Duration(milliseconds: 200)), + ) + .animate() + .slideX( + duration: const Duration(milliseconds: 800), + curve: Curves.easeOut, + ) + .then(delay: const Duration(milliseconds: 200)), ], ), ); @@ -255,10 +266,7 @@ class TeacherHeroWidget extends StatelessWidget { decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(12), - border: Border.all( - color: Colors.white.withOpacity(0.3), - width: 1, - ), + border: Border.all(color: Colors.white.withOpacity(0.3), width: 1), ), child: Column( children: [ @@ -275,10 +283,7 @@ class TeacherHeroWidget extends StatelessWidget { const SizedBox(height: 4), Text( label, - style: const TextStyle( - color: Colors.white, - fontSize: 12, - ), + style: const TextStyle(color: Colors.white, fontSize: 12), textAlign: TextAlign.center, ), ], @@ -286,16 +291,18 @@ class TeacherHeroWidget extends StatelessWidget { ); } - Widget _buildActivityItem(String text, String time, Color color) { + Widget _buildActivityItem( + BuildContext context, + String text, + String time, + Color color, + ) { return Row( children: [ Container( width: 8, height: 8, - decoration: BoxDecoration( - color: color, - shape: BoxShape.circle, - ), + decoration: BoxDecoration(color: color, shape: BoxShape.circle), ), const SizedBox(width: 12), Expanded( @@ -304,16 +311,18 @@ class TeacherHeroWidget extends StatelessWidget { children: [ Text( text, - style: const TextStyle( - color: Color(0xFF4A5568), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 14, ), ), const SizedBox(height: 2), Text( time, - style: const TextStyle( - color: Color(0xFF718096), + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant.withOpacity(0.7), fontSize: 12, ), ), diff --git a/lib/features/dashboard/presentation/widgets/teacher_quick_actions_widget.dart b/lib/features/dashboard/presentation/widgets/teacher_quick_actions_widget.dart index 967e6b9..4e0e9e0 100644 --- a/lib/features/dashboard/presentation/widgets/teacher_quick_actions_widget.dart +++ b/lib/features/dashboard/presentation/widgets/teacher_quick_actions_widget.dart @@ -13,7 +13,8 @@ class TeacherQuickActionsWidget extends StatefulWidget { const TeacherQuickActionsWidget({super.key}); @override - State createState() => _TeacherQuickActionsWidgetState(); + State createState() => + _TeacherQuickActionsWidgetState(); } class _TeacherQuickActionsWidgetState extends State { @@ -22,463 +23,494 @@ class _TeacherQuickActionsWidgetState extends State { @override Widget build(BuildContext context) { return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Ações Rápidas', - style: TextStyle( - color: const Color(0xFF2D3748), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 16), - - // Primary Actions Row - Row( + crossAxisAlignment: CrossAxisAlignment.start, 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), + Text( + 'Ações Rápidas', + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 16), - // Secondary Actions Row - Row( - children: [ - // Manage Students Card - Expanded(child: _buildManageStudentsCard(context)), - const SizedBox(width: 16), - // View Analytics Card - Expanded(child: _buildViewAnalyticsCard(context)), + // 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: [ + // Manage Students Card + Expanded(child: _buildManageStudentsCard(context)), + const SizedBox(width: 16), + // View Analytics Card + Expanded(child: _buildViewAnalyticsCard(context)), + ], + ), ], - ), - ], - ) - .animate() - .slideY( - duration: const Duration(milliseconds: 800), - curve: Curves.easeOut, - ) - .then(delay: const Duration(milliseconds: 200)); + ) + .animate() + .slideY( + duration: const Duration(milliseconds: 800), + curve: Curves.easeOut, + ) + .then(delay: const Duration(milliseconds: 200)); } Widget _buildUploadContentCard(BuildContext context) { return Container( - constraints: const BoxConstraints(minHeight: 135, maxHeight: 160), - decoration: BoxDecoration( - gradient: const LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [Color(0xFF82C9BD), Color(0xFF6BA8A0)], - ), - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: const Color(0xFF82C9BD).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(14), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - 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: 22, - ), - ), - const Spacer(), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 3, - ), - decoration: BoxDecoration( - color: const Color(0xFFF68D2D), - borderRadius: BorderRadius.circular(10), - ), - child: const Text( - 'NOVO', - style: TextStyle( - color: Colors.white, - fontSize: 9, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - const Spacer(), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Upload Conteúdo', - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - SizedBox(height: 4), - Text( - 'PDFs, textos, imagens', - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Colors.white, - fontSize: 12, - height: 1.2, - ), - ), - ], - ), + constraints: const BoxConstraints(minHeight: 135, maxHeight: 160), + 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), + ), + ], ), - ), - ), - ) - .animate() - .scale( - duration: const Duration(milliseconds: 600), - curve: Curves.elasticOut, - ) - .then(delay: const Duration(milliseconds: 100)); + 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(14), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + 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: 22, + ), + ), + const Spacer(), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + 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, + ), + ), + ), + ], + ), + const Spacer(), + const Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Upload Conteúdo', + style: TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 4), + Text( + 'PDFs, textos, imagens', + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Colors.white, + fontSize: 12, + height: 1.2, + ), + ), + ], + ), + ], + ), + ), + ), + ), + ) + .animate() + .scale( + duration: const Duration(milliseconds: 600), + curve: Curves.elasticOut, + ) + .then(delay: const Duration(milliseconds: 100)); } Widget _buildCreateQuizCard(BuildContext context) { return Container( - height: 150, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0), width: 1), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 10, - offset: const Offset(0, 4), + 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(14), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: const Color(0xFFF68D2D).withOpacity(0.1), - borderRadius: BorderRadius.circular(10), - ), - child: const Icon( - Icons.quiz, - color: Color(0xFFF68D2D), - size: 24, - ), - ), - Column( + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(16), + onTap: () => context.go('/teacher/quiz/create'), + child: Padding( + padding: const EdgeInsets.all(14), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Text( - 'Criar Quiz', - style: TextStyle( - color: Color(0xFF2D3748), - fontSize: 16, - fontWeight: FontWeight.bold, + 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: 4), - Text( - 'Avaliações interativas', - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: const Color(0xFF718096), - fontSize: 12, - height: 1.2, - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Criar Quiz', + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4), + Text( + 'Avaliações interativas', + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + fontSize: 12, + height: 1.2, + ), + ), + ], ), ], ), - ], + ), ), ), - ), - ), - ) - .animate() - .scale( - duration: const Duration(milliseconds: 600), - curve: Curves.elasticOut, - ) - .then(delay: const Duration(milliseconds: 200)); + ) + .animate() + .scale( + duration: const Duration(milliseconds: 600), + curve: Curves.elasticOut, + ) + .then(delay: const Duration(milliseconds: 200)); } Widget _buildManageStudentsCard(BuildContext context) { return Container( - height: 120, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0), width: 1), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 10, - offset: const Offset(0, 4), + 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/students'), - 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: const Color(0xFF82C9BD).withOpacity(0.1), - borderRadius: BorderRadius.circular(10), - ), - child: const Icon( - Icons.people, - color: Color(0xFF82C9BD), - size: 20, - ), - ), - const Column( + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(16), + onTap: () => context.go('/teacher/students'), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - 'Gerir Alunos', - style: TextStyle( - color: Color(0xFF2D3748), - fontSize: 14, - fontWeight: FontWeight.bold, + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: Theme.of( + context, + ).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(10), + ), + child: Icon( + Icons.people, + color: Theme.of(context).colorScheme.primary, + size: 20, ), ), - Text( - 'Acesso e permissões', - style: TextStyle( - color: Color(0xFF718096), - fontSize: 11, - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Gerir Alunos', + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + Text( + 'Acesso e permissões', + 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: 300)); + ) + .animate() + .scale( + duration: const Duration(milliseconds: 600), + curve: Curves.elasticOut, + ) + .then(delay: const Duration(milliseconds: 300)); } Widget _buildViewAnalyticsCard(BuildContext context) { return Container( - height: 120, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0), width: 1), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 10, - offset: const Offset(0, 4), + 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: const Color(0xFF6BA8A0).withOpacity(0.1), - borderRadius: BorderRadius.circular(10), - ), - child: const Icon( - Icons.analytics, - color: Color(0xFF6BA8A0), - size: 20, - ), - ), - const Column( + 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: [ - Text( - 'Analytics', - style: TextStyle( - color: Color(0xFF2D3748), - fontSize: 14, - fontWeight: FontWeight.bold, + 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, ), ), - Text( - 'Desempenho da turma', - style: TextStyle( - color: Color(0xFF718096), - fontSize: 11, - ), + 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, + ), + ), + ], ), ], ), - ], + ), ), ), - ), - ), - ) - .animate() - .scale( - duration: const Duration(milliseconds: 600), - curve: Curves.elasticOut, - ) - .then(delay: const Duration(milliseconds: 400)); + ) + .animate() + .scale( + duration: const Duration(milliseconds: 600), + curve: Curves.elasticOut, + ) + .then(delay: const Duration(milliseconds: 400)); } Widget _buildCreateClassCard(BuildContext context) { return Container( - constraints: const BoxConstraints(minHeight: 135, maxHeight: 160), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0), width: 1), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 10, - offset: const Offset(0, 4), + constraints: const BoxConstraints(minHeight: 135, maxHeight: 160), + 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(14), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: const Color(0xFF82C9BD).withOpacity(0.1), - borderRadius: BorderRadius.circular(10), - ), - child: _isCreatingClass - ? const SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - strokeWidth: 2, - color: Color(0xFF82C9BD), - ), - ) - : const Icon( - Icons.school, - color: Color(0xFF82C9BD), - size: 24, - ), - ), - Column( + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(16), + onTap: _isCreatingClass + ? null + : () => _showCreateClassDialog(context), + child: Padding( + padding: const EdgeInsets.all(14), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - 'Criar Turma', - style: TextStyle( - color: const Color(0xFF2D3748), - fontSize: 16, - fontWeight: FontWeight.bold, + Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Theme.of( + context, + ).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(10), ), + child: _isCreatingClass + ? SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Theme.of(context).colorScheme.primary, + ), + ) + : Icon( + Icons.school, + color: Theme.of(context).colorScheme.primary, + size: 24, + ), ), - const SizedBox(height: 4), - Text( - 'Gerar código de acesso', - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: const Color(0xFF718096), - fontSize: 12, - height: 1.2, - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Criar Turma', + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4), + Text( + 'Gerar código de acesso', + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, + fontSize: 12, + height: 1.2, + ), + ), + ], ), ], ), - ], + ), ), ), - ), - ), - ) - .animate() - .scale( - duration: const Duration(milliseconds: 600), - curve: Curves.elasticOut, - ) - .then(delay: const Duration(milliseconds: 150)); + ) + .animate() + .scale( + duration: const Duration(milliseconds: 600), + curve: Curves.elasticOut, + ) + .then(delay: const Duration(milliseconds: 150)); } void _showCreateClassDialog(BuildContext context) { @@ -491,10 +523,10 @@ class _TeacherQuickActionsWidgetState extends State { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), - title: const Text( + title: Text( 'Criar Nova Turma', style: TextStyle( - color: Color(0xFF2D3748), + color: Theme.of(context).colorScheme.onSurface, fontWeight: FontWeight.bold, ), ), @@ -502,10 +534,10 @@ class _TeacherQuickActionsWidgetState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + Text( 'Digite o nome da turma:', style: TextStyle( - color: Color(0xFF718096), + color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 14, ), ), @@ -515,7 +547,9 @@ class _TeacherQuickActionsWidgetState extends State { decoration: InputDecoration( hintText: 'Ex: Matemática 9º Ano', filled: true, - fillColor: const Color(0xFFF7FAFC), + fillColor: Theme.of( + context, + ).colorScheme.surfaceContainerHighest, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, @@ -526,8 +560,8 @@ class _TeacherQuickActionsWidgetState extends State { ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: Color(0xFF82C9BD), + borderSide: BorderSide( + color: Theme.of(context).colorScheme.primary, width: 2, ), ), @@ -538,9 +572,11 @@ class _TeacherQuickActionsWidgetState extends State { actions: [ TextButton( onPressed: () => Navigator.of(dialogContext).pop(), - child: const Text( + child: Text( 'Cancelar', - style: TextStyle(color: Color(0xFF718096)), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ), ElevatedButton( @@ -552,7 +588,7 @@ class _TeacherQuickActionsWidgetState extends State { } }, style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF82C9BD), + backgroundColor: Theme.of(context).colorScheme.primary, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), @@ -601,8 +637,10 @@ class _TeacherQuickActionsWidgetState extends State { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text('Turma "$className" criada com sucesso! Código: $classCode'), - backgroundColor: const Color(0xFF82C9BD), + content: Text( + 'Turma "$className" criada com sucesso! Código: $classCode', + ), + backgroundColor: Theme.of(context).colorScheme.primary, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), diff --git a/lib/features/profile/presentation/pages/profile_page.dart b/lib/features/profile/presentation/pages/profile_page.dart index 585ab4a..9ee7855 100644 --- a/lib/features/profile/presentation/pages/profile_page.dart +++ b/lib/features/profile/presentation/pages/profile_page.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import '../../../../core/theme/app_colors.dart'; class ProfilePage extends StatelessWidget { const ProfilePage({super.key}); @@ -15,20 +14,24 @@ class ProfilePage extends StatelessWidget { context.go('/student-dashboard'); }, child: Scaffold( - backgroundColor: AppColors.background, + backgroundColor: Theme.of(context).colorScheme.background, appBar: AppBar( title: const Text('Profile'), - backgroundColor: AppColors.surface, - foregroundColor: AppColors.textPrimary, + backgroundColor: Theme.of(context).colorScheme.surface, + foregroundColor: Theme.of(context).colorScheme.onSurface, elevation: 0, ), - body: const Center( - child: Text( - 'Profile Page - Coming Soon', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + body: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.primary.withOpacity(0.1), + Theme.of(context).colorScheme.secondary.withOpacity(0.05), + Theme.of(context).colorScheme.background, + ], ), ), ), diff --git a/lib/features/quiz/presentation/pages/quiz_list_page.dart b/lib/features/quiz/presentation/pages/quiz_list_page.dart index b79e6d1..7957fe2 100644 --- a/lib/features/quiz/presentation/pages/quiz_list_page.dart +++ b/lib/features/quiz/presentation/pages/quiz_list_page.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import '../../../../core/theme/app_colors.dart'; class QuizListPage extends StatelessWidget { const QuizListPage({super.key}); @@ -15,20 +14,34 @@ class QuizListPage extends StatelessWidget { context.go('/student-dashboard'); }, child: Scaffold( - backgroundColor: AppColors.background, + backgroundColor: Theme.of(context).colorScheme.background, appBar: AppBar( title: const Text('Quizzes'), - backgroundColor: AppColors.surface, - foregroundColor: AppColors.textPrimary, + backgroundColor: Theme.of(context).colorScheme.surface, + foregroundColor: Theme.of(context).colorScheme.onSurface, elevation: 0, ), - body: const Center( - child: Text( - 'Quiz List - Coming Soon', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + body: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.primary.withOpacity(0.1), + Theme.of(context).colorScheme.secondary.withOpacity(0.05), + Theme.of(context).colorScheme.background, + ], + ), + ), + child: Center( + child: Text( + 'Quiz List - Coming Soon', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.onSurface, + ), ), ), ), diff --git a/lib/features/quiz/presentation/pages/quiz_page.dart b/lib/features/quiz/presentation/pages/quiz_page.dart index 6dc0b95..2538b2b 100644 --- a/lib/features/quiz/presentation/pages/quiz_page.dart +++ b/lib/features/quiz/presentation/pages/quiz_page.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import '../../../../core/theme/app_colors.dart'; class QuizPage extends StatelessWidget { final String quizId; @@ -17,22 +16,25 @@ class QuizPage extends StatelessWidget { context.go('/quiz'); }, child: Scaffold( - backgroundColor: AppColors.background, + backgroundColor: Theme.of(context).colorScheme.background, appBar: AppBar( title: Text('Quiz $quizId'), - backgroundColor: AppColors.surface, - foregroundColor: AppColors.textPrimary, + backgroundColor: Theme.of(context).colorScheme.surface, + foregroundColor: Theme.of(context).colorScheme.onSurface, elevation: 0, ), - body: Center( - child: Text( - 'Quiz Page - ID: $quizId\nComing Soon', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + body: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.primary.withOpacity(0.1), + Theme.of(context).colorScheme.secondary.withOpacity(0.05), + Theme.of(context).colorScheme.background, + ], ), - textAlign: TextAlign.center, ), ), ), diff --git a/lib/features/settings/presentation/pages/help_page.dart b/lib/features/settings/presentation/pages/help_page.dart index ea2f51a..4e94ddd 100644 --- a/lib/features/settings/presentation/pages/help_page.dart +++ b/lib/features/settings/presentation/pages/help_page.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import '../../../../core/theme/app_colors.dart'; /// Help page with user guides class HelpPage extends StatelessWidget { @@ -17,17 +16,17 @@ class HelpPage extends StatelessWidget { }, child: Scaffold( body: Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Color(0xFF82C9BD), - Color(0xFF7BA89C), - Color(0xFFF68D2D), - Color(0xFFF8F9FA), + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.primary.withOpacity(0.9), + Theme.of(context).colorScheme.secondary, + Theme.of(context).colorScheme.background, ], - stops: [0.0, 0.2, 0.6, 1.0], + stops: const [0.0, 0.2, 0.6, 1.0], ), ), child: SafeArea( @@ -39,14 +38,17 @@ class HelpPage extends StatelessWidget { child: Row( children: [ IconButton( - icon: const Icon(Icons.arrow_back, color: Colors.white), + icon: Icon( + Icons.arrow_back, + color: Theme.of(context).colorScheme.onPrimary, + ), onPressed: () => context.pop(), ), - const Expanded( + Expanded( child: Text( 'Ajuda e Suporte', style: TextStyle( - color: Colors.white, + color: Theme.of(context).colorScheme.onPrimary, fontSize: 24, fontWeight: FontWeight.bold, ), @@ -62,6 +64,7 @@ class HelpPage extends StatelessWidget { child: Column( children: [ _buildGuideCard( + context: context, icon: Icons.school, title: 'Como usar o AI Tutor', description: @@ -70,6 +73,7 @@ class HelpPage extends StatelessWidget { ), const SizedBox(height: 16), _buildGuideCard( + context: context, icon: Icons.quiz, title: 'Como fazer quizzes', description: @@ -78,6 +82,7 @@ class HelpPage extends StatelessWidget { ), const SizedBox(height: 16), _buildGuideCard( + context: context, icon: Icons.trending_up, title: 'Ver o seu progresso', description: @@ -86,6 +91,7 @@ class HelpPage extends StatelessWidget { ), const SizedBox(height: 16), _buildGuideCard( + context: context, icon: Icons.settings, title: 'Configurações da app', description: @@ -97,11 +103,13 @@ class HelpPage extends StatelessWidget { Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.1), + color: Theme.of( + context, + ).colorScheme.shadow.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 4), ), @@ -110,34 +118,40 @@ class HelpPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + Text( 'Perguntas Frequentes', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + color: Theme.of( + context, + ).colorScheme.onSurface, ), ), const SizedBox(height: 16), _buildFAQItem( + context: context, question: 'Como posso alterar a minha senha?', answer: 'Pode alterar a sua senha através da secção de segurança nas definições.', ), const SizedBox(height: 12), _buildFAQItem( + context: context, question: 'Os meus dados estão seguros?', answer: 'Sim, utilizamos encriptação de ponta a ponta para proteger todos os seus dados.', ), const SizedBox(height: 12), _buildFAQItem( + context: context, question: 'Posso usar a app offline?', answer: 'Algumas funcionalidades estão disponíveis offline, mas para o AI Tutor necessita de conexão à internet.', ), const SizedBox(height: 12), _buildFAQItem( + context: context, question: 'Como contactar o suporte?', answer: 'Pode contactar-nos através do email suporte@teachit.com.', @@ -150,11 +164,13 @@ class HelpPage extends StatelessWidget { Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.1), + color: Theme.of( + context, + ).colorScheme.shadow.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 4), ), @@ -163,20 +179,24 @@ class HelpPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + Text( 'Ainda precisa de ajuda?', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + color: Theme.of( + context, + ).colorScheme.onSurface, ), ), const SizedBox(height: 8), - const Text( + Text( 'A nossa equipa de suporte está disponível para ajudar.', style: TextStyle( fontSize: 14, - color: AppColors.textSecondary, + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, ), ), const SizedBox(height: 16), @@ -187,8 +207,12 @@ class HelpPage extends StatelessWidget { icon: const Icon(Icons.email), label: const Text('Contactar Suporte'), style: ElevatedButton.styleFrom( - backgroundColor: AppColors.primaryTeal, - foregroundColor: Colors.white, + backgroundColor: Theme.of( + context, + ).colorScheme.primary, + foregroundColor: Theme.of( + context, + ).colorScheme.onPrimary, ), ), ], @@ -207,6 +231,7 @@ class HelpPage extends StatelessWidget { } Widget _buildGuideCard({ + required BuildContext context, required IconData icon, required String title, required String description, @@ -215,11 +240,11 @@ class HelpPage extends StatelessWidget { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.1), + color: Theme.of(context).colorScheme.shadow.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 4), ), @@ -234,12 +259,19 @@ class HelpPage extends StatelessWidget { width: 50, height: 50, decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFF82C9BD), Color(0xFF6BA8A0)], + gradient: LinearGradient( + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.primary.withOpacity(0.8), + ], ), borderRadius: BorderRadius.circular(25), ), - child: Icon(icon, color: Colors.white, size: 24), + child: Icon( + icon, + color: Theme.of(context).colorScheme.onPrimary, + size: 24, + ), ), const SizedBox(width: 16), Expanded( @@ -248,38 +280,45 @@ class HelpPage extends StatelessWidget { children: [ Text( title, - style: const TextStyle( + style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + color: Theme.of(context).colorScheme.onSurface, ), ), const SizedBox(height: 4), Text( description, - style: const TextStyle( + style: TextStyle( fontSize: 12, - color: AppColors.textSecondary, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ], ), ), - const Icon(Icons.chevron_right, color: AppColors.iconInactive), + Icon( + Icons.chevron_right, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ], ), ), ); } - Widget _buildFAQItem({required String question, required String answer}) { + Widget _buildFAQItem({ + required BuildContext context, + required String question, + required String answer, + }) { return ExpansionTile( title: Text( question, - style: const TextStyle( + style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, - color: AppColors.textPrimary, + color: Theme.of(context).colorScheme.onSurface, ), ), children: [ @@ -287,9 +326,9 @@ class HelpPage extends StatelessWidget { padding: const EdgeInsets.all(16.0), child: Text( answer, - style: const TextStyle( + style: TextStyle( fontSize: 13, - color: AppColors.textSecondary, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ), diff --git a/lib/features/settings/presentation/pages/profile_edit_page.dart b/lib/features/settings/presentation/pages/profile_edit_page.dart index faa4cba..30a56e9 100644 --- a/lib/features/settings/presentation/pages/profile_edit_page.dart +++ b/lib/features/settings/presentation/pages/profile_edit_page.dart @@ -98,17 +98,16 @@ class _ProfileEditPageState extends ConsumerState { }, child: Scaffold( body: Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, + begin: Alignment.topLeft, + end: Alignment.bottomRight, colors: [ - Color(0xFF82C9BD), - Color(0xFF7BA89C), - Color(0xFFF68D2D), - Color(0xFFF8F9FA), + Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.primary.withOpacity(0.1), + Theme.of(context).colorScheme.secondary.withOpacity(0.05), + Theme.of(context).colorScheme.background, ], - stops: [0.0, 0.2, 0.6, 1.0], ), ), child: SafeArea( @@ -143,11 +142,13 @@ class _ProfileEditPageState extends ConsumerState { child: Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.1), + color: Theme.of( + context, + ).colorScheme.shadow.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 4), ), @@ -181,10 +182,23 @@ class _ProfileEditPageState extends ConsumerState { ), ), const SizedBox(height: 16), + Text( + user?.displayName ?? 'Utilizador', + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurface, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4), Text( user?.email ?? '', - style: const TextStyle( - color: AppColors.textSecondary, + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant, fontSize: 14, ), ), @@ -194,12 +208,12 @@ class _ProfileEditPageState extends ConsumerState { const SizedBox(height: 32), // Name field - const Text( + Text( 'Nome', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + color: Theme.of(context).colorScheme.onSurface, ), ), const SizedBox(height: 8), @@ -208,7 +222,9 @@ class _ProfileEditPageState extends ConsumerState { decoration: InputDecoration( hintText: 'Introduza o seu nome', filled: true, - fillColor: AppColors.background, + fillColor: Theme.of( + context, + ).colorScheme.surface, border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, @@ -228,12 +244,12 @@ class _ProfileEditPageState extends ConsumerState { const SizedBox(height: 24), // Phone field (optional) - const Text( + Text( 'Telefone (opcional)', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + color: Theme.of(context).colorScheme.onSurface, ), ), const SizedBox(height: 8), @@ -243,7 +259,9 @@ class _ProfileEditPageState extends ConsumerState { decoration: InputDecoration( hintText: 'Introduza o seu telefone', filled: true, - fillColor: AppColors.background, + fillColor: Theme.of( + context, + ).colorScheme.surface, border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, @@ -257,12 +275,12 @@ class _ProfileEditPageState extends ConsumerState { const SizedBox(height: 24), // Bio field (optional) - const Text( + Text( 'Bio (opcional)', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + color: Theme.of(context).colorScheme.onSurface, ), ), const SizedBox(height: 8), @@ -272,7 +290,9 @@ class _ProfileEditPageState extends ConsumerState { decoration: InputDecoration( hintText: 'Conte um pouco sobre si', filled: true, - fillColor: AppColors.background, + fillColor: Theme.of( + context, + ).colorScheme.surface, border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, diff --git a/lib/features/settings/presentation/pages/settings_page.dart b/lib/features/settings/presentation/pages/settings_page.dart index a3a5250..c7e3b2b 100644 --- a/lib/features/settings/presentation/pages/settings_page.dart +++ b/lib/features/settings/presentation/pages/settings_page.dart @@ -29,17 +29,21 @@ class _SettingsPageState extends ConsumerState { }, child: Scaffold( body: Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xFF82C9BD), - Color(0xFF7BA89C), - Color(0xFFF68D2D), - Color(0xFFF8F9FA), - ], - stops: [0.0, 0.2, 0.6, 1.0], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: themeMode == ThemeMode.light + ? [ + const Color(0xFFD4E8E8), + const Color(0xFFE8D4C0), + const Color(0xFFD8E0E8), + ] + : [ + Theme.of(context).colorScheme.primary.withOpacity(0.1), + Theme.of(context).colorScheme.secondary.withOpacity(0.05), + Theme.of(context).colorScheme.background, + ], ), ), child: SafeArea( @@ -54,11 +58,11 @@ class _SettingsPageState extends ConsumerState { icon: const Icon(Icons.arrow_back, color: Colors.white), onPressed: () => context.go('/student-dashboard'), ), - const Expanded( + Expanded( child: Text( 'Configurações', style: TextStyle( - color: Colors.white, + color: Theme.of(context).colorScheme.onSurface, fontSize: 24, fontWeight: FontWeight.bold, ), @@ -187,19 +191,23 @@ class _SettingsPageState extends ConsumerState { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, - color: isDark ? Colors.white70 : AppColors.textSecondary, + color: isDark + ? Colors.white70 + : Theme.of(context).colorScheme.onSurfaceVariant, ), ), ), Container( decoration: BoxDecoration( - color: isDark ? Colors.grey[800] : AppColors.surface, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), + color: Theme.of( + context, + ).colorScheme.onSurfaceVariant.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), ), ], ), @@ -220,17 +228,17 @@ class _SettingsPageState extends ConsumerState { leading: const Icon(Icons.palette, color: AppColors.primaryTeal), title: Text( 'Tema', - style: TextStyle(color: isDark ? Colors.white : AppColors.textPrimary), + style: TextStyle( + color: isDark + ? Colors.white + : Theme.of(context).colorScheme.onSurface, + ), ), subtitle: Text( isDarkModeAvailable ? 'Atual: ${_getThemeModeString(currentTheme)}' : 'Light Mode (padrão)', - style: TextStyle( - color: isDarkModeAvailable - ? (isDark ? Colors.white70 : AppColors.textSecondary) - : AppColors.textHint, - ), + style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant), ), trailing: isDarkModeAvailable ? DropdownButton( @@ -255,7 +263,10 @@ class _SettingsPageState extends ConsumerState { ), ], ) - : const Icon(Icons.lock, color: AppColors.textHint), + : Icon( + Icons.lock, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ); } @@ -283,12 +294,18 @@ class _SettingsPageState extends ConsumerState { leading: const Icon(Icons.notifications, color: AppColors.primaryTeal), title: Text( title, - style: TextStyle(color: isDark ? Colors.white : AppColors.textPrimary), + style: TextStyle( + color: isDark + ? Colors.white + : Theme.of(context).colorScheme.onSurface, + ), ), subtitle: Text( subtitle, style: TextStyle( - color: isDark ? Colors.white70 : AppColors.textSecondary, + color: isDark + ? Colors.white70 + : Theme.of(context).colorScheme.onSurfaceVariant, ), ), trailing: Switch( @@ -312,15 +329,24 @@ class _SettingsPageState extends ConsumerState { leading: Icon(icon, color: AppColors.primaryTeal), title: Text( title, - style: TextStyle(color: isDark ? Colors.white : AppColors.textPrimary), + style: TextStyle( + color: isDark + ? Colors.white + : Theme.of(context).colorScheme.onSurface, + ), ), subtitle: Text( subtitle, style: TextStyle( - color: isDark ? Colors.white70 : AppColors.textSecondary, + color: isDark + ? Colors.white70 + : Theme.of(context).colorScheme.onSurfaceVariant, ), ), - trailing: const Icon(Icons.chevron_right, color: AppColors.iconInactive), + trailing: Icon( + Icons.chevron_right, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), onTap: onTap, ); } @@ -336,12 +362,18 @@ class _SettingsPageState extends ConsumerState { leading: Icon(icon, color: AppColors.primaryTeal), title: Text( title, - style: TextStyle(color: isDark ? Colors.white : AppColors.textPrimary), + style: TextStyle( + color: isDark + ? Colors.white + : Theme.of(context).colorScheme.onSurface, + ), ), subtitle: Text( subtitle, style: TextStyle( - color: isDark ? Colors.white70 : AppColors.textSecondary, + color: isDark + ? Colors.white70 + : Theme.of(context).colorScheme.onSurfaceVariant, ), ), ); diff --git a/lib/features/splash/presentation/pages/splash_page.dart b/lib/features/splash/presentation/pages/splash_page.dart index fab8204..7274baf 100644 --- a/lib/features/splash/presentation/pages/splash_page.dart +++ b/lib/features/splash/presentation/pages/splash_page.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:go_router/go_router.dart'; -import '../../../../core/theme/app_colors.dart'; import '../../../../core/services/auth_service.dart'; import '../../../../core/services/session_service.dart'; import '../../../../l10n/app_localizations.dart'; @@ -119,10 +118,10 @@ class _SplashPageState extends State { begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ - AppColors.background, - AppColors.primaryTeal.withOpacity(0.05), - AppColors.primaryOrange.withOpacity(0.03), - AppColors.background, + Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.primary.withOpacity(0.1), + Theme.of(context).colorScheme.secondary.withOpacity(0.05), + Theme.of(context).colorScheme.background, ], ), ), @@ -147,7 +146,9 @@ class _SplashPageState extends State { decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( - color: AppColors.primaryTeal.withOpacity(0.2), + color: Theme.of( + context, + ).colorScheme.primary.withOpacity(0.2), width: 2, ), ), @@ -174,7 +175,9 @@ class _SplashPageState extends State { decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( - color: AppColors.primaryOrange.withOpacity(0.3), + color: Theme.of( + context, + ).colorScheme.secondary.withOpacity(0.3), width: 3, ), ), @@ -199,10 +202,10 @@ class _SplashPageState extends State { width: 80, height: 80, decoration: BoxDecoration( - gradient: const LinearGradient( + gradient: LinearGradient( colors: [ - AppColors.primaryTeal, - AppColors.primaryOrange, + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.secondary, ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -210,14 +213,16 @@ class _SplashPageState extends State { borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( - color: AppColors.primaryTeal.withOpacity(0.3), + color: Theme.of( + context, + ).colorScheme.primary.withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 8), ), BoxShadow( - color: AppColors.primaryOrange.withOpacity( - 0.2, - ), + color: Theme.of( + context, + ).colorScheme.secondary.withOpacity(0.2), blurRadius: 15, offset: const Offset(0, 4), ), @@ -260,10 +265,10 @@ class _SplashPageState extends State { // School name with gradient ShaderMask( - shaderCallback: (bounds) => const LinearGradient( + shaderCallback: (bounds) => LinearGradient( colors: [ - AppColors.primaryTeal, - AppColors.primaryOrange, + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.secondary, ], begin: Alignment.centerLeft, end: Alignment.centerRight, @@ -295,8 +300,12 @@ class _SplashPageState extends State { ShaderMask( shaderCallback: (bounds) => LinearGradient( colors: [ - AppColors.primaryOrange.withOpacity(0.8), - AppColors.primaryTeal.withOpacity(0.8), + Theme.of( + context, + ).colorScheme.secondary.withOpacity(0.8), + Theme.of( + context, + ).colorScheme.primary.withOpacity(0.8), ], begin: Alignment.centerLeft, end: Alignment.centerRight, @@ -345,7 +354,9 @@ class _SplashPageState extends State { 'A preparar a sua experiência...', style: Theme.of(context).textTheme.bodySmall ?.copyWith( - color: AppColors.primaryOrange, + color: Theme.of( + context, + ).colorScheme.secondary, fontWeight: FontWeight.w500, ), ) @@ -357,7 +368,9 @@ class _SplashPageState extends State { .then() .shimmer( duration: const Duration(milliseconds: 2000), - color: AppColors.primaryTeal.withOpacity(0.3), + color: Theme.of( + context, + ).colorScheme.primary.withOpacity(0.3), ), ], ), @@ -374,9 +387,12 @@ class _SplashPageState extends State { return Container( width: 12, height: 12, - decoration: const BoxDecoration( + decoration: BoxDecoration( gradient: LinearGradient( - colors: [AppColors.primaryTeal, AppColors.primaryOrange], + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.secondary, + ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), @@ -418,8 +434,8 @@ class _SplashPageState extends State { decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppColors.primaryTeal.withOpacity(0.3), - AppColors.primaryOrange.withOpacity(0.2), + Theme.of(context).colorScheme.primary.withOpacity(0.3), + Theme.of(context).colorScheme.secondary.withOpacity(0.2), ], begin: Alignment.topLeft, end: Alignment.bottomRight, diff --git a/lib/features/tutor/presentation/pages/tutor_chat_page.dart b/lib/features/tutor/presentation/pages/tutor_chat_page.dart index 8aeccfe..a467e56 100644 --- a/lib/features/tutor/presentation/pages/tutor_chat_page.dart +++ b/lib/features/tutor/presentation/pages/tutor_chat_page.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import '../../../../core/theme/app_colors.dart'; class TutorChatPage extends StatelessWidget { const TutorChatPage({super.key}); @@ -7,20 +6,34 @@ class TutorChatPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: AppColors.background, + backgroundColor: Theme.of(context).colorScheme.background, appBar: AppBar( title: const Text('AI Tutor'), - backgroundColor: AppColors.surface, - foregroundColor: AppColors.textPrimary, + backgroundColor: Theme.of(context).colorScheme.surface, + foregroundColor: Theme.of(context).colorScheme.onSurface, elevation: 0, ), - body: const Center( - child: Text( - 'AI Tutor Chat - Coming Soon', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + body: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.primary.withOpacity(0.1), + Theme.of(context).colorScheme.secondary.withOpacity(0.05), + Theme.of(context).colorScheme.background, + ], + ), + ), + child: Center( + child: Text( + 'AI Tutor Chat - Coming Soon', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.onSurface, + ), ), ), ), diff --git a/lib/shared/presentation/pages/loading_page.dart b/lib/shared/presentation/pages/loading_page.dart index 51cd0b5..b63db74 100644 --- a/lib/shared/presentation/pages/loading_page.dart +++ b/lib/shared/presentation/pages/loading_page.dart @@ -1,25 +1,29 @@ import 'package:flutter/material.dart'; -import '../../../../core/theme/app_colors.dart'; class LoadingPage extends StatelessWidget { const LoadingPage({super.key}); @override Widget build(BuildContext context) { - return const Scaffold( - backgroundColor: AppColors.background, + return Scaffold( + backgroundColor: Theme.of(context).colorScheme.background, body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator( strokeWidth: 3, - valueColor: AlwaysStoppedAnimation(AppColors.primaryBlue), + valueColor: AlwaysStoppedAnimation( + Theme.of(context).colorScheme.primary, + ), ), - SizedBox(height: 24), + const SizedBox(height: 24), Text( 'Loading...', - style: TextStyle(fontSize: 16, color: AppColors.textSecondary), + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ], ), diff --git a/lib/shared/presentation/pages/not_found_page.dart b/lib/shared/presentation/pages/not_found_page.dart index 20b40fd..2013cba 100644 --- a/lib/shared/presentation/pages/not_found_page.dart +++ b/lib/shared/presentation/pages/not_found_page.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import '../../../../core/theme/app_colors.dart'; import '../../../../l10n/app_localizations.dart'; class NotFoundPage extends StatelessWidget { @@ -9,33 +8,37 @@ class NotFoundPage extends StatelessWidget { Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return Scaffold( - backgroundColor: AppColors.background, + backgroundColor: Theme.of(context).colorScheme.background, appBar: AppBar( title: Text(l10n.pageNotFound), - backgroundColor: AppColors.surface, - foregroundColor: AppColors.textPrimary, + backgroundColor: Theme.of(context).colorScheme.surface, + foregroundColor: Theme.of(context).colorScheme.onSurface, elevation: 0, ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(Icons.error_outline, size: 64, color: AppColors.error), + Icon( + Icons.error_outline, + size: 64, + color: Theme.of(context).colorScheme.error, + ), const SizedBox(height: 16), Text( l10n.pageNotFound, - style: const TextStyle( + style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, - color: AppColors.textPrimary, + color: Theme.of(context).colorScheme.onSurface, ), ), const SizedBox(height: 8), Text( 'A página que procura não existe.', - style: const TextStyle( + style: TextStyle( fontSize: 16, - color: AppColors.textSecondary, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ],