From 84809a5f4f49f32492427cd176d5225bec3083b5 Mon Sep 17 00:00:00 2001 From: Linus Bolls Date: Wed, 8 Jan 2025 12:16:20 +0100 Subject: [PATCH 1/2] fix: filter out modules from study plan that failed to load --- components/ModulesListSection.tsx | 24 ++++++++++++++---------- components/Semester.tsx | 7 +++++++ components/SemestersList/index.tsx | 1 + 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/components/ModulesListSection.tsx b/components/ModulesListSection.tsx index 498944e..7084770 100644 --- a/components/ModulesListSection.tsx +++ b/components/ModulesListSection.tsx @@ -16,6 +16,7 @@ export interface ModulesListSectionProps extends Omit { showAddItemButton?: boolean; isHovered?: boolean; isDragInProgress?: boolean; + isLoading?: boolean; onAddItem?: () => void; } @@ -27,6 +28,7 @@ function ModulesListSection({ showAddItemButton = true, isHovered = false, isDragInProgress = false, + isLoading = false, onAddItem, ...rest @@ -116,16 +118,18 @@ function ModulesListSection({ }} > {provided.placeholder} - {modules.map((module, index) => ( - - ))} + {modules + .filter((i) => (isLoading ? true : i.module != null)) + .map((module, index) => ( + + ))} )} diff --git a/components/Semester.tsx b/components/Semester.tsx index d2a3e95..76b3cd8 100644 --- a/components/Semester.tsx +++ b/components/Semester.tsx @@ -20,6 +20,8 @@ export interface SemesterProps { setMouseUpInboxId: (inboxId: string | null) => void; setHoveredInboxId: (inboxId: string | null) => void; + + isLoading?: boolean; } function SemesterCard({ semester, @@ -28,6 +30,7 @@ function SemesterCard({ draggedModules, setMouseUpInboxId, setHoveredInboxId, + isLoading = false, }: SemesterProps) { const [isHovered, setIsHovered] = useState(false); @@ -157,6 +160,7 @@ function SemesterCard({ }} {}} /> setMouseUpInboxId( @@ -204,6 +209,7 @@ function SemesterCard({ disabled={isPastSemester || isstandardDisabled} /> {}} /> setMouseUpInboxId(`droppable:semester:${semester.id}:reassessments`) diff --git a/components/SemestersList/index.tsx b/components/SemestersList/index.tsx index 5ebb6cc..ff7a9e4 100644 --- a/components/SemestersList/index.tsx +++ b/components/SemestersList/index.tsx @@ -128,6 +128,7 @@ export default function SemestersList({ draggedModules={draggedModules} setMouseUpInboxId={setMouseUpInboxId} setHoveredInboxId={setHoveredInboxId} + isLoading={isLoading} /> ))} From f96db48d8fdac6c5bb1d0cfc87893bff1175584b Mon Sep 17 00:00:00 2001 From: Linus Bolls Date: Wed, 8 Jan 2025 12:28:22 +0100 Subject: [PATCH 2/2] feat: button to reset study plan --- app/api/study-plan/route.ts | 22 ++++++++++++++++++++++ components/Header/index.tsx | 12 ++++++++++++ components/Header/useHeader.ts | 14 ++++++++++++++ services/apiClient/index.ts | 16 ++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/app/api/study-plan/route.ts b/app/api/study-plan/route.ts index f65f4f3..bbcd8f3 100644 --- a/app/api/study-plan/route.ts +++ b/app/api/study-plan/route.ts @@ -65,3 +65,25 @@ export async function GET(req: NextRequest) { }); return res; } + +export async function DELETE(req: NextRequest) { + const user = await getUser(req); + + if (!user) { + return NextResponse.json({}, { status: 401 }); + } + + const semesterRepository = AppDataSource.getRepository(Semester); + + const deleteRes = await semesterRepository.delete({ + studyPlan: { + user: { + id: user.id, + }, + }, + }); + if (deleteRes.affected === 0) { + return NextResponse.json({}, { status: 404 }); + } + return NextResponse.json({}, { status: 200 }); +} diff --git a/components/Header/index.tsx b/components/Header/index.tsx index f965976..c211107 100644 --- a/components/Header/index.tsx +++ b/components/Header/index.tsx @@ -3,6 +3,7 @@ import { AuditOutlined, BugOutlined, + DeleteOutlined, ExperimentOutlined, InfoCircleOutlined, PoweroffOutlined, @@ -32,11 +33,13 @@ export interface HeaderProps { avatarUrl: string; } | null; isMobile?: boolean; + onResetStudyPlan?: () => void; } export default function Header({ isLoading = false, user, isMobile = false, + onResetStudyPlan, }: HeaderProps) { return ( , }, + { + key: "4", + label: ( + + ), + icon: , + }, ], }} > diff --git a/components/Header/useHeader.ts b/components/Header/useHeader.ts index c512338..af8d604 100644 --- a/components/Header/useHeader.ts +++ b/components/Header/useHeader.ts @@ -1,8 +1,10 @@ +import useSession from "@/services/apiClient/useSession"; import { useLearningPlatformCurrentUser } from "@/services/learningPlatform/hooks/useLearningPlatformCurrentUser"; import { HeaderProps } from "."; export default function useHeader(): HeaderProps { + const { api } = useSession(); const currentUserQuery = useLearningPlatformCurrentUser(); const avatarUrl = currentUserQuery.data?.me.avatarUrl; @@ -21,8 +23,20 @@ export default function useHeader(): HeaderProps { } : null; + async function onResetStudyPlan() { + try { + await api?.resetStudyPlan(); + + location.reload(); + } catch (err) { + alert((err as Error).message || "Unknown error"); + } + } + return { isLoading: currentUserQuery.isLoading, user, + + onResetStudyPlan, }; } diff --git a/services/apiClient/index.ts b/services/apiClient/index.ts index 7f5096e..717c506 100644 --- a/services/apiClient/index.ts +++ b/services/apiClient/index.ts @@ -74,6 +74,22 @@ export class StudyPlannerApiClient { return data; } + + public async resetStudyPlan(): Promise<{}> { + const res = await fetch(this.url + "/study-plan", { + headers: { + "Content-Type": "application/json", + Authorization: this.accessToken, + }, + method: "DELETE", + }); + if (!res.ok) { + throw new Error(`Failed to reset study plan (code ${res.status})`); + } + const data: {} = await res.json(); + + return data; + } } export type UpdateSemesterModuleInput = Record;