-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #69 from IamMuuo/dev
Exam timetable
- Loading branch information
Showing
11 changed files
with
698 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import 'package:hive/hive.dart'; | ||
|
||
part 'exam.g.dart'; // This file will be generated by the build_runner | ||
|
||
@HiveType(typeId: 4) | ||
class Exam { | ||
@HiveField(0) | ||
String courseCode; | ||
|
||
@HiveField(1) | ||
String day; | ||
|
||
@HiveField(2) | ||
String time; | ||
|
||
@HiveField(3) | ||
String venue; | ||
|
||
@HiveField(4) | ||
String hrs; | ||
|
||
@HiveField(5) | ||
String? invigilator; | ||
|
||
@HiveField(6) | ||
String? coordinator; | ||
|
||
@HiveField(7) | ||
String? campus; | ||
|
||
Exam({ | ||
required this.courseCode, | ||
required this.day, | ||
required this.time, | ||
required this.venue, | ||
required this.hrs, | ||
this.invigilator, | ||
this.coordinator, | ||
this.campus, | ||
}); | ||
|
||
// Factory constructor to create an Exam object from a Map | ||
factory Exam.fromJson(Map<String, dynamic> json) { | ||
return Exam( | ||
courseCode: json['course_code'], | ||
day: json['day'], | ||
time: json['time'], | ||
venue: json['venue'], | ||
hrs: json['hrs'], | ||
invigilator: json['invigilator'], | ||
coordinator: json['coordinator'], | ||
campus: json['campus'], | ||
); | ||
} | ||
|
||
// Method to convert an Exam object into a Map | ||
Map<String, dynamic> toJson() { | ||
return { | ||
'course_code': courseCode, | ||
'day': day, | ||
'time': time, | ||
'venue': venue, | ||
'hrs': hrs, | ||
}; | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
160 changes: 119 additions & 41 deletions
160
lib/tools/exam_timetable/exams_timetable_controller.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,139 @@ | ||
import 'package:academia/constants/common.dart'; | ||
import 'package:academia/models/courses.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:academia/exports/barrel.dart'; | ||
import 'package:get/get.dart'; | ||
import 'package:intl/intl.dart'; | ||
|
||
class ExamsTimeTableController extends GetxController { | ||
var index = (-1).obs; | ||
var hasExams = false.obs; | ||
var isLoading = false.obs; | ||
|
||
Future<List<dynamic>> fetchExamTimeTable(String units, | ||
{bool athi = true}) async { | ||
isLoading.value = true; | ||
late List<Map<String, dynamic>> quotes = []; | ||
List<Exam> exams = []; | ||
|
||
Future<void> fetchRandomQuote() async { | ||
try { | ||
var fetchedUnits = await magnet.fetchExamTimeTabale(units); | ||
isLoading.value = false; | ||
|
||
return fetchedUnits; | ||
quotes = await magnet.fetchRandomQuotes(); | ||
index.value = 0; | ||
} catch (e) { | ||
Get.snackbar( | ||
"Oh Snap!", | ||
"Something went wrong while attempting to fetch your exam timetable, please check your network connection and try again", | ||
icon: const Icon( | ||
Icons.network_ping, | ||
), | ||
maxWidth: 500, | ||
showCustomSnackbar( | ||
"Error", | ||
e.toString(), | ||
colorText: Colors.red, | ||
backgroundColor: Colors.grey, | ||
); | ||
debugPrint(e.toString()); | ||
} | ||
} | ||
|
||
isLoading.value = false; | ||
return []; | ||
void nextQuote() { | ||
if (quotes.isNotEmpty && index.value < 49) { | ||
index.value++; | ||
} else if (index.value == 49) { | ||
fetchRandomQuote().then((value) => value); // Do nothing | ||
} | ||
} | ||
|
||
Future<void> addFetchedUnits(List<dynamic> fetchedUnits) async { | ||
await appDB.put("exam_timetable", fetchedUnits); | ||
void previousQuote() { | ||
if (quotes.isNotEmpty && index.value > 0) { | ||
index.value--; | ||
} else if (index.value == 0) { | ||
fetchRandomQuote().then((value) => value); // Do nothing | ||
} | ||
} | ||
|
||
@override | ||
void onInit() async { | ||
debugPrint(appDB.get("exam_timetable").toString()); | ||
|
||
if (true) { | ||
var courses = appDB.get("timetable"); | ||
String payload = ""; | ||
for (Courses c in courses) { | ||
payload = | ||
"$payload ${c.name!.replaceAll("-", " ")}${c.section!.split('-')[0]},"; | ||
} | ||
|
||
debugPrint(payload); | ||
var fetchedUnits = await fetchExamTimeTable(payload.trim()); | ||
await addFetchedUnits(fetchedUnits); | ||
hasExams.value = fetchedUnits.isNotEmpty; | ||
Future<List<Exam>> fetchExams(List<String> units) async { | ||
final examData = (await magnet.fetchExam(units)) | ||
.map((e) => Exam.fromJson(e)) | ||
.toList() | ||
.cast<Exam>(); | ||
|
||
examData.sort((a, b) { | ||
final formatter = DateFormat('EEEE dd/MM/yy'); | ||
final aDate = formatter.parse(a.day.title()); | ||
final bDate = formatter.parse(b.day.title()); | ||
|
||
// Compare the dates first | ||
final dateComparison = aDate.compareTo(bDate); | ||
if (dateComparison != 0) return dateComparison; | ||
|
||
// If the dates are the same, compare the times | ||
final aTimeRange = a.time.split('-'); | ||
final bTimeRange = b.time.split('-'); | ||
final aStartTime = DateFormat('h:mma').parse(aTimeRange[0]); | ||
final bStartTime = DateFormat('h:mma').parse(bTimeRange[0]); | ||
|
||
return aStartTime.compareTo(bStartTime); | ||
}); | ||
|
||
return examData; | ||
} | ||
|
||
Future<void> addExamToStorage(Exam exam) async { | ||
exams = await appDB.get("exams").toList().cast<Exam>(); | ||
exams.add(exam); | ||
exams.sort((a, b) { | ||
final formatter = DateFormat('EEEE dd/MM/yy'); | ||
final aDate = formatter.parse(a.day.title()); | ||
final bDate = formatter.parse(b.day.title()); | ||
|
||
// Compare the dates first | ||
final dateComparison = aDate.compareTo(bDate); | ||
if (dateComparison != 0) return dateComparison; | ||
|
||
// If the dates are the same, compare the times | ||
final aTimeRange = a.time.split('-'); | ||
final bTimeRange = b.time.split('-'); | ||
final aStartTime = DateFormat('h:mma').parse(aTimeRange[0]); | ||
final bStartTime = DateFormat('h:mma').parse(bTimeRange[0]); | ||
|
||
return aStartTime.compareTo(bStartTime); | ||
}); | ||
|
||
await appDB.put("exams", exams); | ||
|
||
// trigger a data refersh | ||
hasExams.value = false; | ||
hasExams.value = true; | ||
} | ||
|
||
Future<void> removeExamFromStorage(Exam exam) async { | ||
exams = await appDB.get("exams").toList().cast<Exam>(); | ||
exams.remove(exam); | ||
|
||
if (exams.isEmpty) { | ||
await appDB.delete("exams"); | ||
// trigger a data refersh | ||
hasExams.value = false; | ||
} else { | ||
await appDB.put("exams", exams); | ||
// trigger a data refersh | ||
hasExams.value = false; | ||
hasExams.value = true; | ||
} | ||
} | ||
|
||
debugPrint("do I have exams : ${hasExams.value}"); | ||
@override | ||
Future<void> onInit() async { | ||
await fetchRandomQuote(); | ||
hasExams.value = false; | ||
|
||
// Check if the local database has exams | ||
if (appDB.containsKey("exams")) { | ||
hasExams.value = true; | ||
// load the exams | ||
exams = await appDB.get("exams").toList().cast<Exam>(); | ||
} else { | ||
// load the units | ||
final List<Courses> courses = | ||
await appDB.get("timetable").toList().cast<Courses>(); | ||
List<String> courseTitles = courses | ||
.map((e) => | ||
"${e.name?.replaceAll('-', '')}${e.section?.split('-')[0]}") | ||
.toList(); | ||
print(courseTitles); | ||
|
||
// fetch from server | ||
exams = await fetchExams(courseTitles); | ||
await appDB.put("exams", exams); | ||
hasExams.value = exams.isNotEmpty; | ||
} | ||
super.onInit(); | ||
} | ||
} |
Oops, something went wrong.