+ {{ t('new-cycle.body') }} +
+- {{ props.headerText }} -
-+ {{ props.headerText }} +
++ {{ props.text }} +
+{{ props.firstName }} {{ props.lastName }}
diff --git a/Frontend/i18n/locales/de-DE.json b/Frontend/i18n/locales/de-DE.json index c44e747a..ed5fbd91 100644 --- a/Frontend/i18n/locales/de-DE.json +++ b/Frontend/i18n/locales/de-DE.json @@ -19,6 +19,20 @@ }, "admin": { "availableSpots": "Verfügbare Plätze", + "deleteUser": { + "deleteButton": "Benutzer Löschen", + "deleting": "Lösche...", + "description": "Dies setzt das Benutzerkonto vollständig auf den nicht registrierten Zustand zurück, wobei die E-Mail-Adresse für eine erneute Registrierung erhalten bleibt.", + "generalError": "Ein Fehler ist beim Zurücksetzen des Benutzers aufgetreten", + "noUsersFound": "Keine Benutzer gefunden für", + "permissionError": "Berechtigung verweigert - Admin-Benutzer können nicht zurückgesetzt werden", + "searchInstruction": "Tippen Sie, um nach Benutzern zu suchen...", + "searchPlaceholder": "Benutzer nach Name, E-Mail oder Rolle suchen...", + "selectUserError": "Bitte wählen Sie einen Benutzer zum Löschen aus", + "selectedUser": "Ausgewählter Benutzer:", + "title": "Benutzer Löschen", + "userNotFoundError": "Benutzer nicht gefunden" + }, "downloadDescription": "Laden Sie die bestätigten Betreuer-Studenten-Paare herunter", "downloadFileName": "lade confirmed_supervisions.csv herunter", "downloadTitle": "Bestätigte Betreuungen herunterladen", @@ -30,21 +44,7 @@ "uploadSupervisorsFileName": "wähle *.csv aus", "uploadTagsDescription": "Dies aktualisiert die Tags und die Ähnlichkeitswerte", "uploadTagsFileName": "wähle updated_tag_list.json aus", - "waitingStudents": "warten derzeit auf die Genehmigung der Betreuung", - "deleteUser": { - "title": "Benutzer Löschen", - "searchPlaceholder": "Benutzer nach Name, E-Mail oder Rolle suchen...", - "selectedUser": "Ausgewählter Benutzer:", - "noUsersFound": "Keine Benutzer gefunden für", - "searchInstruction": "Tippen Sie, um nach Benutzern zu suchen...", - "description": "Dies setzt das Benutzerkonto vollständig auf den nicht registrierten Zustand zurück, wobei die E-Mail-Adresse für eine erneute Registrierung erhalten bleibt.", - "deleteButton": "Benutzer Löschen", - "deleting": "Lösche...", - "selectUserError": "Bitte wählen Sie einen Benutzer zum Löschen aus", - "generalError": "Ein Fehler ist beim Zurücksetzen des Benutzers aufgetreten", - "permissionError": "Berechtigung verweigert - Admin-Benutzer können nicht zurückgesetzt werden", - "userNotFoundError": "Benutzer nicht gefunden" - } + "waitingStudents": "warten derzeit auf die Genehmigung der Betreuung" }, "appHeader": { "addAdmin": "Admin Hinzufügen", @@ -151,6 +151,10 @@ "supervising": "Sie betreuen {firstName}" }, "dashboard": { + "progress": { + "button": "Profil vervollständigen...", + "text": "Dein Profil ist fast vollständig! Füge die letzten dinge hinzu für die beste SuperWise erfahrung!" + }, "student": { "downloadConfirmation": "Bestätigung herunterladen", "findSupervisor": "Finde jetzt deinen Betreuer!", @@ -383,7 +387,8 @@ }, "noResults": "Keine Suchergebnisse...", "placeholderForStudents": "Betreuer suchen...", - "placeholderForSupervisors": "Studenten suchen..." + "placeholderForSupervisors": "Studenten suchen...", + "placeholderForAdmins": "Benutzer suchen..." }, "searchBar": { "noResults": "Keine Ergebnisse gefunden" @@ -477,4 +482,4 @@ "withdrawRequestFailed": "Fehler beim Zurückziehen der Betreuungsanfrage", "withdrawnRequest": "Sie haben die Betreuungsanfrage zurückgezogen" } -} +} \ No newline at end of file diff --git a/Frontend/i18n/locales/en-GB.json b/Frontend/i18n/locales/en-GB.json index 4ce5d6fb..f0602024 100644 --- a/Frontend/i18n/locales/en-GB.json +++ b/Frontend/i18n/locales/en-GB.json @@ -19,6 +19,20 @@ }, "admin": { "availableSpots": "Available spots", + "deleteUser": { + "deleteButton": "Delete User", + "deleting": "Deleting...", + "description": "This completely resets the user account to unregistered state while preserving email for re-registration.", + "generalError": "An error occurred while resetting the user", + "noUsersFound": "No users found matching", + "permissionError": "Permission denied - cannot reset admin users", + "searchInstruction": "Type to search for users...", + "searchPlaceholder": "Search users by name, email, or role...", + "selectUserError": "Please select a user to delete", + "selectedUser": "Selected User:", + "title": "Delete User", + "userNotFoundError": "User not found" + }, "downloadDescription": "Download the confirmed Supervisor - Student pairs", "downloadFileName": "Download confirmed_supervisions.csv", "downloadTitle": "Download confirmed Supervisions", @@ -30,21 +44,7 @@ "uploadSupervisorsFileName": "select *.csv", "uploadTagsDescription": "This updates the tags and the similarity scores", "uploadTagsFileName": "select updated_tag_list.json", - "waitingStudents": "are currently waiting for supervision approval", - "deleteUser": { - "title": "Delete User", - "searchPlaceholder": "Search users by name, email, or role...", - "selectedUser": "Selected User:", - "noUsersFound": "No users found matching", - "searchInstruction": "Type to search for users...", - "description": "This completely resets the user account to unregistered state while preserving email for re-registration.", - "deleteButton": "Delete User", - "deleting": "Deleting...", - "selectUserError": "Please select a user to delete", - "generalError": "An error occurred while resetting the user", - "permissionError": "Permission denied - cannot reset admin users", - "userNotFoundError": "User not found" - } + "waitingStudents": "are currently waiting for supervision approval" }, "appHeader": { "addAdmin": "Add Admin", @@ -151,6 +151,10 @@ "supervising": "You are supervising {firstName}" }, "dashboard": { + "progress": { + "button": "Complete Profile...", + "text": "Your profile is almost complete! Add the last things for the best experience of SuperWise" + }, "student": { "downloadConfirmation": "Download Confirmation", "findSupervisor": "Find your supervisor now!", @@ -383,7 +387,8 @@ }, "noResults": "No search results...", "placeholderForStudents": "Search supervisor...", - "placeholderForSupervisors": "Search student..." + "placeholderForSupervisors": "Search student...", + "placeholderForAdmins": "Search users..." }, "searchBar": { "noResults": "No results found" diff --git a/Frontend/middleware/01.routing.global.ts b/Frontend/middleware/01.routing.global.ts index 7bf61f25..e5f5220b 100644 --- a/Frontend/middleware/01.routing.global.ts +++ b/Frontend/middleware/01.routing.global.ts @@ -1,101 +1,101 @@ -import {UserRoles} from "#shared/enums/enums"; -import {until} from "@vueuse/core"; +import { UserRoles } from "#shared/enums/enums"; +import { until } from "@vueuse/core"; export default defineNuxtRouteMiddleware(async (to) => { - // ============ USER IS NOT AUTHENTICATED YET ============ + // ============ USER IS NOT AUTHENTICATED YET ============ - // Skip if middleware is running on the server - if (import.meta.server) return + // Skip if middleware is running on the server + if (import.meta.server) return - const authStore = useAuthStore() - await authStore.initialize() - const { user, isSignedIn, isLoaded } = storeToRefs(authStore) - if (!isLoaded.value) { - await until(isLoaded).toBe(true) - } - const registrationStore = useRegistrationStore() + const authStore = useAuthStore() + await authStore.initialize() + const { user, isSignedIn, isLoaded } = storeToRefs(authStore) + if (!isLoaded.value) { + await until(isLoaded).toBe(true) + } + const registrationStore = useRegistrationStore() - // Only allow access to public paths if not signed in - const publicPaths = ['/'] + // Only allow access to public paths if not signed in + const publicPaths = [ '/' ] - if (!isSignedIn.value) { - if (!publicPaths.includes(to.path)) { - return navigateTo('/') + if (!isSignedIn.value) { + if (!publicPaths.includes(to.path)) { + return navigateTo('/') + } + return } - return - } - - const userEmail = user.value?.primaryEmailAddress?.emailAddress; - if (!userEmail) { - return navigateTo('/') - } - // ============ USER IS NOW SIGNED IN ============ - - // Register user if is not already registered - - if (!registrationStore.status || !registrationStore.status.exists || !registrationStore.status.is_registered) { - await registrationStore.fetchRegistrationStatus(userEmail) - } - let userRole = UserRoles.STUDENT - if (registrationStore.status?.role) { - userRole = registrationStore.status.role - } - - const accountRegistrationCompleted = registrationStore.status?.is_registered || false - - if (userRole === UserRoles.ADMIN) { - if (!accountRegistrationCompleted) { - if (!to.path.startsWith('/admin/app-tour')) { - return navigateTo('/admin/app-tour') - } + + const userEmail = user.value?.primaryEmailAddress?.emailAddress; + if (!userEmail) { + return navigateTo('/') } - if (!to.path.startsWith('/admin')) { - return navigateTo('/admin/dashboard') + // ============ USER IS NOW SIGNED IN ============ + + // Register user if is not already registered + + if (!registrationStore.status || !registrationStore.status.exists || !registrationStore.status.is_registered) { + await registrationStore.fetchRegistrationStatus(userEmail) + } + let userRole = UserRoles.STUDENT + if (registrationStore.status?.role) { + userRole = registrationStore.status.role } - return - } - const tagsSelected = registrationStore.status?.tags || false + const accountRegistrationCompleted = registrationStore.status?.is_registered || false + + if (userRole === UserRoles.ADMIN) { + if (!accountRegistrationCompleted) { + if (!to.path.startsWith('/admin/app-tour')) { + return navigateTo('/admin/app-tour') + } + } + if (!to.path.startsWith('/admin') && !to.path.startsWith('/profiles')) { + return navigateTo('/admin/dashboard') + } + return + } - if (!accountRegistrationCompleted && to.path.startsWith('/onboarding')) { - return - } + const tagsSelected = registrationStore.status?.tags || false - if (!accountRegistrationCompleted && !to.path.startsWith('/onboarding')) { - if (userRole === UserRoles.SUPERVISOR) { - return navigateTo('/onboarding/supervisor') - } else { - return navigateTo('/onboarding/student') + if (!accountRegistrationCompleted && to.path.startsWith('/onboarding')) { + return } - } - if ( - accountRegistrationCompleted && - !tagsSelected - ) { - if (!to.path.startsWith(`/onboarding/${userRole.toLowerCase()}`)) { - return navigateTo(`/onboarding/${userRole.toLowerCase()}`) + + if (!accountRegistrationCompleted && !to.path.startsWith('/onboarding')) { + if (userRole === UserRoles.SUPERVISOR) { + return navigateTo('/onboarding/supervisor') + } else { + return navigateTo('/onboarding/student') + } } - return - } - if (accountRegistrationCompleted && tagsSelected && to.path.startsWith('/onboarding')) { - return navigateTo(`/${userRole.toLowerCase()}/dashboard`) - } - - // ============ USER IS NOW REGISTERED AND ONBOARDED ============ - - // make sure only each role-specific route can only be accessed by the corresponding role - if ( - !to.path.startsWith(`/${userRole.toLowerCase()}`) - && !to.path.startsWith('/profiles') && to.path !== '/playground' - ) { - return navigateTo(`/${userRole.toLowerCase()}/dashboard`) - } - - // Redirect signed-in users away from the root - if (to.path === '/') { - if (userRole) { - return navigateTo(`/${userRole.toLowerCase()}/dashboard`) + if ( + accountRegistrationCompleted && + !tagsSelected + ) { + if (!to.path.startsWith(`/onboarding/${ userRole.toLowerCase() }`)) { + return navigateTo(`/onboarding/${ userRole.toLowerCase() }`) + } + return + } + if (accountRegistrationCompleted && tagsSelected && to.path.startsWith('/onboarding')) { + return navigateTo(`/${ userRole.toLowerCase() }/dashboard`) + } + + // ============ USER IS NOW REGISTERED AND ONBOARDED ============ + + // make sure only each role-specific route can only be accessed by the corresponding role + if ( + !to.path.startsWith(`/${ userRole.toLowerCase() }`) + && !to.path.startsWith('/profiles') && to.path !== '/playground' + ) { + return navigateTo(`/${ userRole.toLowerCase() }/dashboard`) + } + + // Redirect signed-in users away from the root + if (to.path === '/') { + if (userRole) { + return navigateTo(`/${ userRole.toLowerCase() }/dashboard`) + } } - } }) diff --git a/Frontend/pages/admin/dashboard.vue b/Frontend/pages/admin/dashboard.vue index cbb938b6..c0f8131b 100644 --- a/Frontend/pages/admin/dashboard.vue +++ b/Frontend/pages/admin/dashboard.vue @@ -1,86 +1,82 @@
{{ t("dashboard.supervisor.slotsFilled") }}
From 5b77c500bf3f98607fc9086f0e64ea3bfef13b82 Mon Sep 17 00:00:00 2001
From: Jonas Beer <115902941+jb-cc@users.noreply.github.com>
Date: Fri, 20 Jun 2025 21:26:17 +0200
Subject: [PATCH 06/11] feature(frontend): Enable supervisors to
accept/dismiss/add as supervisee students from their profile page (SCRUM-275/
SCRUM-308: (#207)
Co-authored-by: Hesham Alhuraibi
Bcx#BI)4s?z^sS4Vwxw~zM~)JvZ~0uY4mR2&Dcz#8ON}YnS@P#`e7fpM
zg0D^VWTTk_r-u@>va1R2qB{Lc(ebOusfLxb?ok-TT4l%?KrPDm*5A9G_7)V0C;9b$
zmxK8VWpH2w=%-GZ{y}$i2U|3VU&fP}clinQanSYJ7or=2u6Nwe;NBW>1^K6@tdp}D
zeZ1&M?DMOrc>phQT(qlAi1-xX%i^?u6Fc^t@HfjmGvW&{J-(#3+6Co99ry#nNbmmP
zfBntf|Df!+UCb_|`7(WNr%wGHMc89ZY1dzB-&rT_PRZ?$4~);a7xn+R^X7SFRNkTd
z27XDRa_lic;YDo(uZh1Cnv-%EX54P$+o}TX38@e4$>fle{8c}c$d`4i>81aM4p>q`l(F8=g(jz5Q=^gY6SRf!hbP)(W0qKOI
zl!P83gpvdh0z_Jn-r)=AeZTKpYu3!Xvu4)JACrHQoadCie`oJ~_TFbd?;dMuFr5XQ
zJ$CFEljehaPmUcs4nKD6FY(hS87*ak=NJtyk7?e!qvvBbUw?o%B?i(I56;A2UplwB
zKly
=CD==RgUJ_n3`#5n9t+x-U`RsHl
zH*@D>VSw!D-Wy1;XGFewgOY2yLD~YxS|)c&sEQtx&jnD(rSDfa(4Ik@NyZsMf?UV)
zmq3%XGX*XIVq?K7w{;J!l0zj;7ElRuhI&7=;|)AfW~m(