correção de bugs, creação propria para turmas, e preparação para criar quizzes

This commit is contained in:
2026-05-15 12:40:38 +01:00
parent 62b9a107bc
commit 2775205f9e
14 changed files with 970 additions and 604 deletions

View File

@@ -1,3 +1,4 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:go_router/go_router.dart';
@@ -22,12 +23,39 @@ class _SignupPageState extends State<SignupPage> {
bool _isLoading = false;
bool _obscurePassword = true;
late String _selectedRole;
String? _selectedSchoolClassId;
List<Map<String, String>> _availableClasses = [];
bool _isLoadingClasses = false;
@override
void initState() {
super.initState();
// Usar role passado da tela anterior ou default 'student'
_selectedRole = widget.selectedRole ?? 'student';
if (_selectedRole == 'student') {
_loadAvailableClasses();
}
}
Future<void> _loadAvailableClasses() async {
setState(() => _isLoadingClasses = true);
try {
final snapshot = await FirebaseFirestore.instance
.collection('school_classes')
.where('active', isEqualTo: true)
.orderBy('year')
.orderBy('section')
.get();
setState(() {
_availableClasses = snapshot.docs.map((doc) {
final data = doc.data();
return {'id': doc.id, 'name': (data['name'] as String? ?? doc.id)};
}).toList();
_isLoadingClasses = false;
});
} catch (e) {
setState(() => _isLoadingClasses = false);
}
}
@override
@@ -38,6 +66,99 @@ class _SignupPageState extends State<SignupPage> {
super.dispose();
}
Widget _buildClassSelector(BuildContext context) {
if (_isLoadingClasses) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
children: [
SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Theme.of(context).colorScheme.primary,
),
),
const SizedBox(width: 12),
Text(
'A carregar turmas...',
style: TextStyle(
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 14,
),
),
],
),
);
}
if (_availableClasses.isEmpty) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
'Nenhuma turma disponível. Contacta o teu professor.',
style: TextStyle(
color: Theme.of(context).colorScheme.error,
fontSize: 13,
),
),
);
}
return DropdownButtonFormField<String>(
value: _selectedSchoolClassId,
isExpanded: true,
decoration: InputDecoration(
labelText: 'Turma',
labelStyle: TextStyle(color: Theme.of(context).colorScheme.onSurface),
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),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(color: Theme.of(context).colorScheme.error),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(color: Theme.of(context).colorScheme.error),
),
filled: true,
fillColor: Theme.of(context).brightness == Brightness.dark
? Theme.of(context).colorScheme.surfaceContainerHighest
: Theme.of(context).colorScheme.surface,
),
style: TextStyle(color: Theme.of(context).colorScheme.onSurface),
dropdownColor: Theme.of(context).colorScheme.surface,
hint: Text(
'Seleciona a tua turma',
style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
),
items: _availableClasses
.map(
(c) => DropdownMenuItem<String>(
value: c['id'],
child: Text(c['name']!),
),
)
.toList(),
onChanged: (value) => setState(() => _selectedSchoolClassId = value),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Seleciona a tua turma';
}
return null;
},
);
}
Future<void> _handleSignup() async {
if (!_formKey.currentState!.validate()) return;
@@ -60,6 +181,9 @@ class _SignupPageState extends State<SignupPage> {
password: password,
displayName: name,
role: _selectedRole,
schoolClassId: _selectedRole == 'student'
? _selectedSchoolClassId
: null,
);
print('DEBUG: Signup Firebase bem-sucedido, navegando para dashboard');
@@ -295,6 +419,12 @@ class _SignupPageState extends State<SignupPage> {
),
const SizedBox(height: 16),
// Seletor de turma (apenas para alunos)
if (_selectedRole == 'student') ...[
_buildClassSelector(context),
const SizedBox(height: 16),
],
// Email field
TextFormField(
controller: _emailController,