feat: Introduce data manager service with PocketBase authentication and professor dashboard.

This commit is contained in:
Elmar Kresse
2025-11-22 22:46:06 +01:00
parent 5f383f5638
commit f40558646c
7 changed files with 85 additions and 2 deletions

View File

@@ -19,12 +19,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
<script lang="ts" setup>
import { computed, ref, onMounted, onUnmounted } from "vue";
import { useI18n } from "vue-i18n";
import { useToast } from "primevue/usetoast";
import LocaleSwitcher from "./LocaleSwitcher.vue";
import DarkModeSwitcher from "./DarkModeSwitcher.vue";
import { useRoute } from "vue-router";
import { pb, login, logout } from "../service/pocketbase";
const { t } = useI18n({ useScope: "global" });
const toast = useToast();
const route = useRoute();
@@ -98,6 +100,34 @@ const items = computed(() => {
return menuItems;
});
async function handleLogin() {
try {
await login();
toast.add({
severity: 'success',
summary: t('toast.loginSuccess'),
detail: t('toast.loginSuccessDetail'),
life: 3000
});
} catch (error: any) {
if (error?.message && error.message.includes('Login restricted')) {
toast.add({
severity: 'error',
summary: t('toast.loginError'),
detail: t('toast.loginRestricted'),
life: 5000
});
} else {
toast.add({
severity: 'error',
summary: t('toast.loginError'),
detail: error?.message || t('toast.loginErrorDetail'),
life: 5000
});
}
}
}
function handleDarkModeToggled(isDarkVar: boolean) {
// Do something with isDark value
// For example, update the root isDark value
@@ -173,7 +203,7 @@ function handleDarkModeToggled(isDarkVar: boolean) {
label="Login"
icon="pi pi-sign-in"
class="p-button-text"
@click="login"
@click="handleLogin"
/>
<Button
v-else

View File

@@ -9,6 +9,13 @@
"description": "Dein individueller Stundenplan mit Sportevents und Prüfungen. Finde kommende Veranstaltungen oder freie Räume zum Lernen und Arbeiten.",
"english": "Englisch",
"german": "Deutsch",
"toast": {
"loginError": "Login fehlgeschlagen",
"loginRestricted": "Login nur für Mitarbeitende der HTWK Leipzig.",
"loginSuccess": "Login erfolgreich",
"loginSuccessDetail": "Du kannst nun deinen Kalender erstellen.",
"loginErrorDetail": "Fehler beim Login. Bitte versuche es erneut."
},
"courseSelection": {
"headline": "Willkommen beim HTWKalender",
"winterSemester": "Wintersemester",

View File

@@ -9,6 +9,13 @@
"description": "Your individual timetable with sports events and exams. Find upcoming events or free rooms for studying and working.",
"english": "English",
"german": "German",
"toast": {
"loginError": "login failed",
"loginRestricted": "login restricted to htwk employees",
"loginSuccess": "login successful",
"loginSuccessDetail": "you can now create your calendar.",
"loginErrorDetail": "login failed. please try again."
},
"courseSelection": {
"headline": "welcome to HTWKalender",
"winterSemester": "winter semester",

View File

@@ -19,7 +19,7 @@ export const pb = new PocketBase("/");
// Production: https://cal.htwk-leipzig.de/callback
export const login = async () => {
await pb.collection('users').authWithOAuth2({ provider: 'oidc' });
return await pb.collection('users').authWithOAuth2({ provider: 'oidc', scopes: ['openid', 'email', 'profile'] });
}
export const logout = () => {

View File

@@ -68,6 +68,7 @@ onMounted(async () => {
return (b.confidenceScore || 0) - (a.confidenceScore || 0); // Descending order
});
// Clear temporary entries and set actual modules
modules.value = sortedModules;
// Pre-select modules with confidence score >= 0.7 (good match or better)
@@ -77,12 +78,15 @@ onMounted(async () => {
} catch (error: unknown) {
console.error("Failed to fetch modules", error);
const err = error as { status?: number; message?: string };
// Clear temporary entries on error
modules.value = [];
// If unauthorized, redirect to home
if (err.status === 401 || err.message?.includes("401")) {
pb.authStore.clear();
router.push("/");
}
} finally {
// Always disable loading animation
loading.value = false;
}
});