From 1b7b03034da7f5b4e726a6bf619070687c1c029b Mon Sep 17 00:00:00 2001 From: 240403 <240403@epvc.pt> Date: Fri, 8 May 2026 16:37:36 +0100 Subject: [PATCH] =?UTF-8?q?valida=C3=A7=C3=A3o=20entre=20professor=20e=20a?= =?UTF-8?q?luno,=20cria=C3=A7=C3=A3o=20de=20placeholder=20para=20a=20tela?= =?UTF-8?q?=20de=20professores=20e=20mudan=C3=A7as=20na=20firebase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/PROJECT_PROGRESS.md | 302 +++++++++++++++++- lib/core/routing/app_router.dart | 10 +- lib/core/services/auth_service.dart | 42 ++- .../auth/presentation/pages/login_page.dart | 82 ++++- .../pages/role_selection_page.dart | 28 ++ .../auth/presentation/pages/signup_page.dart | 70 +--- 6 files changed, 461 insertions(+), 73 deletions(-) diff --git a/docs/PROJECT_PROGRESS.md b/docs/PROJECT_PROGRESS.md index 64e1621..9f8b295 100644 --- a/docs/PROJECT_PROGRESS.md +++ b/docs/PROJECT_PROGRESS.md @@ -1,292 +1,590 @@ # 📊 Project Progress - AI Study Assistant + + --- + + ## 🎯 OVERVIEW + + This document tracks the overall progress of the AI Study Assistant project development. Updated in real-time as features are implemented. + + --- + + ## 📈 CURRENT STATUS + + ### **Overall Progress: 65% Complete** + + - ✅ **Foundation:** 100% Complete + - ✅ **UI/UX:** 90% Complete + - ✅ **Internationalization:** 100% Complete + - ⏳ **Authentication:** 20% Complete + - ⏳ **Core Features:** 0% Complete + - ⏳ **Backend Integration:** 0% Complete + + --- + + ## ✅ COMPLETED FEATURES + + ### **🏗️ Project Foundation (100%)** + - [x] Flutter project structure setup + - [x] Core theme and color system + - [x] Navigation system (GoRouter) + - [x] Asset management + - [x] Development environment configuration -### **🎨 UI/UX Components (90%)** + + +### **🎨 UI/UX Components (95%)** + - [x] Splash screen with animations + - [x] Login page with improved design + - [x] Role selection page (student/teacher) + - [x] Dynamic background effects + - [x] Responsive animations + - [x] Dark/light theme support + - [ ] Signup page (needs update) -- [ ] Dashboard pages (placeholder) + +- [x] Dashboard pages (fixed overflow issue) + + ### **🌍 Internationalization (100%)** + - [x] Portuguese (Portugal) as primary language + - [x] English fallback support + - [x] Localization system setup + - [x] All UI text localized + - [x] Language policy documentation + + ### **🔧 Development Setup (100%)** + - [x] Flutter SDK configuration + - [x] Device deployment (Samsung S928B) + - [x] Hot reload functionality + - [x] Debug tools setup + - [x] Code structure standards + + --- + + ## 🚧 IN PROGRESS + + ### **📱 Authentication System (20%)** + - [x] Login UI implementation + - [x] Form validation + - [x] Navigation flow + - [ ] Firebase integration + - [ ] Real authentication logic + - [ ] Token management + - [ ] Session persistence + + ### **📝 Signup Page (0%)** + - [ ] Update signup page design + - [ ] Portuguese localization + - [ ] Improved animations + - [ ] Form validation + - [ ] Role-based signup + - [ ] Terms and conditions + + --- + + ## ⏳ PENDING FEATURES + + ### **🤖 AI Tutor System (0%)** + - [ ] Chat interface design + - [ ] AI integration setup + - [ ] Message handling + - [ ] Response formatting + - [ ] Conversation history + - [ ] Voice input support + + ### **📝 Quiz System (0%)** + - [ ] Quiz creation interface + - [ ] Question types implementation + - [ ] Scoring system + - [ ] Progress tracking + - [ ] Results display + - [ ] Quiz categories + + ### **📊 Dashboard System (0%)** + - [ ] Student dashboard + - [ ] Teacher dashboard + - [ ] Analytics display + - [ ] Progress charts + - [ ] Performance metrics + - [ ] Quick actions + + ### **🔍 RAG Engine (0%)** + - [ ] Vector database setup + - [ ] Document processing + - [ ] Search implementation + - [ ] Context retrieval + - [ ] Answer generation + - [ ] Performance optimization + + ### **📈 Analytics System (0%)** + - [ ] Learning progress tracking + - [ ] Usage statistics + - [ ] Performance metrics + - [ ] Export functionality + - [ ] Reporting dashboard + - [ ] Data visualization + + --- + + ## 🎯 CURRENT SPRINT + + ### **Sprint 3: Authentication & Signup (In Progress)** + **Duration:** Current Week + **Goal:** Complete authentication flow + + #### **Tasks:** + - [x] Fix login page design issues + - [x] Improve animations and background + - [x] Update language policy documentation + - [ ] Update signup page with Portuguese + - [ ] Implement Firebase authentication + - [ ] Add role-based routing + + #### **Progress:** 60% Complete + + --- + + ## 📅 RELEASE ROADMAP + + ### **Version 1.0 - MVP (Target: 2 Weeks)** + - ✅ Basic UI/UX + - ✅ Internationalization + - ✅ Navigation flow + - ⏳ Complete authentication + - ⏳ Basic dashboard + - ⏳ Simple quiz system + + ### **Version 1.1 - Enhanced Features (Target: 4 Weeks)** + - ⏳ AI tutor integration + - ⏳ Advanced quiz features + - ⏳ Analytics dashboard + - ⏳ Performance improvements + + ### **Version 2.0 - Full Platform (Target: 8 Weeks)** + - ⏳ Complete RAG engine + - ⏳ Advanced analytics + - ⏳ Teacher tools + - ⏳ Content management + - ⏳ Mobile optimizations + + --- + + ## 🐛 KNOWN ISSUES + + ### **Critical Issues (0)** + - None currently + + ### **Minor Issues (1)** + - [ ] Signup page needs design update + - [ ] Some animations could be optimized + + ### **Technical Debt (2)** + - [ ] Add comprehensive error handling + - [ ] Implement proper logging system + - [ ] Add unit tests + - [ ] Optimize bundle size + + --- + + ## 📊 METRICS + + ### **Development Metrics:** + - **Total Files:** 45+ Dart files + - **Lines of Code:** ~3,000+ lines + - **Dependencies:** 25+ packages + - **Build Time:** ~15 seconds + - **App Size:** ~25MB (debug) + + ### **Quality Metrics:** + - **Code Coverage:** 0% (needs testing) + - **Lint Issues:** 0 critical + - **Performance:** Good + - **Accessibility:** Partially compliant + + --- + + ## 🔄 RECENT CHANGES + + ### **Last 24 Hours:** + +- ✅ Fixed dashboard overflow issue in QuickAccessWidget + +- ✅ Implemented responsive layout with IntrinsicHeight and Flexible + +- ✅ Replaced fixed heights with constraints (minHeight: 135, maxHeight: 160) + - ✅ Fixed login page animations + - ✅ Added dynamic background effects + - ✅ Updated language policy + - ✅ Improved text visibility + - ✅ Created progress documentation + + ### **Last Week:** + - ✅ Implemented role selection page + - ✅ Added Portuguese localization + - ✅ Fixed navigation flow + - ✅ Improved splash screen + - ✅ Setup internationalization + + --- + + ## 🎯 NEXT PRIORITIES + + ### **Immediate (This Week):** + 1. **Update signup page** with Portuguese and improved design + 2. **Implement Firebase authentication** for real login + 3. **Add role-based routing** after login + 4. **Create basic dashboard** placeholder + + ### **Short Term (Next 2 Weeks):** + 1. **Complete authentication system** + 2. **Build student dashboard** + 3. **Implement basic quiz system** + 4. **Add analytics tracking** + + ### **Medium Term (Next Month):** + 1. **Integrate AI tutor** + 2. **Build teacher dashboard** + 3. **Implement RAG engine** + 4. **Add comprehensive testing** + + --- + + ## 📱 DEVICE COMPATIBILITY + + ### **Tested Devices:** + - ✅ **Samsung S928B (Android 16)** - Primary testing device + - ✅ **Windows Desktop** - Development environment + - ✅ **Chrome Browser** - Web testing + - ⏳ **iOS Devices** - Pending testing + - ⏳ **Other Android** - Pending testing + + ### **Performance:** + - **Startup Time:** ~3 seconds + - **Navigation Speed:** Fast + - **Animation Performance:** Smooth (60fps) + - **Memory Usage:** ~150MB + + --- + + ## 🎉 ACHIEVEMENTS + + ### **Milestones Reached:** + - ✅ **Project Kickoff** - Complete + - ✅ **UI/UX Foundation** - Complete + - ✅ **Internationalization** - Complete + - ✅ **Device Deployment** - Complete + - ✅ **User Testing Ready** - Complete + + ### **Technical Achievements:** + - ✅ Successfully deployed to Samsung device + - ✅ Implemented complex animations + - ✅ Created scalable architecture + - ✅ Established development workflow + - ✅ Set up quality standards + + --- + + ## 📞 TEAM STATUS + + ### **Current Team:** + - **Developer:** Active + - **Testing:** In Progress + - **Documentation:** Up to Date + - **Quality Assurance:** Active + + --- + + **📊 Last Updated: 2024-05-06 21:43** + **🔄 Auto-Update: Enabled** + **📈 Progress Tracking: Real-time** + + --- + + *This document is automatically updated as development progresses. Check back regularly for the latest status.* + diff --git a/lib/core/routing/app_router.dart b/lib/core/routing/app_router.dart index 89514d4..58a82b8 100644 --- a/lib/core/routing/app_router.dart +++ b/lib/core/routing/app_router.dart @@ -54,13 +54,19 @@ class AppRouter { GoRoute( path: login, name: 'login', - builder: (context, state) => const LoginPage(), + builder: (context, state) { + final selectedRole = state.uri.queryParameters['role']; + return LoginPage(selectedRole: selectedRole); + }, ), GoRoute( path: signup, name: 'signup', - builder: (context, state) => const SignupPage(), + builder: (context, state) { + final selectedRole = state.uri.queryParameters['role']; + return SignupPage(selectedRole: selectedRole); + }, ), // Dashboard Routes diff --git a/lib/core/services/auth_service.dart b/lib/core/services/auth_service.dart index d144187..a5db605 100644 --- a/lib/core/services/auth_service.dart +++ b/lib/core/services/auth_service.dart @@ -1,15 +1,50 @@ import 'package:firebase_auth/firebase_auth.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; import 'session_service.dart'; /// Service for handling Firebase Authentication class AuthService { static final FirebaseAuth _auth = FirebaseAuth.instance; + static final FirebaseFirestore _firestore = FirebaseFirestore.instance; /// Get current user static User? get currentUser { return _auth.currentUser; } + /// Criar documento do usuário na Firestore após signup + static Future createUserRole(String uid, String role) async { + try { + print('DEBUG: Criando documento users/$uid com role: $role'); + await _firestore.collection('users').doc(uid).set({ + 'role': role, + 'createdAt': FieldValue.serverTimestamp(), + }); + print('DEBUG: Documento criado com sucesso'); + } catch (e) { + print('DEBUG: Erro ao criar documento: $e'); + throw Exception('Erro ao criar perfil do usuário'); + } + } + + /// Ler role do usuário na Firestore + static Future getUserRole(String uid) async { + try { + print('DEBUG: Lendo documento users/$uid'); + final doc = await _firestore.collection('users').doc(uid).get(); + if (doc.exists) { + final role = doc.data()?['role'] as String?; + print('DEBUG: Role encontrado: $role'); + return role; + } + print('DEBUG: Documento não existe'); + return null; + } catch (e) { + print('DEBUG: Erro ao ler documento: $e'); + return null; + } + } + /// Get auth state changes stream static Stream get authStateChanges { return _auth.authStateChanges(); @@ -41,10 +76,9 @@ class AuthService { print('DEBUG: Display name atualizado para: $displayName'); } - // Store user role in custom claims or Firestore (simplified for now) - if (role != null) { - print('DEBUG: Papel do usuário: $role'); - // TODO: Store role in Firestore for future use + // Criar documento na Firestore com role + if (role != null && result.user != null) { + await createUserRole(result.user!.uid, role); } // Verificar se o email foi verificado diff --git a/lib/features/auth/presentation/pages/login_page.dart b/lib/features/auth/presentation/pages/login_page.dart index fc4cd6d..ce0d0e0 100644 --- a/lib/features/auth/presentation/pages/login_page.dart +++ b/lib/features/auth/presentation/pages/login_page.dart @@ -7,7 +7,9 @@ import '../../../../core/services/session_service.dart'; import '../../../../shared/presentation/widgets/custom_notification.dart'; class LoginPage extends StatefulWidget { - const LoginPage({super.key}); + final String? selectedRole; + + const LoginPage({super.key, this.selectedRole}); @override State createState() => _LoginPageState(); @@ -62,12 +64,41 @@ class _LoginPageState extends State { print('DEBUG: Iniciando processo de login para: $email'); // Attempt login with Firebase - await AuthService.signInWithEmailAndPassword( + final result = await AuthService.signInWithEmailAndPassword( email: email, password: password, ); - print('DEBUG: Login Firebase bem-sucedido, salvando sessão'); + print('DEBUG: Login Firebase bem-sucedido'); + print('DEBUG: Role selecionado na tela anterior: ${widget.selectedRole}'); + + // Ler role na Firestore + final uid = result?.user?.uid; + if (uid == null) throw Exception('Erro ao obter UID'); + + final actualRole = await AuthService.getUserRole(uid); + print('DEBUG: Role real do usuário na Firestore: $actualRole'); + + // Validar se o role selecionado corresponde ao role real + final selectedRole = widget.selectedRole; + if (selectedRole != null && actualRole != null && selectedRole != actualRole) { + // Role não corresponde - mostrar erro + setState(() { + _isLoading = false; + }); + + String errorMessage; + if (selectedRole == 'teacher' && actualRole == 'student') { + errorMessage = 'Este email está registado como Aluno. Não pode aceder à área de Professores.'; + } else if (selectedRole == 'student' && actualRole == 'teacher') { + errorMessage = 'Este email está registado como Professor. Não pode aceder à área de Alunos.'; + } else { + errorMessage = 'O tipo de utilizador selecionado não corresponde ao perfil registado.'; + } + + _showRoleErrorDialog('Acesso Negado', errorMessage); + return; + } // Save session based on remember me preference await SessionService.saveSession( @@ -76,9 +107,6 @@ class _LoginPageState extends State { displayName: AuthService.currentUser?.displayName, ); - print('DEBUG: Sessão salva, navegando para dashboard'); - - // Navigate to student dashboard after successful login if (mounted) { setState(() { _isLoading = false; @@ -90,7 +118,12 @@ class _LoginPageState extends State { message: 'Login realizado com sucesso!', ); - context.go('/student-dashboard'); + // Redirecionar baseado no role real + if (actualRole == 'teacher') { + context.go('/teacher-dashboard'); + } else { + context.go('/student-dashboard'); + } } } catch (e) { print('DEBUG: Erro no login: $e'); @@ -110,6 +143,41 @@ class _LoginPageState extends State { } } + void _showRoleErrorDialog(String title, String message) { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AlertDialog( + title: Text( + title, + style: const TextStyle( + color: Color(0xFF2D3748), + fontWeight: FontWeight.bold, + ), + ), + content: Text( + message, + style: const TextStyle(color: Color(0xFF2D3748)), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + // Fazer logout para limpar a sessão + AuthService.signOut(); + }, + child: const Text( + 'Voltar', + style: TextStyle(color: Color(0xFF82C9BD)), + ), + ), + ], + ); + }, + ); + } + @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/features/auth/presentation/pages/role_selection_page.dart b/lib/features/auth/presentation/pages/role_selection_page.dart index bb9dd7e..76f68b3 100644 --- a/lib/features/auth/presentation/pages/role_selection_page.dart +++ b/lib/features/auth/presentation/pages/role_selection_page.dart @@ -278,6 +278,28 @@ class _RoleSelectionPageState extends State { ), const SizedBox(height: 32), + + // Login link + GestureDetector( + onTap: _selectedRole != null ? _handleGoToLogin : null, + child: Text( + 'Já tenho conta', + style: TextStyle( + color: _selectedRole != null + ? AppColors.primaryBlue + : Colors.grey, + fontWeight: FontWeight.w500, + decoration: TextDecoration.underline, + ), + ), + ) + .animate() + .fadeIn( + duration: const Duration(milliseconds: 800), + delay: const Duration(milliseconds: 1400), + ), + + const SizedBox(height: 32), ], ), ), @@ -288,6 +310,12 @@ class _RoleSelectionPageState extends State { ); } + void _handleGoToLogin() { + if (_selectedRole != null) { + context.go('/login?role=$_selectedRole'); + } + } + Widget _buildRoleCard( BuildContext context, String title, diff --git a/lib/features/auth/presentation/pages/signup_page.dart b/lib/features/auth/presentation/pages/signup_page.dart index 86b5a7c..7bb43b6 100644 --- a/lib/features/auth/presentation/pages/signup_page.dart +++ b/lib/features/auth/presentation/pages/signup_page.dart @@ -6,7 +6,9 @@ import '../../../../core/services/auth_service.dart'; import '../../../../shared/presentation/widgets/custom_notification.dart'; class SignupPage extends StatefulWidget { - const SignupPage({super.key}); + final String? selectedRole; + + const SignupPage({super.key, this.selectedRole}); @override State createState() => _SignupPageState(); @@ -19,7 +21,14 @@ class _SignupPageState extends State { final _passwordController = TextEditingController(); bool _isLoading = false; bool _obscurePassword = true; - String _selectedRole = 'student'; // 'student' or 'teacher' + late String _selectedRole; + + @override + void initState() { + super.initState(); + // Usar role passado da tela anterior ou default 'student' + _selectedRole = widget.selectedRole ?? 'student'; + } @override void dispose() { @@ -338,61 +347,6 @@ class _SignupPageState extends State { return null; }, ), - const SizedBox(height: 16), - - // Role selection - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Eu sou:', - style: TextStyle( - color: Color(0xFF2D3748), - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 8), - Row( - children: [ - Expanded( - child: RadioListTile( - title: const Text( - 'Aluno', - style: TextStyle(fontSize: 14), - ), - value: 'student', - groupValue: _selectedRole, - onChanged: (String? value) { - setState(() { - _selectedRole = value!; - }); - }, - activeColor: const Color(0xFF82C9BD), - contentPadding: EdgeInsets.zero, - ), - ), - Expanded( - child: RadioListTile( - title: const Text( - 'Professor', - style: TextStyle(fontSize: 14), - ), - value: 'teacher', - groupValue: _selectedRole, - onChanged: (String? value) { - setState(() { - _selectedRole = value!; - }); - }, - activeColor: const Color(0xFF82C9BD), - contentPadding: EdgeInsets.zero, - ), - ), - ], - ), - ], - ), const SizedBox(height: 24), // Signup button @@ -434,7 +388,7 @@ class _SignupPageState extends State { // Login link GestureDetector( onTap: () { - context.go('/login'); + context.go('/login?role=$_selectedRole'); }, child: Text( 'Já tem conta? Entrar aqui',