Skip to content

Commit a9ca6b4

Browse files
committed
✨ feat: mejoras de ux en las academias 2
1 parent 5b94b29 commit a9ca6b4

2 files changed

Lines changed: 82 additions & 77 deletions

File tree

lib/features/dashboard/views/academy_home_view.dart

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
import 'package:flutter/material.dart';
22
import 'package:provider/provider.dart';
3+
import '../../../data/models/professor_model.dart';
4+
import '../../../data/models/subject_model.dart';
35
import '../../../data/models/user_model.dart';
46
import '../../../theme/theme.dart';
57
import '../viewmodels/academy_home_viewmodel.dart';
68
import '../viewmodels/home_menu_viewmodel.dart';
7-
import 'student_detail_view.dart';
89
import 'student_list_view.dart';
910
import 'subject_management_view.dart';
1011

1112
class AcademyHomeView extends StatelessWidget {
1213
const AcademyHomeView({super.key});
1314

14-
void _navigateToStudentList(BuildContext context, String title, List<UserModel> students) {
15-
Navigator.push(
16-
context,
17-
MaterialPageRoute(builder: (context) => StudentListView(title: title, students: students)),
15+
void _showAssignmentForm(BuildContext context, AcademyViewModel vm, UserModel student) {
16+
vm.filterSubjectsForStudent(student);
17+
showModalBottomSheet(
18+
context: context,
19+
isScrollControlled: true,
20+
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20))),
21+
builder: (_) => ChangeNotifierProvider.value(
22+
value: vm,
23+
child: _AssignmentForm(student: student),
24+
),
1825
);
1926
}
2027

@@ -81,19 +88,53 @@ class AcademyHomeView extends StatelessWidget {
8188
childAspectRatio: 1.5,
8289
children: [
8390
GestureDetector(
84-
onTap: () => _navigateToStudentList(context, 'Pendientes de Asignación', vm.pendingStudents),
91+
onTap: () => Navigator.push(
92+
context,
93+
MaterialPageRoute(builder: (_) =>
94+
StudentListView(
95+
title: 'Pendientes de Asignación',
96+
students: vm.pendingStudents,
97+
onAssign: (student) => _showAssignmentForm(context, vm, student),
98+
)
99+
),
100+
),
85101
child: _buildSummaryCard('Pendientes', vm.pendingStudents.length.toString(), Icons.hourglass_top_outlined, Colors.orange.shade700),
86102
),
87103
GestureDetector(
88-
onTap: () => _navigateToStudentList(context, 'Alumnos en Curso', vm.assignedStudents),
104+
onTap: () => Navigator.push(
105+
context,
106+
MaterialPageRoute(builder: (_) =>
107+
StudentListView(
108+
title: 'Alumnos en Curso',
109+
students: vm.assignedStudents,
110+
onAssign: (student) => _showAssignmentForm(context, vm, student),
111+
)
112+
),
113+
),
89114
child: _buildSummaryCard('En Curso', vm.assignedStudents.length.toString(), Icons.school_outlined, AppTheme.bluePrimary),
90115
),
91-
GestureDetector(
92-
onTap: () => _navigateToStudentList(context, 'Alumnos Acreditados', vm.accreditedStudents),
116+
GestureDetector(
117+
onTap: () => Navigator.push(
118+
context,
119+
MaterialPageRoute(builder: (_) =>
120+
StudentListView(
121+
title: 'Alumnos Acreditados',
122+
students: vm.accreditedStudents,
123+
)
124+
),
125+
),
93126
child: _buildSummaryCard('Acreditados', vm.accreditedStudents.length.toString(), Icons.check_circle_outlined, Colors.green.shade700),
94127
),
95128
GestureDetector(
96-
onTap: () => _navigateToStudentList(context, 'Alumnos No Acreditados', vm.notAccreditedStudents),
129+
onTap: () => Navigator.push(
130+
context,
131+
MaterialPageRoute(builder: (_) =>
132+
StudentListView(
133+
title: 'Alumnos No Acreditados',
134+
students: vm.notAccreditedStudents,
135+
)
136+
),
137+
),
97138
child: _buildSummaryCard('No Acreditados', vm.notAccreditedStudents.length.toString(), Icons.cancel_outlined, Colors.red.shade700),
98139
),
99140
],
@@ -130,19 +171,7 @@ class AcademyHomeView extends StatelessWidget {
130171
),
131172
],
132173
),
133-
<<<<<<< HEAD
134-
=======
135-
const Divider(height: 1, indent: 16, endIndent: 16),
136-
Padding(
137-
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4),
138-
child: TextButton.icon(
139-
icon: const Icon(Icons.add_circle_outline, size: 18),
140-
label: const Text("Asignar Materia"),
141-
style: TextButton.styleFrom(foregroundColor: AppTheme.bluePrimary),
142-
onPressed: onAssign,
143-
),
144-
)
145-
]),
174+
),
146175
);
147176
}
148177
}
@@ -165,7 +194,6 @@ class _AssignmentFormState extends State<_AssignmentForm> {
165194
@override
166195
void initState() {
167196
super.initState();
168-
// Auto-select the subject if there's only one available
169197
final vm = context.read<AcademyViewModel>();
170198
if (vm.availableSubjectsForStudent.length == 1) {
171199
_selectedSubject = vm.availableSubjectsForStudent.first;
@@ -217,10 +245,9 @@ class _AssignmentFormState extends State<_AssignmentForm> {
217245
Text("Alumno: ${widget.student.name}", style: const TextStyle(color: Colors.grey)),
218246
const SizedBox(height: 20),
219247

220-
// --- FIX: Use the filtered list of subjects ---
221248
DropdownButtonFormField<SubjectModel>(
222249
key: ValueKey(_selectedSubject),
223-
initialValue: _selectedSubject,
250+
value: _selectedSubject,
224251
decoration: const InputDecoration(labelText: "Materia", border: OutlineInputBorder()),
225252
items: vm.availableSubjectsForStudent.map((s) => DropdownMenuItem(value: s, child: Text(s.name))).toList(),
226253
onChanged: (val) => setState(() {
@@ -260,7 +287,6 @@ class _AssignmentFormState extends State<_AssignmentForm> {
260287
),
261288
)
262289
],
263-
>>>>>>> b02e3f38a199391d13e8c793264fe648935ec0f9
264290
),
265291
);
266292
}

lib/features/dashboard/views/student_list_view.dart

Lines changed: 29 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import 'student_detail_view.dart';
66
class StudentListView extends StatelessWidget {
77
final String title;
88
final List<UserModel> students;
9+
final Function(UserModel)? onAssign;
910

10-
const StudentListView({super.key, required this.title, required this.students});
11+
const StudentListView({super.key, required this.title, required this.students, this.onAssign});
1112

1213
@override
1314
Widget build(BuildContext context) {
14-
// Sort students alphabetically by name
1515
students.sort((a, b) => a.name.compareTo(b.name));
1616

1717
return Scaffold(
@@ -30,56 +30,35 @@ class StudentListView extends StatelessWidget {
3030
return Card(
3131
margin: const EdgeInsets.only(bottom: 12),
3232
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
33-
<<<<<<< HEAD
3433
elevation: 1,
35-
child: ListTile(
36-
leading: CircleAvatar(
37-
backgroundColor: AppTheme.blueSoft,
38-
child: Text(student.name.isNotEmpty ? student.name[0] : "?", style: const TextStyle(color: AppTheme.blueDark, fontWeight: FontWeight.bold)),
39-
),
40-
title: Text(student.name, style: const TextStyle(fontWeight: FontWeight.bold)),
41-
subtitle: Text("Boleta: ${student.boleta}"),
42-
trailing: const Icon(Icons.chevron_right, color: Colors.grey),
43-
onTap: () {
44-
Navigator.push(
45-
context,
46-
MaterialPageRoute(builder: (context) => StudentDetailView(student: student)),
47-
=======
48-
clipBehavior: Clip.antiAlias,
49-
child: ExpansionTile(
50-
key: PageStorageKey(academy),
51-
leading: const Icon(Icons.school_outlined, color: AppTheme.blueDark, size: 28),
52-
title: Text(academy, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: AppTheme.blueDark)),
53-
backgroundColor: AppTheme.blueSoft.withValues(alpha:0.2),
54-
children: subjects.entries.map((subjectEntry) {
55-
final subject = subjectEntry.key;
56-
final studentList = subjectEntry.value;
57-
58-
return ExpansionTile(
59-
key: PageStorageKey('$academy-$subject'),
60-
tilePadding: const EdgeInsets.only(left: 48, right: 24),
61-
leading: const Icon(Icons.menu_book_outlined, color: AppTheme.bluePrimary),
62-
title: Text(subject, style: TextStyle(color: Colors.grey.shade800, fontWeight: FontWeight.w600, fontSize: 16)),
63-
backgroundColor: AppTheme.baseLight.withValues(alpha:0.5),
64-
children: studentList.map((student) {
65-
// --- FIX: Remove toUpperCase() ---
66-
return ListTile(
67-
contentPadding: const EdgeInsets.only(left: 56, right: 16, top: 4, bottom: 4),
68-
leading: const Icon(Icons.person_outline, color: Colors.grey),
69-
title: Text(student.name),
70-
subtitle: Text('Boleta: ${student.boleta}'),
71-
trailing: const Icon(Icons.chevron_right, size: 18),
72-
onTap: () {
73-
Navigator.push(
74-
context,
75-
MaterialPageRoute(builder: (context) => StudentDetailView(student: student)),
76-
);
77-
},
34+
child: Column(
35+
children: [
36+
ListTile(
37+
leading: CircleAvatar(
38+
backgroundColor: AppTheme.blueSoft,
39+
child: Text(student.name.isNotEmpty ? student.name[0] : "?", style: const TextStyle(color: AppTheme.blueDark, fontWeight: FontWeight.bold)),
40+
),
41+
title: Text(student.name, style: const TextStyle(fontWeight: FontWeight.bold)),
42+
subtitle: Text("Boleta: ${student.boleta}"),
43+
trailing: const Icon(Icons.chevron_right, color: Colors.grey),
44+
onTap: () {
45+
Navigator.push(
46+
context,
47+
MaterialPageRoute(builder: (context) => StudentDetailView(student: student)),
7848
);
79-
}).toList(),
80-
>>>>>>> b02e3f38a199391d13e8c793264fe648935ec0f9
81-
);
82-
},
49+
},
50+
),
51+
if (onAssign != null)
52+
Padding(
53+
padding: const EdgeInsets.only(bottom: 8.0),
54+
child: TextButton.icon(
55+
icon: const Icon(Icons.add_circle_outline, size: 18),
56+
label: const Text("Asignar Materia"),
57+
style: TextButton.styleFrom(foregroundColor: AppTheme.bluePrimary),
58+
onPressed: () => onAssign!(student),
59+
),
60+
),
61+
],
8362
),
8463
);
8564
},

0 commit comments

Comments
 (0)