Refactor LearningContent routing

This commit is contained in:
Daniel Egger 2022-09-09 17:36:43 +02:00
parent dc5adb6214
commit 6b0cf9effd
5 changed files with 97 additions and 97 deletions

View File

@ -1,23 +1,28 @@
<script setup lang="ts"> <script setup lang="ts">
import * as log from 'loglevel' import * as log from 'loglevel'
import { computed } from 'vue' import { computed } from 'vue'
import type { LearningContent } from '@/types'
import { useCircleStore } from '@/stores/circle' import { useCircleStore } from '@/stores/circle'
log.debug('LearningContent.vue setup') log.debug('LearningContent.vue setup')
const circleStore = useCircleStore() const circleStore = useCircleStore()
const learningContent = computed(() => circleStore.currentLearningContent) const props = defineProps<{
learningContent: LearningContent
}>()
const block = computed(() => { const block = computed(() => {
if (learningContent.value) { if (props.learningContent?.contents?.length) {
return learningContent.value.contents[0] return props.learningContent.contents[0]
} }
return undefined
}) })
</script> </script>
<template> <template>
<div> <div v-if="block">
<nav class="px-4 lg:px-8 py-4 flex justify-between items-center border-b border-gray-500"> <nav class="px-4 lg:px-8 py-4 flex justify-between items-center border-b border-gray-500">
<button <button
type="button" type="button"
@ -35,7 +40,7 @@ const block = computed(() => {
type="button" type="button"
class="btn-blue" class="btn-blue"
data-cy="complete-and-continue" data-cy="complete-and-continue"
@click="circleStore.continueFromLearningContent()" @click="circleStore.continueFromLearningContent(this.learningContent)"
> >
Abschliessen und weiter Abschliessen und weiter
</button> </button>

View File

@ -1,42 +1,39 @@
<script setup lang="ts"> <script setup lang="ts">
import * as log from 'loglevel'; import * as log from 'loglevel'
import {computed, reactive} from 'vue'; import { computed, reactive } from 'vue'
import {useCircleStore} from '@/stores/circle'; import { useCircleStore } from '@/stores/circle'
import { LearningUnit } from '@/types'
log.debug('LearningContent.vue setup'); log.debug('LearningContent.vue setup')
const circleStore = useCircleStore(); const circleStore = useCircleStore()
const state = reactive({ const state = reactive({
questionIndex: 0, questionIndex: 0,
}); })
const questions = computed(() => circleStore.currentSelfEvaluation!.children); const props = defineProps<{
const currentQuestion = computed(() => questions.value[state.questionIndex]); learningUnit: LearningUnit
}>()
const questions = computed(() => props.learningUnit?.children)
const currentQuestion = computed(() => questions.value[state.questionIndex])
function handleContinue() { function handleContinue() {
log.debug('handleContinue'); log.debug('handleContinue')
if (state.questionIndex + 1 < questions.value.length) { if (state.questionIndex + 1 < questions.value.length) {
log.debug('increment questionIndex', state.questionIndex); log.debug('increment questionIndex', state.questionIndex)
state.questionIndex += 1; state.questionIndex += 1
} else { } else {
log.debug('continue to next learning content'); log.debug('continue to next learning content')
circleStore.continueFromSelfEvaluation(); circleStore.continueFromSelfEvaluation()
} }
} }
</script> </script>
<template> <template>
<div> <div v-if="learningUnit">
<nav <nav class="px-4 lg:px-8 py-4 flex justify-between items-center border-b border-gray-500">
class="
px-4 lg:px-8
py-4
flex justify-between items-center
border-b border-gray-500
"
>
<button <button
type="button" type="button"
class="btn-text inline-flex items-center px-3 py-2 font-normal" class="btn-text inline-flex items-center px-3 py-2 font-normal"
@ -46,24 +43,17 @@ function handleContinue() {
<span class="hidden lg:inline">zurück zum Circle</span> <span class="hidden lg:inline">zurück zum Circle</span>
</button> </button>
<h1 class="text-xl hidden lg:block">{{ circleStore.currentSelfEvaluation.title }}</h1> <h1 class="text-xl hidden lg:block">{{ learningUnit.title }}</h1>
<button <button type="button" class="btn-blue" @click="handleContinue()">Weiter</button>
type="button"
class="btn-blue"
@click="handleContinue()"
>
Weiter
</button>
</nav> </nav>
<div class="mx-auto max-w-6xl px-4 lg:px-8 py-4"> <div class="mx-auto max-w-6xl px-4 lg:px-8 py-4">
<div class="mt-2 lg:mt-8 text-gray-700">Schritt {{ state.questionIndex + 1 }} von {{ questions.length }}</div> <div class="mt-2 lg:mt-8 text-gray-700">Schritt {{ state.questionIndex + 1 }} von {{ questions.length }}</div>
<p class="text-xl mt-4"> <p class="text-xl mt-4">
Überprüfe, ob du in der Lernheinheit <span class="font-bold">"{{ circleStore.currentSelfEvaluation.title }}"</span> alles verstanden hast.<br> Überprüfe, ob du in der Lernheinheit
<span class="font-bold">"{{ learningUnit.title }}"</span> alles verstanden hast.<br />
Lies die folgende Aussage und bewerte sie: Lies die folgende Aussage und bewerte sie:
</p> </p>
@ -81,9 +71,7 @@ function handleContinue() {
}" }"
> >
<it-icon-smiley-happy class="w-16 h-16 mr-4"></it-icon-smiley-happy> <it-icon-smiley-happy class="w-16 h-16 mr-4"></it-icon-smiley-happy>
<span class="font-bold text-xl"> <span class="font-bold text-xl"> Ja, ich kann das. </span>
Ja, ich kann das.
</span>
</button> </button>
<button <button
@click="circleStore.markCompletion(currentQuestion, false)" @click="circleStore.markCompletion(currentQuestion, false)"
@ -95,20 +83,14 @@ function handleContinue() {
}" }"
> >
<it-icon-smiley-thinking class="w-16 h-16 mr-4"></it-icon-smiley-thinking> <it-icon-smiley-thinking class="w-16 h-16 mr-4"></it-icon-smiley-thinking>
<span class="font-bold text-xl"> <span class="font-bold text-xl"> Das muss ich nochmals anschauen. </span>
Das muss ich nochmals anschauen.
</span>
</button> </button>
</div> </div>
<div class="mt-6 lg:mt-12">Schau dein Fortschritt in deinem Kompetenzprofil: Kompetenzprofil öffnen</div> <div class="mt-6 lg:mt-12">Schau dein Fortschritt in deinem Kompetenzprofil: Kompetenzprofil öffnen</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<style scoped> <style scoped></style>
</style>

View File

@ -9,9 +9,6 @@ import { useLearningPathStore } from '@/stores/learningPath'
export type CircleStoreState = { export type CircleStoreState = {
circle: Circle | undefined circle: Circle | undefined
currentLearningContent: LearningContent | undefined
currentSelfEvaluation: LearningUnit | undefined
page: 'INDEX' | 'OVERVIEW' | 'LEARNING_CONTENT' | 'SELF_EVALUATION'
} }
export const useCircleStore = defineStore({ export const useCircleStore = defineStore({
@ -19,9 +16,6 @@ export const useCircleStore = defineStore({
state: () => { state: () => {
return { return {
circle: undefined, circle: undefined,
currentLearningContent: undefined,
currentSelfEvaluation: undefined,
page: 'INDEX',
} as CircleStoreState; } as CircleStoreState;
}, },
getters: { getters: {
@ -45,32 +39,27 @@ export const useCircleStore = defineStore({
}, },
async loadLearningContent(learningPathSlug: string, circleSlug: string, learningContentSlug: string) { async loadLearningContent(learningPathSlug: string, circleSlug: string, learningContentSlug: string) {
const circle = await this.loadCircle(learningPathSlug, circleSlug); const circle = await this.loadCircle(learningPathSlug, circleSlug);
if (circle) { const result = circle.flatLearningContents.find((learningContent) => {
this.currentLearningContent = circle.flatLearningContents.find((learningContent) => { return learningContent.slug.endsWith(learningContentSlug);
return learningContent.slug.endsWith(learningContentSlug); });
});
}
if (!this.currentLearningContent) { if (!result) {
throw `No learning content found with slug: ${learningContentSlug}`; throw `No learning content found with slug: ${learningContentSlug}`;
} }
return this.currentLearningContent; return result
}, },
async loadSelfEvaluation(learningPathSlug: string, circleSlug: string, learningUnitSlug: string) { async loadSelfEvaluation(learningPathSlug: string, circleSlug: string, learningUnitSlug: string) {
const circle = await this.loadCircle(learningPathSlug, circleSlug); const circle = await this.loadCircle(learningPathSlug, circleSlug);
if (circle) { const learningUnit = circle.flatLearningUnits.find((child) => {
this.currentSelfEvaluation = circle.flatLearningUnits.find((child) => { return child.slug.endsWith(learningUnitSlug)
return child.slug.endsWith(learningUnitSlug) });
});
}
if (!this.currentSelfEvaluation) { if (!learningUnit) {
throw `No self evaluation found with slug: ${learningUnitSlug}`; throw `No self evaluation found with slug: ${learningUnitSlug}`;
} }
return this.currentLearningContent; return learningUnit
}, },
async markCompletion(page: LearningContent | LearningUnitQuestion, flag = true) { async markCompletion(page: LearningContent | LearningUnitQuestion, flag = true) {
try { try {
@ -88,7 +77,6 @@ export const useCircleStore = defineStore({
} }
}, },
openLearningContent(learningContent: LearningContent) { openLearningContent(learningContent: LearningContent) {
this.currentLearningContent = learningContent;
const shortSlug = learningContent.slug.replace(`${this.circle?.slug}-lc-`, ''); const shortSlug = learningContent.slug.replace(`${this.circle?.slug}-lc-`, '');
this.router.push({ this.router.push({
path: `${this.circle?.getUrl()}/${shortSlug}`, path: `${this.circle?.getUrl()}/${shortSlug}`,
@ -100,7 +88,6 @@ export const useCircleStore = defineStore({
}); });
}, },
openSelfEvaluation(learningUnit: LearningUnit) { openSelfEvaluation(learningUnit: LearningUnit) {
this.currentSelfEvaluation = learningUnit;
const shortSlug = learningUnit.slug.replace(`${this.circle?.slug}-lu-`, ''); const shortSlug = learningUnit.slug.replace(`${this.circle?.slug}-lu-`, '');
this.router.push({ this.router.push({
path: `${this.circle?.getUrl()}/evaluate/${shortSlug}`, path: `${this.circle?.getUrl()}/evaluate/${shortSlug}`,
@ -122,12 +109,12 @@ export const useCircleStore = defineStore({
} }
return undefined; return undefined;
}, },
continueFromLearningContent() { continueFromLearningContent(currentLearningContent: LearningContent) {
if (this.currentLearningContent) { if (currentLearningContent) {
this.markCompletion(this.currentLearningContent, true); this.markCompletion(currentLearningContent, true);
const nextLearningContent = this.currentLearningContent.nextLearningContent; const nextLearningContent = currentLearningContent.nextLearningContent;
const currentParent = this.currentLearningContent.parentLearningUnit; const currentParent = currentLearningContent.parentLearningUnit;
const nextParent = nextLearningContent?.parentLearningUnit; const nextParent = nextLearningContent?.parentLearningUnit;
if ( if (
@ -138,12 +125,12 @@ export const useCircleStore = defineStore({
// go to self evaluation // go to self evaluation
// this.openSelfEvaluation(currentParent); // this.openSelfEvaluation(currentParent);
this.closeLearningContent(); this.closeLearningContent();
} else if (this.currentLearningContent.nextLearningContent) { } else if (currentLearningContent.nextLearningContent) {
if ( if (
this.currentLearningContent.parentLearningSequence && currentLearningContent.parentLearningSequence &&
this.currentLearningContent.parentLearningSequence.id === nextLearningContent?.parentLearningSequence?.id currentLearningContent.parentLearningSequence.id === nextLearningContent?.parentLearningSequence?.id
) { ) {
this.openLearningContent(this.currentLearningContent.nextLearningContent); this.openLearningContent(currentLearningContent.nextLearningContent);
} else { } else {
this.closeLearningContent(); this.closeLearningContent();
} }

View File

@ -1,10 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import * as log from 'loglevel' import * as log from 'loglevel'
import LearningContent from '@/components/circle/LearningContent.vue' import { onMounted, reactive, watch } from 'vue'
import { onMounted } from 'vue'
import { useCircleStore } from '@/stores/circle' import { useCircleStore } from '@/stores/circle'
import { useAppStore } from '@/stores/app' import { useAppStore } from '@/stores/app'
import LearningContent from '@/components/circle/LearningContent.vue'
import { LearningContent as LearningContentType } from '@/types'
log.debug('LearningContentView created') log.debug('LearningContentView created')
@ -14,27 +14,46 @@ const props = defineProps<{
contentSlug: string contentSlug: string
}>() }>()
const state: { learningContent?: LearningContentType } = reactive({})
const appStore = useAppStore() const appStore = useAppStore()
appStore.showMainNavigationBar = false appStore.showMainNavigationBar = false
const circleStore = useCircleStore() const circleStore = useCircleStore()
onMounted(async () => { const loadLearningContent = async () => {
log.debug('LearningContentView mounted', props.learningPathSlug, props.circleSlug, props.contentSlug)
try { try {
await circleStore.loadLearningContent(props.learningPathSlug, props.circleSlug, props.contentSlug) state.learningContent = await circleStore.loadLearningContent(
props.learningPathSlug,
props.circleSlug,
props.contentSlug
)
} catch (error) { } catch (error) {
log.error(error) log.error(error)
} }
}
watch(
() => props.contentSlug,
async () => {
log.debug(
'LearningContentView props.contentSlug changed',
props.learningPathSlug,
props.circleSlug,
props.contentSlug
)
await loadLearningContent()
}
)
onMounted(async () => {
log.debug('LearningContentView mounted', props.learningPathSlug, props.circleSlug, props.contentSlug)
await loadLearningContent()
}) })
</script> </script>
<template> <template>
<LearningContent <LearningContent v-if="state.learningContent" :learning-content="state.learningContent" />
v-if="circleStore.currentLearningContent"
:key="circleStore.currentLearningContent.translation_key"
/>
</template> </template>
<style lang="postcss" scoped></style> <style lang="postcss" scoped></style>

View File

@ -3,9 +3,10 @@ import * as log from 'loglevel'
import SelfEvaluation from '@/components/circle/SelfEvaluation.vue' import SelfEvaluation from '@/components/circle/SelfEvaluation.vue'
import { onMounted } from 'vue' import { onMounted, reactive } from 'vue'
import { useCircleStore } from '@/stores/circle'
import { useAppStore } from '@/stores/app' import { useAppStore } from '@/stores/app'
import { useCircleStore } from '@/stores/circle'
import type { LearningUnit } from '@/types'
log.debug('LearningUnitSelfEvaluationView created') log.debug('LearningUnitSelfEvaluationView created')
@ -20,11 +21,17 @@ appStore.showMainNavigationBar = false
const circleStore = useCircleStore() const circleStore = useCircleStore()
const state: { learningUnit?: LearningUnit } = reactive({})
onMounted(async () => { onMounted(async () => {
log.debug('LearningUnitSelfEvaluationView mounted', props.learningPathSlug, props.circleSlug, props.learningUnitSlug) log.debug('LearningUnitSelfEvaluationView mounted', props.learningPathSlug, props.circleSlug, props.learningUnitSlug)
try { try {
await circleStore.loadSelfEvaluation(props.learningPathSlug, props.circleSlug, props.learningUnitSlug) state.learningUnit = await circleStore.loadSelfEvaluation(
props.learningPathSlug,
props.circleSlug,
props.learningUnitSlug
)
} catch (error) { } catch (error) {
log.error(error) log.error(error)
} }
@ -32,7 +39,7 @@ onMounted(async () => {
</script> </script>
<template> <template>
<SelfEvaluation v-if="circleStore.currentSelfEvaluation" :key="circleStore.currentSelfEvaluation.translation_key" /> <SelfEvaluation v-if="state.learningUnit" :learning-unit="state.learningUnit" />
</template> </template>
<style lang="postcss" scoped></style> <style lang="postcss" scoped></style>