Skip to content

Commit

Permalink
feat: exam timetable done!
Browse files Browse the repository at this point in the history
  • Loading branch information
IamMuuo committed Apr 6, 2024
1 parent 0fa57af commit 1a0624d
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 23 deletions.
23 changes: 12 additions & 11 deletions lib/constants/tools.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@ import 'package:get/get.dart';
import 'package:academia/exports/barrel.dart';

final List<Map<String, dynamic>> allTools = [
{
"id": 8,
"name": "Exam Timetable",
"action": "Show exam timetable",
"image": "assets/images/exam_timetable.png",
"ontap": () {
Get.to(const ExamTimeTablePage());
},
"description":
"Exams around the corner? Don't panic we've got you covered with the timetable",
},

{
"id": 1,
"name": "GPA Calculator",
Expand Down Expand Up @@ -139,17 +151,6 @@ final List<Map<String, dynamic>> allTools = [
"description":
"Curious to know how many classes you have missed this semester, this might be the tool",
},
{
"id": 8,
"name": "Exam Timetable",
"action": "Show exam timetable",
"image": "assets/images/exam_timetable.png",
"ontap": () {
Get.to(const ExamTimeTablePage());
},
"description":
"Exams around the corner? Don't panic we've got you covered with the timetable",
},
{
"id": 9,
"name": "Task Manager",
Expand Down
47 changes: 45 additions & 2 deletions lib/tools/exam_timetable/exams_timetable_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,35 @@ class ExamsTimeTableController extends GetxController {
}

Future<List<Exam>> fetchExams(List<String> units) async {
exams = (await magnet.fetchExam(units))
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());
Expand All @@ -64,7 +88,25 @@ class ExamsTimeTableController extends GetxController {

await appDB.put("exams", exams);

return 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;
}
}

@override
Expand All @@ -89,6 +131,7 @@ class ExamsTimeTableController extends GetxController {

// fetch from server
exams = await fetchExams(courseTitles);
await appDB.put("exams", exams);
hasExams.value = exams.isNotEmpty;
}
super.onInit();
Expand Down
78 changes: 69 additions & 9 deletions lib/tools/exam_timetable/exams_timetable_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,18 @@ class _ExamTimeTablePageState extends State<ExamTimeTablePage> {
final controller = Get.put(ExamsTimeTableController());
final _searchController = TextEditingController();
bool _isSearching = false;
bool _searchComplete = false;
List<Exam> searchedExams = [];

@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
floating: true,
snap: true,
pinned: true,
title: Text(
"Hi ${userController.user.value!.name!.split(' ')[0].title()}",
),
Expand All @@ -35,7 +40,7 @@ class _ExamTimeTablePageState extends State<ExamTimeTablePage> {
Get.defaultDialog(
title: "Academia Help",
content: const Text(
"Never miss an exam again with the intuitive exam timetable",
"Never miss an exam again with the intuitive exam timetable\nDouble tap an exam card to remove it",
),
);
},
Expand All @@ -46,7 +51,7 @@ class _ExamTimeTablePageState extends State<ExamTimeTablePage> {
flexibleSpace: FlexibleSpaceBar(
background: Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primaryContainer,
color: Theme.of(context).colorScheme.tertiaryContainer,
),
padding: const EdgeInsets.all(12),
child: GestureDetector(
Expand Down Expand Up @@ -107,12 +112,17 @@ class _ExamTimeTablePageState extends State<ExamTimeTablePage> {
() => controller.hasExams.value
? ListView.builder(
itemCount: controller.exams.length,
itemBuilder: (context, index) =>
ExamCard(exam: controller.exams[index]),
itemBuilder: (context, index) => GestureDetector(
onDoubleTap: () async {
await controller
.removeExamFromStorage(controller.exams[index]);
},
child: ExamCard(exam: controller.exams[index]),
),
)
: Center(
child: Text(
"Seems you have no exams at the moment 🤞",
"Who dares summon me?🧞",
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
Expand Down Expand Up @@ -162,7 +172,17 @@ class _ExamTimeTablePageState extends State<ExamTimeTablePage> {
if (mounted) {
setState(() {
_isSearching = true;
_searchComplete = false;
});
searchedExams = await controller.fetchExams(
_searchController.text.split(","),
);

if (searchedExams.isNotEmpty) {
setState(() {
_searchComplete = true;
});
}

// await examtimetableController.fetchExams();
if (!mounted) {
Expand All @@ -179,8 +199,7 @@ class _ExamTimeTablePageState extends State<ExamTimeTablePage> {
),
const SizedBox(height: 12),
_isSearching
? const Text("Loading")
: Container(
? Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
Expand All @@ -189,7 +208,7 @@ class _ExamTimeTablePageState extends State<ExamTimeTablePage> {
.tertiaryContainer,
),
child: Text(
"Please input your units seperated with commas and wait for the magic to happen🪄",
"Your wish is my command. Performing forbidden magic 🧞\n Double Tap a course to add it",
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
Expand All @@ -199,7 +218,48 @@ class _ExamTimeTablePageState extends State<ExamTimeTablePage> {
GoogleFonts.figtree().fontFamily,
),
),
),
)
: _searchComplete
? SizedBox(
height:
MediaQuery.of(context).size.height * 0.4,
child: ListView.builder(
itemCount: searchedExams.length,
itemBuilder: (context, index) =>
GestureDetector(
onDoubleTap: () async {
// Add exam
await controller.addExamToStorage(
searchedExams[index]);
searchedExams
.remove(searchedExams[index]);
setState(() {});
},
child: ExamCard(
exam: searchedExams[index],
),
)),
)
: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: Theme.of(context)
.colorScheme
.tertiaryContainer,
),
child: Text(
"Please input your units seperated with commas and let the genie work his forbidden magic!",
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.titleLarge!
.copyWith(
fontFamily:
GoogleFonts.figtree().fontFamily,
),
),
),
],
),
);
Expand Down
2 changes: 1 addition & 1 deletion lib/tools/exam_timetable/widgets/count_down_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class _ExamCountDownWidgetState extends State<ExamCountDownWidget> {
: ExamCard(exam: widget.exam!),
Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primaryContainer,
color: Theme.of(context).colorScheme.tertiaryContainer,
borderRadius: BorderRadius.circular(8)),
width: MediaQuery.of(context).size.width * 0.8,
child: Center(
Expand Down

0 comments on commit 1a0624d

Please sign in to comment.