Skip to content

Commit

Permalink
feat: courses background task to notify users upcoming classes daily
Browse files Browse the repository at this point in the history
  • Loading branch information
IamMuuo committed Sep 24, 2024
1 parent 294f595 commit bf2d062
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 13 deletions.
24 changes: 24 additions & 0 deletions lib/constants/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,27 @@ double calculateSemesterPercent(DateTime start, DateTime end) {
return percentage;
}
}

// Extension method to convert weekday number to string
extension WeekdayToString on DateTime {
String weekdayToString() {
switch (weekday) {
case DateTime.monday:
return "MONDAY";
case DateTime.tuesday:
return "TUESDAY";
case DateTime.wednesday:
return "WEDNESDAY";
case DateTime.thursday:
return "THURSDAY";
case DateTime.friday:
return "FRIDAY";
case DateTime.saturday:
return "SATURDAY";
case DateTime.sunday:
return "SUNDAY";
default:
return "";
}
}
}
75 changes: 72 additions & 3 deletions lib/models/core/course/course_model.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,64 @@
// /// The course model represents a course just as its name implies
// class Course {
// final String unit;
// final String section;
// final String dayOfWeek;
// final String period;
// final String campus;
// final String room;
// final String lecturer;
//
// Course({
// required this.unit,
// required this.section,
// required this.dayOfWeek,
// required this.period,
// required this.campus,
// required this.room,
// required this.lecturer,
// });
//
// // Method to convert Course instance to a Map (JSON format)
// Map<String, dynamic> toJson() {
// return {
// 'unit': unit,
// 'section': section,
// 'day_of_the_week': dayOfWeek,
// 'period': period,
// 'campus': campus,
// 'room': room,
// 'lecturer': lecturer,
// };
// }
//
// // Static method to create a Course instance from a Map (JSON format)
// static Course fromJson(Map<String, dynamic> json) {
// return Course(
// unit: json['unit'],
// section: json['section'],
// dayOfWeek: json['day_of_the_week'],
// period: json['period'],
// campus: json['campus'],
// room: json['room'],
// lecturer: json['lecturer'],
// );
// }
// }

import 'package:intl/intl.dart';

/// The course model represents a course just as its name implies
class Course {
final String unit;
final String section;
final String dayOfWeek;
final String period;
final String
period; // This contains the time range (e.g., "02:10 PM-05:10 PM")
final String campus;
final String room;
final String lecturer;
late DateTime startTime;
late DateTime stopTime;

Course({
required this.unit,
Expand All @@ -16,7 +68,9 @@ class Course {
required this.campus,
required this.room,
required this.lecturer,
});
}) {
extractTimesFromPeriod(period);
}

// Method to convert Course instance to a Map (JSON format)
Map<String, dynamic> toJson() {
Expand All @@ -28,6 +82,8 @@ class Course {
'campus': campus,
'room': room,
'lecturer': lecturer,
'start_time': startTime.toIso8601String(),
'stop_time': stopTime.toIso8601String(),
};
}

Expand All @@ -41,6 +97,19 @@ class Course {
campus: json['campus'],
room: json['room'],
lecturer: json['lecturer'],
);
)..extractTimesFromPeriod(json['period']);
}

// Private method to extract start and stop times from the period string
void extractTimesFromPeriod(String period) {
// Split the period by the dash ('-')
List<String> times = period.split('-');

// Define a DateFormat to parse the time strings
DateFormat formatter = DateFormat("hh:mm a");

// Parse start and stop times
startTime = formatter.parse(times[0].trim());
stopTime = formatter.parse(times[1].trim());
}
}
1 change: 1 addition & 0 deletions lib/pages/courses/courses.dart
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export 'courses_page.dart';
export 'service/courses_background_service.dart';
37 changes: 37 additions & 0 deletions lib/pages/courses/service/courses_background_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:academia/exports/barrel.dart';
import 'package:academia/models/core/course/course.dart';
import 'package:academia/notifier/local_notification_channel.dart';
import 'package:academia/notifier/local_notification_status_manager.dart';
import 'package:academia/notifier/local_notifier_service.dart';

class CoursesBackgroundService {
static final CoursesBackgroundService _instance =
CoursesBackgroundService._internal();

factory CoursesBackgroundService() {
return _instance;
}

/// Private named constructor that prevents external instantiation.
CoursesBackgroundService._internal();

void notifyTodaysCourses() {
CourseModelHelper().queryAll().then((value) {
int coursestoday = 0;
value.map((e) {
final course = Course.fromJson(e);
if (course.dayOfWeek == DateTime.now().weekdayToString()) {
coursestoday++;
}
});

LocalNotifierService().showNotification(
id: LocalNotificationStatusManager().getNextId(),
title: "Class! Class! Class! ${Emojis.building_school}",
body:
"Hey, you have $coursestoday classes today ${Emojis.smile_face_screaming_in_fear}",
channelKey: LocalNotificationChannelType.reminders.channelKey,
);
});
}
}
4 changes: 3 additions & 1 deletion lib/storage/schemas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ const schemas = <String, String>{
period TEXT NOT NULL,
campus TEXT NOT NULL,
room TEXT NOT NULL,
lecturer TEXT NOT NULL
lecturer TEXT NOT NULL,
start_time TEXT NOT NULL,
stop_time TEXT NOT NULL
);
""",

Expand Down
30 changes: 21 additions & 9 deletions lib/workers/background_worker.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import 'package:academia/exports/barrel.dart';
import 'package:academia/notifier/local_notification_channel.dart';
import 'package:academia/notifier/local_notification_status_manager.dart';
import 'package:academia/notifier/local_notifier_service.dart';

// background services
@pragma('vm:entry-point')
Expand All @@ -11,18 +8,21 @@ void callbackDispatcher() {
case BackgroundConfig.todosIDentifier:
TodoBackgroundService().notifyPendingTasks();
break;
case BackgroundConfig.coursesIDentifier:
CoursesBackgroundService().notifyTodaysCourses();
break;
default:
}
LocalNotifierService().showNotification(
id: LocalNotificationStatusManager().getNextId(),
title: "Dick",
body: "How are you doing pussy",
channelKey: LocalNotificationChannelType.general.channelKey,
);
return Future.value(true);
});
}

Duration timeUntilNextTarget(DateTime targetTime) {
DateTime now = DateTime.now();
Duration difference = targetTime.difference(now);
return difference;
}

class BackgroundWorker {
static final BackgroundWorker _instance = BackgroundWorker._internal();

Expand All @@ -40,6 +40,18 @@ class BackgroundWorker {
isInDebugMode: true,
);

DateTime now = DateTime.now();

/// Courses background service
Workmanager().registerPeriodicTask(
BackgroundConfig.coursesIDentifier,
BackgroundConfig.coursesIDentifier,
initialDelay: timeUntilNextTarget(
DateTime(now.year, now.month, now.day, 12, 0, 0),
),
frequency: const Duration(minutes: 15),
);

/// Todos task that is suppossed to run after every 24 hours at 8 am
Workmanager().registerPeriodicTask(
BackgroundConfig.todosIDentifier,
Expand Down
1 change: 1 addition & 0 deletions lib/workers/workers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export 'background_worker.dart';

class BackgroundConfig {
static const String todosIDentifier = "com.dita.academia.todos";
static const String coursesIDentifier = "com.dita.academia.courses";
}

0 comments on commit bf2d062

Please sign in to comment.