From cd80cac6cd08b2994830d963895afdd36dfe9c67 Mon Sep 17 00:00:00 2001 From: Nutthapat Pongtanyavichai Date: Sat, 13 Jul 2024 01:54:42 +0700 Subject: [PATCH] feat: schedule import --- .changeset/rich-grapes-kiss.md | 5 + .../[studyProgram]/schedule/import/index.tsx | 104 ++++++++++-------- 2 files changed, 65 insertions(+), 44 deletions(-) create mode 100644 .changeset/rich-grapes-kiss.md diff --git a/.changeset/rich-grapes-kiss.md b/.changeset/rich-grapes-kiss.md new file mode 100644 index 000000000..de7c54ebb --- /dev/null +++ b/.changeset/rich-grapes-kiss.md @@ -0,0 +1,5 @@ +--- +"web": minor +--- + +feat: schedule import diff --git a/apps/web/src/pages/[studyProgram]/schedule/import/index.tsx b/apps/web/src/pages/[studyProgram]/schedule/import/index.tsx index 6663ccd57..8d89cb81b 100644 --- a/apps/web/src/pages/[studyProgram]/schedule/import/index.tsx +++ b/apps/web/src/pages/[studyProgram]/schedule/import/index.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react' -import { ApolloClient, NormalizedCacheObject, isApolloError } from '@apollo/client' +import { ApolloClient, NormalizedCacheObject } from '@apollo/client' import { observer } from 'mobx-react' import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next' import { useRouter } from 'next/router' @@ -32,9 +32,10 @@ interface ScheduleItem { interface ImportPageProps { items: ScheduleItem[] + errorMessage: string[] } -function ImportSchedulePage({ items }: ImportPageProps) { +function ImportSchedulePage({ items, errorMessage }: ImportPageProps) { const router = useRouter() const { buildLink } = useLinkBuilder() @@ -46,12 +47,29 @@ function ImportSchedulePage({ items }: ImportPageProps) { items.forEach(({ course, sectionNo }) => { courseCartStore.addItem(course, sectionNo) }) - router.replace(buildLink(`/schedule`)) + + if (!errorMessage) router.replace(buildLink(`/schedule`)) } fn() - }, [items, router, buildLink]) + }, [items, router, buildLink, errorMessage]) + + return ( + <> + + + {errorMessage && ( +
+

ERROR

- return +
    + {errorMessage.map((msg, i) => ( +
  • {msg}
  • + ))} +
+
+ )} + + ) } // TODO: research security issues for importing from other 3rd party data sources @@ -69,48 +87,46 @@ export async function getServerSideProps( // notFound: true, // } // } - try { - const client = createApolloServerClient() - const q = context.query - const courseGroup = parseCourseGroup(q) - const itemsQuery = (q.items as string) ?? '' - const rawItems = itemsQuery - .split(',') - .map((it) => { - if (it.length === 0) { - return null - } - const parts = it.split(':') - if (parts.length !== 2) { - throw new Error('expected 2 parts for each item') - } - return { - courseNo: parts[0], - sectionNo: parts[1], - } - }) - .filter((it) => it !== null) as RawScheduleItem[] - console.log({ rawItems, courseGroup }) - const items = await Promise.all( + const client = createApolloServerClient() + const q = context.query + const courseGroup = parseCourseGroup(q) + const itemsQuery = (q.items as string) ?? '' + + const errorMessage: string[] = [] + + const rawItems = itemsQuery + .split(',') + .map((it) => { + if (it.length === 0) { + return null + } + const parts = it.split(':') + if (parts.length !== 2) { + errorMessage.push(`expected 2 parts for each item: ${it}`) + } + return { + courseNo: parts[0], + sectionNo: parts[1], + } + }) + .filter((it) => it !== null) as RawScheduleItem[] + + const items = ( + await Promise.all( rawItems.map((it) => { - console.log({ courseGroup, it }) - return fetchItem(client, courseGroup, it) + return fetchItem(client, courseGroup, it).catch(() => { + errorMessage.push(`error fetching item: ${it.courseNo} ${it.sectionNo}`) + return null + }) }) ) - return { - props: { - items, - }, - } - } catch (e: unknown) { - console.log({ e }) - if (isApolloError(e as Error)) { - return { - notFound: true, - } - } else { - throw e - } + ).filter((x) => x !== null) + + return { + props: { + items, + errorMessage, + }, } }