Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import 'package:uni/controller/parsers/schedule/new_api/parser.dart';
import 'package:uni/model/entities/lecture.dart';
import 'package:uni/session/flows/base/session.dart';

/// Class for fetching the user's lectures from the schedule's HTML page.
class ScheduleFetcherNewApi extends ScheduleFetcher {
/// Abstract base class for fetching lectures from the schedule's HTML page.
abstract class ScheduleFetcherNewApiBase extends ScheduleFetcher {
String getEndpointView();

Map<String, String> getQueryParams(Session session);

@override
List<String> getEndpoints(Session session) {
final urls =
NetworkRouter.getBaseUrlsFromSession(
session,
).map((url) => '${url}hor_geral.estudantes_view').toList();
).map((url) => '${url}hor_geral.${getEndpointView()}').toList();
return urls;
}

Expand All @@ -22,7 +26,7 @@ class ScheduleFetcherNewApi extends ScheduleFetcher {
final lectiveYear = getLectiveYear(DateTime.now());

final scheduleResponse = await NetworkRouter.getWithCookies(url, {
'pv_num_unico': session.username,
...getQueryParams(session),
'pv_ano_lectivo': lectiveYear.toString(),
'pv_periodos': '1',
}, session);
Expand All @@ -47,3 +51,28 @@ class ScheduleFetcherNewApi extends ScheduleFetcher {
return lectures;
}
}

/// Class for fetching student lectures from the schedule's HTML page.
class ScheduleFetcherNewApi extends ScheduleFetcherNewApiBase {
@override
String getEndpointView() => 'estudantes_view';

@override
Map<String, String> getQueryParams(Session session) => {
'pv_num_unico': session.username,
};
}

/// Class for fetching professor lectures from the schedule's HTML page.
class ScheduleFetcherNewApiProfessor extends ScheduleFetcherNewApiBase {
ScheduleFetcherNewApiProfessor({required this.professorCode});
final String professorCode;

@override
String getEndpointView() => 'docentes_view';

@override
Map<String, String> getQueryParams(Session session) => {
'pv_doc_codigo': professorCode,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ List<Lecture> getLecturesFromApiResponse(http.Response response) {
lecture.persons.map((person) => person.acronym).join('+'),
_filterTeacherName(lecture.persons.first.name),
_filterTeacherCode(lecture.persons.first.name),
lecture.classes.length > 1
? '${lecture.classes.first.acronym} + ${lecture.classes.length - 1}'
: lecture.classes.first.acronym,
lecture.classes.first.acronym,
lecture.units.first.sigarraId,
),
)
Expand Down
1 change: 1 addition & 0 deletions packages/uni_app/lib/generated/intl/messages_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class MessageLookup extends MessageLookupByLibrary {
"check_internet": MessageLookupByLibrary.simpleMessage(
"Check your internet connection",
),
"classProfessor": MessageLookupByLibrary.simpleMessage("Class Professor"),
"class_registration": MessageLookupByLibrary.simpleMessage(
"Class Registration",
),
Expand Down
3 changes: 3 additions & 0 deletions packages/uni_app/lib/generated/intl/messages_pt_PT.dart
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ class MessageLookup extends MessageLookupByLibrary {
"check_internet": MessageLookupByLibrary.simpleMessage(
"Verifica a tua ligação à internet",
),
"classProfessor": MessageLookupByLibrary.simpleMessage(
"Professor da Turma",
),
"class_registration": MessageLookupByLibrary.simpleMessage(
"Inscrição de Turmas",
),
Expand Down
10 changes: 10 additions & 0 deletions packages/uni_app/lib/generated/l10n.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/uni_app/lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@
"@courseRegent": {},
"instructor": "Instructor",
"@instructor": {},
"classProfessor": "Class Professor",
"@classProfessor": {},
"lectures": "Lectures",
"@lectures": {},
"exams": "Exams",
Expand Down
2 changes: 2 additions & 0 deletions packages/uni_app/lib/l10n/intl_pt_PT.arb
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@
"@courseRegent": {},
"instructor": "Docente",
"@instructor": {},
"classProfessor": "Professor da Turma",
"@classProfessor": {},
"lectures": "Aulas",
"@lectures": {},
"exams": "Exames",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:collection';

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:uni/controller/fetchers/course_units_fetcher/course_units_info_fetcher.dart';
import 'package:uni/controller/fetchers/schedule_fetcher/schedule_fetcher_new_api.dart';
import 'package:uni/model/entities/course_units/course_unit.dart';
import 'package:uni/model/entities/course_units/course_unit_class.dart';
import 'package:uni/model/entities/course_units/course_unit_directory.dart';
Expand All @@ -12,7 +13,9 @@ import 'package:uni/model/providers/riverpod/session_provider.dart';
typedef SheetsMap = Map<CourseUnit, Sheet>;
typedef ClassesMap = Map<CourseUnit, List<CourseUnitClass>>;
typedef FilesMap = Map<CourseUnit, List<CourseUnitFileDirectory>>;
typedef CourseUnitsInfoState = (SheetsMap, ClassesMap, FilesMap);
typedef ClassProfessorsMap = Map<CourseUnit, Map<String, List<Professor>>>;
typedef CourseUnitsInfoState =
(SheetsMap, ClassesMap, FilesMap, ClassProfessorsMap);

final courseUnitsInfoProvider =
AsyncNotifierProvider<CourseUnitsInfoNotifier, CourseUnitsInfoState?>(
Expand Down Expand Up @@ -45,12 +48,21 @@ class CourseUnitsInfoNotifier
);
}

UnmodifiableMapView<CourseUnit, Map<String, List<Professor>>>
get courseUnitsClassProfessors {
final currentState = state.value;
return UnmodifiableMapView(
currentState?.$4 ?? <CourseUnit, Map<String, List<Professor>>>{},
);
}

@override
Future<CourseUnitsInfoState?> loadFromStorage() async {
return (
<CourseUnit, Sheet>{},
<CourseUnit, List<CourseUnitClass>>{},
<CourseUnit, List<CourseUnitFileDirectory>>{},
<CourseUnit, Map<String, List<Professor>>>{},
);
}

Expand All @@ -60,6 +72,7 @@ class CourseUnitsInfoNotifier
<CourseUnit, Sheet>{},
<CourseUnit, List<CourseUnitClass>>{},
<CourseUnit, List<CourseUnitFileDirectory>>{},
<CourseUnit, Map<String, List<Professor>>>{},
);
}

Expand All @@ -82,11 +95,17 @@ class CourseUnitsInfoNotifier
<CourseUnit, Sheet>{},
<CourseUnit, List<CourseUnitClass>>{},
<CourseUnit, List<CourseUnitFileDirectory>>{},
<CourseUnit, Map<String, List<Professor>>>{},
);

final updatedSheetsMap = Map<CourseUnit, Sheet>.from(currentState.$1);
updatedSheetsMap[courseUnit] = sheet;
updateState((updatedSheetsMap, currentState.$2, currentState.$3));
updateState((
updatedSheetsMap,
currentState.$2,
currentState.$3,
currentState.$4,
));
}

Future<void> fetchCourseUnitClasses(CourseUnit courseUnit) async {
Expand All @@ -111,13 +130,19 @@ class CourseUnitsInfoNotifier
<CourseUnit, Sheet>{},
<CourseUnit, List<CourseUnitClass>>{},
<CourseUnit, List<CourseUnitFileDirectory>>{},
<CourseUnit, Map<String, List<Professor>>>{},
);

final updatedClassesMap = Map<CourseUnit, List<CourseUnitClass>>.from(
currentState.$2,
);
updatedClassesMap[courseUnit] = classes;
updateState((currentState.$1, updatedClassesMap, currentState.$3));
updateState((
currentState.$1,
updatedClassesMap,
currentState.$3,
currentState.$4,
));
}

Future<void> fetchCourseUnitFiles(CourseUnit courseUnit) async {
Expand All @@ -142,12 +167,73 @@ class CourseUnitsInfoNotifier
<CourseUnit, Sheet>{},
<CourseUnit, List<CourseUnitClass>>{},
<CourseUnit, List<CourseUnitFileDirectory>>{},
<CourseUnit, Map<String, List<Professor>>>{},
);

final updatedFilesMap = Map<CourseUnit, List<CourseUnitFileDirectory>>.from(
currentState.$3,
);
updatedFilesMap[courseUnit] = files;
updateState((currentState.$1, currentState.$2, updatedFilesMap));
updateState((
currentState.$1,
currentState.$2,
updatedFilesMap,
currentState.$4,
));
}

Future<void> fetchClassProfessors(CourseUnit courseUnit) async {
final session = await ref.read(sessionProvider.future);
if (session == null) {
return;
}

final sheet = courseUnitsSheets[courseUnit];
if (sheet == null) {
return;
}

final professors = sheet.professors;
final Map<String, List<Professor>> classProfessors = {};
final courseAcronym = courseUnit.abbreviation;

for (final professor in professors) {
final fetcher = ScheduleFetcherNewApiProfessor(
professorCode: professor.code,
);
final lectures = await fetcher.getLectures(session);

for (final lecture in lectures) {
if (lecture.classNumber.isNotEmpty &&
lecture.acronym == courseAcronym &&
lecture.typeClass != 'T') {
if (!classProfessors.containsKey(lecture.classNumber)) {
classProfessors[lecture.classNumber] = [];
}
if (!classProfessors[lecture.classNumber]!.contains(professor)) {
classProfessors[lecture.classNumber]!.add(professor);
}
}
}
}

final currentState =
state.value ??
(
<CourseUnit, Sheet>{},
<CourseUnit, List<CourseUnitClass>>{},
<CourseUnit, List<CourseUnitFileDirectory>>{},
<CourseUnit, Map<String, List<Professor>>>{},
);

final updatedClassProfessorsMap =
Map<CourseUnit, Map<String, List<Professor>>>.from(currentState.$4);
updatedClassProfessorsMap[courseUnit] = classProfessors;
updateState((
currentState.$1,
currentState.$2,
currentState.$3,
updatedClassProfessorsMap,
));
}
}
59 changes: 50 additions & 9 deletions packages/uni_app/lib/view/course_unit_info/course_unit_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ class CourseUnitDetailPageViewState
void initState() {
super.initState();
tabController = TabController(vsync: this, length: 3);
tabController.addListener(_onTabChanged);
}

void _onTabChanged() {
if (tabController.index == 1) {
loadClasses(force: false);
}
}

Future<void> loadInfo({required bool force}) async {
Expand All @@ -52,17 +59,30 @@ class CourseUnitDetailPageViewState
if (courseUnitFiles == null || force) {
await courseUnitsProvider.fetchCourseUnitFiles(widget.courseUnit);
}
}

Future<void> loadClasses({required bool force}) async {
final courseUnitsProvider = ref.read(courseUnitsInfoProvider.notifier);

final courseUnitClasses =
courseUnitsProvider.courseUnitsClasses[widget.courseUnit];
if (courseUnitClasses == null || force) {
await courseUnitsProvider.fetchCourseUnitClasses(widget.courseUnit);
}

final courseUnitClassProfessors =
courseUnitsProvider.courseUnitsClassProfessors[widget.courseUnit];
if (courseUnitClassProfessors == null || force) {
await courseUnitsProvider.fetchClassProfessors(widget.courseUnit);
}
}

@override
Future<void> onRefresh() async {
await loadInfo(force: true);
if (tabController.index == 1) {
await loadClasses(force: true);
}
}

@override
Expand Down Expand Up @@ -151,17 +171,38 @@ class CourseUnitDetailPageViewState
}

Widget _courseUnitClassesView(BuildContext context) {
final classes =
ref.read(courseUnitsInfoProvider.notifier).courseUnitsClasses[widget
.courseUnit];
return Consumer(
builder: (context, ref, _) {
ref.watch(courseUnitsInfoProvider);
final provider = ref.read(courseUnitsInfoProvider.notifier);

if (classes == null || classes.isEmpty) {
return Center(
child: Text(S.of(context).no_class, textAlign: TextAlign.center),
);
}
final classes = provider.courseUnitsClasses[widget.courseUnit];
final sheet = provider.courseUnitsSheets[widget.courseUnit];
final classProfessors =
provider.courseUnitsClassProfessors[widget.courseUnit];

if (classes == null) {
return const Center(child: CircularProgressIndicator());
}

if (classes.isEmpty) {
return Center(
child: Text(S.of(context).no_class, textAlign: TextAlign.center),
);
}

if (classProfessors == null) {
return const Center(child: CircularProgressIndicator());
}

return CourseUnitClassesView(classes);
return CourseUnitClassesView(
classes,
sheet?.professors ?? [],
widget.courseUnit,
classProfessors: classProfessors,
);
},
);
}

@override
Expand Down
Loading