- Dark / light mode a funcionar no lado do aluno

- Atualização dos ficheiros markdown.
This commit is contained in:
2026-05-14 22:07:03 +01:00
parent 55ec2521cf
commit 62b9a107bc
30 changed files with 2582 additions and 1839 deletions

View File

@@ -87,6 +87,29 @@
- Loading state with CircularProgressIndicator - Loading state with CircularProgressIndicator
### Fixed ### 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** - **Unified Quick Action Cards Text Style**
- "Upload Conteúdo" and "Criar Quiz" cards now match "Criar Turma" text alignment - "Upload Conteúdo" and "Criar Quiz" cards now match "Criar Turma" text alignment
- All cards use `Column` with `crossAxisAlignment: CrossAxisAlignment.start` for text section - All cards use `Column` with `crossAxisAlignment: CrossAxisAlignment.start` for text section

View File

@@ -496,14 +496,20 @@ class FirebaseConstants {
**Dependencies**: Task 1.4 **Dependencies**: Task 1.4
#### Subtasks: #### Subtasks:
- [ ] Implement Firebase Auth service - [x] Implement Firebase Auth service
- [ ] Create user models and entities - [x] Create user models and entities
- [ ] Build authentication repository - [x] Build authentication repository
- [ ] Implement sign in use case - [x] Implement sign in use case
- [ ] Implement sign up use case - [x] Implement sign up use case
- [ ] Implement password reset - [ ] Implement password reset
- [ ] Create authentication providers - [x] Create authentication providers
- [ ] Build login/signup screens - [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: #### Implementation:

View File

@@ -28,7 +28,7 @@ This document tracks the overall progress of the AI Study Assistant project deve
-**Foundation:** 100% Complete -**Foundation:** 100% Complete
-**UI/UX:** 90% Complete -**UI/UX:** 95% Complete
-**Internationalization:** 100% 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] Splash screen with animations
- [x] Login page with improved design - [x] Login page with improved design and navigation
- [x] Role selection page (student/teacher) - [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 - [x] Dark/light theme support
- [ ] Signup page (needs update) - [x] Signup page (updated with theme fixes)
- [x] Dashboard pages (fixed overflow issue) - [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 - None currently
- [ ] Some animations could be optimized
@@ -419,6 +417,31 @@ This document tracks the overall progress of the AI Study Assistant project deve
### **Last 24 Hours:** ### **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 -**Teacher Materials Upload Page** - Nova tela dedicada para professores enviarem materiais para a IA
- Ficheiro: `lib/features/materials/presentation/pages/teacher_materials_page.dart` - Ficheiro: `lib/features/materials/presentation/pages/teacher_materials_page.dart`
- **FASE 1**: Criar tela com AppBar "Materiais da Turma" e design consistente - **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** **🔄 Auto-Update: Enabled**

View File

@@ -25,23 +25,17 @@ class ThemeNotifier extends StateNotifier<ThemeMode> {
/// Change theme mode /// Change theme mode
Future<void> setThemeMode(ThemeMode themeMode) async { Future<void> setThemeMode(ThemeMode themeMode) async {
// For now, only allow light mode
// Future: Allow dark mode when available
if (themeMode == ThemeMode.light || ThemeService.isDarkModeAvailable()) {
state = themeMode; state = themeMode;
await ThemeService.setThemeMode(themeMode); await ThemeService.setThemeMode(themeMode);
} }
}
/// Toggle between light and dark mode (for future use) /// Toggle between light and dark mode
Future<void> toggleTheme() async { Future<void> toggleTheme() async {
if (ThemeService.isDarkModeAvailable()) {
final newTheme = state == ThemeMode.light final newTheme = state == ThemeMode.light
? ThemeMode.dark ? ThemeMode.dark
: ThemeMode.light; : ThemeMode.light;
await setThemeMode(newTheme); await setThemeMode(newTheme);
} }
}
/// Reset to default theme /// Reset to default theme
Future<void> resetTheme() async { Future<void> resetTheme() async {

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; 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 { class AppColors {
// Primary Brand Colors // Primary Brand Colors (same for both modes)
static const Color primaryTeal = Color( static const Color primaryTeal = Color(
0xFF82C9BD, 0xFF82C9BD,
); // Main teal color - PRIMARY ); // Main teal color - PRIMARY
@@ -10,17 +10,30 @@ class AppColors {
0xFFF68D2D, 0xFFF68D2D,
); // Accent orange - SECONDARY ); // Accent orange - SECONDARY
// Gradient Colors // Gradient Colors (same for both modes)
static const Color gradientStart = Color(0xFF82C9BD); // Teal gradient start static const Color gradientStart = Color(0xFF82C9BD); // Teal gradient start
static const Color gradientEnd = Color( static const Color gradientEnd = Color(
0xFF6AB8A8, 0xFF6AB8A8,
); // Darker teal gradient end ); // Darker teal gradient end
// Secondary Colors // Secondary Colors (same for both modes)
static const Color secondaryTeal = Color(0xFF6AB8A8); // Darker teal static const Color secondaryTeal = Color(0xFF6AB8A8); // Darker teal
static const Color accentTeal = Color(0xFF5AA69A); // Lighter teal accent static const Color accentTeal = Color(0xFF5AA69A); // Lighter teal accent
static const Color lightOrange = Color(0xFFF7A960); // Lighter orange 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 // Neutral Colors
static const Color background = Color(0xFFF8F9FA); // Light gray background static const Color background = Color(0xFFF8F9FA); // Light gray background
static const Color surface = Color(0xFFFFFFFF); // White surfaces 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 textSecondary = Color(0xFF6B7280); // Secondary text
static const Color textHint = Color(0xFF9CA3AF); // Hint 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 // Interactive Colors
static const Color buttonPrimary = Color(0xFF82C9BD); // Primary button (teal) static const Color buttonPrimary =
static const Color buttonAccent = Color(0xFFF68D2D); // Accent button (orange) 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 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 static const Color iconInactive = Color(0xFF9CA3AF); // Inactive icons
// Chat Specific Colors // Chat Specific Colors
static const Color chatBubbleStudent = Color( static const Color chatBubbleStudent =
0xFF82C9BD, AppColors.primaryTeal; // Student messages (teal)
); // Student messages (teal)
static const Color chatBubbleAI = Color(0xFFF3F4F6); // AI messages static const Color chatBubbleAI = Color(0xFFF3F4F6); // AI messages
static const Color chatInputBackground = Color( static const Color chatInputBackground = Color(
0xFFF8F9FA, 0xFFF8F9FA,
); // Input background ); // Input background
static const Color chatSendButton = Color(0xFF82C9BD); // Send button (teal) static const Color chatSendButton =
AppColors.primaryTeal; // Send button (teal)
// Dark Mode Colors // Border Colors
static const Color darkBackground = Color(0xFF1F2937); // Dark background static const Color border = Color(0xFFE2E8F0); // Border color
static const Color darkSurface = Color(0xFF374151); // Dark surface static const Color divider = Color(0xFFE5E7EB); // Divider color
static const Color darkTextPrimary = Color(0xFFF9FAFB); // Dark primary text
static const Color darkTextSecondary = Color(
0xFFD1D5DB,
); // Dark secondary text
// Legacy compatibility (for existing code) // Overlay Colors
@deprecated static const Color overlay = Color(0x80000000); // Overlay color
static const Color primaryBlue = primaryTeal; // Map old primaryBlue to new primaryTeal }
/// 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
} }

View File

@@ -9,24 +9,24 @@ class AppTheme {
useMaterial3: true, useMaterial3: true,
brightness: Brightness.light, brightness: Brightness.light,
colorScheme: ColorScheme.fromSeed( colorScheme: ColorScheme.fromSeed(
seedColor: AppColors.primaryBlue, seedColor: AppColors.primaryTeal,
brightness: Brightness.light, brightness: Brightness.light,
primary: AppColors.primaryBlue, primary: AppColors.primaryTeal,
secondary: AppColors.primaryTeal, secondary: AppColors.primaryOrange,
surface: AppColors.surface, surface: LightColors.surface,
background: AppColors.background, background: LightColors.background,
error: AppColors.error, error: AppColors.error,
), ),
// App Bar Theme // App Bar Theme
appBarTheme: const AppBarTheme( appBarTheme: const AppBarTheme(
backgroundColor: AppColors.surface, backgroundColor: LightColors.surface,
foregroundColor: AppColors.textPrimary, foregroundColor: LightColors.textPrimary,
elevation: 0, elevation: 0,
centerTitle: true, centerTitle: true,
systemOverlayStyle: SystemUiOverlayStyle.dark, systemOverlayStyle: SystemUiOverlayStyle.dark,
titleTextStyle: TextStyle( titleTextStyle: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
@@ -34,7 +34,7 @@ class AppTheme {
// Card Theme // Card Theme
cardTheme: CardThemeData( cardTheme: CardThemeData(
color: AppColors.cardBackground, color: LightColors.cardBackground,
elevation: 2, elevation: 2,
shadowColor: Colors.black.withOpacity(0.08), shadowColor: Colors.black.withOpacity(0.08),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
@@ -44,10 +44,10 @@ class AppTheme {
// Elevated Button Theme // Elevated Button Theme
elevatedButtonTheme: ElevatedButtonThemeData( elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: AppColors.buttonPrimary, backgroundColor: LightColors.buttonPrimary,
foregroundColor: Colors.white, foregroundColor: Colors.white,
elevation: 2, elevation: 2,
shadowColor: AppColors.primaryBlue.withOpacity(0.3), shadowColor: AppColors.primaryTeal.withOpacity(0.3),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
@@ -59,8 +59,8 @@ class AppTheme {
// Outlined Button Theme // Outlined Button Theme
outlinedButtonTheme: OutlinedButtonThemeData( outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom( style: OutlinedButton.styleFrom(
foregroundColor: AppColors.primaryBlue, foregroundColor: AppColors.primaryTeal,
side: BorderSide(color: AppColors.primaryBlue.withOpacity(0.3)), side: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
@@ -72,7 +72,7 @@ class AppTheme {
// Text Button Theme // Text Button Theme
textButtonTheme: TextButtonThemeData( textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: AppColors.primaryBlue, foregroundColor: AppColors.primaryTeal,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
@@ -82,18 +82,18 @@ class AppTheme {
// Input Field Theme // Input Field Theme
inputDecorationTheme: InputDecorationTheme( inputDecorationTheme: InputDecorationTheme(
filled: true, filled: true,
fillColor: AppColors.surface, fillColor: LightColors.surface,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: AppColors.primaryBlue.withOpacity(0.3)), borderSide: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)),
), ),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: AppColors.primaryBlue.withOpacity(0.3)), borderSide: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: AppColors.primaryBlue, width: 2), borderSide: const BorderSide(color: AppColors.primaryTeal, width: 2),
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
@@ -103,9 +103,9 @@ class AppTheme {
horizontal: 16, horizontal: 16,
vertical: 12, vertical: 12,
), ),
hintStyle: const TextStyle(color: AppColors.textHint, fontSize: 14), hintStyle: const TextStyle(color: LightColors.textHint, fontSize: 14),
labelStyle: const TextStyle( labelStyle: const TextStyle(
color: AppColors.textSecondary, color: LightColors.textSecondary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
@@ -113,85 +113,85 @@ class AppTheme {
// Text Field Theme // Text Field Theme
textSelectionTheme: TextSelectionThemeData( textSelectionTheme: TextSelectionThemeData(
cursorColor: AppColors.primaryBlue, cursorColor: AppColors.primaryTeal,
selectionColor: AppColors.primaryBlue.withOpacity(0.3), selectionColor: AppColors.primaryTeal.withOpacity(0.3),
selectionHandleColor: AppColors.primaryBlue, selectionHandleColor: AppColors.primaryTeal,
), ),
// Text Theme // Text Theme
textTheme: const TextTheme( textTheme: const TextTheme(
displayLarge: TextStyle( displayLarge: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
displayMedium: TextStyle( displayMedium: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 28, fontSize: 28,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
displaySmall: TextStyle( displaySmall: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
headlineLarge: TextStyle( headlineLarge: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 22, fontSize: 22,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
headlineMedium: TextStyle( headlineMedium: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
headlineSmall: TextStyle( headlineSmall: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
titleLarge: TextStyle( titleLarge: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
titleMedium: TextStyle( titleMedium: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
titleSmall: TextStyle( titleSmall: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
bodyLarge: TextStyle( bodyLarge: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
), ),
bodyMedium: TextStyle( bodyMedium: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
), ),
bodySmall: TextStyle( bodySmall: TextStyle(
color: AppColors.textSecondary, color: LightColors.textSecondary,
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
), ),
labelLarge: TextStyle( labelLarge: TextStyle(
color: AppColors.textPrimary, color: LightColors.textPrimary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
labelMedium: TextStyle( labelMedium: TextStyle(
color: AppColors.textSecondary, color: LightColors.textSecondary,
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
labelSmall: TextStyle( labelSmall: TextStyle(
color: AppColors.textHint, color: LightColors.textHint,
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
@@ -199,9 +199,9 @@ class AppTheme {
// Bottom Navigation Bar Theme // Bottom Navigation Bar Theme
bottomNavigationBarTheme: const BottomNavigationBarThemeData( bottomNavigationBarTheme: const BottomNavigationBarThemeData(
backgroundColor: AppColors.surface, backgroundColor: LightColors.surface,
selectedItemColor: AppColors.primaryBlue, selectedItemColor: AppColors.primaryTeal,
unselectedItemColor: AppColors.iconInactive, unselectedItemColor: LightColors.iconInactive,
type: BottomNavigationBarType.fixed, type: BottomNavigationBarType.fixed,
elevation: 8, elevation: 8,
selectedLabelStyle: TextStyle( selectedLabelStyle: TextStyle(
@@ -216,7 +216,7 @@ class AppTheme {
// Floating Action Button Theme // Floating Action Button Theme
floatingActionButtonTheme: FloatingActionButtonThemeData( floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: AppColors.primaryBlue, backgroundColor: AppColors.primaryTeal,
foregroundColor: Colors.white, foregroundColor: Colors.white,
elevation: 4, elevation: 4,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
@@ -224,28 +224,28 @@ class AppTheme {
// Divider Theme // Divider Theme
dividerTheme: const DividerThemeData( dividerTheme: const DividerThemeData(
color: AppColors.buttonSecondary, color: LightColors.divider,
thickness: 1, thickness: 1,
space: 1, space: 1,
), ),
// Icon Theme // Icon Theme
iconTheme: const IconThemeData(color: AppColors.iconActive, size: 24), iconTheme: const IconThemeData(color: LightColors.iconActive, size: 24),
// Progress Indicator Theme // Progress Indicator Theme
progressIndicatorTheme: const ProgressIndicatorThemeData( progressIndicatorTheme: const ProgressIndicatorThemeData(
color: AppColors.primaryBlue, color: AppColors.primaryTeal,
linearTrackColor: AppColors.buttonSecondary, linearTrackColor: LightColors.buttonSecondary,
circularTrackColor: AppColors.buttonSecondary, circularTrackColor: LightColors.buttonSecondary,
), ),
// Chip Theme // Chip Theme
chipTheme: ChipThemeData( chipTheme: ChipThemeData(
backgroundColor: AppColors.buttonSecondary, backgroundColor: LightColors.buttonSecondary,
selectedColor: AppColors.primaryBlue.withOpacity(0.1), selectedColor: AppColors.primaryTeal.withOpacity(0.1),
disabledColor: AppColors.buttonSecondary.withOpacity(0.5), disabledColor: LightColors.buttonSecondary.withOpacity(0.5),
labelStyle: const TextStyle(color: AppColors.textPrimary), labelStyle: const TextStyle(color: LightColors.textPrimary),
secondaryLabelStyle: const TextStyle(color: AppColors.textPrimary), secondaryLabelStyle: const TextStyle(color: LightColors.textPrimary),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
), ),
@@ -257,52 +257,90 @@ class AppTheme {
useMaterial3: true, useMaterial3: true,
brightness: Brightness.dark, brightness: Brightness.dark,
colorScheme: ColorScheme.fromSeed( colorScheme: ColorScheme.fromSeed(
seedColor: AppColors.primaryBlue, seedColor: AppColors.primaryTeal,
brightness: Brightness.dark, brightness: Brightness.dark,
primary: AppColors.primaryBlue, primary: AppColors.primaryTeal,
secondary: AppColors.primaryTeal, secondary: AppColors.primaryOrange,
surface: AppColors.darkSurface, surface: DarkColors.surface,
background: AppColors.darkBackground, background: DarkColors.background,
error: AppColors.error, error: AppColors.error,
), ),
// Dark mode specific overrides would go here // Dark mode specific overrides would go here
appBarTheme: const AppBarTheme( appBarTheme: const AppBarTheme(
backgroundColor: AppColors.darkSurface, backgroundColor: DarkColors.surface,
foregroundColor: AppColors.darkTextPrimary, foregroundColor: DarkColors.textPrimary,
elevation: 0, elevation: 0,
centerTitle: true, centerTitle: true,
systemOverlayStyle: SystemUiOverlayStyle.light, systemOverlayStyle: SystemUiOverlayStyle.light,
titleTextStyle: TextStyle( titleTextStyle: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
cardTheme: CardThemeData( cardTheme: CardThemeData(
color: AppColors.darkSurface, color: DarkColors.cardBackground,
elevation: 2, elevation: 2,
shadowColor: Colors.black.withOpacity(0.3), shadowColor: Colors.black.withOpacity(0.3),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), 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 // Input Field Theme for Dark Mode
inputDecorationTheme: InputDecorationTheme( inputDecorationTheme: InputDecorationTheme(
filled: true, filled: true,
fillColor: AppColors.darkSurface, fillColor: DarkColors.surface,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: AppColors.primaryBlue.withOpacity(0.3)), borderSide: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)),
), ),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: AppColors.primaryBlue.withOpacity(0.3)), borderSide: BorderSide(color: AppColors.primaryTeal.withOpacity(0.3)),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: AppColors.primaryBlue, width: 2), borderSide: const BorderSide(color: AppColors.primaryTeal, width: 2),
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
@@ -313,11 +351,11 @@ class AppTheme {
vertical: 12, vertical: 12,
), ),
hintStyle: const TextStyle( hintStyle: const TextStyle(
color: AppColors.darkTextSecondary, color: DarkColors.textSecondary,
fontSize: 14, fontSize: 14,
), ),
labelStyle: const TextStyle( labelStyle: const TextStyle(
color: AppColors.darkTextSecondary, color: DarkColors.textSecondary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
@@ -325,88 +363,141 @@ class AppTheme {
// Text Field Theme for Dark Mode // Text Field Theme for Dark Mode
textSelectionTheme: TextSelectionThemeData( textSelectionTheme: TextSelectionThemeData(
cursorColor: AppColors.primaryBlue, cursorColor: AppColors.primaryTeal,
selectionColor: AppColors.primaryBlue.withOpacity(0.3), selectionColor: AppColors.primaryTeal.withOpacity(0.3),
selectionHandleColor: AppColors.primaryBlue, selectionHandleColor: AppColors.primaryTeal,
), ),
textTheme: const TextTheme( textTheme: const TextTheme(
displayLarge: TextStyle( displayLarge: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
displayMedium: TextStyle( displayMedium: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 28, fontSize: 28,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
displaySmall: TextStyle( displaySmall: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
headlineLarge: TextStyle( headlineLarge: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 22, fontSize: 22,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
headlineMedium: TextStyle( headlineMedium: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
headlineSmall: TextStyle( headlineSmall: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
titleLarge: TextStyle( titleLarge: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
titleMedium: TextStyle( titleMedium: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
titleSmall: TextStyle( titleSmall: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
bodyLarge: TextStyle( bodyLarge: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
), ),
bodyMedium: TextStyle( bodyMedium: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
), ),
bodySmall: TextStyle( bodySmall: TextStyle(
color: AppColors.darkTextSecondary, color: DarkColors.textSecondary,
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
), ),
labelLarge: TextStyle( labelLarge: TextStyle(
color: AppColors.darkTextPrimary, color: DarkColors.textPrimary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
labelMedium: TextStyle( labelMedium: TextStyle(
color: AppColors.darkTextSecondary, color: DarkColors.textSecondary,
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
labelSmall: TextStyle( labelSmall: TextStyle(
color: AppColors.darkTextSecondary, color: DarkColors.textSecondary,
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.w500, 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)),
),
); );
} }
} }

View File

@@ -48,9 +48,9 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
} }
}, },
child: Scaffold( child: Scaffold(
backgroundColor: const Color(0xFFF8F9FA), backgroundColor: Theme.of(context).colorScheme.background,
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.white, backgroundColor: Theme.of(context).colorScheme.surface,
elevation: 0, elevation: 0,
title: Row( title: Row(
children: [ children: [
@@ -58,8 +58,11 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
width: 40, width: 40,
height: 40, height: 40,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: const LinearGradient( gradient: LinearGradient(
colors: [Color(0xFF82C9BD), Color(0xFF6BA5A0)], colors: [
Theme.of(context).colorScheme.primary,
Theme.of(context).colorScheme.primary.withOpacity(0.8),
],
), ),
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
), ),
@@ -74,12 +77,15 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
style: TextStyle( style: TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.grey[800], color: Theme.of(context).colorScheme.onSurface,
), ),
), ),
Text( Text(
'Seu tutor educacional inteligente', '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<TutorChatPageSimple>
actions: [ actions: [
IconButton( IconButton(
onPressed: _handleLogout, onPressed: _handleLogout,
icon: Icon(Icons.logout, color: Colors.grey[700]), icon: Icon(
Icons.logout,
color: Theme.of(context).colorScheme.onSurface,
),
tooltip: 'Sair', tooltip: 'Sair',
), ),
], ],
@@ -98,14 +107,14 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
// Messages area // Messages area
Expanded( Expanded(
child: Container( child: Container(
decoration: const BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topCenter, begin: Alignment.topCenter,
end: Alignment.bottomCenter, end: Alignment.bottomCenter,
colors: [ colors: [
Color(0xFFF8F9FA), Theme.of(context).colorScheme.background,
Color(0xFFE8F0FE), Theme.of(context).colorScheme.primary.withOpacity(0.05),
Color(0xFFF8F9FA), Theme.of(context).colorScheme.background,
], ],
), ),
), ),
@@ -163,15 +172,24 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: isUser gradient: isUser
? const LinearGradient( ? LinearGradient(
colors: [Color(0xFF82C9BD), Color(0xFF6BA5A0)], colors: [
Theme.of(context).colorScheme.primary,
Theme.of(
context,
).colorScheme.primary.withOpacity(0.8),
],
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
) )
: LinearGradient( : LinearGradient(
colors: [ colors: [
Colors.white.withOpacity(0.95), Theme.of(
Colors.white.withOpacity(0.9), context,
).colorScheme.surface.withOpacity(0.95),
Theme.of(
context,
).colorScheme.surface.withOpacity(0.9),
], ],
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
@@ -208,24 +226,32 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
data: content, data: content,
styleSheet: MarkdownStyleSheet( styleSheet: MarkdownStyleSheet(
p: TextStyle( p: TextStyle(
color: const Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
height: 1.4, height: 1.4,
), ),
strong: TextStyle( strong: TextStyle(
color: const Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
height: 1.4, height: 1.4,
), ),
em: TextStyle( em: TextStyle(
color: const Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
height: 1.4, height: 1.4,
), ),
listBullet: TextStyle( listBullet: TextStyle(
color: const Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
height: 1.4, height: 1.4,
), ),
@@ -247,7 +273,10 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
), ),
child: Text( child: Text(
_formatTimestamp(timestamp), _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<TutorChatPageSimple>
width: 36, width: 36,
height: 36, height: 36,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: const LinearGradient( gradient: LinearGradient(
colors: [Color(0xFF82C9BD), Color(0xFF6BA5A0)], colors: [
Theme.of(context).colorScheme.primary,
Theme.of(context).colorScheme.primary.withOpacity(0.8),
],
), ),
borderRadius: BorderRadius.circular(18), borderRadius: BorderRadius.circular(18),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: const Color(0xFF82C9BD).withOpacity(0.3), color: Theme.of(context).colorScheme.primary.withOpacity(0.3),
blurRadius: 8, blurRadius: 8,
offset: const Offset(0, 2), offset: const Offset(0, 2),
), ),
@@ -295,7 +327,7 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
bottom: bottomPadding + 16.0, // Add system navigation bar padding bottom: bottomPadding + 16.0, // Add system navigation bar padding
), ),
decoration: BoxDecoration( 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)), borderRadius: const BorderRadius.vertical(top: Radius.circular(20)),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
@@ -308,8 +340,11 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
color: Colors.white, color: Theme.of(context).colorScheme.surface,
border: Border.all(color: const Color(0xFFE2E8F0), width: 1), border: Border.all(
color: Theme.of(context).colorScheme.outline.withOpacity(0.5),
width: 1,
),
), ),
child: Row( child: Row(
children: [ children: [
@@ -317,9 +352,9 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
Expanded( Expanded(
child: TextField( child: TextField(
controller: _messageController, controller: _messageController,
style: const TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: Color(0xFF1A1A1A), // Dark text for visibility color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
decoration: InputDecoration( decoration: InputDecoration(
@@ -330,7 +365,7 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
), ),
hintText: 'Faz a tua pergunta!', hintText: 'Faz a tua pergunta!',
hintStyle: TextStyle( hintStyle: TextStyle(
color: Colors.grey[400], color: Theme.of(context).colorScheme.onSurfaceVariant,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: 16, fontSize: 16,
), ),
@@ -351,20 +386,27 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
height: 44, height: 44,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: _messageController.text.isNotEmpty gradient: _messageController.text.isNotEmpty
? const LinearGradient( ? LinearGradient(
colors: [Color(0xFF82C9BD), Color(0xFF6BA5A0)], colors: [
Theme.of(context).colorScheme.primary,
Theme.of(
context,
).colorScheme.primary.withOpacity(0.8),
],
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
) )
: null, : null,
color: _messageController.text.isNotEmpty color: _messageController.text.isNotEmpty
? null ? null
: Colors.grey[300], : Theme.of(context).colorScheme.outline.withOpacity(0.3),
borderRadius: BorderRadius.circular(22), borderRadius: BorderRadius.circular(22),
boxShadow: _messageController.text.isNotEmpty boxShadow: _messageController.text.isNotEmpty
? [ ? [
BoxShadow( BoxShadow(
color: const Color(0xFF82C9BD).withOpacity(0.3), color: Theme.of(
context,
).colorScheme.primary.withOpacity(0.3),
blurRadius: 8, blurRadius: 8,
offset: const Offset(0, 2), offset: const Offset(0, 2),
), ),
@@ -398,7 +440,8 @@ class _TutorChatPageSimpleState extends State<TutorChatPageSimple>
void _addWelcomeMessage() { void _addWelcomeMessage() {
final welcomeMessage = { 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! 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) { } catch (e) {
// Fallback to error message if API fails // Fallback to error message if API fails
Logger.error('RAG AI Service error: $e'); 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(() { setState(() {
_messages.add({ _messages.add({

View File

@@ -70,7 +70,9 @@ class _LoginPageState extends State<LoginPage> {
); );
print('DEBUG: Login Firebase bem-sucedido'); 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 // Ler role na Firestore
final uid = result?.user?.uid; final uid = result?.user?.uid;
@@ -81,7 +83,9 @@ class _LoginPageState extends State<LoginPage> {
// Validar se o role selecionado corresponde ao role real // Validar se o role selecionado corresponde ao role real
final selectedRole = widget.selectedRole; final selectedRole = widget.selectedRole;
if (selectedRole != null && actualRole != null && selectedRole != actualRole) { if (selectedRole != null &&
actualRole != null &&
selectedRole != actualRole) {
// Role não corresponde - mostrar erro // Role não corresponde - mostrar erro
setState(() { setState(() {
_isLoading = false; _isLoading = false;
@@ -89,11 +93,14 @@ class _LoginPageState extends State<LoginPage> {
String errorMessage; String errorMessage;
if (selectedRole == 'teacher' && actualRole == 'student') { 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') { } 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 { } 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); _showRoleErrorDialog('Acesso Negado', errorMessage);
@@ -151,14 +158,14 @@ class _LoginPageState extends State<LoginPage> {
return AlertDialog( return AlertDialog(
title: Text( title: Text(
title, title,
style: const TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
content: Text( content: Text(
message, message,
style: const TextStyle(color: Color(0xFF2D3748)), style: TextStyle(color: Theme.of(context).colorScheme.onSurface),
), ),
actions: [ actions: [
TextButton( TextButton(
@@ -167,9 +174,9 @@ class _LoginPageState extends State<LoginPage> {
// Fazer logout para limpar a sessão // Fazer logout para limpar a sessão
AuthService.signOut(); AuthService.signOut();
}, },
child: const Text( child: Text(
'Voltar', 'Voltar',
style: TextStyle(color: Color(0xFF82C9BD)), style: TextStyle(color: Theme.of(context).colorScheme.primary),
), ),
), ),
], ],
@@ -180,17 +187,27 @@ class _LoginPageState extends State<LoginPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return PopScope(
body: Container( canPop: false,
decoration: const BoxDecoration( onPopInvokedWithResult: (didPop, result) {
if (!didPop) {
context.go('/role-selection');
}
},
child: Scaffold(
body: Stack(
children: [
// Main content
Container(
decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
Color(0xFFF8F9FA), Theme.of(context).colorScheme.background,
Color.fromRGBO(130, 201, 189, 0.1), Theme.of(context).colorScheme.primary.withOpacity(0.1),
Color.fromRGBO(246, 141, 45, 0.05), Theme.of(context).colorScheme.secondary.withOpacity(0.05),
Color(0xFFF8F9FA), Theme.of(context).colorScheme.background,
], ],
), ),
), ),
@@ -210,7 +227,9 @@ class _LoginPageState extends State<LoginPage> {
Container( Container(
padding: const EdgeInsets.all(20.0), padding: const EdgeInsets.all(20.0),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white.withOpacity(0.9), color: Theme.of(
context,
).colorScheme.surface.withOpacity(0.9),
borderRadius: BorderRadius.circular(16.0), borderRadius: BorderRadius.circular(16.0),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
@@ -228,12 +247,19 @@ class _LoginPageState extends State<LoginPage> {
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
foreground: Paint() foreground: Paint()
..shader = LinearGradient( ..shader =
LinearGradient(
colors: [ colors: [
const Color(0xFF82C9BD), Theme.of(
const Color(0xFFF68D2D), context,
).colorScheme.primary,
Theme.of(
context,
).colorScheme.secondary,
], ],
).createShader(Rect.fromLTWH(0, 0, 200, 20)), ).createShader(
Rect.fromLTWH(0, 0, 200, 20),
),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@@ -241,7 +267,9 @@ class _LoginPageState extends State<LoginPage> {
'Escola Profissional de Vila do Conde', 'Escola Profissional de Vila do Conde',
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: const Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
), ),
@@ -257,7 +285,9 @@ class _LoginPageState extends State<LoginPage> {
Container( Container(
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white.withOpacity(0.9), color: Theme.of(
context,
).colorScheme.surface.withOpacity(0.9),
borderRadius: BorderRadius.circular(16.0), borderRadius: BorderRadius.circular(16.0),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
@@ -272,10 +302,12 @@ class _LoginPageState extends State<LoginPage> {
children: [ children: [
Text( Text(
'Entrar', 'Entrar',
style: const TextStyle( style: TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
), ),
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
@@ -284,34 +316,50 @@ class _LoginPageState extends State<LoginPage> {
TextFormField( TextFormField(
controller: _emailController, controller: _emailController,
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress,
style: const TextStyle(color: Color(0xFF2D3748)), style: TextStyle(
color: Theme.of(
context,
).colorScheme.onSurface,
),
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Email', labelText: 'Email',
labelStyle: const TextStyle( labelStyle: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
), ),
hintStyle: const TextStyle( hintStyle: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
), ),
prefixIcon: const Icon( prefixIcon: Icon(
Icons.email, Icons.email,
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
border: InputBorder.none, border: InputBorder.none,
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFFE2E8F0), color: Theme.of(
context,
).colorScheme.outline.withOpacity(0.5),
), ),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
), ),
filled: true, filled: true,
fillColor: const Color(0xFFF8F9FA), fillColor: Theme.of(
context,
).colorScheme.surface,
), ),
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -329,25 +377,37 @@ class _LoginPageState extends State<LoginPage> {
TextFormField( TextFormField(
controller: _passwordController, controller: _passwordController,
obscureText: _obscurePassword, obscureText: _obscurePassword,
style: const TextStyle(color: Color(0xFF2D3748)), style: TextStyle(
color: Theme.of(
context,
).colorScheme.onSurface,
),
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Palavra-passe', labelText: 'Palavra-passe',
labelStyle: const TextStyle( labelStyle: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
), ),
hintStyle: const TextStyle( hintStyle: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
), ),
prefixIcon: const Icon( prefixIcon: Icon(
Icons.lock, Icons.lock,
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon( icon: Icon(
_obscurePassword _obscurePassword
? Icons.visibility ? Icons.visibility
: Icons.visibility_off, : Icons.visibility_off,
color: const Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
onPressed: () { onPressed: () {
setState(() { setState(() {
@@ -358,18 +418,24 @@ class _LoginPageState extends State<LoginPage> {
border: InputBorder.none, border: InputBorder.none,
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFFE2E8F0), color: Theme.of(
context,
).colorScheme.outline.withOpacity(0.5),
), ),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
), ),
filled: true, filled: true,
fillColor: const Color(0xFFF8F9FA), fillColor: Theme.of(
context,
).colorScheme.surface,
), ),
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -393,7 +459,9 @@ class _LoginPageState extends State<LoginPage> {
_rememberMe = value ?? false; _rememberMe = value ?? false;
}); });
}, },
activeColor: const Color(0xFF82C9BD), activeColor: Theme.of(
context,
).colorScheme.primary,
checkColor: Colors.white, checkColor: Colors.white,
), ),
GestureDetector( GestureDetector(
@@ -405,7 +473,9 @@ class _LoginPageState extends State<LoginPage> {
child: Text( child: Text(
'Manter sessão iniciada', 'Manter sessão iniciada',
style: TextStyle( style: TextStyle(
color: const Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
fontSize: 14, fontSize: 14,
fontWeight: _rememberMe fontWeight: _rememberMe
? FontWeight.w500 ? FontWeight.w500
@@ -423,10 +493,14 @@ class _LoginPageState extends State<LoginPage> {
child: ElevatedButton( child: ElevatedButton(
onPressed: _isLoading ? null : _handleLogin, onPressed: _isLoading ? null : _handleLogin,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF82C9BD), backgroundColor: Theme.of(
context,
).colorScheme.primary,
foregroundColor: Colors.white, foregroundColor: Colors.white,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(
8.0,
),
), ),
elevation: 2, elevation: 2,
), ),
@@ -460,8 +534,10 @@ class _LoginPageState extends State<LoginPage> {
}, },
child: Text( child: Text(
'Não tem conta? Criar aqui', 'Não tem conta? Criar aqui',
style: const TextStyle( style: TextStyle(
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
), ),
@@ -480,6 +556,36 @@ class _LoginPageState extends State<LoginPage> {
), ),
), ),
), ),
// 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'),
),
),
),
],
),
),
); );
} }
} }

View File

@@ -23,9 +23,10 @@ class _RoleSelectionPageState extends State<RoleSelectionPage> {
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
AppColors.background, Theme.of(context).colorScheme.background,
AppColors.primaryBlue.withOpacity(0.05), Theme.of(context).colorScheme.primary.withOpacity(0.1),
AppColors.gradientStart.withOpacity(0.1), Theme.of(context).colorScheme.secondary.withOpacity(0.05),
Theme.of(context).colorScheme.background,
], ],
), ),
), ),
@@ -92,7 +93,9 @@ class _RoleSelectionPageState extends State<RoleSelectionPage> {
AppLocalizations.of(context)!.appTitle, AppLocalizations.of(context)!.appTitle,
style: Theme.of(context).textTheme.headlineLarge style: Theme.of(context).textTheme.headlineLarge
?.copyWith( ?.copyWith(
color: AppColors.textPrimary, color: Theme.of(
context,
).colorScheme.onSurface,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
) )
@@ -149,7 +152,7 @@ class _RoleSelectionPageState extends State<RoleSelectionPage> {
'Quem é você?', 'Quem é você?',
style: Theme.of(context).textTheme.headlineMedium style: Theme.of(context).textTheme.headlineMedium
?.copyWith( ?.copyWith(
color: AppColors.textPrimary, color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
) )
@@ -351,7 +354,7 @@ class _RoleSelectionPageState extends State<RoleSelectionPage> {
style: Theme.of(context).textTheme.titleLarge?.copyWith( style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: isSelected color: isSelected
? Colors.white ? Colors.white
: AppColors.textPrimary, : Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),

View File

@@ -101,17 +101,27 @@ class _SignupPageState extends State<SignupPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return PopScope(
body: Container( canPop: false,
decoration: const BoxDecoration( onPopInvokedWithResult: (didPop, result) {
if (!didPop) {
context.go('/role-selection');
}
},
child: Scaffold(
body: Stack(
children: [
// Main content
Container(
decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
Color(0xFFF8F9FA), Theme.of(context).colorScheme.background,
Color.fromRGBO(130, 201, 189, 0.1), Theme.of(context).colorScheme.primary.withOpacity(0.1),
Color.fromRGBO(246, 141, 45, 0.05), Theme.of(context).colorScheme.secondary.withOpacity(0.05),
Color(0xFFF8F9FA), Theme.of(context).colorScheme.background,
], ],
), ),
), ),
@@ -131,11 +141,15 @@ class _SignupPageState extends State<SignupPage> {
Container( Container(
padding: const EdgeInsets.all(20.0), padding: const EdgeInsets.all(20.0),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white.withOpacity(0.9), color: Theme.of(
context,
).colorScheme.surface.withOpacity(0.9),
borderRadius: BorderRadius.circular(16.0), borderRadius: BorderRadius.circular(16.0),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: Theme.of(
context,
).colorScheme.shadow.withOpacity(0.1),
blurRadius: 10.0, blurRadius: 10.0,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -149,12 +163,19 @@ class _SignupPageState extends State<SignupPage> {
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
foreground: Paint() foreground: Paint()
..shader = LinearGradient( ..shader =
LinearGradient(
colors: [ colors: [
const Color(0xFF82C9BD), Theme.of(
const Color(0xFFF68D2D), context,
).colorScheme.primary,
Theme.of(
context,
).colorScheme.secondary,
], ],
).createShader(Rect.fromLTWH(0, 0, 200, 20)), ).createShader(
Rect.fromLTWH(0, 0, 200, 20),
),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@@ -162,7 +183,9 @@ class _SignupPageState extends State<SignupPage> {
'Escola Profissional de Vila do Conde', 'Escola Profissional de Vila do Conde',
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: const Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
), ),
@@ -178,11 +201,15 @@ class _SignupPageState extends State<SignupPage> {
Container( Container(
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white.withOpacity(0.9), color: Theme.of(
context,
).colorScheme.surface.withOpacity(0.9),
borderRadius: BorderRadius.circular(16.0), borderRadius: BorderRadius.circular(16.0),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: Theme.of(
context,
).colorScheme.shadow.withOpacity(0.1),
blurRadius: 10.0, blurRadius: 10.0,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -193,10 +220,12 @@ class _SignupPageState extends State<SignupPage> {
children: [ children: [
Text( Text(
'Criar Conta', 'Criar Conta',
style: const TextStyle( style: TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
), ),
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
@@ -205,34 +234,54 @@ class _SignupPageState extends State<SignupPage> {
TextFormField( TextFormField(
controller: _nameController, controller: _nameController,
keyboardType: TextInputType.name, keyboardType: TextInputType.name,
style: const TextStyle(color: Color(0xFF2D3748)), style: TextStyle(
color: Theme.of(
context,
).colorScheme.onSurface,
),
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Nome Completo', labelText: 'Nome Completo',
labelStyle: const TextStyle( labelStyle: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
), ),
hintStyle: const TextStyle( hintStyle: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
), ),
prefixIcon: const Icon( prefixIcon: Icon(
Icons.person, Icons.person,
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
border: InputBorder.none, border: InputBorder.none,
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFFE2E8F0), color: Theme.of(
context,
).colorScheme.outline.withOpacity(0.3),
), ),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
), ),
filled: true, filled: true,
fillColor: const Color(0xFFF8F9FA), fillColor:
Theme.of(context).brightness ==
Brightness.dark
? Theme.of(
context,
).colorScheme.surfaceContainerHighest
: Theme.of(context).colorScheme.surface,
), ),
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -250,34 +299,54 @@ class _SignupPageState extends State<SignupPage> {
TextFormField( TextFormField(
controller: _emailController, controller: _emailController,
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress,
style: const TextStyle(color: Color(0xFF2D3748)), style: TextStyle(
color: Theme.of(
context,
).colorScheme.onSurface,
),
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Email', labelText: 'Email',
labelStyle: const TextStyle( labelStyle: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
), ),
hintStyle: const TextStyle( hintStyle: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
), ),
prefixIcon: const Icon( prefixIcon: Icon(
Icons.email, Icons.email,
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
border: InputBorder.none, border: InputBorder.none,
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFFE2E8F0), color: Theme.of(
context,
).colorScheme.outline.withOpacity(0.3),
), ),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
), ),
filled: true, filled: true,
fillColor: const Color(0xFFF8F9FA), fillColor:
Theme.of(context).brightness ==
Brightness.dark
? Theme.of(
context,
).colorScheme.surfaceContainerHighest
: Theme.of(context).colorScheme.surface,
), ),
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -295,25 +364,37 @@ class _SignupPageState extends State<SignupPage> {
TextFormField( TextFormField(
controller: _passwordController, controller: _passwordController,
obscureText: _obscurePassword, obscureText: _obscurePassword,
style: const TextStyle(color: Color(0xFF2D3748)), style: TextStyle(
color: Theme.of(
context,
).colorScheme.onSurface,
),
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Palavra-passe', labelText: 'Palavra-passe',
labelStyle: const TextStyle( labelStyle: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(
context,
).colorScheme.onSurface,
), ),
hintStyle: const TextStyle( hintStyle: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
), ),
prefixIcon: const Icon( prefixIcon: Icon(
Icons.lock, Icons.lock,
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon( icon: Icon(
_obscurePassword _obscurePassword
? Icons.visibility ? Icons.visibility
: Icons.visibility_off, : Icons.visibility_off,
color: const Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
onPressed: () { onPressed: () {
setState(() { setState(() {
@@ -324,18 +405,28 @@ class _SignupPageState extends State<SignupPage> {
border: InputBorder.none, border: InputBorder.none,
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFFE2E8F0), color: Theme.of(
context,
).colorScheme.outline.withOpacity(0.3),
), ),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
), ),
), ),
filled: true, filled: true,
fillColor: const Color(0xFFF8F9FA), fillColor:
Theme.of(context).brightness ==
Brightness.dark
? Theme.of(
context,
).colorScheme.surfaceContainerHighest
: Theme.of(context).colorScheme.surface,
), ),
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -353,12 +444,18 @@ class _SignupPageState extends State<SignupPage> {
SizedBox( SizedBox(
height: 50, height: 50,
child: ElevatedButton( child: ElevatedButton(
onPressed: _isLoading ? null : _handleSignup, onPressed: _isLoading
? null
: _handleSignup,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF82C9BD), backgroundColor: Theme.of(
context,
).colorScheme.primary,
foregroundColor: Colors.white, foregroundColor: Colors.white,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(
8.0,
),
), ),
elevation: 2, elevation: 2,
), ),
@@ -392,8 +489,10 @@ class _SignupPageState extends State<SignupPage> {
}, },
child: Text( child: Text(
'Já tem conta? Entrar aqui', 'Já tem conta? Entrar aqui',
style: const TextStyle( style: TextStyle(
color: Color(0xFF82C9BD), color: Theme.of(
context,
).colorScheme.primary,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
), ),
@@ -412,6 +511,36 @@ class _SignupPageState extends State<SignupPage> {
), ),
), ),
), ),
// 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'),
),
),
),
],
),
),
); );
} }
} }

View File

@@ -76,15 +76,15 @@ class _StudentDashboardPageState extends State<StudentDashboardPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: Container( body: Container(
decoration: const BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topCenter, begin: Alignment.topCenter,
end: Alignment.bottomCenter, end: Alignment.bottomCenter,
colors: [ colors: [
Color(0xFF82C9BD), Theme.of(context).colorScheme.primary,
Color(0xFF7BA89C), Theme.of(context).colorScheme.primary.withOpacity(0.8),
Color(0xFFF68D2D), Theme.of(context).colorScheme.secondary,
Color(0xFFF8F9FA), Theme.of(context).colorScheme.background,
], ],
stops: [0.0, 0.2, 0.6, 1.0], stops: [0.0, 0.2, 0.6, 1.0],
), ),

View File

@@ -71,15 +71,15 @@ class _TeacherDashboardPageState extends State<TeacherDashboardPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: Container( body: Container(
decoration: const BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topCenter, begin: Alignment.topCenter,
end: Alignment.bottomCenter, end: Alignment.bottomCenter,
colors: [ colors: [
Color(0xFF82C9BD), Theme.of(context).colorScheme.primary,
Color(0xFF7BA89C), Theme.of(context).colorScheme.primary.withOpacity(0.8),
Color(0xFFF68D2D), Theme.of(context).colorScheme.secondary,
Color(0xFFF8F9FA), Theme.of(context).colorScheme.background,
], ],
stops: [0.0, 0.2, 0.6, 1.0], stops: [0.0, 0.2, 0.6, 1.0],
), ),

View File

@@ -17,12 +17,14 @@ class ProfileSectionWidget extends StatelessWidget {
margin: const EdgeInsets.only(top: 24), margin: const EdgeInsets.only(top: 24),
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), 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: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -38,8 +40,13 @@ class ProfileSectionWidget extends StatelessWidget {
width: 48, width: 48,
height: 48, height: 48,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: const LinearGradient( gradient: LinearGradient(
colors: [Color(0xFF82C9BD), Color(0xFF6BA8A0)], colors: [
Theme.of(context).colorScheme.primary,
Theme.of(
context,
).colorScheme.primary.withOpacity(0.8),
],
), ),
borderRadius: BorderRadius.circular(24), borderRadius: BorderRadius.circular(24),
), ),
@@ -56,8 +63,8 @@ class ProfileSectionWidget extends StatelessWidget {
children: [ children: [
Text( Text(
userName, userName,
style: const TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -70,16 +77,20 @@ class ProfileSectionWidget extends StatelessWidget {
children: [ children: [
Text( Text(
userEmail, userEmail,
style: const TextStyle( style: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 14, fontSize: 14,
), ),
), ),
if (userEmail.length > 20) ...[ if (userEmail.length > 20) ...[
const SizedBox(width: 8), const SizedBox(width: 8),
const Icon( Icon(
Icons.more_horiz, Icons.more_horiz,
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
size: 16, size: 16,
), ),
], ],
@@ -96,12 +107,14 @@ class ProfileSectionWidget extends StatelessWidget {
child: Container( child: Container(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF68D2D).withOpacity(0.1), color: Theme.of(
context,
).colorScheme.secondary.withOpacity(0.1),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: const Icon( child: Icon(
Icons.settings, Icons.settings,
color: Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
size: 20, size: 20,
), ),
), ),
@@ -113,16 +126,16 @@ class ProfileSectionWidget extends StatelessWidget {
// Achievements // Achievements
Row( Row(
children: [ children: [
const Icon( Icon(
Icons.emoji_events, Icons.emoji_events,
color: Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
size: 20, size: 20,
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
const Text( Text(
'Conquistas', 'Conquistas',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -137,25 +150,27 @@ class ProfileSectionWidget extends StatelessWidget {
_buildAchievementBadge( _buildAchievementBadge(
icon: Icons.local_fire_department, icon: Icons.local_fire_department,
label: '7 dias', label: '7 dias',
color: const Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
_buildAchievementBadge( _buildAchievementBadge(
icon: Icons.school, icon: Icons.school,
label: '3 conceitos', label: '3 conceitos',
color: const Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
_buildAchievementBadge( _buildAchievementBadge(
icon: Icons.speed, icon: Icons.speed,
label: 'Rápido', label: 'Rápido',
color: const Color(0xFF6BA8A0), color: Theme.of(
context,
).colorScheme.primary.withOpacity(0.8),
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
_buildAchievementBadge( _buildAchievementBadge(
icon: Icons.star, icon: Icons.star,
label: '100%', label: '100%',
color: const Color(0xFF4CAF50), color: Theme.of(context).colorScheme.tertiary,
), ),
], ],
), ),
@@ -165,15 +180,21 @@ class ProfileSectionWidget extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( 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), 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( child: Row(
children: [ children: [
const Icon( Icon(
Icons.trending_up, Icons.trending_up,
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
size: 20, size: 20,
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
@@ -181,10 +202,10 @@ class ProfileSectionWidget extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'Ótimo progresso!', 'Ótimo progresso!',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -192,8 +213,10 @@ class ProfileSectionWidget extends StatelessWidget {
const SizedBox(height: 2), const SizedBox(height: 2),
Text( Text(
'Você está 15% acima da média esta semana', 'Você está 15% acima da média esta semana',
style: const TextStyle( style: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 12, fontSize: 12,
), ),
), ),

View File

@@ -39,7 +39,7 @@ class ProgressHeroWidget extends StatelessWidget {
Text( Text(
'Seu Progresso', 'Seu Progresso',
style: TextStyle( style: TextStyle(
color: const Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -48,7 +48,7 @@ class ProgressHeroWidget extends StatelessWidget {
Text( Text(
'Continue assim, $userName!', 'Continue assim, $userName!',
style: TextStyle( style: TextStyle(
color: const Color(0xFF718096), color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 16, fontSize: 16,
), ),
), ),
@@ -56,9 +56,12 @@ class ProgressHeroWidget extends StatelessWidget {
), ),
), ),
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
), ),
child: Row( child: Row(
@@ -93,8 +96,8 @@ class ProgressHeroWidget extends StatelessWidget {
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
const Color(0xFF82C9BD), Theme.of(context).colorScheme.primary,
const Color(0xFF6BA8A0), Theme.of(context).colorScheme.primary.withOpacity(0.8),
], ],
), ),
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
@@ -188,12 +191,18 @@ class ProgressHeroWidget extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), 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: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(
context,
).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -204,16 +213,16 @@ class ProgressHeroWidget extends StatelessWidget {
children: [ children: [
Row( Row(
children: [ children: [
const Icon( Icon(
Icons.school, Icons.school,
color: Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
size: 20, size: 20,
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
const Text( Text(
'Conceitos Dominados', 'Conceitos Dominados',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -221,15 +230,16 @@ class ProgressHeroWidget extends StatelessWidget {
], ],
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
...masteredConcepts.map((concept) => Padding( ...masteredConcepts.map(
(concept) => Padding(
padding: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.only(bottom: 8),
child: Row( child: Row(
children: [ children: [
Container( Container(
width: 8, width: 8,
height: 8, height: 8,
decoration: const BoxDecoration( decoration: BoxDecoration(
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
), ),
@@ -237,26 +247,32 @@ class ProgressHeroWidget extends StatelessWidget {
Expanded( Expanded(
child: Text( child: Text(
concept, concept,
style: const TextStyle( style: TextStyle(
color: Color(0xFF4A5568), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 14, fontSize: 14,
), ),
), ),
), ),
const Icon( Icon(
Icons.check_circle, Icons.check_circle,
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
size: 16, size: 16,
), ),
], ],
), ),
)), ),
),
], ],
), ),
).animate().slideX( )
.animate()
.slideX(
duration: const Duration(milliseconds: 800), duration: const Duration(milliseconds: 800),
curve: Curves.easeOut, curve: Curves.easeOut,
).then(delay: const Duration(milliseconds: 200)), )
.then(delay: const Duration(milliseconds: 200)),
], ],
), ),
); );
@@ -272,10 +288,7 @@ class ProgressHeroWidget extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2), color: Colors.white.withOpacity(0.2),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all( border: Border.all(color: Colors.white.withOpacity(0.3), width: 1),
color: Colors.white.withOpacity(0.3),
width: 1,
),
), ),
child: Column( child: Column(
children: [ children: [
@@ -292,10 +305,7 @@ class ProgressHeroWidget extends StatelessWidget {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
label, label,
style: const TextStyle( style: const TextStyle(color: Colors.white, fontSize: 12),
color: Colors.white,
fontSize: 12,
),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
], ],

View File

@@ -15,7 +15,7 @@ class QuickAccessWidget extends StatelessWidget {
Text( Text(
'Acesso Rápido', 'Acesso Rápido',
style: TextStyle( style: TextStyle(
color: const Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -48,15 +48,18 @@ class QuickAccessWidget extends StatelessWidget {
return Container( return Container(
height: 150, height: 150,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: const LinearGradient( gradient: LinearGradient(
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, 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), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: const Color(0xFF82C9BD).withOpacity(0.3), color: Theme.of(context).colorScheme.primary.withOpacity(0.3),
blurRadius: 15, blurRadius: 15,
offset: const Offset(0, 8), offset: const Offset(0, 8),
), ),
@@ -102,7 +105,7 @@ class QuickAccessWidget extends StatelessWidget {
vertical: 4, vertical: 4,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: const Text( child: const Text(
@@ -159,12 +162,15 @@ class QuickAccessWidget extends StatelessWidget {
return Container( return Container(
height: 150, height: 150,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), 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: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -192,34 +198,38 @@ class QuickAccessWidget extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF68D2D).withOpacity(0.1), color: Theme.of(
context,
).colorScheme.secondary.withOpacity(0.1),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: const Icon( child: Icon(
Icons.quiz, Icons.quiz,
color: Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
size: 24, size: 24,
), ),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
const Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'Quiz', 'Quiz',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
'Teste conhecimentos', 'Testa os teus conhecimentos',
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 12, fontSize: 12,
height: 1.2, height: 1.2,
), ),
@@ -242,14 +252,17 @@ class QuickAccessWidget extends StatelessWidget {
Widget _buildJoinClassCard(BuildContext context) { Widget _buildJoinClassCard(BuildContext context) {
return Container( return Container(
height: 80, height: 86,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), 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: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -262,9 +275,7 @@ class QuickAccessWidget extends StatelessWidget {
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(builder: (_) => const JoinClassPage()),
builder: (_) => const JoinClassPage(),
),
); );
}, },
child: Padding( child: Padding(
@@ -274,17 +285,19 @@ class QuickAccessWidget extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFF82C9BD).withOpacity(0.1), color: Theme.of(
context,
).colorScheme.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: const Icon( child: Icon(
Icons.group_add, Icons.group_add,
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
size: 24, size: 24,
), ),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
const Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@@ -292,27 +305,29 @@ class QuickAccessWidget extends StatelessWidget {
Text( Text(
'Entrar numa Turma', 'Entrar numa Turma',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
'Junta-te a uma turma com o código', 'Junta-te a uma turma com o código',
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 13, fontSize: 13,
), ),
), ),
], ],
), ),
), ),
const Icon( Icon(
Icons.arrow_forward_ios, Icons.arrow_forward_ios,
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
size: 16, size: 16,
), ),
], ],

View File

@@ -23,11 +23,11 @@ class StudentClassesListWidget extends StatelessWidget {
.snapshots(), .snapshots(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) { if (snapshot.connectionState == ConnectionState.waiting) {
return const Center( return Center(
child: Padding( child: Padding(
padding: EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: CircularProgressIndicator( 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), padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text( child: Text(
'Ainda não entraste em nenhuma turma.', 'Ainda não entraste em nenhuma turma.',
style: TextStyle( style: TextStyle(color: Colors.grey[600], fontSize: 14),
color: Colors.grey[600],
fontSize: 14,
),
), ),
); );
} }
@@ -58,7 +55,7 @@ class StudentClassesListWidget extends StatelessWidget {
Text( Text(
'As Minhas Turmas', 'As Minhas Turmas',
style: Theme.of(context).textTheme.titleLarge?.copyWith( style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: const Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
@@ -102,7 +99,10 @@ class StudentClassesListWidget extends StatelessWidget {
} }
return FutureBuilder<DocumentSnapshot>( return FutureBuilder<DocumentSnapshot>(
future: FirebaseFirestore.instance.collection('classes').doc(classId).get(), future: FirebaseFirestore.instance
.collection('classes')
.doc(classId)
.get(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (!snapshot.hasData || !snapshot.data!.exists) { if (!snapshot.hasData || !snapshot.data!.exists) {
return Container( return Container(
@@ -110,19 +110,19 @@ class StudentClassesListWidget extends StatelessWidget {
height: 150, height: 150,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
], ],
), ),
child: const Center( child: Center(
child: CircularProgressIndicator( child: CircularProgressIndicator(
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
strokeWidth: 2, strokeWidth: 2,
), ),
), ),
@@ -138,11 +138,11 @@ class StudentClassesListWidget extends StatelessWidget {
height: 150, height: 150,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -155,20 +155,20 @@ class StudentClassesListWidget extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFF82C9BD).withOpacity(0.1), color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: const Icon( child: Icon(
Icons.school, Icons.school,
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
size: 24, size: 24,
), ),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
Text( Text(
className, className,
style: const TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -179,7 +179,7 @@ class StudentClassesListWidget extends StatelessWidget {
Text( Text(
'Código: $classCode', 'Código: $classCode',
style: TextStyle( style: TextStyle(
color: Colors.grey[600], color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 13, fontSize: 13,
), ),
), ),

View File

@@ -16,12 +16,14 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
margin: const EdgeInsets.only(top: 24), margin: const EdgeInsets.only(top: 24),
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), 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: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -37,8 +39,13 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
width: 48, width: 48,
height: 48, height: 48,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: const LinearGradient( gradient: LinearGradient(
colors: [Color(0xFF82C9BD), Color(0xFF6BA8A0)], colors: [
Theme.of(context).colorScheme.primary,
Theme.of(
context,
).colorScheme.primary.withOpacity(0.8),
],
), ),
borderRadius: BorderRadius.circular(24), borderRadius: BorderRadius.circular(24),
), ),
@@ -55,8 +62,8 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
children: [ children: [
Text( Text(
userName, userName,
style: const TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -69,16 +76,20 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
children: [ children: [
Text( Text(
userEmail, userEmail,
style: const TextStyle( style: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 14, fontSize: 14,
), ),
), ),
if (userEmail.length > 20) ...[ if (userEmail.length > 20) ...[
const SizedBox(width: 8), const SizedBox(width: 8),
const Icon( Icon(
Icons.more_horiz, Icons.more_horiz,
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
size: 16, size: 16,
), ),
], ],
@@ -91,12 +102,14 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF68D2D).withOpacity(0.1), color: Theme.of(
context,
).colorScheme.secondary.withOpacity(0.1),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: const Icon( child: Icon(
Icons.settings, Icons.settings,
color: Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
size: 20, size: 20,
), ),
), ),
@@ -111,21 +124,23 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
icon: Icons.check_circle, icon: Icons.check_circle,
label: 'Alunos Ativos', label: 'Alunos Ativos',
value: '18/24', value: '18/24',
color: const Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
_buildQuickStat( _buildQuickStat(
icon: Icons.warning_amber, icon: Icons.warning_amber,
label: 'Precisam Apoio', label: 'Precisam Apoio',
value: '3', value: '3',
color: const Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
_buildQuickStat( _buildQuickStat(
icon: Icons.emoji_events, icon: Icons.emoji_events,
label: 'Média Turma', label: 'Média Turma',
value: '72%', value: '72%',
color: const Color(0xFF6BA8A0), color: Theme.of(
context,
).colorScheme.primary.withOpacity(0.8),
), ),
], ],
), ),
@@ -134,16 +149,16 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
// Top Performing Students Preview // Top Performing Students Preview
Row( Row(
children: [ children: [
const Icon( Icon(
Icons.leaderboard, Icons.leaderboard,
color: Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
size: 20, size: 20,
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
const Text( Text(
'Melhores Desempenhos', 'Melhores Desempenhos',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -153,13 +168,33 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
const SizedBox(height: 12), const SizedBox(height: 12),
// Student List Preview // Student List Preview
_buildStudentPerformanceItem('Ana Silva', 95, const Color(0xFF4CAF50)), _buildStudentPerformanceItem(
context,
'Ana Silva',
95,
Theme.of(context).colorScheme.tertiary,
),
const SizedBox(height: 8), const SizedBox(height: 8),
_buildStudentPerformanceItem('João Costa', 88, const Color(0xFF82C9BD)), _buildStudentPerformanceItem(
context,
'João Costa',
88,
Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 8), const SizedBox(height: 8),
_buildStudentPerformanceItem('Maria Santos', 82, const Color(0xFF82C9BD)), _buildStudentPerformanceItem(
context,
'Maria Santos',
82,
Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 8), const SizedBox(height: 8),
_buildStudentPerformanceItem('Pedro Lima', 45, const Color(0xFFF68D2D)), _buildStudentPerformanceItem(
context,
'Pedro Lima',
45,
Theme.of(context).colorScheme.secondary,
),
const SizedBox(height: 20), const SizedBox(height: 20),
@@ -167,15 +202,19 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF8F9FA), color: Theme.of(context).colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(12), 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( child: Row(
children: [ children: [
const Icon( Icon(
Icons.info_outline, Icons.info_outline,
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
size: 20, size: 20,
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
@@ -183,10 +222,10 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'Qualidade do Conteúdo', 'Qualidade do Conteúdo',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -194,8 +233,10 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
const SizedBox(height: 2), const SizedBox(height: 2),
Text( Text(
'12 conteúdos verificados • 2 pendentes de revisão', '12 conteúdos verificados • 2 pendentes de revisão',
style: const TextStyle( style: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 12, fontSize: 12,
), ),
), ),
@@ -245,10 +286,7 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
const SizedBox(height: 2), const SizedBox(height: 2),
Text( Text(
label, label,
style: TextStyle( style: TextStyle(color: color.withOpacity(0.8), fontSize: 10),
color: color.withOpacity(0.8),
fontSize: 10,
),
textAlign: TextAlign.center, 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( return Row(
children: [ children: [
Container( Container(
@@ -282,8 +325,8 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
Expanded( Expanded(
child: Text( child: Text(
name, name,
style: const TextStyle( style: TextStyle(
color: Color(0xFF4A5568), color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 14, fontSize: 14,
), ),
), ),

View File

@@ -24,11 +24,11 @@ class TeacherClassesListWidget extends StatelessWidget {
.snapshots(), .snapshots(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) { if (snapshot.connectionState == ConnectionState.waiting) {
return const Center( return Center(
child: Padding( child: Padding(
padding: EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: CircularProgressIndicator( child: CircularProgressIndicator(
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
), ),
), ),
); );
@@ -46,7 +46,7 @@ class TeacherClassesListWidget extends StatelessWidget {
child: Text( child: Text(
'Ainda não criaste nenhuma turma.', 'Ainda não criaste nenhuma turma.',
style: TextStyle( style: TextStyle(
color: Colors.grey[600], color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 14, fontSize: 14,
), ),
), ),
@@ -59,7 +59,7 @@ class TeacherClassesListWidget extends StatelessWidget {
Text( Text(
'As Minhas Turmas', 'As Minhas Turmas',
style: Theme.of(context).textTheme.titleLarge?.copyWith( style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: const Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
@@ -105,10 +105,8 @@ class TeacherClassesListWidget extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (_) => ClassStudentsPage( builder: (_) =>
classId: classId, ClassStudentsPage(classId: classId, className: className),
className: className,
),
), ),
); );
}, },
@@ -117,11 +115,11 @@ class TeacherClassesListWidget extends StatelessWidget {
height: 150, height: 150,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -134,20 +132,20 @@ class TeacherClassesListWidget extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFF82C9BD).withOpacity(0.1), color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: const Icon( child: Icon(
Icons.school, Icons.school,
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
size: 24, size: 24,
), ),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
Text( Text(
className, className,
style: const TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -158,7 +156,7 @@ class TeacherClassesListWidget extends StatelessWidget {
Text( Text(
'Código: $classCode', 'Código: $classCode',
style: TextStyle( style: TextStyle(
color: Colors.grey[600], color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 13, fontSize: 13,
), ),
), ),

View File

@@ -35,7 +35,7 @@ class TeacherHeroWidget extends StatelessWidget {
Text( Text(
'Visão Geral da Turma', 'Visão Geral da Turma',
style: TextStyle( style: TextStyle(
color: const Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -44,7 +44,7 @@ class TeacherHeroWidget extends StatelessWidget {
Text( Text(
'Acompanhe o progresso dos seus alunos', 'Acompanhe o progresso dos seus alunos',
style: TextStyle( style: TextStyle(
color: const Color(0xFF718096), color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 16, fontSize: 16,
), ),
), ),
@@ -52,19 +52,18 @@ class TeacherHeroWidget extends StatelessWidget {
), ),
), ),
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
), ),
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Icon( const Icon(Icons.people, color: Colors.white, size: 16),
Icons.people,
color: Colors.white,
size: 16,
),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
'$totalStudents alunos', '$totalStudents alunos',
@@ -89,14 +88,14 @@ class TeacherHeroWidget extends StatelessWidget {
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
const Color(0xFF82C9BD), Theme.of(context).colorScheme.primary,
const Color(0xFF6BA8A0), Theme.of(context).colorScheme.primary.withOpacity(0.8),
], ],
), ),
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: Theme.of(context).colorScheme.shadow.withOpacity(0.1),
blurRadius: 20, blurRadius: 20,
offset: const Offset(0, 10), offset: const Offset(0, 10),
), ),
@@ -184,12 +183,18 @@ class TeacherHeroWidget extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), 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: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(
context,
).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -200,16 +205,16 @@ class TeacherHeroWidget extends StatelessWidget {
children: [ children: [
Row( Row(
children: [ children: [
const Icon( Icon(
Icons.trending_up, Icons.trending_up,
color: Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
size: 20, size: 20,
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
const Text( Text(
'Atividade Recente', 'Atividade Recente',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -218,28 +223,34 @@ class TeacherHeroWidget extends StatelessWidget {
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
_buildActivityItem( _buildActivityItem(
context,
'15 alunos completaram o quiz de Derivadas', '15 alunos completaram o quiz de Derivadas',
'Hoje, 14:30', 'Hoje, 14:30',
const Color(0xFF82C9BD), Theme.of(context).colorScheme.primary,
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
_buildActivityItem( _buildActivityItem(
context,
'Novo conteúdo: Regra da Cadeia', 'Novo conteúdo: Regra da Cadeia',
'Ontem, 09:15', 'Ontem, 09:15',
const Color(0xFFF68D2D), Theme.of(context).colorScheme.secondary,
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
_buildActivityItem( _buildActivityItem(
context,
'3 alunos precisam de apoio em Limites', '3 alunos precisam de apoio em Limites',
'Ontem, 16:45', 'Ontem, 16:45',
const Color(0xFFE53E3E), Theme.of(context).colorScheme.error,
), ),
], ],
), ),
).animate().slideX( )
.animate()
.slideX(
duration: const Duration(milliseconds: 800), duration: const Duration(milliseconds: 800),
curve: Curves.easeOut, curve: Curves.easeOut,
).then(delay: const Duration(milliseconds: 200)), )
.then(delay: const Duration(milliseconds: 200)),
], ],
), ),
); );
@@ -255,10 +266,7 @@ class TeacherHeroWidget extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2), color: Colors.white.withOpacity(0.2),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all( border: Border.all(color: Colors.white.withOpacity(0.3), width: 1),
color: Colors.white.withOpacity(0.3),
width: 1,
),
), ),
child: Column( child: Column(
children: [ children: [
@@ -275,10 +283,7 @@ class TeacherHeroWidget extends StatelessWidget {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
label, label,
style: const TextStyle( style: const TextStyle(color: Colors.white, fontSize: 12),
color: Colors.white,
fontSize: 12,
),
textAlign: TextAlign.center, 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( return Row(
children: [ children: [
Container( Container(
width: 8, width: 8,
height: 8, height: 8,
decoration: BoxDecoration( decoration: BoxDecoration(color: color, shape: BoxShape.circle),
color: color,
shape: BoxShape.circle,
),
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded( Expanded(
@@ -304,16 +311,18 @@ class TeacherHeroWidget extends StatelessWidget {
children: [ children: [
Text( Text(
text, text,
style: const TextStyle( style: TextStyle(
color: Color(0xFF4A5568), color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 14, fontSize: 14,
), ),
), ),
const SizedBox(height: 2), const SizedBox(height: 2),
Text( Text(
time, time,
style: const TextStyle( style: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant.withOpacity(0.7),
fontSize: 12, fontSize: 12,
), ),
), ),

View File

@@ -13,7 +13,8 @@ class TeacherQuickActionsWidget extends StatefulWidget {
const TeacherQuickActionsWidget({super.key}); const TeacherQuickActionsWidget({super.key});
@override @override
State<TeacherQuickActionsWidget> createState() => _TeacherQuickActionsWidgetState(); State<TeacherQuickActionsWidget> createState() =>
_TeacherQuickActionsWidgetState();
} }
class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> { class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
@@ -27,7 +28,7 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
Text( Text(
'Ações Rápidas', 'Ações Rápidas',
style: TextStyle( style: TextStyle(
color: const Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -73,15 +74,18 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
return Container( return Container(
constraints: const BoxConstraints(minHeight: 135, maxHeight: 160), constraints: const BoxConstraints(minHeight: 135, maxHeight: 160),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: const LinearGradient( gradient: LinearGradient(
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, 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), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: const Color(0xFF82C9BD).withOpacity(0.3), color: Theme.of(context).colorScheme.primary.withOpacity(0.3),
blurRadius: 15, blurRadius: 15,
offset: const Offset(0, 8), offset: const Offset(0, 8),
), ),
@@ -93,9 +97,7 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
onTap: () => Navigator.push( onTap: () => Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(builder: (_) => const TeacherMaterialsPage()),
builder: (_) => const TeacherMaterialsPage(),
),
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.all(14), padding: const EdgeInsets.all(14),
@@ -123,7 +125,7 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
vertical: 3, vertical: 3,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: const Text( child: const Text(
@@ -180,12 +182,15 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
return Container( return Container(
height: 150, height: 150,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), 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: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -205,22 +210,24 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
Container( Container(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF68D2D).withOpacity(0.1), color: Theme.of(
context,
).colorScheme.secondary.withOpacity(0.1),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: const Icon( child: Icon(
Icons.quiz, Icons.quiz,
color: Color(0xFFF68D2D), color: Theme.of(context).colorScheme.secondary,
size: 24, size: 24,
), ),
), ),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'Criar Quiz', 'Criar Quiz',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -231,7 +238,9 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
color: const Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 12, fontSize: 12,
height: 1.2, height: 1.2,
), ),
@@ -256,12 +265,15 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
return Container( return Container(
height: 120, height: 120,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), 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: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -281,22 +293,24 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
Container( Container(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFF82C9BD).withOpacity(0.1), color: Theme.of(
context,
).colorScheme.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: const Icon( child: Icon(
Icons.people, Icons.people,
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
size: 20, size: 20,
), ),
), ),
const Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'Gerir Alunos', 'Gerir Alunos',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -304,7 +318,9 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
Text( Text(
'Acesso e permissões', 'Acesso e permissões',
style: TextStyle( style: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 11, fontSize: 11,
), ),
), ),
@@ -328,12 +344,15 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
return Container( return Container(
height: 120, height: 120,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), 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: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -353,22 +372,24 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
Container( Container(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFF6BA8A0).withOpacity(0.1), color: Theme.of(
context,
).colorScheme.primary.withOpacity(0.8),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: const Icon( child: Icon(
Icons.analytics, Icons.analytics,
color: Color(0xFF6BA8A0), color: Theme.of(context).colorScheme.primary,
size: 20, size: 20,
), ),
), ),
const Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'Analytics', 'Analytics',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -376,7 +397,9 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
Text( Text(
'Desempenho da turma', 'Desempenho da turma',
style: TextStyle( style: TextStyle(
color: Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 11, fontSize: 11,
), ),
), ),
@@ -400,12 +423,15 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
return Container( return Container(
constraints: const BoxConstraints(minHeight: 135, maxHeight: 160), constraints: const BoxConstraints(minHeight: 135, maxHeight: 160),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), 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: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -415,7 +441,9 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
color: Colors.transparent, color: Colors.transparent,
child: InkWell( child: InkWell(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
onTap: _isCreatingClass ? null : () => _showCreateClassDialog(context), onTap: _isCreatingClass
? null
: () => _showCreateClassDialog(context),
child: Padding( child: Padding(
padding: const EdgeInsets.all(14), padding: const EdgeInsets.all(14),
child: Column( child: Column(
@@ -425,21 +453,23 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
Container( Container(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFF82C9BD).withOpacity(0.1), color: Theme.of(
context,
).colorScheme.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: _isCreatingClass child: _isCreatingClass
? const SizedBox( ? SizedBox(
width: 24, width: 24,
height: 24, height: 24,
child: CircularProgressIndicator( child: CircularProgressIndicator(
strokeWidth: 2, strokeWidth: 2,
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
), ),
) )
: const Icon( : Icon(
Icons.school, Icons.school,
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
size: 24, size: 24,
), ),
), ),
@@ -449,7 +479,7 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
Text( Text(
'Criar Turma', 'Criar Turma',
style: TextStyle( style: TextStyle(
color: const Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -460,7 +490,9 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
color: const Color(0xFF718096), color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 12, fontSize: 12,
height: 1.2, height: 1.2,
), ),
@@ -491,10 +523,10 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
), ),
title: const Text( title: Text(
'Criar Nova Turma', 'Criar Nova Turma',
style: TextStyle( style: TextStyle(
color: Color(0xFF2D3748), color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
@@ -502,10 +534,10 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'Digite o nome da turma:', 'Digite o nome da turma:',
style: TextStyle( style: TextStyle(
color: Color(0xFF718096), color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 14, fontSize: 14,
), ),
), ),
@@ -515,7 +547,9 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Ex: Matemática 9º Ano', hintText: 'Ex: Matemática 9º Ano',
filled: true, filled: true,
fillColor: const Color(0xFFF7FAFC), fillColor: Theme.of(
context,
).colorScheme.surfaceContainerHighest,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: BorderSide.none, borderSide: BorderSide.none,
@@ -526,8 +560,8 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide( borderSide: BorderSide(
color: Color(0xFF82C9BD), color: Theme.of(context).colorScheme.primary,
width: 2, width: 2,
), ),
), ),
@@ -538,9 +572,11 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.of(dialogContext).pop(), onPressed: () => Navigator.of(dialogContext).pop(),
child: const Text( child: Text(
'Cancelar', 'Cancelar',
style: TextStyle(color: Color(0xFF718096)), style: TextStyle(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
), ),
), ),
ElevatedButton( ElevatedButton(
@@ -552,7 +588,7 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
} }
}, },
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF82C9BD), backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Colors.white, foregroundColor: Colors.white,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
@@ -601,8 +637,10 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text('Turma "$className" criada com sucesso! Código: $classCode'), content: Text(
backgroundColor: const Color(0xFF82C9BD), 'Turma "$className" criada com sucesso! Código: $classCode',
),
backgroundColor: Theme.of(context).colorScheme.primary,
behavior: SnackBarBehavior.floating, behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),

View File

@@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import '../../../../core/theme/app_colors.dart';
class ProfilePage extends StatelessWidget { class ProfilePage extends StatelessWidget {
const ProfilePage({super.key}); const ProfilePage({super.key});
@@ -15,20 +14,24 @@ class ProfilePage extends StatelessWidget {
context.go('/student-dashboard'); context.go('/student-dashboard');
}, },
child: Scaffold( child: Scaffold(
backgroundColor: AppColors.background, backgroundColor: Theme.of(context).colorScheme.background,
appBar: AppBar( appBar: AppBar(
title: const Text('Profile'), title: const Text('Profile'),
backgroundColor: AppColors.surface, backgroundColor: Theme.of(context).colorScheme.surface,
foregroundColor: AppColors.textPrimary, foregroundColor: Theme.of(context).colorScheme.onSurface,
elevation: 0, elevation: 0,
), ),
body: const Center( body: Container(
child: Text( decoration: BoxDecoration(
'Profile Page - Coming Soon', gradient: LinearGradient(
style: TextStyle( begin: Alignment.topLeft,
fontSize: 24, end: Alignment.bottomRight,
fontWeight: FontWeight.bold, colors: [
color: AppColors.textPrimary, 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,
],
), ),
), ),
), ),

View File

@@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import '../../../../core/theme/app_colors.dart';
class QuizListPage extends StatelessWidget { class QuizListPage extends StatelessWidget {
const QuizListPage({super.key}); const QuizListPage({super.key});
@@ -15,20 +14,34 @@ class QuizListPage extends StatelessWidget {
context.go('/student-dashboard'); context.go('/student-dashboard');
}, },
child: Scaffold( child: Scaffold(
backgroundColor: AppColors.background, backgroundColor: Theme.of(context).colorScheme.background,
appBar: AppBar( appBar: AppBar(
title: const Text('Quizzes'), title: const Text('Quizzes'),
backgroundColor: AppColors.surface, backgroundColor: Theme.of(context).colorScheme.surface,
foregroundColor: AppColors.textPrimary, foregroundColor: Theme.of(context).colorScheme.onSurface,
elevation: 0, elevation: 0,
), ),
body: const Center( 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( child: Text(
'Quiz List - Coming Soon', 'Quiz List - Coming Soon',
style: TextStyle( style: TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.textPrimary, color: Theme.of(context).colorScheme.onSurface,
),
), ),
), ),
), ),

View File

@@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import '../../../../core/theme/app_colors.dart';
class QuizPage extends StatelessWidget { class QuizPage extends StatelessWidget {
final String quizId; final String quizId;
@@ -17,22 +16,25 @@ class QuizPage extends StatelessWidget {
context.go('/quiz'); context.go('/quiz');
}, },
child: Scaffold( child: Scaffold(
backgroundColor: AppColors.background, backgroundColor: Theme.of(context).colorScheme.background,
appBar: AppBar( appBar: AppBar(
title: Text('Quiz $quizId'), title: Text('Quiz $quizId'),
backgroundColor: AppColors.surface, backgroundColor: Theme.of(context).colorScheme.surface,
foregroundColor: AppColors.textPrimary, foregroundColor: Theme.of(context).colorScheme.onSurface,
elevation: 0, elevation: 0,
), ),
body: Center( body: Container(
child: Text( decoration: BoxDecoration(
'Quiz Page - ID: $quizId\nComing Soon', gradient: LinearGradient(
style: const TextStyle( begin: Alignment.topLeft,
fontSize: 24, end: Alignment.bottomRight,
fontWeight: FontWeight.bold, colors: [
color: AppColors.textPrimary, 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,
), ),
), ),
), ),

View File

@@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import '../../../../core/theme/app_colors.dart';
/// Help page with user guides /// Help page with user guides
class HelpPage extends StatelessWidget { class HelpPage extends StatelessWidget {
@@ -17,17 +16,17 @@ class HelpPage extends StatelessWidget {
}, },
child: Scaffold( child: Scaffold(
body: Container( body: Container(
decoration: const BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topCenter, begin: Alignment.topCenter,
end: Alignment.bottomCenter, end: Alignment.bottomCenter,
colors: [ colors: [
Color(0xFF82C9BD), Theme.of(context).colorScheme.primary,
Color(0xFF7BA89C), Theme.of(context).colorScheme.primary.withOpacity(0.9),
Color(0xFFF68D2D), Theme.of(context).colorScheme.secondary,
Color(0xFFF8F9FA), 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( child: SafeArea(
@@ -39,14 +38,17 @@ class HelpPage extends StatelessWidget {
child: Row( child: Row(
children: [ children: [
IconButton( IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white), icon: Icon(
Icons.arrow_back,
color: Theme.of(context).colorScheme.onPrimary,
),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
const Expanded( Expanded(
child: Text( child: Text(
'Ajuda e Suporte', 'Ajuda e Suporte',
style: TextStyle( style: TextStyle(
color: Colors.white, color: Theme.of(context).colorScheme.onPrimary,
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -62,6 +64,7 @@ class HelpPage extends StatelessWidget {
child: Column( child: Column(
children: [ children: [
_buildGuideCard( _buildGuideCard(
context: context,
icon: Icons.school, icon: Icons.school,
title: 'Como usar o AI Tutor', title: 'Como usar o AI Tutor',
description: description:
@@ -70,6 +73,7 @@ class HelpPage extends StatelessWidget {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildGuideCard( _buildGuideCard(
context: context,
icon: Icons.quiz, icon: Icons.quiz,
title: 'Como fazer quizzes', title: 'Como fazer quizzes',
description: description:
@@ -78,6 +82,7 @@ class HelpPage extends StatelessWidget {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildGuideCard( _buildGuideCard(
context: context,
icon: Icons.trending_up, icon: Icons.trending_up,
title: 'Ver o seu progresso', title: 'Ver o seu progresso',
description: description:
@@ -86,6 +91,7 @@ class HelpPage extends StatelessWidget {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildGuideCard( _buildGuideCard(
context: context,
icon: Icons.settings, icon: Icons.settings,
title: 'Configurações da app', title: 'Configurações da app',
description: description:
@@ -97,11 +103,13 @@ class HelpPage extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: Theme.of(
context,
).colorScheme.shadow.withOpacity(0.1),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -110,34 +118,40 @@ class HelpPage extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'Perguntas Frequentes', 'Perguntas Frequentes',
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.textPrimary, color: Theme.of(
context,
).colorScheme.onSurface,
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildFAQItem( _buildFAQItem(
context: context,
question: 'Como posso alterar a minha senha?', question: 'Como posso alterar a minha senha?',
answer: answer:
'Pode alterar a sua senha através da secção de segurança nas definições.', 'Pode alterar a sua senha através da secção de segurança nas definições.',
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
_buildFAQItem( _buildFAQItem(
context: context,
question: 'Os meus dados estão seguros?', question: 'Os meus dados estão seguros?',
answer: answer:
'Sim, utilizamos encriptação de ponta a ponta para proteger todos os seus dados.', 'Sim, utilizamos encriptação de ponta a ponta para proteger todos os seus dados.',
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
_buildFAQItem( _buildFAQItem(
context: context,
question: 'Posso usar a app offline?', question: 'Posso usar a app offline?',
answer: answer:
'Algumas funcionalidades estão disponíveis offline, mas para o AI Tutor necessita de conexão à internet.', 'Algumas funcionalidades estão disponíveis offline, mas para o AI Tutor necessita de conexão à internet.',
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
_buildFAQItem( _buildFAQItem(
context: context,
question: 'Como contactar o suporte?', question: 'Como contactar o suporte?',
answer: answer:
'Pode contactar-nos através do email suporte@teachit.com.', 'Pode contactar-nos através do email suporte@teachit.com.',
@@ -150,11 +164,13 @@ class HelpPage extends StatelessWidget {
Container( Container(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: Theme.of(
context,
).colorScheme.shadow.withOpacity(0.1),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -163,20 +179,24 @@ class HelpPage extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'Ainda precisa de ajuda?', 'Ainda precisa de ajuda?',
style: TextStyle( style: TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.textPrimary, color: Theme.of(
context,
).colorScheme.onSurface,
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
const Text( Text(
'A nossa equipa de suporte está disponível para ajudar.', 'A nossa equipa de suporte está disponível para ajudar.',
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: AppColors.textSecondary, color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
@@ -187,8 +207,12 @@ class HelpPage extends StatelessWidget {
icon: const Icon(Icons.email), icon: const Icon(Icons.email),
label: const Text('Contactar Suporte'), label: const Text('Contactar Suporte'),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primaryTeal, backgroundColor: Theme.of(
foregroundColor: Colors.white, context,
).colorScheme.primary,
foregroundColor: Theme.of(
context,
).colorScheme.onPrimary,
), ),
), ),
], ],
@@ -207,6 +231,7 @@ class HelpPage extends StatelessWidget {
} }
Widget _buildGuideCard({ Widget _buildGuideCard({
required BuildContext context,
required IconData icon, required IconData icon,
required String title, required String title,
required String description, required String description,
@@ -215,11 +240,11 @@ class HelpPage extends StatelessWidget {
return Container( return Container(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: Theme.of(context).colorScheme.shadow.withOpacity(0.1),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -234,12 +259,19 @@ class HelpPage extends StatelessWidget {
width: 50, width: 50,
height: 50, height: 50,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: const LinearGradient( gradient: LinearGradient(
colors: [Color(0xFF82C9BD), Color(0xFF6BA8A0)], colors: [
Theme.of(context).colorScheme.primary,
Theme.of(context).colorScheme.primary.withOpacity(0.8),
],
), ),
borderRadius: BorderRadius.circular(25), 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), const SizedBox(width: 16),
Expanded( Expanded(
@@ -248,38 +280,45 @@ class HelpPage extends StatelessWidget {
children: [ children: [
Text( Text(
title, title,
style: const TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.textPrimary, color: Theme.of(context).colorScheme.onSurface,
), ),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
description, description,
style: const TextStyle( style: TextStyle(
fontSize: 12, 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( return ExpansionTile(
title: Text( title: Text(
question, question,
style: const TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.textPrimary, color: Theme.of(context).colorScheme.onSurface,
), ),
), ),
children: [ children: [
@@ -287,9 +326,9 @@ class HelpPage extends StatelessWidget {
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Text( child: Text(
answer, answer,
style: const TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
color: AppColors.textSecondary, color: Theme.of(context).colorScheme.onSurfaceVariant,
), ),
), ),
), ),

View File

@@ -98,17 +98,16 @@ class _ProfileEditPageState extends ConsumerState<ProfileEditPage> {
}, },
child: Scaffold( child: Scaffold(
body: Container( body: Container(
decoration: const BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topCenter, begin: Alignment.topLeft,
end: Alignment.bottomCenter, end: Alignment.bottomRight,
colors: [ colors: [
Color(0xFF82C9BD), Theme.of(context).colorScheme.background,
Color(0xFF7BA89C), Theme.of(context).colorScheme.primary.withOpacity(0.1),
Color(0xFFF68D2D), Theme.of(context).colorScheme.secondary.withOpacity(0.05),
Color(0xFFF8F9FA), Theme.of(context).colorScheme.background,
], ],
stops: [0.0, 0.2, 0.6, 1.0],
), ),
), ),
child: SafeArea( child: SafeArea(
@@ -143,11 +142,13 @@ class _ProfileEditPageState extends ConsumerState<ProfileEditPage> {
child: Container( child: Container(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: Theme.of(
context,
).colorScheme.shadow.withOpacity(0.1),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -181,10 +182,23 @@ class _ProfileEditPageState extends ConsumerState<ProfileEditPage> {
), ),
), ),
const SizedBox(height: 16), 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( Text(
user?.email ?? '', user?.email ?? '',
style: const TextStyle( style: TextStyle(
color: AppColors.textSecondary, color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
fontSize: 14, fontSize: 14,
), ),
), ),
@@ -194,12 +208,12 @@ class _ProfileEditPageState extends ConsumerState<ProfileEditPage> {
const SizedBox(height: 32), const SizedBox(height: 32),
// Name field // Name field
const Text( Text(
'Nome', 'Nome',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.textPrimary, color: Theme.of(context).colorScheme.onSurface,
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@@ -208,7 +222,9 @@ class _ProfileEditPageState extends ConsumerState<ProfileEditPage> {
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Introduza o seu nome', hintText: 'Introduza o seu nome',
filled: true, filled: true,
fillColor: AppColors.background, fillColor: Theme.of(
context,
).colorScheme.surface,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
borderSide: BorderSide.none, borderSide: BorderSide.none,
@@ -228,12 +244,12 @@ class _ProfileEditPageState extends ConsumerState<ProfileEditPage> {
const SizedBox(height: 24), const SizedBox(height: 24),
// Phone field (optional) // Phone field (optional)
const Text( Text(
'Telefone (opcional)', 'Telefone (opcional)',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.textPrimary, color: Theme.of(context).colorScheme.onSurface,
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@@ -243,7 +259,9 @@ class _ProfileEditPageState extends ConsumerState<ProfileEditPage> {
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Introduza o seu telefone', hintText: 'Introduza o seu telefone',
filled: true, filled: true,
fillColor: AppColors.background, fillColor: Theme.of(
context,
).colorScheme.surface,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
borderSide: BorderSide.none, borderSide: BorderSide.none,
@@ -257,12 +275,12 @@ class _ProfileEditPageState extends ConsumerState<ProfileEditPage> {
const SizedBox(height: 24), const SizedBox(height: 24),
// Bio field (optional) // Bio field (optional)
const Text( Text(
'Bio (opcional)', 'Bio (opcional)',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.textPrimary, color: Theme.of(context).colorScheme.onSurface,
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@@ -272,7 +290,9 @@ class _ProfileEditPageState extends ConsumerState<ProfileEditPage> {
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Conte um pouco sobre si', hintText: 'Conte um pouco sobre si',
filled: true, filled: true,
fillColor: AppColors.background, fillColor: Theme.of(
context,
).colorScheme.surface,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
borderSide: BorderSide.none, borderSide: BorderSide.none,

View File

@@ -29,17 +29,21 @@ class _SettingsPageState extends ConsumerState<SettingsPage> {
}, },
child: Scaffold( child: Scaffold(
body: Container( body: Container(
decoration: const BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topCenter, begin: Alignment.topLeft,
end: Alignment.bottomCenter, end: Alignment.bottomRight,
colors: [ colors: themeMode == ThemeMode.light
Color(0xFF82C9BD), ? [
Color(0xFF7BA89C), const Color(0xFFD4E8E8),
Color(0xFFF68D2D), const Color(0xFFE8D4C0),
Color(0xFFF8F9FA), const Color(0xFFD8E0E8),
]
: [
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( child: SafeArea(
@@ -54,11 +58,11 @@ class _SettingsPageState extends ConsumerState<SettingsPage> {
icon: const Icon(Icons.arrow_back, color: Colors.white), icon: const Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => context.go('/student-dashboard'), onPressed: () => context.go('/student-dashboard'),
), ),
const Expanded( Expanded(
child: Text( child: Text(
'Configurações', 'Configurações',
style: TextStyle( style: TextStyle(
color: Colors.white, color: Theme.of(context).colorScheme.onSurface,
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -187,19 +191,23 @@ class _SettingsPageState extends ConsumerState<SettingsPage> {
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: isDark ? Colors.white70 : AppColors.textSecondary, color: isDark
? Colors.white70
: Theme.of(context).colorScheme.onSurfaceVariant,
), ),
), ),
), ),
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: isDark ? Colors.grey[800] : AppColors.surface, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Theme.of(
blurRadius: 2, context,
offset: const Offset(0, 1), ).colorScheme.onSurfaceVariant.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
), ),
], ],
), ),
@@ -220,17 +228,17 @@ class _SettingsPageState extends ConsumerState<SettingsPage> {
leading: const Icon(Icons.palette, color: AppColors.primaryTeal), leading: const Icon(Icons.palette, color: AppColors.primaryTeal),
title: Text( title: Text(
'Tema', 'Tema',
style: TextStyle(color: isDark ? Colors.white : AppColors.textPrimary), style: TextStyle(
color: isDark
? Colors.white
: Theme.of(context).colorScheme.onSurface,
),
), ),
subtitle: Text( subtitle: Text(
isDarkModeAvailable isDarkModeAvailable
? 'Atual: ${_getThemeModeString(currentTheme)}' ? 'Atual: ${_getThemeModeString(currentTheme)}'
: 'Light Mode (padrão)', : 'Light Mode (padrão)',
style: TextStyle( style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
color: isDarkModeAvailable
? (isDark ? Colors.white70 : AppColors.textSecondary)
: AppColors.textHint,
),
), ),
trailing: isDarkModeAvailable trailing: isDarkModeAvailable
? DropdownButton<ThemeMode>( ? DropdownButton<ThemeMode>(
@@ -255,7 +263,10 @@ class _SettingsPageState extends ConsumerState<SettingsPage> {
), ),
], ],
) )
: const Icon(Icons.lock, color: AppColors.textHint), : Icon(
Icons.lock,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
); );
} }
@@ -283,12 +294,18 @@ class _SettingsPageState extends ConsumerState<SettingsPage> {
leading: const Icon(Icons.notifications, color: AppColors.primaryTeal), leading: const Icon(Icons.notifications, color: AppColors.primaryTeal),
title: Text( title: Text(
title, title,
style: TextStyle(color: isDark ? Colors.white : AppColors.textPrimary), style: TextStyle(
color: isDark
? Colors.white
: Theme.of(context).colorScheme.onSurface,
),
), ),
subtitle: Text( subtitle: Text(
subtitle, subtitle,
style: TextStyle( style: TextStyle(
color: isDark ? Colors.white70 : AppColors.textSecondary, color: isDark
? Colors.white70
: Theme.of(context).colorScheme.onSurfaceVariant,
), ),
), ),
trailing: Switch( trailing: Switch(
@@ -312,15 +329,24 @@ class _SettingsPageState extends ConsumerState<SettingsPage> {
leading: Icon(icon, color: AppColors.primaryTeal), leading: Icon(icon, color: AppColors.primaryTeal),
title: Text( title: Text(
title, title,
style: TextStyle(color: isDark ? Colors.white : AppColors.textPrimary), style: TextStyle(
color: isDark
? Colors.white
: Theme.of(context).colorScheme.onSurface,
),
), ),
subtitle: Text( subtitle: Text(
subtitle, subtitle,
style: TextStyle( 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, onTap: onTap,
); );
} }
@@ -336,12 +362,18 @@ class _SettingsPageState extends ConsumerState<SettingsPage> {
leading: Icon(icon, color: AppColors.primaryTeal), leading: Icon(icon, color: AppColors.primaryTeal),
title: Text( title: Text(
title, title,
style: TextStyle(color: isDark ? Colors.white : AppColors.textPrimary), style: TextStyle(
color: isDark
? Colors.white
: Theme.of(context).colorScheme.onSurface,
),
), ),
subtitle: Text( subtitle: Text(
subtitle, subtitle,
style: TextStyle( style: TextStyle(
color: isDark ? Colors.white70 : AppColors.textSecondary, color: isDark
? Colors.white70
: Theme.of(context).colorScheme.onSurfaceVariant,
), ),
), ),
); );

View File

@@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_animate/flutter_animate.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import '../../../../core/theme/app_colors.dart';
import '../../../../core/services/auth_service.dart'; import '../../../../core/services/auth_service.dart';
import '../../../../core/services/session_service.dart'; import '../../../../core/services/session_service.dart';
import '../../../../l10n/app_localizations.dart'; import '../../../../l10n/app_localizations.dart';
@@ -119,10 +118,10 @@ class _SplashPageState extends State<SplashPage> {
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
AppColors.background, Theme.of(context).colorScheme.background,
AppColors.primaryTeal.withOpacity(0.05), Theme.of(context).colorScheme.primary.withOpacity(0.1),
AppColors.primaryOrange.withOpacity(0.03), Theme.of(context).colorScheme.secondary.withOpacity(0.05),
AppColors.background, Theme.of(context).colorScheme.background,
], ],
), ),
), ),
@@ -147,7 +146,9 @@ class _SplashPageState extends State<SplashPage> {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all( border: Border.all(
color: AppColors.primaryTeal.withOpacity(0.2), color: Theme.of(
context,
).colorScheme.primary.withOpacity(0.2),
width: 2, width: 2,
), ),
), ),
@@ -174,7 +175,9 @@ class _SplashPageState extends State<SplashPage> {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all( border: Border.all(
color: AppColors.primaryOrange.withOpacity(0.3), color: Theme.of(
context,
).colorScheme.secondary.withOpacity(0.3),
width: 3, width: 3,
), ),
), ),
@@ -199,10 +202,10 @@ class _SplashPageState extends State<SplashPage> {
width: 80, width: 80,
height: 80, height: 80,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: const LinearGradient( gradient: LinearGradient(
colors: [ colors: [
AppColors.primaryTeal, Theme.of(context).colorScheme.primary,
AppColors.primaryOrange, Theme.of(context).colorScheme.secondary,
], ],
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
@@ -210,14 +213,16 @@ class _SplashPageState extends State<SplashPage> {
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: AppColors.primaryTeal.withOpacity(0.3), color: Theme.of(
context,
).colorScheme.primary.withOpacity(0.3),
blurRadius: 20, blurRadius: 20,
offset: const Offset(0, 8), offset: const Offset(0, 8),
), ),
BoxShadow( BoxShadow(
color: AppColors.primaryOrange.withOpacity( color: Theme.of(
0.2, context,
), ).colorScheme.secondary.withOpacity(0.2),
blurRadius: 15, blurRadius: 15,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -260,10 +265,10 @@ class _SplashPageState extends State<SplashPage> {
// School name with gradient // School name with gradient
ShaderMask( ShaderMask(
shaderCallback: (bounds) => const LinearGradient( shaderCallback: (bounds) => LinearGradient(
colors: [ colors: [
AppColors.primaryTeal, Theme.of(context).colorScheme.primary,
AppColors.primaryOrange, Theme.of(context).colorScheme.secondary,
], ],
begin: Alignment.centerLeft, begin: Alignment.centerLeft,
end: Alignment.centerRight, end: Alignment.centerRight,
@@ -295,8 +300,12 @@ class _SplashPageState extends State<SplashPage> {
ShaderMask( ShaderMask(
shaderCallback: (bounds) => LinearGradient( shaderCallback: (bounds) => LinearGradient(
colors: [ colors: [
AppColors.primaryOrange.withOpacity(0.8), Theme.of(
AppColors.primaryTeal.withOpacity(0.8), context,
).colorScheme.secondary.withOpacity(0.8),
Theme.of(
context,
).colorScheme.primary.withOpacity(0.8),
], ],
begin: Alignment.centerLeft, begin: Alignment.centerLeft,
end: Alignment.centerRight, end: Alignment.centerRight,
@@ -345,7 +354,9 @@ class _SplashPageState extends State<SplashPage> {
'A preparar a sua experiência...', 'A preparar a sua experiência...',
style: Theme.of(context).textTheme.bodySmall style: Theme.of(context).textTheme.bodySmall
?.copyWith( ?.copyWith(
color: AppColors.primaryOrange, color: Theme.of(
context,
).colorScheme.secondary,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
) )
@@ -357,7 +368,9 @@ class _SplashPageState extends State<SplashPage> {
.then() .then()
.shimmer( .shimmer(
duration: const Duration(milliseconds: 2000), 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<SplashPage> {
return Container( return Container(
width: 12, width: 12,
height: 12, height: 12,
decoration: const BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
colors: [AppColors.primaryTeal, AppColors.primaryOrange], colors: [
Theme.of(context).colorScheme.primary,
Theme.of(context).colorScheme.secondary,
],
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
), ),
@@ -418,8 +434,8 @@ class _SplashPageState extends State<SplashPage> {
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
colors: [ colors: [
AppColors.primaryTeal.withOpacity(0.3), Theme.of(context).colorScheme.primary.withOpacity(0.3),
AppColors.primaryOrange.withOpacity(0.2), Theme.of(context).colorScheme.secondary.withOpacity(0.2),
], ],
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,

View File

@@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../../core/theme/app_colors.dart';
class TutorChatPage extends StatelessWidget { class TutorChatPage extends StatelessWidget {
const TutorChatPage({super.key}); const TutorChatPage({super.key});
@@ -7,20 +6,34 @@ class TutorChatPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: AppColors.background, backgroundColor: Theme.of(context).colorScheme.background,
appBar: AppBar( appBar: AppBar(
title: const Text('AI Tutor'), title: const Text('AI Tutor'),
backgroundColor: AppColors.surface, backgroundColor: Theme.of(context).colorScheme.surface,
foregroundColor: AppColors.textPrimary, foregroundColor: Theme.of(context).colorScheme.onSurface,
elevation: 0, elevation: 0,
), ),
body: const Center( 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( child: Text(
'AI Tutor Chat - Coming Soon', 'AI Tutor Chat - Coming Soon',
style: TextStyle( style: TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.textPrimary, color: Theme.of(context).colorScheme.onSurface,
),
), ),
), ),
), ),

View File

@@ -1,25 +1,29 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../../core/theme/app_colors.dart';
class LoadingPage extends StatelessWidget { class LoadingPage extends StatelessWidget {
const LoadingPage({super.key}); const LoadingPage({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const Scaffold( return Scaffold(
backgroundColor: AppColors.background, backgroundColor: Theme.of(context).colorScheme.background,
body: Center( body: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
CircularProgressIndicator( CircularProgressIndicator(
strokeWidth: 3, strokeWidth: 3,
valueColor: AlwaysStoppedAnimation<Color>(AppColors.primaryBlue), valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).colorScheme.primary,
), ),
SizedBox(height: 24), ),
const SizedBox(height: 24),
Text( Text(
'Loading...', 'Loading...',
style: TextStyle(fontSize: 16, color: AppColors.textSecondary), style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
), ),
], ],
), ),

View File

@@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../../core/theme/app_colors.dart';
import '../../../../l10n/app_localizations.dart'; import '../../../../l10n/app_localizations.dart';
class NotFoundPage extends StatelessWidget { class NotFoundPage extends StatelessWidget {
@@ -9,33 +8,37 @@ class NotFoundPage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!; final l10n = AppLocalizations.of(context)!;
return Scaffold( return Scaffold(
backgroundColor: AppColors.background, backgroundColor: Theme.of(context).colorScheme.background,
appBar: AppBar( appBar: AppBar(
title: Text(l10n.pageNotFound), title: Text(l10n.pageNotFound),
backgroundColor: AppColors.surface, backgroundColor: Theme.of(context).colorScheme.surface,
foregroundColor: AppColors.textPrimary, foregroundColor: Theme.of(context).colorScheme.onSurface,
elevation: 0, elevation: 0,
), ),
body: Center( body: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ 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), const SizedBox(height: 16),
Text( Text(
l10n.pageNotFound, l10n.pageNotFound,
style: const TextStyle( style: TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.textPrimary, color: Theme.of(context).colorScheme.onSurface,
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'A página que procura não existe.', 'A página que procura não existe.',
style: const TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: AppColors.textSecondary, color: Theme.of(context).colorScheme.onSurfaceVariant,
), ),
), ),
], ],