diff --git a/frontend/src/components/UsingRemoteResource.vue b/frontend/src/components/UsingRemoteResource.vue index 5248d7a9..a33e327b 100644 --- a/frontend/src/components/UsingRemoteResource.vue +++ b/frontend/src/components/UsingRemoteResource.vue @@ -35,6 +35,7 @@ diff --git a/frontend/src/i18n/locale/de.json b/frontend/src/i18n/locale/de.json index b9a087fc..13638aaa 100644 --- a/frontend/src/i18n/locale/de.json +++ b/frontend/src/i18n/locale/de.json @@ -1,4 +1,6 @@ { "welcome": "Willkommen", - "error_title": "Fehler" + "error_title": "Fehler", + "previous": "Zurück", + "next": "Weiter" } diff --git a/frontend/src/i18n/locale/en.json b/frontend/src/i18n/locale/en.json index a04b3fa5..3e149759 100644 --- a/frontend/src/i18n/locale/en.json +++ b/frontend/src/i18n/locale/en.json @@ -6,5 +6,7 @@ "classes": "classes", "discussions": "discussions", "logout": "log out", - "error_title": "Error" + "error_title": "Error", + "previous": "Previous", + "next": "Next" } diff --git a/frontend/src/i18n/locale/fr.json b/frontend/src/i18n/locale/fr.json index 1d59c4dd..924dc94b 100644 --- a/frontend/src/i18n/locale/fr.json +++ b/frontend/src/i18n/locale/fr.json @@ -1,4 +1,6 @@ { "welcome": "Bienvenue", - "error_title": "Erreur" + "error_title": "Erreur", + "previous": "Précédente", + "next": "Suivante" } diff --git a/frontend/src/i18n/locale/nl.json b/frontend/src/i18n/locale/nl.json index 576a95b4..8e058396 100644 --- a/frontend/src/i18n/locale/nl.json +++ b/frontend/src/i18n/locale/nl.json @@ -6,5 +6,7 @@ "classes": "klassen", "discussions": "discussies", "logout": "log uit", - "error_title": "Fout" + "error_title": "Fout", + "previous": "Vorige", + "next": "Volgende" } diff --git a/frontend/src/services/learning-content/learning-path-service.ts b/frontend/src/services/learning-content/learning-path-service.ts index 6c0043ad..a0a9f1a9 100644 --- a/frontend/src/services/learning-content/learning-path-service.ts +++ b/frontend/src/services/learning-content/learning-path-service.ts @@ -3,16 +3,21 @@ import {LearningPath, type LearningPathDTO} from "@/services/learning-content/le import type {Language} from "@/services/learning-content/language.ts"; import {single} from "@/utils/response-assertions.ts"; -const learningPathEndpoint = new GetEndpoint<{}, {search?: string, hruid?: string, language?: Language}, LearningPathDTO[]>( - "/learningPath" -); +const learningPathEndpoint = new GetEndpoint< + {}, + {search?: string, hruid?: string, language?: Language, forGroup?: string, forStudent?: string}, + LearningPathDTO[] +>("/learningPath"); export async function searchLearningPaths(query: string): Promise { let dtos = await learningPathEndpoint.get({}, {search: query}) return dtos.map(dto => LearningPath.fromDTO(dto)); } -export async function getLearningPath(hruid: string, language: Language): Promise { - let dtos = await learningPathEndpoint.get({}, {hruid, language}); +export async function getLearningPath(hruid: string, language: Language, options?: {forGroup?: string, forStudent?: string}): Promise { + let dtos = await learningPathEndpoint.get( + {}, + {hruid, language, forGroup: options?.forGroup, forStudent: options?.forStudent} + ); return LearningPath.fromDTO(single(dtos)); } diff --git a/frontend/src/services/learning-content/learning-path.ts b/frontend/src/services/learning-content/learning-path.ts index a07faf9c..2bbef7f2 100644 --- a/frontend/src/services/learning-content/learning-path.ts +++ b/frontend/src/services/learning-content/learning-path.ts @@ -49,7 +49,8 @@ export class LearningPathNode { public readonly language: Language, public readonly transitions: {next: LearningPathNode, default: boolean}[], public readonly createdAt: Date, - public readonly updatedAt: Date + public readonly updatedAt: Date, + public readonly done: boolean = false ) { } @@ -80,6 +81,7 @@ export class LearningPathNode { }), new Date(dto.created_at), new Date(dto.updatedAt), + dto.done ) } } diff --git a/frontend/src/views/learning-paths/LearningPathPage.vue b/frontend/src/views/learning-paths/LearningPathPage.vue index cadc02c0..05f0e116 100644 --- a/frontend/src/views/learning-paths/LearningPathPage.vue +++ b/frontend/src/views/learning-paths/LearningPathPage.vue @@ -2,20 +2,36 @@ import {Language} from "@/services/learning-content/language.ts"; import {getLearningPath} from "@/services/learning-content/learning-path-service.ts"; import UsingRemoteResource from "@/components/UsingRemoteResource.vue"; - import {type LearningPath} from "@/services/learning-content/learning-path.ts"; - import {computed, watch, watchEffect} from "vue"; + import {type LearningPath, LearningPathNode} from "@/services/learning-content/learning-path.ts"; + import {computed, type ComputedRef, watch} from "vue"; import type {LearningObject} from "@/services/learning-content/learning-object.ts"; - import {useRouter} from "vue-router"; + import {useRoute, useRouter} from "vue-router"; import {loadResource, remoteResource, type SuccessState} from "@/services/api-client/remote-resource.ts"; import LearningObjectView from "@/views/learning-paths/LearningObjectView.vue"; + import {useI18n} from "vue-i18n"; const router = useRouter(); + const route = useRoute(); + const { t } = useI18n(); + const props = defineProps<{hruid: string, language: Language, learningObjectHruid?: string}>() + interface QueryParams { + forStudent?: string, + forGroup?: string + } + const learningPathResource = remoteResource(); - watchEffect(() => { - loadResource(learningPathResource, getLearningPath(props.hruid, props.language)); - }); + watch([() => props.hruid, () => props.language, () => route.query.forStudent, () => route.query.forGroup], () => { + loadResource( + learningPathResource, + getLearningPath( + props.hruid, + props.language, + route.query as QueryParams + ) + ) + }, {immediate: true}); const learningObjectListResource = remoteResource(); watch(learningPathResource, () => { @@ -24,12 +40,36 @@ } }, {immediate: true}); - const currentNode = computed(() => { - let currentHruid = props.learningObjectHruid; + const nodesList: ComputedRef = computed(() => { if (learningPathResource.state.type === "success") { - return learningPathResource.state.data.nodesAsList.filter(it => it.learningobjectHruid === currentHruid)[0] + return learningPathResource.state.data.nodesAsList; } else { - return undefined; + return null; + } + }) + + const currentNode = computed(() => { + const currentHruid = props.learningObjectHruid; + if (nodesList.value) { + return nodesList.value.filter(it => it.learningobjectHruid === currentHruid)[0] + } + }); + + const nextNode = computed(() => { + if (!currentNode.value || !nodesList.value) + return; + const currentIndex = nodesList.value?.indexOf(currentNode.value); + if (currentIndex < nodesList.value?.length) { + return nodesList.value?.[currentIndex + 1]; + } + }); + + const previousNode = computed(() => { + if (!currentNode.value || !nodesList.value) + return; + const currentIndex = nodesList.value?.indexOf(currentNode.value); + if (currentIndex < nodesList.value?.length) { + return nodesList.value?.[currentIndex - 1]; } }); @@ -41,6 +81,17 @@ } }); } + + function isLearningObjectCompleted(learningObject: LearningObject): boolean { + if (learningPathResource.state.type === "success") { + return learningPathResource.state.data.nodesAsList.filter(it => + it.learningobjectHruid === learningObject.key + && it.version === learningObject.version + && it.language == learningObject.language + )[0].done; + } + return false; + } @@ -62,9 +113,10 @@ > @@ -80,9 +132,31 @@ :version="currentNode.version" v-if="currentNode" > + + + {{ t("previous") }} + + + {{ t("next") }} + +