From 5f383f563878bcd9b05ec4f945d7a5f54c839da0 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sat, 22 Nov 2025 21:38:30 +0100 Subject: [PATCH] feat: add professor dashboard to view and select modules for calendar creation --- frontend/src/api/fetchProfessorModules.ts | 40 +++++++++++++++++++ .../src/view/professor/ProfessorDashboard.vue | 31 +++++--------- 2 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 frontend/src/api/fetchProfessorModules.ts diff --git a/frontend/src/api/fetchProfessorModules.ts b/frontend/src/api/fetchProfessorModules.ts new file mode 100644 index 0000000..932cc0e --- /dev/null +++ b/frontend/src/api/fetchProfessorModules.ts @@ -0,0 +1,40 @@ +export interface ApiModule { + uuid: string; + name: string; + course: string; + eventType?: string; + prof: string; + semester: string; + confidenceScore?: number; +} + +export async function fetchProfessorModules(): Promise { + if (import.meta.env.SSR) { + return []; + } + try { + const { pb } = await import("../service/pocketbase"); + + if (!pb.authStore.isValid || !pb.authStore.token) { + return Promise.reject(new Error("User is not authenticated")); + } + + const response = await fetch("/api/professor/modules", { + method: "GET", + headers: { + "Authorization": pb.authStore.token, + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + const error = new Error(`HTTP error! status: ${response.status}`); + Object.assign(error, { status: response.status }); + throw error; + } + + return await response.json(); + } catch (error) { + return Promise.reject(error); + } +} diff --git a/frontend/src/view/professor/ProfessorDashboard.vue b/frontend/src/view/professor/ProfessorDashboard.vue index a95f0b1..ed006c9 100644 --- a/frontend/src/view/professor/ProfessorDashboard.vue +++ b/frontend/src/view/professor/ProfessorDashboard.vue @@ -13,6 +13,9 @@ import { useRouter } from "vue-router"; const { t } = useI18n({ useScope: "global" }); const router = useRouter(); +import { fetchProfessorModules, type ApiModule } from "../../api/fetchProfessorModules"; + +type ModuleWithScore = Module & { confidenceScore: number }; const modules = ref(new Array(10)); const selectedModules = ref([]); @@ -38,25 +41,10 @@ onMounted(async () => { return; } - console.log("Auth token:", pb.authStore.token); // Debug - - // Make request with explicit Authorization header - const response = await fetch("/api/professor/modules", { - method: "GET", - headers: { - "Authorization": pb.authStore.token, - "Content-Type": "application/json", - }, - }); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const result = await response.json(); + const result = await fetchProfessorModules(); // Convert API response to Module instances with all required fields - const moduleObjects = result.map((apiModule: any) => new Module( + const moduleObjects = result.map((apiModule: ApiModule) => new Module( apiModule.uuid, apiModule.name, apiModule.course, @@ -76,20 +64,21 @@ onMounted(async () => { ...module, confidenceScore: originalData.confidenceScore || 0 }; - }).sort((a: any, b: any) => { + }).sort((a: ModuleWithScore, b: ModuleWithScore) => { return (b.confidenceScore || 0) - (a.confidenceScore || 0); // Descending order }); modules.value = sortedModules; // Pre-select modules with confidence score >= 0.7 (good match or better) - selectedModules.value = sortedModules.filter((m: any) => (m.confidenceScore || 0) >= 0.7); + selectedModules.value = sortedModules.filter((m: ModuleWithScore) => (m.confidenceScore || 0) >= 0.7); console.log("Modules loaded:", modules.value.length, "Pre-selected:", selectedModules.value.length); - } catch (error: any) { + } catch (error: unknown) { console.error("Failed to fetch modules", error); + const err = error as { status?: number; message?: string }; // If unauthorized, redirect to home - if (error.status === 401 || error.message?.includes("401")) { + if (err.status === 401 || err.message?.includes("401")) { pb.authStore.clear(); router.push("/"); }