Add component for learning content
This commit is contained in:
parent
9d768c8205
commit
b893dcbcc8
|
|
@ -0,0 +1,54 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type {Circle, LearningContent} from '@/types';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
circleData: Circle,
|
||||||
|
learningContent: LearningContent,
|
||||||
|
}>()
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="learningContent">
|
||||||
|
<nav
|
||||||
|
class="
|
||||||
|
px-8
|
||||||
|
py-4
|
||||||
|
lg:flex lg:justify-between lg:items-center
|
||||||
|
border-b border-gray-500
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn-text inline-flex items-center px-3 py-2 font-normal"
|
||||||
|
@click="$emit('close')"
|
||||||
|
>
|
||||||
|
<it-icon-arrow-left class="-ml-1 mr-1 h-5 w-5"></it-icon-arrow-left>
|
||||||
|
<span class="">zurück zum Circle</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<h1 class="text-xl">{{ learningContent.title }}</h1>
|
||||||
|
|
||||||
|
<button type="button" class="btn-blue">Abschliessen und weiter</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="mx-auto max-w-5xl px-8 py-4">
|
||||||
|
<p>{{ learningContent.contents[0].value.description }}</p>
|
||||||
|
|
||||||
|
<iframe
|
||||||
|
class="mt-8 w-full aspect-video"
|
||||||
|
:src="learningContent.contents[0].value.url"
|
||||||
|
:title="learningContent.title"
|
||||||
|
frameborder="0"
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||||
|
allowfullscreen>
|
||||||
|
</iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
|
|
@ -7,13 +7,16 @@ const props = defineProps<{
|
||||||
learningSequence: LearningSequence
|
learningSequence: LearningSequence
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'clickContent', value: LearningContent): void
|
||||||
|
}>()
|
||||||
|
|
||||||
const circleStore = useCircleStore();
|
const circleStore = useCircleStore();
|
||||||
|
|
||||||
function toggleCompleted(learningContent: LearningContent) {
|
function toggleCompleted(learningContent: LearningContent) {
|
||||||
circleStore.toggleCompleted(learningContent, !learningContent.completed);
|
circleStore.toggleCompleted(learningContent, !learningContent.completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -44,7 +47,7 @@ function toggleCompleted(learningContent: LearningContent) {
|
||||||
:modelValue="learningContent.completed"
|
:modelValue="learningContent.completed"
|
||||||
@click="toggleCompleted(learningContent)"
|
@click="toggleCompleted(learningContent)"
|
||||||
>
|
>
|
||||||
{{ learningContent.contents[0].type }}: {{ learningContent.title }}
|
<span @click.stop="$emit('clickContent', learningContent)">{{ learningContent.contents[0].type }}: {{ learningContent.title }}</span>
|
||||||
</ItCheckbox>
|
</ItCheckbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {parseLearningSequences} from '@/services/circle';
|
||||||
export type CircleStoreState = {
|
export type CircleStoreState = {
|
||||||
circleData: Circle;
|
circleData: Circle;
|
||||||
completionData: any;
|
completionData: any;
|
||||||
|
currentLearningContent: LearningContent | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCircleStore = defineStore({
|
export const useCircleStore = defineStore({
|
||||||
|
|
@ -15,6 +16,7 @@ export const useCircleStore = defineStore({
|
||||||
return {
|
return {
|
||||||
circleData: {},
|
circleData: {},
|
||||||
completionData: {},
|
completionData: {},
|
||||||
|
currentLearningContent: undefined,
|
||||||
} as CircleStoreState;
|
} as CircleStoreState;
|
||||||
},
|
},
|
||||||
getters: {},
|
getters: {},
|
||||||
|
|
@ -26,6 +28,9 @@ export const useCircleStore = defineStore({
|
||||||
this.circleData.learningSequences = parseLearningSequences(this.circleData.children);
|
this.circleData.learningSequences = parseLearningSequences(this.circleData.children);
|
||||||
this.completionData = await itGet(`/api/completion/circle/${this.circleData.translation_key}/`);
|
this.completionData = await itGet(`/api/completion/circle/${this.circleData.translation_key}/`);
|
||||||
this.parseCompletionData();
|
this.parseCompletionData();
|
||||||
|
|
||||||
|
// TODO set currentLearningContent for testing
|
||||||
|
this.setCurrentLearningContent(this.circleData.learningSequences[0].learningUnits[0].learningContents[0]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
return error
|
return error
|
||||||
|
|
@ -54,6 +59,9 @@ export const useCircleStore = defineStore({
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
setCurrentLearningContent(learningContent: LearningContent) {
|
||||||
|
this.currentLearningContent = learningContent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import * as log from 'loglevel';
|
||||||
import MainNavigationBar from '@/components/MainNavigationBar.vue';
|
import MainNavigationBar from '@/components/MainNavigationBar.vue';
|
||||||
import LearningSequence from '@/components/circle/LearningSequence.vue';
|
import LearningSequence from '@/components/circle/LearningSequence.vue';
|
||||||
import CircleOverview from '@/components/circle/CircleOverview.vue';
|
import CircleOverview from '@/components/circle/CircleOverview.vue';
|
||||||
|
import LearningContent from '@/components/circle/LearningContent.vue';
|
||||||
|
|
||||||
import {onMounted, reactive} from 'vue'
|
import {onMounted, reactive} from 'vue'
|
||||||
import {useCircleStore} from '@/stores/circle';
|
import {useCircleStore} from '@/stores/circle';
|
||||||
|
|
@ -12,23 +13,42 @@ const props = defineProps<{
|
||||||
circleSlug: string
|
circleSlug: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
page: 'INDEX' | 'OVERVIEW' | 'LEARNING_CONTENT',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const circleStore = useCircleStore();
|
const circleStore = useCircleStore();
|
||||||
|
|
||||||
const state = reactive({
|
const state:State = reactive({
|
||||||
showOverview: false,
|
page: 'LEARNING_CONTENT',
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
log.info('CircleView.vue mounted');
|
log.info('CircleView.vue mounted');
|
||||||
circleStore.loadCircle(props.circleSlug);
|
await circleStore.loadCircle(props.circleSlug);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function openLearningContent(learningContent: LearningContent) {
|
||||||
|
log.info('openLearningContent', learningContent);
|
||||||
|
circleStore.setCurrentLearningContent(learningContent);
|
||||||
|
state.page = 'LEARNING_CONTENT';
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Transition>
|
<Transition>
|
||||||
<div v-if="state.showOverview">
|
<div v-if="state.page === 'OVERVIEW'">
|
||||||
<CircleOverview :circle-data="circleStore.circleData" @close="state.showOverview = false"/>
|
<CircleOverview :circle-data="circleStore.circleData" @close="state.page = 'INDEX'"/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="state.page === 'LEARNING_CONTENT'">
|
||||||
|
<LearningContent
|
||||||
|
:circle-data="circleStore.circleData"
|
||||||
|
:learning-content="circleStore.currentLearningContent"
|
||||||
|
@close="state.page = 'INDEX'"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<MainNavigationBar/>
|
<MainNavigationBar/>
|
||||||
|
|
@ -68,8 +88,9 @@ onMounted(() => {
|
||||||
:key="learningSequence.translation_key"
|
:key="learningSequence.translation_key"
|
||||||
>
|
>
|
||||||
<LearningSequence
|
<LearningSequence
|
||||||
:learning-sequence="learningSequence" @toggleLearningContentCheckbox="toggleLearningContentCheckbox"
|
:learning-sequence="learningSequence"
|
||||||
:completion-data="circleStore.completionData"
|
:completion-data="circleStore.completionData"
|
||||||
|
@click-content="openLearningContent"
|
||||||
></LearningSequence>
|
></LearningSequence>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,7 @@ function colorBgClass(color: string, value: number) {
|
||||||
<button class="btn-primary">Primary</button>
|
<button class="btn-primary">Primary</button>
|
||||||
<button class="btn-secondary">Secondary</button>
|
<button class="btn-secondary">Secondary</button>
|
||||||
<button class="btn-blue">Blue</button>
|
<button class="btn-blue">Blue</button>
|
||||||
|
<button class="btn-text">Text</button>
|
||||||
<a class="btn-primary inline-block" href="/">Primary Link</a>
|
<a class="btn-primary inline-block" href="/">Primary Link</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -223,9 +224,7 @@ function colorBgClass(color: string, value: number) {
|
||||||
<button disabled class="btn-blue">Blue disabled</button>
|
<button disabled class="btn-blue">Blue disabled</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-4 flex-wrap lg:flex-row lg:w-128 content-center lg:justify-start mb-16">
|
<div class="flex flex-col gap-4 flex-wrap lg:flex-row content-center lg:justify-start mb-16">
|
||||||
|
|
||||||
|
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="btn-primary inline-flex items-center p-3 rounded-full">
|
class="btn-primary inline-flex items-center p-3 rounded-full">
|
||||||
<it-icon-message class="h-5 w-5"></it-icon-message>
|
<it-icon-message class="h-5 w-5"></it-icon-message>
|
||||||
|
|
@ -242,6 +241,13 @@ function colorBgClass(color: string, value: number) {
|
||||||
Button text
|
Button text
|
||||||
<it-icon-message class="ml-3 -mr-1 h-5 w-5"></it-icon-message>
|
<it-icon-message class="ml-3 -mr-1 h-5 w-5"></it-icon-message>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button type="button"
|
||||||
|
class="btn-text inline-flex items-center px-3 py-2">
|
||||||
|
<it-icon-message class="-ml-1 mr-3 h-5 w-5"></it-icon-message>
|
||||||
|
Button text
|
||||||
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="mt-8 mb-8">Dropdown (Work-in-progress)</h2>
|
<h2 class="mt-8 mb-8">Dropdown (Work-in-progress)</h2>
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,11 @@ Fachspezialisten bei.
|
||||||
title='Einleitung Circle "Anlayse"',
|
title='Einleitung Circle "Anlayse"',
|
||||||
parent=circe_analyse,
|
parent=circe_analyse,
|
||||||
minutes=15,
|
minutes=15,
|
||||||
contents=[('video', VideoBlockFactory())]
|
contents=[('video', VideoBlockFactory(
|
||||||
|
url='https://www.youtube.com/embed/qhPIfxS2hvI',
|
||||||
|
description='In dieser Circle zeigt dir ein Fachexperte anhand von Kundensituationen, wie du erfolgreich'
|
||||||
|
'den Kundenbedarf ermitteln, analysieren, priorisieren und anschliessend zusammenfassen kannst.'
|
||||||
|
))]
|
||||||
)
|
)
|
||||||
|
|
||||||
LearningSequenceFactory(title='Beobachten', parent=circe_analyse, icon='it-icon-ls-watch')
|
LearningSequenceFactory(title='Beobachten', parent=circe_analyse, icon='it-icon-ls-watch')
|
||||||
|
|
|
||||||
|
|
@ -66,5 +66,11 @@ svg {
|
||||||
hover:bg-sky-400 hover:border-sky-400
|
hover:bg-sky-400 hover:border-sky-400
|
||||||
disabled:opacity-50 disabled:cursor-not-allowed
|
disabled:opacity-50 disabled:cursor-not-allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-text {
|
||||||
|
@apply font-bold py-2 px-4 align-middle inline-block
|
||||||
|
hover:text-gray-700
|
||||||
|
disabled:opacity-50 disabled:cursor-not-allowed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue