diff --git a/frontend/src/controllers/learning-paths.ts b/frontend/src/controllers/learning-paths.ts index 15967d28..f1db8b2b 100644 --- a/frontend/src/controllers/learning-paths.ts +++ b/frontend/src/controllers/learning-paths.ts @@ -1,17 +1,19 @@ -import { BaseController } from "@/controllers/base-controller.ts"; -import { LearningPath } from "@/data-objects/learning-paths/learning-path.ts"; -import type { Language } from "@/data-objects/language.ts"; -import { single } from "@/utils/response-assertions.ts"; -import type { LearningPathDTO } from "@/data-objects/learning-paths/learning-path-dto.ts"; +import {BaseController} from "@/controllers/base-controller.ts"; +import {LearningPath} from "@/data-objects/learning-paths/learning-path.ts"; +import type {Language} from "@/data-objects/language.ts"; +import {single} from "@/utils/response-assertions.ts"; +import type {LearningPathDTO} from "@/data-objects/learning-paths/learning-path-dto.ts"; export class LearningPathController extends BaseController { constructor() { super("learningPath"); } + async search(query: string): Promise { - const dtos = await this.get("/", { search: query }); + const dtos = await this.get("/", {search: query}); return dtos.map((dto) => LearningPath.fromDTO(dto)); } + async getBy( hruid: string, language: Language, @@ -25,8 +27,15 @@ export class LearningPathController extends BaseController { }); return LearningPath.fromDTO(single(dtos)); } + async getAllByTheme(theme: string): Promise { - const dtos = await this.get("/", { theme }); + const dtos = await this.get("/", {theme}); + return dtos.map((dto) => LearningPath.fromDTO(dto)); + } + + async getAllLearningPaths(language: string | null = null): Promise { + const query = language ? { language } : undefined; + const dtos = await this.get("/", query); return dtos.map((dto) => LearningPath.fromDTO(dto)); } } diff --git a/frontend/src/queries/assignments.ts b/frontend/src/queries/assignments.ts new file mode 100644 index 00000000..e69de29b diff --git a/frontend/src/queries/learning-paths.ts b/frontend/src/queries/learning-paths.ts index 3d8e6fcf..0ce9cbbd 100644 --- a/frontend/src/queries/learning-paths.ts +++ b/frontend/src/queries/learning-paths.ts @@ -1,8 +1,8 @@ -import { type MaybeRefOrGetter, toValue } from "vue"; -import type { Language } from "@/data-objects/language.ts"; -import { useQuery, type UseQueryReturnType } from "@tanstack/vue-query"; -import { getLearningPathController } from "@/controllers/controllers"; -import type { LearningPath } from "@/data-objects/learning-paths/learning-path.ts"; +import {type MaybeRefOrGetter, toValue} from "vue"; +import type {Language} from "@/data-objects/language.ts"; +import {useQuery, type UseQueryReturnType} from "@tanstack/vue-query"; +import {getLearningPathController} from "@/controllers/controllers"; +import type {LearningPath} from "@/data-objects/learning-paths/learning-path.ts"; const LEARNING_PATH_KEY = "learningPath"; const learningPathController = getLearningPathController(); @@ -44,3 +44,15 @@ export function useSearchLearningPathQuery( enabled: () => Boolean(toValue(query)), }); } + +export function useGetAllLearningPaths(language: MaybeRefOrGetter +): UseQueryReturnType { + return useQuery({ + queryKey: [LEARNING_PATH_KEY, "getAllLearningPaths", language], + queryFn: async () => { + const lang = toValue(language); + return learningPathController.getAllLearningPaths(lang); + }, + enabled: () => Boolean(toValue(language)) + }); +} diff --git a/frontend/src/queries/teachers.ts b/frontend/src/queries/teachers.ts index 778b2cba..e0b0d203 100644 --- a/frontend/src/queries/teachers.ts +++ b/frontend/src/queries/teachers.ts @@ -1,6 +1,6 @@ import { computed, toValue } from "vue"; import type { MaybeRefOrGetter } from "vue"; -import { useMutation, useQuery, useQueryClient, UseMutationReturnType, UseQueryReturnType } from "@tanstack/vue-query"; +import { useMutation, useQuery, useQueryClient, type UseMutationReturnType, type UseQueryReturnType } from "@tanstack/vue-query"; import { TeacherController, type TeacherResponse, type TeachersResponse } from "@/controllers/teachers.ts"; import type { ClassesResponse } from "@/controllers/classes.ts"; import type { JoinRequestResponse, JoinRequestsResponse, StudentsResponse } from "@/controllers/students.ts"; diff --git a/frontend/src/utils/assignmentForm.ts b/frontend/src/utils/assignmentForm.ts index da4d584f..0f5525dd 100644 --- a/frontend/src/utils/assignmentForm.ts +++ b/frontend/src/utils/assignmentForm.ts @@ -1,4 +1,3 @@ - /** * Submits the form data to the backend. * @@ -16,21 +15,21 @@ import type {AssignmentDTO} from "@dwengo-1/common/interfaces/assignment"; export const submitForm = async ( assignmentTitle: string, - selectedLearningPath: any, + selectedLearningPath: string, selectedClass: string, - groups: string[][], + groups: string[], deadline: string, description: string, currentLanguage: string ) => { const formData: AssignmentDTO = { - id: 0, + id: 4, class: selectedClass, title: assignmentTitle, description: description, learningPath: selectedLearningPath, - language: currentLanguage, - groups: [], + language: currentLanguage + //groups: [], //deadline: deadline, }; diff --git a/frontend/src/utils/tempData.ts b/frontend/src/utils/tempData.ts index d49c304e..6ac619d9 100644 --- a/frontend/src/utils/tempData.ts +++ b/frontend/src/utils/tempData.ts @@ -29,7 +29,7 @@ const teacher02: Student = {username: "id12", firstName: "John", lastName: "Hiat const teacher03: Student = {username: "id13", firstName: "Aaron", lastName: "Lewis", classes: []}; const class01: Class = { - id: "34d484a1-295f-4e9f-bfdc-3e7a23d86a89", + id: "8764b861-90a6-42e5-9732-c0d9eb2f55f9", displayName: "class 01", teachers: [teacher01], students: [student01, student02], diff --git a/frontend/src/views/assignments/CreateAssignment.vue b/frontend/src/views/assignments/CreateAssignment.vue index 2e7865c7..1cf03917 100644 --- a/frontend/src/views/assignments/CreateAssignment.vue +++ b/frontend/src/views/assignments/CreateAssignment.vue @@ -2,7 +2,6 @@ import {useI18n} from "vue-i18n"; import {computed, onMounted, ref, watch} from "vue"; import GroupSelector from "@/components/GroupSelector.vue"; - import {classes} from "@/utils/tempData.ts"; import { assignmentTitleRules, classRules, @@ -11,39 +10,80 @@ submitForm } from "@/utils/assignmentForm.ts"; import DeadlineSelector from "@/components/DeadlineSelector.vue"; + import auth from "@/services/auth/auth-service.ts"; + import {useTeacherClassesQuery} from "@/queries/teachers.ts"; + import {useRouter} from "vue-router"; + import {useGetAllLearningPaths} from "@/queries/learning-paths.ts"; + import UsingQueryResult from "@/components/UsingQueryResult.vue"; + import type {LearningPath} from "@/data-objects/learning-paths/learning-path.ts"; + import type {Language} from "@/data-objects/language.ts"; + const router = useRouter(); const {t, locale} = useI18n(); + const role = ref(auth.authState.activeRole); + const username = ref(null); + + onMounted(async () => { + // Redirect student + if (role.value === 'student') { + await router.push('/user'); + } + + // Get the user's username + const user = await auth.loadUser(); + username.value = user?.profile?.preferred_username ?? null; + }); + + + const language = computed(() => locale.value); + //Fetch all learning paths + const learningPathsQueryResults = useGetAllLearningPaths(language); + + watch(language, (newLanguage) => { + console.log(newLanguage); + learningPathsQueryResults.refetch(); + }); + + // Fetch and store all the teacher's classes + const { data: classes, isLoading, error, refetch } = useTeacherClassesQuery(username, true); + const allClasses = computed(() => { + if (isLoading.value) { + return []; + } + if (error.value) { + return []; + } + return classes.value?.classes || []; + }); + const form = ref(); - const language = ref(locale.value); - const searchQuery = ref(''); const assignmentTitle = ref(''); const deadline = ref(null); const description = ref(''); const allLearningPaths = ref([]); - const filteredLearningPaths = ref([]); const selectedLearningPath = ref(null); - const allClasses = ref([...classes.map(cl => ({title: cl.displayName, value: cl.id}))]); const selectedClass = ref(null); const groups = ref([]); const availableClass = computed(() => { //TODO: replace by real data - return classes.find(cl => selectedClass.value?.value === cl.id) || null; + return /*classes.find(cl => selectedClass.value?.value === cl.id) ||*/ null; }); const allStudents = computed(() => { //TODO: replace by real data - if (!selectedClass.value) return []; + /*if (!selectedClass.value) return []; const cl = classes.find(c => c.id === selectedClass.value.value); return cl ? cl.students.map(st => ({ title: `${st.firstName} ${st.lastName}`, value: st.username, classes: cl - })) : []; + })) : [];*/ + return []; }); @@ -54,48 +94,13 @@ } }; - async function fetchAllLearningPaths() { - try { - //TODO: replace by function from controller - const response = await fetch(`http://localhost:3000/api/learningPath?language=${language.value}`); - if (!response.ok) throw new Error("Failed to fetch learning paths"); - const data = await response.json(); - allLearningPaths.value = data.map((lp: { hruid: string; title: string }) => ({ - hruid: lp.hruid, - title: lp.title - })); - filteredLearningPaths.value = [...allLearningPaths.value]; - } catch (error) { - console.error(error); - } - } - - watch( - () => locale.value, - (newLocale) => { - if (!["nl", "en"].includes(newLocale)) { - language.value = "en"; - } - fetchAllLearningPaths(); - }, - {immediate: true} - ); - watch(selectedClass, () => { groups.value = []; }); - const searchResults = computed(() => { - return filteredLearningPaths.value.filter((lp: { hruid: string; title: string }) => - lp.title.toLowerCase().includes(searchQuery.value.toLowerCase()) - ); - }); - - onMounted(fetchAllLearningPaths); - const submitFormHandler = async () => { const { valid } = await form.value.validate(); - // Don't submit thr form if all rules don't apply + // Don't submit the form if all rules don't apply if (!valid) return; submitForm(assignmentTitle.value, selectedLearningPath.value?.hruid, selectedClass.value.value, groups.value, deadline.value, description.value, locale.value); }; @@ -113,23 +118,28 @@ density="compact" variant="outlined" clearable required> - - - + + + + +