Skip to content

Commit

Permalink
Redesigning academic page (#1151)
Browse files Browse the repository at this point in the history
  • Loading branch information
DGoiana authored Jul 13, 2024
2 parents a8d82b5 + aed0bfc commit 7007b32
Show file tree
Hide file tree
Showing 12 changed files with 669 additions and 99 deletions.
Binary file added uni/assets/images/book_placeholder.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions uni/lib/controller/fetchers/book_fetcher.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:uni/controller/networking/network_router.dart';

class BookThumbFetcher {
Future<String> fetchBookThumb(String isbn) async {
final url = Uri.https(
'www.googleapis.com',
'/books/v1/volumes',
{'q': '+isbn:$isbn'},
);

final response =
await http.get(Uri.decodeComponent(url.toString()).toUri());

final bookInformation = ((json.decode(response.body)
as Map<String, dynamic>)['items'] as List<dynamic>)
.first as Map<String, dynamic>;

final thumbnailURL =
((bookInformation['volumeInfo'] as Map<String, dynamic>)['imageLinks']
as Map<String, dynamic>)['thumbnail'];

return thumbnailURL.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:uni/controller/parsers/parser_course_unit_info.dart';
import 'package:uni/model/entities/course_units/course_unit_class.dart';
import 'package:uni/model/entities/course_units/course_unit_directory.dart';
import 'package:uni/model/entities/course_units/course_unit_sheet.dart';
import 'package:uni/model/entities/course_units/sheet.dart';
import 'package:uni/model/entities/session.dart';

class CourseUnitsInfoFetcher implements SessionDependantFetcher {
Expand All @@ -27,16 +28,27 @@ class CourseUnitsInfoFetcher implements SessionDependantFetcher {
return parseCourseUnitSheet(response);
}

Future<Sheet> fetchSheet(
Session session,
int occurId,
) async {
final url = '${getEndpoints(session)[0]}mob_ucurr_geral.perfil';
final response = await NetworkRouter.getWithCookies(
url,
{'pv_ocorrencia_id': occurId.toString()},
session,
);
return parseSheet(response);
}

Future<List<CourseUnitFileDirectory>> fetchCourseUnitFiles(
Session session,
int occurId,
) async {
final url = '${getEndpoints(session)[0]}mob_ucurr_geral.conteudos';
final response = await NetworkRouter.getWithCookies(
url,
{
'pv_ocorrencia_id': occurId.toString(),
},
{'pv_ocorrencia_id': occurId.toString()},
session,
);
return parseFiles(response, session);
Expand Down
59 changes: 59 additions & 0 deletions uni/lib/controller/parsers/parser_course_unit_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:uni/model/entities/course_units/course_unit_class.dart';
import 'package:uni/model/entities/course_units/course_unit_directory.dart';
import 'package:uni/model/entities/course_units/course_unit_file.dart';
import 'package:uni/model/entities/course_units/course_unit_sheet.dart';
import 'package:uni/model/entities/course_units/sheet.dart';
import 'package:uni/model/entities/session.dart';

Future<List<CourseUnitFileDirectory>> parseFiles(
Expand Down Expand Up @@ -44,6 +45,59 @@ Future<List<CourseUnitFileDirectory>> parseFiles(
return dirs;
}

Future<Sheet> parseSheet(http.Response response) async {
final json = jsonDecode(response.body) as Map<String, dynamic>;

final professors = getCourseUnitProfessors(
(json['ds'] as List)
.map((element) => element as Map<String, dynamic>)
.toList(),
);

final regents = (json['responsabilidades'] as List).map((element) {
return Professor.fromJson(element as Map<String, dynamic>);
}).toList();

final books = (json['bibliografia'] as List)
.map((element) => element as Map<String, dynamic>)
.toList()
.map<Book>((element) {
return Book(
title: element['titulo'].toString(),
isbn: element['isbn'].toString(),
);
}).toList();

return Sheet(
professors: professors,
content: json['conteudo'].toString(),
evaluation: json['for_avaliacao'].toString(),
regents: regents,
books: books,
);
}

List<Professor> getCourseUnitProfessors(List<Map<String, dynamic>> ds) {
final professors = <Professor>[];
for (final map in ds) {
for (final docente in map['docentes'] as List<dynamic>) {
final professor = Professor(
code: (docente as Map<String, dynamic>)['doc_codigo'].toString(),
name: shortName(docente['nome'].toString()),
classes: [map['tipo'].toString()],
);
if (professors.contains(professor)) {
professors[professors.indexWhere((element) => element == professor)]
.classes
.add(map['tipo'].toString());
} else {
professors.add(professor);
}
}
}
return professors;
}

Future<CourseUnitSheet> parseCourseUnitSheet(http.Response response) async {
final document = parse(response.body);
final titles = document.querySelectorAll('#conteudoinner h3');
Expand Down Expand Up @@ -121,3 +175,8 @@ String _htmlAfterElement(String body, String elementOuterHtml) {
final index = body.indexOf(elementOuterHtml) + elementOuterHtml.length;
return body.substring(index, body.indexOf('<h3>', index));
}

String shortName(String name) {
final splitName = name.split(' ');
return '${splitName.first} ${splitName.last}';
}
58 changes: 58 additions & 0 deletions uni/lib/model/entities/course_units/sheet.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'dart:io';

import 'package:uni/controller/parsers/parser_course_unit_info.dart';

class Sheet {
Sheet({
required this.professors,
required this.content,
required this.evaluation,
required this.regents,
required this.books,
});
List<Professor> professors;
List<Professor> regents;
String content;
String evaluation;
List<Book> books;
}

class Book {
Book({required this.title, required this.isbn});

String title;
String isbn;
}

class Professor {
Professor({
required this.code,
required this.name,
required this.classes,
this.picture,
});

factory Professor.fromJson(Map<String, dynamic> json) {
return Professor(
code: json['codigo'].toString(),
name: shortName(json['nome'].toString()),
classes: [],
);
}

File? picture;
String code;
String name;
List<String> classes;

@override
bool operator ==(Object other) {
if (other is Professor) {
return other.code == code;
}
return false;
}

@override
int get hashCode => code.hashCode;
}
11 changes: 5 additions & 6 deletions uni/lib/model/providers/lazy/course_units_info_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import 'package:uni/controller/fetchers/course_units_fetcher/course_units_info_f
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';
import 'package:uni/model/entities/course_units/course_unit_sheet.dart';
import 'package:uni/model/entities/course_units/sheet.dart';
import 'package:uni/model/entities/session.dart';
import 'package:uni/model/providers/state_provider_notifier.dart';
import 'package:uni/model/providers/state_providers.dart';

typedef SheetsMap = Map<CourseUnit, CourseUnitSheet>;
typedef SheetsMap = Map<CourseUnit, Sheet>;
typedef ClassesMap = Map<CourseUnit, List<CourseUnitClass>>;
typedef FilesMap = Map<CourseUnit, List<CourseUnitFileDirectory>>;

Expand All @@ -25,7 +25,7 @@ class CourseUnitsInfoProvider
initialState: Tuple3({}, {}, {}),
);

UnmodifiableMapView<CourseUnit, CourseUnitSheet> get courseUnitsSheets =>
UnmodifiableMapView<CourseUnit, Sheet> get courseUnitsSheets =>
UnmodifiableMapView(state!.item1);

UnmodifiableMapView<CourseUnit, List<CourseUnitClass>>
Expand All @@ -38,9 +38,8 @@ class CourseUnitsInfoProvider
CourseUnit courseUnit,
Session session,
) async {
state!.item1[courseUnit] = await CourseUnitsInfoFetcher()
.fetchCourseUnitSheet(session, courseUnit.occurrId);
notifyListeners();
state!.item1[courseUnit] =
await CourseUnitsInfoFetcher().fetchSheet(session, courseUnit.occurrId);
}

Future<void> fetchCourseUnitClasses(
Expand Down
43 changes: 43 additions & 0 deletions uni/lib/view/common_widgets/generic_animated_expandable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';

class AnimatedExpandable extends StatefulWidget {
const AnimatedExpandable({
required this.firstChild,
required this.secondChild,
super.key,
});

final Widget firstChild;
final Widget secondChild;

@override
State<StatefulWidget> createState() {
return AnimatedExpandableState();
}
}

class AnimatedExpandableState extends State<AnimatedExpandable> {
bool _expanded = false;

@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
setState(() {
_expanded = !_expanded;
});
},
child: AnimatedCrossFade(
firstCurve: Curves.easeInOutCubic,
secondCurve: Curves.easeInOut,
sizeCurve: Curves.easeInOut,
duration: const Duration(milliseconds: 500),
firstChild: widget.firstChild,
secondChild: widget.secondChild,
crossFadeState:
_expanded ? CrossFadeState.showSecond : CrossFadeState.showFirst,
),
);
}
}
40 changes: 40 additions & 0 deletions uni/lib/view/common_widgets/generic_expandable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:expandable/expandable.dart';
import 'package:flutter/material.dart';

class GenericExpandable extends StatelessWidget {
const GenericExpandable({
required this.title,
required this.content,
super.key,
});

final String title;
final Widget content;

@override
Widget build(BuildContext context) {
return ExpandablePanel(
header: Align(
alignment: Alignment.centerLeft,
child: Text(title, style: const TextStyle(fontSize: 20)),
),
collapsed: ShaderMask(
shaderCallback: (bounds) => const LinearGradient(
colors: [Colors.black, Colors.transparent],
stops: [0.7, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
).createShader(bounds),
blendMode: BlendMode.dstIn,
child: ClipRect(
child: Align(
alignment: Alignment.topCenter,
heightFactor: 0.25,
child: content,
),
),
),
expanded: content,
);
}
}
3 changes: 1 addition & 2 deletions uni/lib/view/course_unit_info/course_unit_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ class CourseUnitDetailPageViewState
final sheet = context
.read<CourseUnitsInfoProvider>()
.courseUnitsSheets[widget.courseUnit];

if (sheet == null || sheet.sections.isEmpty) {
if (sheet == null) {
return Center(
child: Text(
S.of(context).no_info,
Expand Down
Loading

0 comments on commit 7007b32

Please sign in to comment.