diff --git a/src/background/handler/userScheduleHandler.ts b/src/background/handler/userScheduleHandler.ts index 8a33fcb5..8ad916ef 100644 --- a/src/background/handler/userScheduleHandler.ts +++ b/src/background/handler/userScheduleHandler.ts @@ -2,7 +2,12 @@ import { MessageHandler } from 'chrome-extension-toolkit'; import { UserScheduleMessages } from 'src/shared/messages/UserScheduleMessages'; import { Course } from 'src/shared/types/Course'; import addCourse from '../lib/addCourse'; +import clearCourses from '../lib/clearCourses'; +import createSchedule from '../lib/createSchedule'; +import deleteSchedule from '../lib/deleteSchedule'; import removeCourse from '../lib/removeCourse'; +import renameSchedule from '../lib/renameSchedule'; +import switchSchedule from '../lib/switchSchedule'; const userScheduleHandler: MessageHandler = { addCourse({ data, sendResponse }) { @@ -11,6 +16,21 @@ const userScheduleHandler: MessageHandler = { removeCourse({ data, sendResponse }) { removeCourse(data.scheduleName, new Course(data.course)).then(sendResponse); }, + clearCourses({ data, sendResponse }) { + clearCourses(data.scheduleName).then(sendResponse); + }, + switchSchedule({ data, sendResponse }) { + switchSchedule(data.scheduleName).then(sendResponse); + }, + createSchedule({ data, sendResponse }) { + createSchedule(data.scheduleName).then(sendResponse); + }, + deleteSchedule({ data, sendResponse }) { + deleteSchedule(data.scheduleName).then(sendResponse); + }, + renameSchedule({ data, sendResponse }) { + renameSchedule(data.scheduleName, data.newName).then(sendResponse); + }, }; export default userScheduleHandler; diff --git a/src/background/lib/addCourse.ts b/src/background/lib/addCourse.ts index 4d0e6bd8..c3d5362b 100644 --- a/src/background/lib/addCourse.ts +++ b/src/background/lib/addCourse.ts @@ -11,7 +11,6 @@ export default async function addCourse(scheduleName: string, course: Course): P throw new Error('Schedule not found'); } - activeSchedule.creditHours += course.creditHours; activeSchedule.courses.push(course); await UserScheduleStore.set('schedules', schedules); diff --git a/src/background/lib/clearCourses.ts b/src/background/lib/clearCourses.ts new file mode 100644 index 00000000..1491693a --- /dev/null +++ b/src/background/lib/clearCourses.ts @@ -0,0 +1,11 @@ +import { UserScheduleStore } from 'src/shared/storage/UserScheduleStore'; + +export default async function clearCourses(scheduleName: string): Promise { + const schedules = await UserScheduleStore.get('schedules'); + const schedule = schedules.find(schedule => schedule.name === scheduleName); + if (!schedule) { + throw new Error(`Schedule ${scheduleName} does not exist`); + } + schedule.courses = []; + await UserScheduleStore.set('schedules', schedules); +} diff --git a/src/background/lib/createSchedule.ts b/src/background/lib/createSchedule.ts index e69de29b..bfe4445b 100644 --- a/src/background/lib/createSchedule.ts +++ b/src/background/lib/createSchedule.ts @@ -0,0 +1,21 @@ +import { UserScheduleStore } from 'src/shared/storage/UserScheduleStore'; + +/** + * Creates a new schedule with the given name + * @param scheduleName the name of the schedule to create + * @returns undefined if successful, otherwise an error message + */ +export default async function createSchedule(scheduleName: string): Promise { + const schedules = await UserScheduleStore.get('schedules'); + if (schedules.find(schedule => schedule.name === scheduleName)) { + return `Schedule ${scheduleName} already exists`; + } + + schedules.push({ + name: scheduleName, + courses: [], + }); + + await UserScheduleStore.set('schedules', schedules); + return undefined; +} diff --git a/src/background/lib/deleteSchedule.ts b/src/background/lib/deleteSchedule.ts new file mode 100644 index 00000000..78d9b0e5 --- /dev/null +++ b/src/background/lib/deleteSchedule.ts @@ -0,0 +1,20 @@ +import { UserScheduleStore } from 'src/shared/storage/UserScheduleStore'; + +export default async function deleteSchedule(scheduleName: string): Promise { + const [schedules, activeIndex] = await Promise.all([ + UserScheduleStore.get('schedules'), + UserScheduleStore.get('activeIndex'), + ]); + + const scheduleIndex = schedules.findIndex(schedule => schedule.name === scheduleName); + if (scheduleIndex === -1) { + return `Schedule ${scheduleName} does not exist`; + } + if (scheduleIndex === activeIndex) { + return 'Cannot delete active schedule'; + } + + schedules.splice(scheduleIndex, 1); + await UserScheduleStore.set('schedules', schedules); + return undefined; +} diff --git a/src/background/lib/removeCourse.ts b/src/background/lib/removeCourse.ts index ca93684d..f6914f7f 100644 --- a/src/background/lib/removeCourse.ts +++ b/src/background/lib/removeCourse.ts @@ -11,7 +11,6 @@ export default async function removeCourse(scheduleName: string, course: Course) throw new Error('Schedule not found'); } - activeSchedule.creditHours -= course.creditHours; activeSchedule.courses = activeSchedule.courses.filter(c => c.uniqueId !== course.uniqueId); await UserScheduleStore.set('schedules', schedules); diff --git a/src/background/lib/renameSchedule.ts b/src/background/lib/renameSchedule.ts new file mode 100644 index 00000000..f33c6c10 --- /dev/null +++ b/src/background/lib/renameSchedule.ts @@ -0,0 +1,17 @@ +import { UserScheduleStore } from 'src/shared/storage/UserScheduleStore'; + +export default async function renameSchedule(scheduleName: string, newName: string): Promise { + const schedules = await UserScheduleStore.get('schedules'); + const scheduleIndex = schedules.findIndex(schedule => schedule.name === scheduleName); + if (scheduleIndex === -1) { + return `Schedule ${scheduleName} does not exist`; + } + if (schedules.find(schedule => schedule.name === newName)) { + return `Schedule ${newName} already exists`; + } + + schedules[scheduleIndex].name = newName; + + await UserScheduleStore.set('schedules', schedules); + return undefined; +} diff --git a/src/background/lib/switchSchedule.ts b/src/background/lib/switchSchedule.ts new file mode 100644 index 00000000..4389d292 --- /dev/null +++ b/src/background/lib/switchSchedule.ts @@ -0,0 +1,12 @@ +import { UserScheduleStore } from 'src/shared/storage/UserScheduleStore'; + +export default async function switchSchedule(scheduleName: string): Promise { + const schedules = await UserScheduleStore.get('schedules'); + + const scheduleIndex = schedules.findIndex(schedule => schedule.name === scheduleName); + if (scheduleIndex === -1) { + throw new Error(`Schedule ${scheduleName} does not exist`); + } + + await UserScheduleStore.set('activeIndex', scheduleIndex); +} diff --git a/src/shared/messages/UserScheduleMessages.ts b/src/shared/messages/UserScheduleMessages.ts index a601a0aa..1332b369 100644 --- a/src/shared/messages/UserScheduleMessages.ts +++ b/src/shared/messages/UserScheduleMessages.ts @@ -1,7 +1,44 @@ import { Course } from '../types/Course'; export interface UserScheduleMessages { + /** + * Add a course to a schedule + * @param data the schedule name and course to add + */ addCourse: (data: { scheduleName: string; course: Course }) => void; - + /** + * Remove a course from a schedule + * @param data the schedule name and course to remove + */ removeCourse: (data: { scheduleName: string; course: Course }) => void; + /** + * Clears all courses from a schedule + * @param data the name of the schedule to clear + */ + clearCourses: (data: { scheduleName: string }) => void; + + /** + * Switches the active schedule to the one specified + * @param data the name of the schedule to switch to + */ + switchSchedule: (data: { scheduleName: string }) => void; + + /** + * Creates a new schedule with the specified name + * @param data the name of the schedule to create + * @returns undefined if successful, otherwise an error message + */ + createSchedule: (data: { scheduleName: string }) => string | undefined; + /** + * Deletes a schedule with the specified name + * @param data the name of the schedule to delete + * @returns undefined if successful, otherwise an error message + */ + deleteSchedule: (data: { scheduleName: string }) => string | undefined; + /** + * Renames a schedule with the specified name + * @param data the name of the schedule to rename and the new name + * @returns undefined if successful, otherwise an error message + */ + renameSchedule: (data: { scheduleName: string; newName: string }) => string | undefined; } diff --git a/src/shared/storage/UserScheduleStore.ts b/src/shared/storage/UserScheduleStore.ts index 618e0f45..64f53586 100644 --- a/src/shared/storage/UserScheduleStore.ts +++ b/src/shared/storage/UserScheduleStore.ts @@ -14,7 +14,6 @@ export const UserScheduleStore = createLocalStore({ new UserSchedule({ courses: [], name: 'Schedule 1', - creditHours: 0, }), ], activeIndex: 0, diff --git a/src/shared/types/UserSchedule.ts b/src/shared/types/UserSchedule.ts index b35e9e26..e91c0780 100644 --- a/src/shared/types/UserSchedule.ts +++ b/src/shared/types/UserSchedule.ts @@ -7,11 +7,9 @@ import { Course } from './Course'; export class UserSchedule { courses: Course[]; name: string; - creditHours: number; constructor(schedule: Serialized) { this.courses = schedule.courses.map(c => new Course(c)); - this.creditHours = this.courses.reduce((acc, course) => acc + course.creditHours, 0); this.name = schedule.name; } diff --git a/src/views/components/PopupMain.tsx b/src/views/components/PopupMain.tsx index 5b90735b..c17cb8fe 100644 --- a/src/views/components/PopupMain.tsx +++ b/src/views/components/PopupMain.tsx @@ -1,6 +1,25 @@ import React from 'react'; +import { bMessenger } from 'src/shared/messages'; +import useSchedules from '../hooks/useSchedules'; +import { Button } from './common/Button/Button'; import ExtensionRoot from './common/ExtensionRoot/ExtensionRoot'; +const { clearCourses } = bMessenger; export default function PopupMain() { - return Popup; + const [activeSchedule, schedules] = useSchedules(); + + // TODO: Add a button to to switch the active schedule + + return ( + + + + ); }