- Dark / light mode a funcionar no lado do aluno
- Atualização dos ficheiros markdown.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|
||||||
|
|||||||
@@ -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**
|
||||||
|
|
||||||
|
|||||||
@@ -25,22 +25,16 @@ 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
|
state = themeMode;
|
||||||
// Future: Allow dark mode when available
|
await ThemeService.setThemeMode(themeMode);
|
||||||
if (themeMode == ThemeMode.light || ThemeService.isDarkModeAvailable()) {
|
|
||||||
state = 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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
@@ -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,304 +187,403 @@ 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) {
|
||||||
gradient: LinearGradient(
|
if (!didPop) {
|
||||||
begin: Alignment.topLeft,
|
context.go('/role-selection');
|
||||||
end: Alignment.bottomRight,
|
}
|
||||||
colors: [
|
},
|
||||||
Color(0xFFF8F9FA),
|
child: Scaffold(
|
||||||
Color.fromRGBO(130, 201, 189, 0.1),
|
body: Stack(
|
||||||
Color.fromRGBO(246, 141, 45, 0.05),
|
children: [
|
||||||
Color(0xFFF8F9FA),
|
// Main content
|
||||||
],
|
Container(
|
||||||
),
|
decoration: BoxDecoration(
|
||||||
),
|
gradient: LinearGradient(
|
||||||
child: SafeArea(
|
begin: Alignment.topLeft,
|
||||||
child: Center(
|
end: Alignment.bottomRight,
|
||||||
child: SingleChildScrollView(
|
colors: [
|
||||||
padding: const EdgeInsets.all(24.0),
|
Theme.of(context).colorScheme.background,
|
||||||
child: Form(
|
Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
||||||
key: _formKey,
|
Theme.of(context).colorScheme.secondary.withOpacity(0.05),
|
||||||
child: Column(
|
Theme.of(context).colorScheme.background,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
const SizedBox(height: 60),
|
|
||||||
|
|
||||||
// Logo/Title
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(20.0),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white.withOpacity(0.9),
|
|
||||||
borderRadius: BorderRadius.circular(16.0),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.1),
|
|
||||||
blurRadius: 10.0,
|
|
||||||
offset: const Offset(0, 4),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'EPVC',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 32,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
foreground: Paint()
|
|
||||||
..shader = LinearGradient(
|
|
||||||
colors: [
|
|
||||||
const Color(0xFF82C9BD),
|
|
||||||
const Color(0xFFF68D2D),
|
|
||||||
],
|
|
||||||
).createShader(Rect.fromLTWH(0, 0, 200, 20)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
'Escola Profissional de Vila do Conde',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: const Color(0xFF2D3748),
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
).animate().fadeIn(
|
|
||||||
duration: const Duration(milliseconds: 800),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 40),
|
|
||||||
|
|
||||||
// Login form
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(24.0),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white.withOpacity(0.9),
|
|
||||||
borderRadius: BorderRadius.circular(16.0),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.1),
|
|
||||||
blurRadius: 10.0,
|
|
||||||
offset: const Offset(0, 4),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Entrar',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Color(0xFF2D3748),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
|
|
||||||
// Email field
|
|
||||||
TextFormField(
|
|
||||||
controller: _emailController,
|
|
||||||
keyboardType: TextInputType.emailAddress,
|
|
||||||
style: const TextStyle(color: Color(0xFF2D3748)),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'Email',
|
|
||||||
labelStyle: const TextStyle(
|
|
||||||
color: Color(0xFF2D3748),
|
|
||||||
),
|
|
||||||
hintStyle: const TextStyle(
|
|
||||||
color: Color(0xFF718096),
|
|
||||||
),
|
|
||||||
prefixIcon: const Icon(
|
|
||||||
Icons.email,
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
border: InputBorder.none,
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
borderSide: const BorderSide(
|
|
||||||
color: Color(0xFFE2E8F0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
borderSide: const BorderSide(
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
filled: true,
|
|
||||||
fillColor: const Color(0xFFF8F9FA),
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Email é obrigatório';
|
|
||||||
}
|
|
||||||
if (!value.contains('@')) {
|
|
||||||
return 'Email inválido';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Password field
|
|
||||||
TextFormField(
|
|
||||||
controller: _passwordController,
|
|
||||||
obscureText: _obscurePassword,
|
|
||||||
style: const TextStyle(color: Color(0xFF2D3748)),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'Palavra-passe',
|
|
||||||
labelStyle: const TextStyle(
|
|
||||||
color: Color(0xFF2D3748),
|
|
||||||
),
|
|
||||||
hintStyle: const TextStyle(
|
|
||||||
color: Color(0xFF718096),
|
|
||||||
),
|
|
||||||
prefixIcon: const Icon(
|
|
||||||
Icons.lock,
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
suffixIcon: IconButton(
|
|
||||||
icon: Icon(
|
|
||||||
_obscurePassword
|
|
||||||
? Icons.visibility
|
|
||||||
: Icons.visibility_off,
|
|
||||||
color: const Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
_obscurePassword = !_obscurePassword;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
border: InputBorder.none,
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
borderSide: const BorderSide(
|
|
||||||
color: Color(0xFFE2E8F0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
borderSide: const BorderSide(
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
filled: true,
|
|
||||||
fillColor: const Color(0xFFF8F9FA),
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Palavra-passe é obrigatória';
|
|
||||||
}
|
|
||||||
if (value.length < 6) {
|
|
||||||
return 'Palavra-passe muito curta';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
|
|
||||||
// Remember me checkbox
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Checkbox(
|
|
||||||
value: _rememberMe,
|
|
||||||
onChanged: (bool? value) {
|
|
||||||
setState(() {
|
|
||||||
_rememberMe = value ?? false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
activeColor: const Color(0xFF82C9BD),
|
|
||||||
checkColor: Colors.white,
|
|
||||||
),
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
setState(() {
|
|
||||||
_rememberMe = !_rememberMe;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'Manter sessão iniciada',
|
|
||||||
style: TextStyle(
|
|
||||||
color: const Color(0xFF2D3748),
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: _rememberMe
|
|
||||||
? FontWeight.w500
|
|
||||||
: FontWeight.normal,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
|
|
||||||
// Login button
|
|
||||||
SizedBox(
|
|
||||||
height: 50,
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: _isLoading ? null : _handleLogin,
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: const Color(0xFF82C9BD),
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
),
|
|
||||||
elevation: 2,
|
|
||||||
),
|
|
||||||
child: _isLoading
|
|
||||||
? const SizedBox(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
strokeWidth: 2,
|
|
||||||
valueColor:
|
|
||||||
AlwaysStoppedAnimation<Color>(
|
|
||||||
Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Text(
|
|
||||||
'Entrar',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Signup link
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
context.go('/signup');
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'Não tem conta? Criar aqui',
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
).animate().fadeIn(
|
|
||||||
duration: const Duration(milliseconds: 1000),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 40),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
child: SafeArea(
|
||||||
|
child: Center(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(24.0),
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 60),
|
||||||
|
|
||||||
|
// Logo/Title
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(20.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surface.withOpacity(0.9),
|
||||||
|
borderRadius: BorderRadius.circular(16.0),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 10.0,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'EPVC',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 32,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
foreground: Paint()
|
||||||
|
..shader =
|
||||||
|
LinearGradient(
|
||||||
|
colors: [
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.secondary,
|
||||||
|
],
|
||||||
|
).createShader(
|
||||||
|
Rect.fromLTWH(0, 0, 200, 20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
'Escola Profissional de Vila do Conde',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).animate().fadeIn(
|
||||||
|
duration: const Duration(milliseconds: 800),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
|
||||||
|
// Login form
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(24.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surface.withOpacity(0.9),
|
||||||
|
borderRadius: BorderRadius.circular(16.0),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 10.0,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Entrar',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
|
// Email field
|
||||||
|
TextFormField(
|
||||||
|
controller: _emailController,
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Email',
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
prefixIcon: Icon(
|
||||||
|
Icons.email,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.outline.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surface,
|
||||||
|
),
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Email é obrigatório';
|
||||||
|
}
|
||||||
|
if (!value.contains('@')) {
|
||||||
|
return 'Email inválido';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
// Password field
|
||||||
|
TextFormField(
|
||||||
|
controller: _passwordController,
|
||||||
|
obscureText: _obscurePassword,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Palavra-passe',
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
prefixIcon: Icon(
|
||||||
|
Icons.lock,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
_obscurePassword
|
||||||
|
? Icons.visibility
|
||||||
|
: Icons.visibility_off,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_obscurePassword = !_obscurePassword;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.outline.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surface,
|
||||||
|
),
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Palavra-passe é obrigatória';
|
||||||
|
}
|
||||||
|
if (value.length < 6) {
|
||||||
|
return 'Palavra-passe muito curta';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
|
// Remember me checkbox
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: _rememberMe,
|
||||||
|
onChanged: (bool? value) {
|
||||||
|
setState(() {
|
||||||
|
_rememberMe = value ?? false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
activeColor: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
checkColor: Colors.white,
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_rememberMe = !_rememberMe;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'Manter sessão iniciada',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: _rememberMe
|
||||||
|
? FontWeight.w500
|
||||||
|
: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
|
// Login button
|
||||||
|
SizedBox(
|
||||||
|
height: 50,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: _isLoading ? null : _handleLogin,
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
8.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
elevation: 2,
|
||||||
|
),
|
||||||
|
child: _isLoading
|
||||||
|
? const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
valueColor:
|
||||||
|
AlwaysStoppedAnimation<Color>(
|
||||||
|
Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
'Entrar',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
// Signup link
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
context.go('/signup');
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'Não tem conta? Criar aqui',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).animate().fadeIn(
|
||||||
|
duration: const Duration(milliseconds: 1000),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
// Custom back button
|
||||||
|
Positioned(
|
||||||
|
top: 50,
|
||||||
|
left: 16,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surface.withOpacity(0.8),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.shadow.withOpacity(0.1),
|
||||||
|
blurRadius: 8,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.arrow_back,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
onPressed: () => context.go('/role-selection'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -410,4 +413,4 @@ class _RoleSelectionPageState extends State<RoleSelectionPage> {
|
|||||||
context.go('/signup?role=$_selectedRole');
|
context.go('/signup?role=$_selectedRole');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,315 +101,444 @@ 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) {
|
||||||
gradient: LinearGradient(
|
if (!didPop) {
|
||||||
begin: Alignment.topLeft,
|
context.go('/role-selection');
|
||||||
end: Alignment.bottomRight,
|
}
|
||||||
colors: [
|
},
|
||||||
Color(0xFFF8F9FA),
|
child: Scaffold(
|
||||||
Color.fromRGBO(130, 201, 189, 0.1),
|
body: Stack(
|
||||||
Color.fromRGBO(246, 141, 45, 0.05),
|
children: [
|
||||||
Color(0xFFF8F9FA),
|
// Main content
|
||||||
],
|
Container(
|
||||||
),
|
decoration: BoxDecoration(
|
||||||
),
|
gradient: LinearGradient(
|
||||||
child: SafeArea(
|
begin: Alignment.topLeft,
|
||||||
child: Center(
|
end: Alignment.bottomRight,
|
||||||
child: SingleChildScrollView(
|
colors: [
|
||||||
padding: const EdgeInsets.all(24.0),
|
Theme.of(context).colorScheme.background,
|
||||||
child: Form(
|
Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
||||||
key: _formKey,
|
Theme.of(context).colorScheme.secondary.withOpacity(0.05),
|
||||||
child: Column(
|
Theme.of(context).colorScheme.background,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
const SizedBox(height: 60),
|
|
||||||
|
|
||||||
// Logo/Title
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(20.0),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white.withOpacity(0.9),
|
|
||||||
borderRadius: BorderRadius.circular(16.0),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.1),
|
|
||||||
blurRadius: 10.0,
|
|
||||||
offset: const Offset(0, 4),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'EPVC',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 32,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
foreground: Paint()
|
|
||||||
..shader = LinearGradient(
|
|
||||||
colors: [
|
|
||||||
const Color(0xFF82C9BD),
|
|
||||||
const Color(0xFFF68D2D),
|
|
||||||
],
|
|
||||||
).createShader(Rect.fromLTWH(0, 0, 200, 20)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
'Escola Profissional de Vila do Conde',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: const Color(0xFF2D3748),
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
).animate().fadeIn(
|
|
||||||
duration: const Duration(milliseconds: 800),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 40),
|
|
||||||
|
|
||||||
// Signup form
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(24.0),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white.withOpacity(0.9),
|
|
||||||
borderRadius: BorderRadius.circular(16.0),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.1),
|
|
||||||
blurRadius: 10.0,
|
|
||||||
offset: const Offset(0, 4),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Criar Conta',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Color(0xFF2D3748),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
|
|
||||||
// Name field
|
|
||||||
TextFormField(
|
|
||||||
controller: _nameController,
|
|
||||||
keyboardType: TextInputType.name,
|
|
||||||
style: const TextStyle(color: Color(0xFF2D3748)),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'Nome Completo',
|
|
||||||
labelStyle: const TextStyle(
|
|
||||||
color: Color(0xFF2D3748),
|
|
||||||
),
|
|
||||||
hintStyle: const TextStyle(
|
|
||||||
color: Color(0xFF718096),
|
|
||||||
),
|
|
||||||
prefixIcon: const Icon(
|
|
||||||
Icons.person,
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
border: InputBorder.none,
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
borderSide: const BorderSide(
|
|
||||||
color: Color(0xFFE2E8F0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
borderSide: const BorderSide(
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
filled: true,
|
|
||||||
fillColor: const Color(0xFFF8F9FA),
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Nome é obrigatório';
|
|
||||||
}
|
|
||||||
if (value.length < 2) {
|
|
||||||
return 'Nome muito curto';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Email field
|
|
||||||
TextFormField(
|
|
||||||
controller: _emailController,
|
|
||||||
keyboardType: TextInputType.emailAddress,
|
|
||||||
style: const TextStyle(color: Color(0xFF2D3748)),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'Email',
|
|
||||||
labelStyle: const TextStyle(
|
|
||||||
color: Color(0xFF2D3748),
|
|
||||||
),
|
|
||||||
hintStyle: const TextStyle(
|
|
||||||
color: Color(0xFF718096),
|
|
||||||
),
|
|
||||||
prefixIcon: const Icon(
|
|
||||||
Icons.email,
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
border: InputBorder.none,
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
borderSide: const BorderSide(
|
|
||||||
color: Color(0xFFE2E8F0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
borderSide: const BorderSide(
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
filled: true,
|
|
||||||
fillColor: const Color(0xFFF8F9FA),
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Email é obrigatório';
|
|
||||||
}
|
|
||||||
if (!value.contains('@')) {
|
|
||||||
return 'Email inválido';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Password field
|
|
||||||
TextFormField(
|
|
||||||
controller: _passwordController,
|
|
||||||
obscureText: _obscurePassword,
|
|
||||||
style: const TextStyle(color: Color(0xFF2D3748)),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'Palavra-passe',
|
|
||||||
labelStyle: const TextStyle(
|
|
||||||
color: Color(0xFF2D3748),
|
|
||||||
),
|
|
||||||
hintStyle: const TextStyle(
|
|
||||||
color: Color(0xFF718096),
|
|
||||||
),
|
|
||||||
prefixIcon: const Icon(
|
|
||||||
Icons.lock,
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
suffixIcon: IconButton(
|
|
||||||
icon: Icon(
|
|
||||||
_obscurePassword
|
|
||||||
? Icons.visibility
|
|
||||||
: Icons.visibility_off,
|
|
||||||
color: const Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
_obscurePassword = !_obscurePassword;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
border: InputBorder.none,
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
borderSide: const BorderSide(
|
|
||||||
color: Color(0xFFE2E8F0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
borderSide: const BorderSide(
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
filled: true,
|
|
||||||
fillColor: const Color(0xFFF8F9FA),
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Palavra-passe é obrigatória';
|
|
||||||
}
|
|
||||||
if (value.length < 6) {
|
|
||||||
return 'Palavra-passe muito curta';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
|
|
||||||
// Signup button
|
|
||||||
SizedBox(
|
|
||||||
height: 50,
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: _isLoading ? null : _handleSignup,
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: const Color(0xFF82C9BD),
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
),
|
|
||||||
elevation: 2,
|
|
||||||
),
|
|
||||||
child: _isLoading
|
|
||||||
? const SizedBox(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
strokeWidth: 2,
|
|
||||||
valueColor:
|
|
||||||
AlwaysStoppedAnimation<Color>(
|
|
||||||
Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Text(
|
|
||||||
'Criar Conta',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Login link
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
context.go('/login?role=$_selectedRole');
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'Já tem conta? Entrar aqui',
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
).animate().fadeIn(
|
|
||||||
duration: const Duration(milliseconds: 1000),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 40),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
child: SafeArea(
|
||||||
|
child: Center(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(24.0),
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 60),
|
||||||
|
|
||||||
|
// Logo/Title
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(20.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surface.withOpacity(0.9),
|
||||||
|
borderRadius: BorderRadius.circular(16.0),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.shadow.withOpacity(0.1),
|
||||||
|
blurRadius: 10.0,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'EPVC',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 32,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
foreground: Paint()
|
||||||
|
..shader =
|
||||||
|
LinearGradient(
|
||||||
|
colors: [
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.secondary,
|
||||||
|
],
|
||||||
|
).createShader(
|
||||||
|
Rect.fromLTWH(0, 0, 200, 20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
'Escola Profissional de Vila do Conde',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).animate().fadeIn(
|
||||||
|
duration: const Duration(milliseconds: 800),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
|
||||||
|
// Signup form
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(24.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surface.withOpacity(0.9),
|
||||||
|
borderRadius: BorderRadius.circular(16.0),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.shadow.withOpacity(0.1),
|
||||||
|
blurRadius: 10.0,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Criar Conta',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
|
// Name field
|
||||||
|
TextFormField(
|
||||||
|
controller: _nameController,
|
||||||
|
keyboardType: TextInputType.name,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Nome Completo',
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
prefixIcon: Icon(
|
||||||
|
Icons.person,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.outline.withOpacity(0.3),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor:
|
||||||
|
Theme.of(context).brightness ==
|
||||||
|
Brightness.dark
|
||||||
|
? Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surfaceContainerHighest
|
||||||
|
: Theme.of(context).colorScheme.surface,
|
||||||
|
),
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Nome é obrigatório';
|
||||||
|
}
|
||||||
|
if (value.length < 2) {
|
||||||
|
return 'Nome muito curto';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
// Email field
|
||||||
|
TextFormField(
|
||||||
|
controller: _emailController,
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Email',
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
prefixIcon: Icon(
|
||||||
|
Icons.email,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.outline.withOpacity(0.3),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor:
|
||||||
|
Theme.of(context).brightness ==
|
||||||
|
Brightness.dark
|
||||||
|
? Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surfaceContainerHighest
|
||||||
|
: Theme.of(context).colorScheme.surface,
|
||||||
|
),
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Email é obrigatório';
|
||||||
|
}
|
||||||
|
if (!value.contains('@')) {
|
||||||
|
return 'Email inválido';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
// Password field
|
||||||
|
TextFormField(
|
||||||
|
controller: _passwordController,
|
||||||
|
obscureText: _obscurePassword,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Palavra-passe',
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
prefixIcon: Icon(
|
||||||
|
Icons.lock,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
_obscurePassword
|
||||||
|
? Icons.visibility
|
||||||
|
: Icons.visibility_off,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_obscurePassword = !_obscurePassword;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.outline.withOpacity(0.3),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor:
|
||||||
|
Theme.of(context).brightness ==
|
||||||
|
Brightness.dark
|
||||||
|
? Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surfaceContainerHighest
|
||||||
|
: Theme.of(context).colorScheme.surface,
|
||||||
|
),
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Palavra-passe é obrigatória';
|
||||||
|
}
|
||||||
|
if (value.length < 6) {
|
||||||
|
return 'Palavra-passe muito curta';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
|
// Signup button
|
||||||
|
SizedBox(
|
||||||
|
height: 50,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: _isLoading
|
||||||
|
? null
|
||||||
|
: _handleSignup,
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
8.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
elevation: 2,
|
||||||
|
),
|
||||||
|
child: _isLoading
|
||||||
|
? const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
valueColor:
|
||||||
|
AlwaysStoppedAnimation<Color>(
|
||||||
|
Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
'Criar Conta',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
// Login link
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
context.go('/login?role=$_selectedRole');
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'Já tem conta? Entrar aqui',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).animate().fadeIn(
|
||||||
|
duration: const Duration(milliseconds: 1000),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
// Custom back button
|
||||||
|
Positioned(
|
||||||
|
top: 50,
|
||||||
|
left: 16,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surface.withOpacity(0.8),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.shadow.withOpacity(0.1),
|
||||||
|
blurRadius: 8,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.arrow_back,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
onPressed: () => context.go('/role-selection'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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),
|
||||||
@@ -132,7 +135,7 @@ class ProgressHeroWidget extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// Progress Bar
|
// Progress Bar
|
||||||
Container(
|
Container(
|
||||||
height: 12,
|
height: 12,
|
||||||
@@ -186,77 +189,90 @@ class ProgressHeroWidget extends StatelessWidget {
|
|||||||
|
|
||||||
// Mastered Concepts
|
// Mastered Concepts
|
||||||
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(
|
||||||
boxShadow: [
|
color: Theme.of(
|
||||||
BoxShadow(
|
context,
|
||||||
color: Colors.black.withOpacity(0.05),
|
).colorScheme.outline.withOpacity(0.2),
|
||||||
blurRadius: 10,
|
),
|
||||||
offset: const Offset(0, 4),
|
boxShadow: [
|
||||||
),
|
BoxShadow(
|
||||||
],
|
color: Theme.of(
|
||||||
),
|
context,
|
||||||
child: Column(
|
).colorScheme.shadow.withOpacity(0.05),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
blurRadius: 10,
|
||||||
children: [
|
offset: const Offset(0, 4),
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
Icons.school,
|
|
||||||
color: Color(0xFFF68D2D),
|
|
||||||
size: 20,
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
],
|
||||||
const Text(
|
),
|
||||||
'Conceitos Dominados',
|
child: Column(
|
||||||
style: TextStyle(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
color: Color(0xFF2D3748),
|
children: [
|
||||||
fontSize: 16,
|
Row(
|
||||||
fontWeight: FontWeight.bold,
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.school,
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
'Conceitos Dominados',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
...masteredConcepts.map(
|
||||||
|
(concept) => Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
concept,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
Icons.check_circle,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
)
|
||||||
...masteredConcepts.map((concept) => Padding(
|
.animate()
|
||||||
padding: const EdgeInsets.only(bottom: 8),
|
.slideX(
|
||||||
child: Row(
|
duration: const Duration(milliseconds: 800),
|
||||||
children: [
|
curve: Curves.easeOut,
|
||||||
Container(
|
)
|
||||||
width: 8,
|
.then(delay: const Duration(milliseconds: 200)),
|
||||||
height: 8,
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
concept,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Color(0xFF4A5568),
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Icon(
|
|
||||||
Icons.check_circle,
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
size: 16,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
).animate().slideX(
|
|
||||||
duration: const Duration(milliseconds: 800),
|
|
||||||
curve: Curves.easeOut,
|
|
||||||
).then(delay: const Duration(milliseconds: 200)),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -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,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -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,9 +55,9 @@ 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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@@ -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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -13,207 +13,248 @@ class TeacherAnalyticsPreviewWidget extends StatelessWidget {
|
|||||||
final userEmail = user?.email ?? '';
|
final userEmail = user?.email ?? '';
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
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(
|
||||||
boxShadow: [
|
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
|
||||||
BoxShadow(
|
),
|
||||||
color: Colors.black.withOpacity(0.05),
|
boxShadow: [
|
||||||
blurRadius: 10,
|
BoxShadow(
|
||||||
offset: const Offset(0, 4),
|
color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
|
||||||
),
|
blurRadius: 10,
|
||||||
],
|
offset: const Offset(0, 4),
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
// Profile Header
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 48,
|
|
||||||
height: 48,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
gradient: const LinearGradient(
|
|
||||||
colors: [Color(0xFF82C9BD), Color(0xFF6BA8A0)],
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(24),
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.school,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 24,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
],
|
||||||
Expanded(
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
// Profile Header
|
||||||
userName,
|
Row(
|
||||||
style: const TextStyle(
|
children: [
|
||||||
color: Color(0xFF2D3748),
|
Container(
|
||||||
fontSize: 18,
|
width: 48,
|
||||||
fontWeight: FontWeight.bold,
|
height: 48,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary.withOpacity(0.8),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
|
borderRadius: BorderRadius.circular(24),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
child: const Icon(
|
||||||
SingleChildScrollView(
|
Icons.school,
|
||||||
scrollDirection: Axis.horizontal,
|
color: Colors.white,
|
||||||
child: Row(
|
size: 24,
|
||||||
mainAxisSize: MainAxisSize.min,
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
userName,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
userEmail,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (userEmail.length > 20) ...[
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Icon(
|
||||||
|
Icons.more_horiz,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.secondary.withOpacity(0.1),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.settings,
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
|
// Quick Stats Row
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
_buildQuickStat(
|
||||||
|
icon: Icons.check_circle,
|
||||||
|
label: 'Alunos Ativos',
|
||||||
|
value: '18/24',
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
_buildQuickStat(
|
||||||
|
icon: Icons.warning_amber,
|
||||||
|
label: 'Precisam Apoio',
|
||||||
|
value: '3',
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
_buildQuickStat(
|
||||||
|
icon: Icons.emoji_events,
|
||||||
|
label: 'Média Turma',
|
||||||
|
value: '72%',
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary.withOpacity(0.8),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
|
// Top Performing Students Preview
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.leaderboard,
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
'Melhores Desempenhos',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
|
// Student List Preview
|
||||||
|
_buildStudentPerformanceItem(
|
||||||
|
context,
|
||||||
|
'Ana Silva',
|
||||||
|
95,
|
||||||
|
Theme.of(context).colorScheme.tertiary,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
_buildStudentPerformanceItem(
|
||||||
|
context,
|
||||||
|
'João Costa',
|
||||||
|
88,
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
_buildStudentPerformanceItem(
|
||||||
|
context,
|
||||||
|
'Maria Santos',
|
||||||
|
82,
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
_buildStudentPerformanceItem(
|
||||||
|
context,
|
||||||
|
'Pedro Lima',
|
||||||
|
45,
|
||||||
|
Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
|
// Content Quality Alert
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.outline.withOpacity(0.2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.info_outline,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
userEmail,
|
'Qualidade do Conteúdo',
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
color: Color(0xFF718096),
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (userEmail.length > 20) ...[
|
const SizedBox(height: 2),
|
||||||
const SizedBox(width: 8),
|
Text(
|
||||||
const Icon(
|
'12 conteúdos verificados • 2 pendentes de revisão',
|
||||||
Icons.more_horiz,
|
style: TextStyle(
|
||||||
color: Color(0xFF718096),
|
color: Theme.of(
|
||||||
size: 16,
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
fontSize: 12,
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color(0xFFF68D2D).withOpacity(0.1),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.settings,
|
|
||||||
color: Color(0xFFF68D2D),
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
)
|
||||||
|
.animate()
|
||||||
// Quick Stats Row
|
.slideY(
|
||||||
Row(
|
duration: const Duration(milliseconds: 800),
|
||||||
children: [
|
curve: Curves.easeOut,
|
||||||
_buildQuickStat(
|
)
|
||||||
icon: Icons.check_circle,
|
.then(delay: const Duration(milliseconds: 400));
|
||||||
label: 'Alunos Ativos',
|
|
||||||
value: '18/24',
|
|
||||||
color: const Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
_buildQuickStat(
|
|
||||||
icon: Icons.warning_amber,
|
|
||||||
label: 'Precisam Apoio',
|
|
||||||
value: '3',
|
|
||||||
color: const Color(0xFFF68D2D),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
_buildQuickStat(
|
|
||||||
icon: Icons.emoji_events,
|
|
||||||
label: 'Média Turma',
|
|
||||||
value: '72%',
|
|
||||||
color: const Color(0xFF6BA8A0),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
|
|
||||||
// Top Performing Students Preview
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
Icons.leaderboard,
|
|
||||||
color: Color(0xFFF68D2D),
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
const Text(
|
|
||||||
'Melhores Desempenhos',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Color(0xFF2D3748),
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
|
|
||||||
// Student List Preview
|
|
||||||
_buildStudentPerformanceItem('Ana Silva', 95, const Color(0xFF4CAF50)),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
_buildStudentPerformanceItem('João Costa', 88, const Color(0xFF82C9BD)),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
_buildStudentPerformanceItem('Maria Santos', 82, const Color(0xFF82C9BD)),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
_buildStudentPerformanceItem('Pedro Lima', 45, const Color(0xFFF68D2D)),
|
|
||||||
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
|
|
||||||
// Content Quality Alert
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color(0xFFF8F9FA),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
border: Border.all(color: const Color(0xFFE2E8F0)),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
Icons.info_outline,
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const Text(
|
|
||||||
'Qualidade do Conteúdo',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Color(0xFF2D3748),
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 2),
|
|
||||||
Text(
|
|
||||||
'12 conteúdos verificados • 2 pendentes de revisão',
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Color(0xFF718096),
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.animate()
|
|
||||||
.slideY(
|
|
||||||
duration: const Duration(milliseconds: 800),
|
|
||||||
curve: Curves.easeOut,
|
|
||||||
)
|
|
||||||
.then(delay: const Duration(milliseconds: 400));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildQuickStat({
|
Widget _buildQuickStat({
|
||||||
@@ -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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,9 +59,9 @@ 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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@@ -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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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),
|
||||||
),
|
),
|
||||||
@@ -128,7 +127,7 @@ class TeacherHeroWidget extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// Progress Bar
|
// Progress Bar
|
||||||
Container(
|
Container(
|
||||||
height: 12,
|
height: 12,
|
||||||
@@ -182,64 +181,76 @@ class TeacherHeroWidget extends StatelessWidget {
|
|||||||
|
|
||||||
// Recent Activity
|
// Recent Activity
|
||||||
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(
|
||||||
boxShadow: [
|
color: Theme.of(
|
||||||
BoxShadow(
|
context,
|
||||||
color: Colors.black.withOpacity(0.05),
|
).colorScheme.outline.withOpacity(0.2),
|
||||||
blurRadius: 10,
|
),
|
||||||
offset: const Offset(0, 4),
|
boxShadow: [
|
||||||
),
|
BoxShadow(
|
||||||
],
|
color: Theme.of(
|
||||||
),
|
context,
|
||||||
child: Column(
|
).colorScheme.shadow.withOpacity(0.05),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
blurRadius: 10,
|
||||||
children: [
|
offset: const Offset(0, 4),
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
Icons.trending_up,
|
|
||||||
color: Color(0xFFF68D2D),
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
const Text(
|
|
||||||
'Atividade Recente',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Color(0xFF2D3748),
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
child: Column(
|
||||||
_buildActivityItem(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
'15 alunos completaram o quiz de Derivadas',
|
children: [
|
||||||
'Hoje, 14:30',
|
Row(
|
||||||
const Color(0xFF82C9BD),
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.trending_up,
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
'Atividade Recente',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
_buildActivityItem(
|
||||||
|
context,
|
||||||
|
'15 alunos completaram o quiz de Derivadas',
|
||||||
|
'Hoje, 14:30',
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
_buildActivityItem(
|
||||||
|
context,
|
||||||
|
'Novo conteúdo: Regra da Cadeia',
|
||||||
|
'Ontem, 09:15',
|
||||||
|
Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
_buildActivityItem(
|
||||||
|
context,
|
||||||
|
'3 alunos precisam de apoio em Limites',
|
||||||
|
'Ontem, 16:45',
|
||||||
|
Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
)
|
||||||
_buildActivityItem(
|
.animate()
|
||||||
'Novo conteúdo: Regra da Cadeia',
|
.slideX(
|
||||||
'Ontem, 09:15',
|
duration: const Duration(milliseconds: 800),
|
||||||
const Color(0xFFF68D2D),
|
curve: Curves.easeOut,
|
||||||
),
|
)
|
||||||
const SizedBox(height: 8),
|
.then(delay: const Duration(milliseconds: 200)),
|
||||||
_buildActivityItem(
|
|
||||||
'3 alunos precisam de apoio em Limites',
|
|
||||||
'Ontem, 16:45',
|
|
||||||
const Color(0xFFE53E3E),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
).animate().slideX(
|
|
||||||
duration: const Duration(milliseconds: 800),
|
|
||||||
curve: Curves.easeOut,
|
|
||||||
).then(delay: const Duration(milliseconds: 200)),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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> {
|
||||||
@@ -22,463 +23,494 @@ class _TeacherQuickActionsWidgetState extends State<TeacherQuickActionsWidget> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Ações Rápidas',
|
|
||||||
style: TextStyle(
|
|
||||||
color: const Color(0xFF2D3748),
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Primary Actions Row
|
|
||||||
Row(
|
|
||||||
children: [
|
children: [
|
||||||
// Upload Content Card (Primary)
|
Text(
|
||||||
Expanded(flex: 2, child: _buildUploadContentCard(context)),
|
'Ações Rápidas',
|
||||||
const SizedBox(width: 16),
|
style: TextStyle(
|
||||||
// Create Class Card
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
Expanded(flex: 2, child: _buildCreateClassCard(context)),
|
fontSize: 20,
|
||||||
const SizedBox(width: 16),
|
fontWeight: FontWeight.bold,
|
||||||
// Create Quiz Card (Secondary)
|
),
|
||||||
Expanded(flex: 2, child: _buildCreateQuizCard(context)),
|
),
|
||||||
],
|
const SizedBox(height: 16),
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Secondary Actions Row
|
// Primary Actions Row
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
// Manage Students Card
|
// Upload Content Card (Primary)
|
||||||
Expanded(child: _buildManageStudentsCard(context)),
|
Expanded(flex: 2, child: _buildUploadContentCard(context)),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
// View Analytics Card
|
// Create Class Card
|
||||||
Expanded(child: _buildViewAnalyticsCard(context)),
|
Expanded(flex: 2, child: _buildCreateClassCard(context)),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
// Create Quiz Card (Secondary)
|
||||||
|
Expanded(flex: 2, child: _buildCreateQuizCard(context)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
// Secondary Actions Row
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
// Manage Students Card
|
||||||
|
Expanded(child: _buildManageStudentsCard(context)),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
// View Analytics Card
|
||||||
|
Expanded(child: _buildViewAnalyticsCard(context)),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
)
|
||||||
],
|
.animate()
|
||||||
)
|
.slideY(
|
||||||
.animate()
|
duration: const Duration(milliseconds: 800),
|
||||||
.slideY(
|
curve: Curves.easeOut,
|
||||||
duration: const Duration(milliseconds: 800),
|
)
|
||||||
curve: Curves.easeOut,
|
.then(delay: const Duration(milliseconds: 200));
|
||||||
)
|
|
||||||
.then(delay: const Duration(milliseconds: 200));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildUploadContentCard(BuildContext context) {
|
Widget _buildUploadContentCard(BuildContext context) {
|
||||||
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,
|
||||||
borderRadius: BorderRadius.circular(16),
|
Theme.of(context).colorScheme.primary.withOpacity(0.8),
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: const Color(0xFF82C9BD).withOpacity(0.3),
|
|
||||||
blurRadius: 15,
|
|
||||||
offset: const Offset(0, 8),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: InkWell(
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
onTap: () => Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (_) => const TeacherMaterialsPage(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(14),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white.withOpacity(0.2),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.upload_file,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 22,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 8,
|
|
||||||
vertical: 3,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color(0xFFF68D2D),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
child: const Text(
|
|
||||||
'NOVO',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 9,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
const Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Upload Conteúdo',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 4),
|
|
||||||
Text(
|
|
||||||
'PDFs, textos, imagens',
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 12,
|
|
||||||
height: 1.2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Theme.of(context).colorScheme.primary.withOpacity(0.3),
|
||||||
|
blurRadius: 15,
|
||||||
|
offset: const Offset(0, 8),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
child: Material(
|
||||||
),
|
color: Colors.transparent,
|
||||||
)
|
child: InkWell(
|
||||||
.animate()
|
borderRadius: BorderRadius.circular(16),
|
||||||
.scale(
|
onTap: () => Navigator.push(
|
||||||
duration: const Duration(milliseconds: 600),
|
context,
|
||||||
curve: Curves.elasticOut,
|
MaterialPageRoute(builder: (_) => const TeacherMaterialsPage()),
|
||||||
)
|
),
|
||||||
.then(delay: const Duration(milliseconds: 100));
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white.withOpacity(0.2),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.upload_file,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 22,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 3,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'NOVO',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 9,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
const Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Upload Conteúdo',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'PDFs, textos, imagens',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 12,
|
||||||
|
height: 1.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.animate()
|
||||||
|
.scale(
|
||||||
|
duration: const Duration(milliseconds: 600),
|
||||||
|
curve: Curves.elasticOut,
|
||||||
|
)
|
||||||
|
.then(delay: const Duration(milliseconds: 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCreateQuizCard(BuildContext context) {
|
Widget _buildCreateQuizCard(BuildContext context) {
|
||||||
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(
|
||||||
boxShadow: [
|
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
|
||||||
BoxShadow(
|
width: 1,
|
||||||
color: Colors.black.withOpacity(0.05),
|
),
|
||||||
blurRadius: 10,
|
boxShadow: [
|
||||||
offset: const Offset(0, 4),
|
BoxShadow(
|
||||||
|
color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
child: Material(
|
||||||
),
|
color: Colors.transparent,
|
||||||
child: Material(
|
child: InkWell(
|
||||||
color: Colors.transparent,
|
borderRadius: BorderRadius.circular(16),
|
||||||
child: InkWell(
|
onTap: () => context.go('/teacher/quiz/create'),
|
||||||
borderRadius: BorderRadius.circular(16),
|
child: Padding(
|
||||||
onTap: () => context.go('/teacher/quiz/create'),
|
padding: const EdgeInsets.all(14),
|
||||||
child: Padding(
|
child: Column(
|
||||||
padding: const EdgeInsets.all(14),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(10),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color(0xFFF68D2D).withOpacity(0.1),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.quiz,
|
|
||||||
color: Color(0xFFF68D2D),
|
|
||||||
size: 24,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
Container(
|
||||||
'Criar Quiz',
|
padding: const EdgeInsets.all(10),
|
||||||
style: TextStyle(
|
decoration: BoxDecoration(
|
||||||
color: Color(0xFF2D3748),
|
color: Theme.of(
|
||||||
fontSize: 16,
|
context,
|
||||||
fontWeight: FontWeight.bold,
|
).colorScheme.secondary.withOpacity(0.1),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.quiz,
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
size: 24,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
Column(
|
||||||
Text(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
'Avaliações interativas',
|
children: [
|
||||||
maxLines: 2,
|
Text(
|
||||||
overflow: TextOverflow.ellipsis,
|
'Criar Quiz',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: const Color(0xFF718096),
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
fontSize: 12,
|
fontSize: 16,
|
||||||
height: 1.2,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'Avaliações interativas',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
fontSize: 12,
|
||||||
|
height: 1.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
),
|
.animate()
|
||||||
)
|
.scale(
|
||||||
.animate()
|
duration: const Duration(milliseconds: 600),
|
||||||
.scale(
|
curve: Curves.elasticOut,
|
||||||
duration: const Duration(milliseconds: 600),
|
)
|
||||||
curve: Curves.elasticOut,
|
.then(delay: const Duration(milliseconds: 200));
|
||||||
)
|
|
||||||
.then(delay: const Duration(milliseconds: 200));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildManageStudentsCard(BuildContext context) {
|
Widget _buildManageStudentsCard(BuildContext context) {
|
||||||
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(
|
||||||
boxShadow: [
|
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
|
||||||
BoxShadow(
|
width: 1,
|
||||||
color: Colors.black.withOpacity(0.05),
|
),
|
||||||
blurRadius: 10,
|
boxShadow: [
|
||||||
offset: const Offset(0, 4),
|
BoxShadow(
|
||||||
|
color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
child: Material(
|
||||||
),
|
color: Colors.transparent,
|
||||||
child: Material(
|
child: InkWell(
|
||||||
color: Colors.transparent,
|
borderRadius: BorderRadius.circular(16),
|
||||||
child: InkWell(
|
onTap: () => context.go('/teacher/students'),
|
||||||
borderRadius: BorderRadius.circular(16),
|
child: Padding(
|
||||||
onTap: () => context.go('/teacher/students'),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Padding(
|
child: Column(
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color(0xFF82C9BD).withOpacity(0.1),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.people,
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Container(
|
||||||
'Gerir Alunos',
|
padding: const EdgeInsets.all(8),
|
||||||
style: TextStyle(
|
decoration: BoxDecoration(
|
||||||
color: Color(0xFF2D3748),
|
color: Theme.of(
|
||||||
fontSize: 14,
|
context,
|
||||||
fontWeight: FontWeight.bold,
|
).colorScheme.primary.withOpacity(0.1),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.people,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
size: 20,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Column(
|
||||||
'Acesso e permissões',
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
style: TextStyle(
|
children: [
|
||||||
color: Color(0xFF718096),
|
Text(
|
||||||
fontSize: 11,
|
'Gerir Alunos',
|
||||||
),
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Acesso e permissões',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
fontSize: 11,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
),
|
.animate()
|
||||||
)
|
.scale(
|
||||||
.animate()
|
duration: const Duration(milliseconds: 600),
|
||||||
.scale(
|
curve: Curves.elasticOut,
|
||||||
duration: const Duration(milliseconds: 600),
|
)
|
||||||
curve: Curves.elasticOut,
|
.then(delay: const Duration(milliseconds: 300));
|
||||||
)
|
|
||||||
.then(delay: const Duration(milliseconds: 300));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildViewAnalyticsCard(BuildContext context) {
|
Widget _buildViewAnalyticsCard(BuildContext context) {
|
||||||
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(
|
||||||
boxShadow: [
|
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
|
||||||
BoxShadow(
|
width: 1,
|
||||||
color: Colors.black.withOpacity(0.05),
|
),
|
||||||
blurRadius: 10,
|
boxShadow: [
|
||||||
offset: const Offset(0, 4),
|
BoxShadow(
|
||||||
|
color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
child: Material(
|
||||||
),
|
color: Colors.transparent,
|
||||||
child: Material(
|
child: InkWell(
|
||||||
color: Colors.transparent,
|
borderRadius: BorderRadius.circular(16),
|
||||||
child: InkWell(
|
onTap: () => context.go('/teacher/analytics'),
|
||||||
borderRadius: BorderRadius.circular(16),
|
child: Padding(
|
||||||
onTap: () => context.go('/teacher/analytics'),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Padding(
|
child: Column(
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color(0xFF6BA8A0).withOpacity(0.1),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.analytics,
|
|
||||||
color: Color(0xFF6BA8A0),
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Container(
|
||||||
'Analytics',
|
padding: const EdgeInsets.all(8),
|
||||||
style: TextStyle(
|
decoration: BoxDecoration(
|
||||||
color: Color(0xFF2D3748),
|
color: Theme.of(
|
||||||
fontSize: 14,
|
context,
|
||||||
fontWeight: FontWeight.bold,
|
).colorScheme.primary.withOpacity(0.8),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.analytics,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
size: 20,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Column(
|
||||||
'Desempenho da turma',
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
style: TextStyle(
|
children: [
|
||||||
color: Color(0xFF718096),
|
Text(
|
||||||
fontSize: 11,
|
'Analytics',
|
||||||
),
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Desempenho da turma',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
fontSize: 11,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
),
|
.animate()
|
||||||
)
|
.scale(
|
||||||
.animate()
|
duration: const Duration(milliseconds: 600),
|
||||||
.scale(
|
curve: Curves.elasticOut,
|
||||||
duration: const Duration(milliseconds: 600),
|
)
|
||||||
curve: Curves.elasticOut,
|
.then(delay: const Duration(milliseconds: 400));
|
||||||
)
|
|
||||||
.then(delay: const Duration(milliseconds: 400));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCreateClassCard(BuildContext context) {
|
Widget _buildCreateClassCard(BuildContext context) {
|
||||||
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(
|
||||||
boxShadow: [
|
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
|
||||||
BoxShadow(
|
width: 1,
|
||||||
color: Colors.black.withOpacity(0.05),
|
),
|
||||||
blurRadius: 10,
|
boxShadow: [
|
||||||
offset: const Offset(0, 4),
|
BoxShadow(
|
||||||
|
color: Theme.of(context).colorScheme.shadow.withOpacity(0.05),
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
child: Material(
|
||||||
),
|
color: Colors.transparent,
|
||||||
child: Material(
|
child: InkWell(
|
||||||
color: Colors.transparent,
|
borderRadius: BorderRadius.circular(16),
|
||||||
child: InkWell(
|
onTap: _isCreatingClass
|
||||||
borderRadius: BorderRadius.circular(16),
|
? null
|
||||||
onTap: _isCreatingClass ? null : () => _showCreateClassDialog(context),
|
: () => _showCreateClassDialog(context),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(14),
|
padding: const EdgeInsets.all(14),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(10),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color(0xFF82C9BD).withOpacity(0.1),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
child: _isCreatingClass
|
|
||||||
? const SizedBox(
|
|
||||||
width: 24,
|
|
||||||
height: 24,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
strokeWidth: 2,
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: const Icon(
|
|
||||||
Icons.school,
|
|
||||||
color: Color(0xFF82C9BD),
|
|
||||||
size: 24,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Container(
|
||||||
'Criar Turma',
|
padding: const EdgeInsets.all(10),
|
||||||
style: TextStyle(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF2D3748),
|
color: Theme.of(
|
||||||
fontSize: 16,
|
context,
|
||||||
fontWeight: FontWeight.bold,
|
).colorScheme.primary.withOpacity(0.1),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
|
child: _isCreatingClass
|
||||||
|
? SizedBox(
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Icon(
|
||||||
|
Icons.school,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
size: 24,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
Column(
|
||||||
Text(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
'Gerar código de acesso',
|
children: [
|
||||||
maxLines: 2,
|
Text(
|
||||||
overflow: TextOverflow.ellipsis,
|
'Criar Turma',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: const Color(0xFF718096),
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
fontSize: 12,
|
fontSize: 16,
|
||||||
height: 1.2,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'Gerar código de acesso',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurfaceVariant,
|
||||||
|
fontSize: 12,
|
||||||
|
height: 1.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
),
|
.animate()
|
||||||
)
|
.scale(
|
||||||
.animate()
|
duration: const Duration(milliseconds: 600),
|
||||||
.scale(
|
curve: Curves.elasticOut,
|
||||||
duration: const Duration(milliseconds: 600),
|
)
|
||||||
curve: Curves.elasticOut,
|
.then(delay: const Duration(milliseconds: 150));
|
||||||
)
|
|
||||||
.then(delay: const Duration(milliseconds: 150));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showCreateClassDialog(BuildContext context) {
|
void _showCreateClassDialog(BuildContext context) {
|
||||||
@@ -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),
|
||||||
|
|||||||
@@ -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,
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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(
|
||||||
child: Text(
|
decoration: BoxDecoration(
|
||||||
'Quiz List - 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,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'Quiz List - Coming Soon',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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),
|
||||||
],
|
]
|
||||||
stops: [0.0, 0.2, 0.6, 1.0],
|
: [
|
||||||
|
Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
||||||
|
Theme.of(context).colorScheme.secondary.withOpacity(0.05),
|
||||||
|
Theme.of(context).colorScheme.background,
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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(
|
||||||
child: Text(
|
decoration: BoxDecoration(
|
||||||
'AI Tutor Chat - 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,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'AI Tutor Chat - Coming Soon',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user