diff --git a/apps/antalmanac/src/components/Header/Import.tsx b/apps/antalmanac/src/components/Header/Import.tsx index 8220b9c66..d0e3e0746 100644 --- a/apps/antalmanac/src/components/Header/Import.tsx +++ b/apps/antalmanac/src/components/Header/Import.tsx @@ -19,14 +19,16 @@ import { ChangeEvent, useCallback, useEffect, useState } from 'react'; import TermSelector from '../RightPane/CoursePane/SearchForm/TermSelector'; import RightPaneStore from '../RightPane/RightPaneStore'; + import { addCustomEvent, openSnackbar } from '$actions/AppStoreActions'; +import { addCourse } from '$actions/AppStoreActions'; import analyticsEnum, { logAnalytics } from '$lib/analytics'; +import { CourseInfo } from '$lib/course_data.types'; +import { QueryZotcourseError } from '$lib/customErrors'; import { warnMultipleTerms } from '$lib/helpers'; -import AppStore from '$stores/AppStore'; import WebSOC from '$lib/websoc'; -import { CourseInfo } from '$lib/course_data.types'; -import { addCourse } from '$actions/AppStoreActions'; -import { ZotCourseResponse, queryZotCourse } from '$lib/zotcourse'; +import { ZotcourseResponse, queryZotcourse } from '$lib/zotcourse'; +import AppStore from '$stores/AppStore'; import { useThemeStore } from '$stores/SettingsStore'; function Import() { @@ -51,34 +53,37 @@ function Import() { const handleSubmit = async () => { const currentSchedule = AppStore.getCurrentScheduleIndex(); - let zotcourseImport: ZotCourseResponse | null = null; - if (importSource === 'zotcourse') { + const isZotcourseImport = importSource === 'zotcourse'; + let sectionCodes: string[] | null = null; + + if (isZotcourseImport) { try { - zotcourseImport = await queryZotCourse(zotcourseScheduleName); + const zotcourseImport: ZotcourseResponse = await queryZotcourse(zotcourseScheduleName); + sectionCodes = zotcourseImport.codes; + for (const event of zotcourseImport.customEvents) { + addCustomEvent(event, [currentSchedule]); + } } catch (e) { - openSnackbar('error', 'Could not import from Zotcourse.'); + if (e instanceof QueryZotcourseError) { + openSnackbar('error', e.message); + } else { + openSnackbar('error', 'Could not import from Zotcourse.'); + } console.error(e); handleClose(); return; } + } else { + // Is importing from Study List + sectionCodes = studyListText.match(/\d{5}/g); } - const sectionCodes = zotcourseImport ? zotcourseImport.codes : studyListText.match(/\d{5}/g); - if (!sectionCodes) { - openSnackbar('error', 'Cannot import an empty/invalid Study List/Zotcourse.'); + openSnackbar('error', `Cannot import an empty ${isZotcourseImport ? 'Zotcourse' : 'Study List'}.`); handleClose(); return; } - // Import Custom Events from Zotcourse - if (zotcourseImport) { - const events = zotcourseImport.customEvents; - for (const event of events) { - addCustomEvent(event, [currentSchedule]); - } - } - try { const sectionsAdded = addCoursesMultiple( await WebSOC.getCourseInfo({ diff --git a/apps/antalmanac/src/lib/customErrors.ts b/apps/antalmanac/src/lib/customErrors.ts new file mode 100644 index 000000000..224e280f7 --- /dev/null +++ b/apps/antalmanac/src/lib/customErrors.ts @@ -0,0 +1,6 @@ +export class QueryZotcourseError extends Error { + constructor(message: string) { + super(message); + this.name = 'QueryZotcourseError'; + } +} diff --git a/apps/antalmanac/src/lib/zotcourse.ts b/apps/antalmanac/src/lib/zotcourse.ts index 276dd1600..cba5df2ef 100644 --- a/apps/antalmanac/src/lib/zotcourse.ts +++ b/apps/antalmanac/src/lib/zotcourse.ts @@ -1,13 +1,18 @@ import { RepeatingCustomEvent } from '@packages/antalmanac-types'; + import trpc from './api/trpc'; +import { QueryZotcourseError } from './customErrors'; + import AppStore from '$stores/AppStore'; -export interface ZotCourseResponse { +export interface ZotcourseResponse { codes: string[]; customEvents: RepeatingCustomEvent[]; } -export async function queryZotCourse(schedule_name: string) { +export async function queryZotcourse(schedule_name: string) { + if (!schedule_name) throw new QueryZotcourseError('Cannot import an empty Zotcourse schedule name'); const response = await trpc.zotcourse.getUserData.mutate({ scheduleName: schedule_name }); + if (!response.success) throw new QueryZotcourseError('Cannot import an invalid Zotcourse'); // For custom event, there is no course attribute in each. const codes = response.data .filter((section: { eventType: number }) => section.eventType === 3)