Add component for learning content

This commit is contained in:
Daniel Egger 2022-06-21 15:58:05 +02:00
parent 9d768c8205
commit b893dcbcc8
7 changed files with 115 additions and 13 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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;
} }
} }
}) })

View File

@ -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>

View File

@ -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>

View File

@ -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')

View File

@ -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
}
} }