Add single criteria view
This commit is contained in:
parent
e653f915fe
commit
bbc67a8526
|
|
@ -8,9 +8,17 @@ import ItDropdown from "@/components/ui/ItDropdown.vue";
|
|||
import { useAppStore } from "@/stores/app";
|
||||
import { useLearningPathStore } from "@/stores/learningPath";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import type { DropdownListItem } from "@/types";
|
||||
import type { Component } from "vue";
|
||||
import { onMounted, reactive } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
type DropdownActions = "logout" | "settings";
|
||||
|
||||
interface DropdownData {
|
||||
action: DropdownActions;
|
||||
}
|
||||
|
||||
log.debug("MainNavigationBar created");
|
||||
|
||||
const route = useRoute();
|
||||
|
|
@ -46,7 +54,7 @@ function learninPathSlug(): string {
|
|||
return getLearningPathStringProp("slug");
|
||||
}
|
||||
|
||||
function handleDropdownSelect(data) {
|
||||
function handleDropdownSelect(data: DropdownData) {
|
||||
log.debug("Selected action:", data.action);
|
||||
switch (data.action) {
|
||||
case "settings":
|
||||
|
|
@ -56,7 +64,7 @@ function handleDropdownSelect(data) {
|
|||
userStore.handleLogout();
|
||||
break;
|
||||
default:
|
||||
console.log("no action");
|
||||
console.log("No action");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,11 +76,11 @@ onMounted(() => {
|
|||
log.debug("MainNavigationBar mounted");
|
||||
});
|
||||
|
||||
const profileDropdownData = [
|
||||
const profileDropdownData: DropdownListItem[][] = [
|
||||
[
|
||||
{
|
||||
title: "Kontoeinstellungen",
|
||||
icon: IconSettings,
|
||||
icon: IconSettings as Component,
|
||||
data: {
|
||||
action: "settings",
|
||||
},
|
||||
|
|
@ -81,7 +89,7 @@ const profileDropdownData = [
|
|||
[
|
||||
{
|
||||
title: "Abmelden",
|
||||
icon: IconLogout,
|
||||
icon: IconLogout as Component,
|
||||
data: {
|
||||
action: "logout",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,17 +21,18 @@ const togglePerformanceCriteria = () => {
|
|||
<template>
|
||||
<div>
|
||||
<div :class="{ 'pb-8 border-b mb-4': isOpen }" class="-mx-8 px-8">
|
||||
<div class="mb-4 flex flex-row justify-between items-center">
|
||||
<div
|
||||
class="mb-4 flex flex-row justify-between items-center"
|
||||
role="button"
|
||||
aria-pressed="false"
|
||||
@click="togglePerformanceCriteria()"
|
||||
>
|
||||
<h2 class="text-large">
|
||||
{{ competence.competence_id }} {{ competence.title }}
|
||||
</h2>
|
||||
<button class="transition-transform" :class="{ 'rotate-180': isOpen }">
|
||||
<it-icon-arrow-down
|
||||
class="h-10 w-10"
|
||||
aria-hidden="true"
|
||||
@click="togglePerformanceCriteria()"
|
||||
/>
|
||||
</button>
|
||||
<div class="transition-transform" :class="{ 'rotate-180': isOpen }">
|
||||
<it-icon-arrow-down class="h-10 w-10" aria-hidden="true" />
|
||||
</div>
|
||||
</div>
|
||||
<ComptenceProgress
|
||||
:status-count="
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { PerformanceCriteria } from "@/types";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
interface Props {
|
||||
criteria: PerformanceCriteria;
|
||||
|
|
@ -10,6 +11,9 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
criteria: undefined,
|
||||
showState: false,
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const profilePageSlug = route.params["competenceProfilePageSlug"];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -37,7 +41,10 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
</div>
|
||||
</div>
|
||||
<span class="whitespace-nowrap">
|
||||
<router-link class="link" :to="criteria.learning_unit.evaluate_url">
|
||||
<router-link
|
||||
class="link"
|
||||
:to="`/competence/${profilePageSlug}/criteria/${criteria.slug}`"
|
||||
>
|
||||
Sich nochmals einschätzen
|
||||
</router-link>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import LearningContentContainer from "@/components/learningPath/LearningContentContainer.vue";
|
||||
import { useCircleStore } from "@/stores/circle";
|
||||
import type { LearningContent } from "@/types";
|
||||
import * as log from "loglevel";
|
||||
|
|
@ -26,75 +27,58 @@ const block = computed(() => {
|
|||
|
||||
<template>
|
||||
<div v-if="block">
|
||||
<nav class="px-4 lg:px-8 py-4 flex justify-between items-center border-b">
|
||||
<button
|
||||
type="button"
|
||||
class="btn-text inline-flex items-center px-3 py-2"
|
||||
data-cy="close-learning-content"
|
||||
@click="circleStore.closeLearningContent(props.learningContent)"
|
||||
>
|
||||
<it-icon-arrow-left class="-ml-1 mr-1 h-5 w-5"></it-icon-arrow-left>
|
||||
<span class="hidden lg:inline">zurück zum Circle</span>
|
||||
</button>
|
||||
<LearningContentContainer
|
||||
:title="learningContent.title"
|
||||
next-button-text="Abschliessen und weiter"
|
||||
back-text="zurück zum Circle"
|
||||
@back="circleStore.closeLearningContent(props.learningContent)"
|
||||
@next="circleStore.continueFromLearningContent(props.learningContent)"
|
||||
>
|
||||
<div v-if="block.type === 'exercise' || block.type === 'test'" class="h-screen">
|
||||
<iframe width="100%" height="100%" scrolling="no" :src="block.value.url" />
|
||||
</div>
|
||||
|
||||
<h1 class="text-large hidden lg:block" data-cy="ln-title">
|
||||
{{ learningContent.title }}
|
||||
</h1>
|
||||
<div v-else class="container-medium">
|
||||
<div v-if="block.type === 'video'">
|
||||
<iframe
|
||||
class="mt-8 w-full aspect-video"
|
||||
:src="block.value.url"
|
||||
:title="learningContent.title"
|
||||
frameborder="0"
|
||||
allow="accelerometer; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen
|
||||
>
|
||||
</iframe>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn-blue"
|
||||
data-cy="complete-and-continue"
|
||||
@click="circleStore.continueFromLearningContent(props.learningContent)"
|
||||
>
|
||||
Abschliessen und weiter
|
||||
</button>
|
||||
</nav>
|
||||
<div v-else-if="block.type === 'media_library'" class="mt-4 lg:mt-12">
|
||||
<h1>{{ learningContent.title }}</h1>
|
||||
|
||||
<div v-if="block.type === 'exercise' || block.type === 'test'" class="h-screen">
|
||||
<iframe width="100%" height="100%" scrolling="no" :src="block.value.url" />
|
||||
</div>
|
||||
<p class="text-large my-4 lg:my-8">{{ block.value.description }}</p>
|
||||
<router-link
|
||||
:to="`${block.value.url}?back=${route.path}`"
|
||||
class="button btn-primary"
|
||||
>
|
||||
Mediathek öffnen
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<div v-else class="container-medium">
|
||||
<div v-if="block.type === 'video'">
|
||||
<iframe
|
||||
class="mt-8 w-full aspect-video"
|
||||
:src="block.value.url"
|
||||
:title="learningContent.title"
|
||||
frameborder="0"
|
||||
allow="accelerometer; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen
|
||||
<div
|
||||
v-else-if="block.type === 'resource' || block.type === 'assignment'"
|
||||
class="mt-4 lg:mt-12"
|
||||
>
|
||||
</iframe>
|
||||
<p class="text-large my-4">{{ block.value.description }}</p>
|
||||
<div class="resource-text" v-html="block.value.text"></div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="block.type === 'placeholder'" class="mt-4 lg:mt-12">
|
||||
<p class="text-large my-4">{{ block.value.description }}</p>
|
||||
<h1>{{ learningContent.title }}</h1>
|
||||
</div>
|
||||
|
||||
<div v-else class="text-large my-4">{{ block.value.description }}</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="block.type === 'media_library'" class="mt-4 lg:mt-12">
|
||||
<h1>{{ learningContent.title }}</h1>
|
||||
|
||||
<p class="text-large my-4 lg:my-8">{{ block.value.description }}</p>
|
||||
<router-link
|
||||
:to="`${block.value.url}?back=${route.path}`"
|
||||
class="button btn-primary"
|
||||
>
|
||||
Mediathek öffnen
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else-if="block.type === 'resource' || block.type === 'assignment'"
|
||||
class="mt-4 lg:mt-12"
|
||||
>
|
||||
<p class="text-large my-4">{{ block.value.description }}</p>
|
||||
<div class="resource-text" v-html="block.value.text"></div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="block.type === 'placeholder'" class="mt-4 lg:mt-12">
|
||||
<p class="text-large my-4">{{ block.value.description }}</p>
|
||||
<h1>{{ learningContent.title }}</h1>
|
||||
</div>
|
||||
|
||||
<div v-else class="text-large my-4">{{ block.value.description }}</div>
|
||||
</div>
|
||||
</LearningContentContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
<script setup lang="ts">
|
||||
import * as log from "loglevel";
|
||||
|
||||
log.debug("LeariningContentContainer.vue setup");
|
||||
|
||||
const props = defineProps<{
|
||||
backText: string;
|
||||
title: string;
|
||||
nextButtonText: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(["back", "next"]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<nav class="px-4 lg:px-8 py-4 flex justify-between items-center border-b">
|
||||
<button
|
||||
type="button"
|
||||
class="btn-text inline-flex items-center px-3 py-2"
|
||||
@click="$emit('back')"
|
||||
>
|
||||
<it-icon-arrow-left class="-ml-1 mr-1 h-5 w-5"></it-icon-arrow-left>
|
||||
<span class="hidden lg:inline">{{ backText }}</span>
|
||||
</button>
|
||||
|
||||
<h1 class="text-large hidden lg:block" data-cy="ln-title">
|
||||
{{ title }}
|
||||
</h1>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn-blue"
|
||||
data-cy="complete-and-continue"
|
||||
@click="$emit('next')"
|
||||
>
|
||||
{{ nextButtonText }}
|
||||
</button>
|
||||
</nav>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
import { useCircleStore } from "@/stores/circle";
|
||||
import type { LearningUnit } from "@/types";
|
||||
import * as log from "loglevel";
|
||||
|
||||
import LearningContentContainer from "@/components/learningPath/LearningContentContainer.vue";
|
||||
import { computed, reactive } from "vue";
|
||||
|
||||
log.debug("LearningContent.vue setup");
|
||||
|
|
@ -33,79 +35,63 @@ function handleContinue() {
|
|||
|
||||
<template>
|
||||
<div v-if="learningUnit">
|
||||
<nav class="px-4 lg:px-8 py-4 flex justify-between items-center border-b">
|
||||
<button
|
||||
type="button"
|
||||
class="btn-text inline-flex items-center px-3 py-2"
|
||||
@click="circleStore.closeSelfEvaluation(props.learningUnit)"
|
||||
>
|
||||
<it-icon-arrow-left class="-ml-1 mr-1 h-5 w-5"></it-icon-arrow-left>
|
||||
<span class="hidden lg:inline">zurück zum Circle</span>
|
||||
</button>
|
||||
|
||||
<h1 class="text-large hidden lg:block" data-cy="ln-title">
|
||||
Selbsteinschätzung {{ learningUnit.title }}
|
||||
</h1>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn-blue"
|
||||
data-cy="complete-and-continue"
|
||||
@click="handleContinue()"
|
||||
>
|
||||
Weiter
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div class="container-medium">
|
||||
<div class="mt-2 lg:mt-8 text-gray-700">
|
||||
Schritt {{ state.questionIndex + 1 }} von {{ questions.length }}
|
||||
</div>
|
||||
|
||||
<p class="text-large mt-4">
|
||||
Ü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:
|
||||
</p>
|
||||
|
||||
<div class="mt-4 lg:mt-8 p-6 lg:p-12 border">
|
||||
<h2 class="heading-2">
|
||||
{{ currentQuestion.competence_id }} {{ currentQuestion.title }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-4 lg:mt-8 flex flex-col lg:flex-row justify-between gap-6">
|
||||
<button
|
||||
class="flex-1 inline-flex items-center text-left p-4 border"
|
||||
:class="{
|
||||
'border-green-500': currentQuestion.completion_status === 'success',
|
||||
'border-2': currentQuestion.completion_status === 'success',
|
||||
}"
|
||||
data-cy="success"
|
||||
@click="circleStore.markCompletion(currentQuestion, 'success')"
|
||||
>
|
||||
<it-icon-smiley-happy class="w-16 h-16 mr-4"></it-icon-smiley-happy>
|
||||
<span class="font-bold text-large"> Ja, ich kann das. </span>
|
||||
</button>
|
||||
<button
|
||||
class="flex-1 inline-flex items-center text-left p-4 border"
|
||||
:class="{
|
||||
'border-orange-500': currentQuestion.completion_status === 'fail',
|
||||
'border-2': currentQuestion.completion_status === 'fail',
|
||||
}"
|
||||
data-cy="fail"
|
||||
@click="circleStore.markCompletion(currentQuestion, 'fail')"
|
||||
>
|
||||
<it-icon-smiley-thinking class="w-16 h-16 mr-4"></it-icon-smiley-thinking>
|
||||
<span class="font-bold text-xl"> Das muss ich nochmals anschauen. </span>
|
||||
</button>
|
||||
<LearningContentContainer
|
||||
:title="`Selbsteinschätzung ${learningUnit.title}`"
|
||||
:back-text="'zurück zum Circle'"
|
||||
:next-button-text="'Weiter'"
|
||||
@back="circleStore.closeSelfEvaluation(props.learningUnit)"
|
||||
@next="handleContinue()"
|
||||
>
|
||||
<div class="container-medium">
|
||||
<div class="mt-2 lg:mt-8 text-gray-700">
|
||||
Schritt {{ state.questionIndex + 1 }} von {{ questions.length }}
|
||||
</div>
|
||||
|
||||
<div class="mt-6 lg:mt-12">
|
||||
Schau dein Fortschritt in deinem KompetenzNavi: KompetenzNavi öffnen
|
||||
<p class="text-large mt-4">
|
||||
Ü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:
|
||||
</p>
|
||||
|
||||
<div class="mt-4 lg:mt-8 p-6 lg:p-12 border">
|
||||
<h2 class="heading-2">
|
||||
{{ currentQuestion.competence_id }} {{ currentQuestion.title }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-4 lg:mt-8 flex flex-col lg:flex-row justify-between gap-6">
|
||||
<button
|
||||
class="flex-1 inline-flex items-center text-left p-4 border"
|
||||
:class="{
|
||||
'border-green-500': currentQuestion.completion_status === 'success',
|
||||
'border-2': currentQuestion.completion_status === 'success',
|
||||
}"
|
||||
data-cy="success"
|
||||
@click="circleStore.markCompletion(currentQuestion, 'success')"
|
||||
>
|
||||
<it-icon-smiley-happy class="w-16 h-16 mr-4"></it-icon-smiley-happy>
|
||||
<span class="font-bold text-large"> Ja, ich kann das. </span>
|
||||
</button>
|
||||
<button
|
||||
class="flex-1 inline-flex items-center text-left p-4 border"
|
||||
:class="{
|
||||
'border-orange-500': currentQuestion.completion_status === 'fail',
|
||||
'border-2': currentQuestion.completion_status === 'fail',
|
||||
}"
|
||||
data-cy="fail"
|
||||
@click="circleStore.markCompletion(currentQuestion, 'fail')"
|
||||
>
|
||||
<it-icon-smiley-thinking class="w-16 h-16 mr-4"></it-icon-smiley-thinking>
|
||||
<span class="font-bold text-xl"> Das muss ich nochmals anschauen. </span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 lg:mt-12">
|
||||
Schau dein Fortschritt in deinem KompetenzNavi: KompetenzNavi öffnen
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LearningContentContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import type { DropdownListItem } from "@/types";
|
||||
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/vue";
|
||||
|
||||
const props = defineProps<{
|
||||
buttonClasses: [string];
|
||||
listItems: [[object]];
|
||||
listItems: [[DropdownListItem]];
|
||||
align: "left" | "right";
|
||||
}>();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/vue";
|
||||
import { computed, defineEmits } from "vue";
|
||||
import { computed } from "vue";
|
||||
|
||||
interface DropdownSelectable {
|
||||
id: number | string;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,104 @@
|
|||
<script setup lang="ts">
|
||||
import { useCircleStore } from "@/stores/circle";
|
||||
import { useCompetenceStore } from "@/stores/competence";
|
||||
import type { CompetencePage, LearningUnit, PerformanceCriteria } from "@/types";
|
||||
import * as log from "loglevel";
|
||||
|
||||
import LearningContentContainer from "@/components/learningPath/LearningContentContainer.vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
log.debug("SinglePerformanceCriteriaPage.vue setup");
|
||||
|
||||
const competenceStore = useCompetenceStore();
|
||||
const circleStore = useCircleStore();
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
let currentQuestion: PerformanceCriteria | undefined;
|
||||
let competencePage: CompetencePage | undefined;
|
||||
|
||||
const findCriteria = () => {
|
||||
for (const page of competenceStore.competenceProfilePage
|
||||
?.children as CompetencePage[]) {
|
||||
for (let criteria of page.children) {
|
||||
if (criteria.slug === route.params["criteriaSlug"]) {
|
||||
currentQuestion = criteria;
|
||||
competencePage = page;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (competencePage) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
findCriteria();
|
||||
// onMounted(() => {
|
||||
// console.log(route.params)
|
||||
// });
|
||||
|
||||
// const questions = computed(() => props.learningUnit?.children);
|
||||
// const currentQuestion = computed(() => questions.value[state.questionIndex]);
|
||||
//
|
||||
// function handleContinue() {
|
||||
// log.debug("handleContinue");
|
||||
// if (state.questionIndex + 1 < questions.value.length) {
|
||||
// log.debug("increment questionIndex", state.questionIndex);
|
||||
// state.questionIndex += 1;
|
||||
// } else {
|
||||
// log.debug("continue to next learning content");
|
||||
// circleStore.continueFromSelfEvaluation(props.learningUnit);
|
||||
// }
|
||||
// }
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="competencePage" class="absolute top-0 w-full bottom-0 bg-white">
|
||||
<LearningContentContainer
|
||||
:title="''"
|
||||
:back-text="'zurück'"
|
||||
:next-button-text="'Speichern'"
|
||||
@back="router.back()"
|
||||
@next="router.back()"
|
||||
>
|
||||
<div class="container-medium">
|
||||
<div class="mt-4 lg:mt-8 p-6 lg:p-12 border">
|
||||
<h2 class="heading-2">
|
||||
{{ currentQuestion.competence_id }} {{ currentQuestion.title }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-4 lg:mt-8 flex flex-col lg:flex-row justify-between gap-6">
|
||||
<button
|
||||
class="flex-1 inline-flex items-center text-left p-4 border"
|
||||
:class="{
|
||||
'border-green-500': currentQuestion.completion_status === 'success',
|
||||
'border-2': currentQuestion.completion_status === 'success',
|
||||
}"
|
||||
data-cy="success"
|
||||
@click="circleStore.markCompletion(currentQuestion, 'success')"
|
||||
>
|
||||
<it-icon-smiley-happy class="w-16 h-16 mr-4"></it-icon-smiley-happy>
|
||||
<span class="font-bold text-large"> Ja, ich kann das. </span>
|
||||
</button>
|
||||
<button
|
||||
class="flex-1 inline-flex items-center text-left p-4 border"
|
||||
:class="{
|
||||
'border-orange-500': currentQuestion.completion_status === 'fail',
|
||||
'border-2': currentQuestion.completion_status === 'fail',
|
||||
}"
|
||||
data-cy="fail"
|
||||
@click="circleStore.markCompletion(currentQuestion, 'fail')"
|
||||
>
|
||||
<it-icon-smiley-thinking class="w-16 h-16 mr-4"></it-icon-smiley-thinking>
|
||||
<span class="font-bold text-xl"> Das muss ich nochmals anschauen. </span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LearningContentContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
@ -69,6 +69,11 @@ const router = createRouter({
|
|||
path: "criteria",
|
||||
component: () => import("@/pages/competence/PerformanceCriteriaPage.vue"),
|
||||
},
|
||||
{
|
||||
path: "criteria/:criteriaSlug",
|
||||
component: () =>
|
||||
import("@/pages/competence/SinglePerformanceCriteriaPage.vue"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { Circle } from "@/services/circle";
|
||||
import type { Component } from "vue";
|
||||
|
||||
export type CourseCompletionStatus = "unknown" | "fail" | "success";
|
||||
|
||||
|
|
@ -320,3 +321,10 @@ export interface CompetenceProfilePage extends CourseWagtailPage {
|
|||
circles: CircleLight[];
|
||||
children: CompetencePage[];
|
||||
}
|
||||
|
||||
// dropdown
|
||||
export interface DropdownListItem {
|
||||
title: string;
|
||||
icon: Component;
|
||||
data: object;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue