Completion data in Performance Criteria view
This commit is contained in:
parent
dc3b1a4ca6
commit
46ad6cab36
|
|
@ -3,7 +3,7 @@ import type { PerformanceCriteria } from "@/types";
|
|||
|
||||
interface Props {
|
||||
criteria: PerformanceCriteria;
|
||||
showState: boolean;
|
||||
showState?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
|
|
|
|||
|
|
@ -1,95 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { default as PerformanceCriteriaRow } from "@/components/competences/PerformanceCriteriaRow.vue";
|
||||
import { useCompetenceStore } from "@/stores/competence";
|
||||
import type { CourseCompletionStatus } from "@/types";
|
||||
import * as log from "loglevel";
|
||||
import { computed, Ref, ref } from "vue";
|
||||
|
||||
log.debug("CompetencesMainView created");
|
||||
|
||||
enum UserCriteriaState {
|
||||
Open = "open",
|
||||
Done = "done",
|
||||
Nok = "notDone",
|
||||
}
|
||||
|
||||
const competenceStore = useCompetenceStore();
|
||||
|
||||
const data = {
|
||||
id: 340,
|
||||
title: "Kompetenzprofil",
|
||||
slug: "versicherungsvermittlerin-competence",
|
||||
type: "competence.CompetenceProfilePage",
|
||||
translation_key: "a3adb9ac-606d-42fd-b115-842af3706926",
|
||||
course: {
|
||||
id: -1,
|
||||
title: "Versicherungsvermittler/in",
|
||||
category_name: "Handlungsfeld",
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 341,
|
||||
title:
|
||||
"Innerhalb des Handlungsfelds «Fahrzeug» bin ich fähig, die Ziele und Pläne des Kunden zu ergründen (SOLL).",
|
||||
slug: "kompetenzprofil-crit-innerhalb-des-handlungsfelds-fahrzeug-bin-ich-fähig-die-ziele-und-pläne-des-kunden-zu-ergründen-soll",
|
||||
type: "competence.PerformanceCriteria",
|
||||
translation_key: "e4aeeb81-0730-44f5-9c70-cec84d162569",
|
||||
pc_id: "B1.3 Fahrzeug",
|
||||
learning_unit: {
|
||||
id: 123,
|
||||
title: "Auto verkaufen",
|
||||
slug: "versicherungsvermittlerin-lp-circle-analyse-lu-fahrzeug",
|
||||
type: "learnpath.LearningUnit",
|
||||
translation_key: "c4797663-90c3-493f-9f21-e95ad0a37eb2",
|
||||
},
|
||||
circle: "Analyse",
|
||||
},
|
||||
{
|
||||
id: 342,
|
||||
title:
|
||||
"Innerhalb des Handlungsfelds «Fahrzeug» bin ich fähig, die IST-Situation des Kunden mit der geeigneten Gesprächs-/Fragetechnik zu erfassen.",
|
||||
slug: "kompetenzprofil-crit-innerhalb-des-handlungsfelds-fahrzeug-bin-ich-fähig-die-ist-situation-des-kunden-mit-der-geeigneten-gesprächs-fragetechnik-zu-erfassen",
|
||||
type: "competence.PerformanceCriteria",
|
||||
translation_key: "25d56b74-4151-49bd-ac1f-5e706a660aae",
|
||||
pc_id: "B2.1 Fahrzeug",
|
||||
learning_unit: {
|
||||
id: 123,
|
||||
title: "Auto verkaufen",
|
||||
slug: "versicherungsvermittlerin-lp-circle-analyse-lu-fahrzeug",
|
||||
type: "learnpath.LearningUnit",
|
||||
translation_key: "c4797663-90c3-493f-9f21-e95ad0a37eb2",
|
||||
},
|
||||
circle: "Analyse",
|
||||
},
|
||||
{
|
||||
id: 343,
|
||||
title:
|
||||
"Innerhalb des Handlungsfelds «Fahrzeug» bin ich fähig, die Risiken aufzuzeigen.",
|
||||
slug: "kompetenzprofil-crit-innerhalb-des-handlungsfelds-fahrzeug-bin-ich-fähig-die-risiken-aufzuzeigen",
|
||||
type: "competence.PerformanceCriteria",
|
||||
translation_key: "71bfb708-70c7-4e50-a424-104fe10ab7bc",
|
||||
pc_id: "B2.2 Fahrzeug",
|
||||
learning_unit: {
|
||||
id: 123,
|
||||
title: "Auto verkaufen",
|
||||
slug: "versicherungsvermittlerin-lp-circle-analyse-lu-fahrzeug",
|
||||
type: "learnpath.LearningUnit",
|
||||
translation_key: "c4797663-90c3-493f-9f21-e95ad0a37eb2",
|
||||
},
|
||||
circle: "Analyse",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const userProgress = {
|
||||
341: "open",
|
||||
342: "notDone",
|
||||
343: "done",
|
||||
};
|
||||
|
||||
const activeState: Ref<UserCriteriaState> = ref(UserCriteriaState.Nok);
|
||||
const activeState: Ref<CourseCompletionStatus> = ref("fail");
|
||||
|
||||
const shownCriteria = computed(() => {
|
||||
return competenceStore.flatPerformanceCriteria;
|
||||
return competenceStore.flatPerformanceCriteria.filter((criteria) => {
|
||||
return criteria.completion_status === activeState.value;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
@ -112,25 +37,25 @@ const shownCriteria = computed(() => {
|
|||
class="border-b border-gray-500 flex flex-col lg:flex-row lg:items-center pb-4 mb-4"
|
||||
>
|
||||
<button
|
||||
:class="{ 'bg-gray-200': activeState === UserCriteriaState.Nok }"
|
||||
:class="{ 'bg-gray-200': activeState === 'fail' }"
|
||||
class="flex flex-row items-center py-4 px-2 mr-6"
|
||||
@click="activeState = UserCriteriaState.Nok"
|
||||
@click="activeState = 'fail'"
|
||||
>
|
||||
<span class="inline-block mr-2">«Das muss ich nochmals anschauen»</span>
|
||||
<span><it-icon-smiley-thinking></it-icon-smiley-thinking></span>
|
||||
</button>
|
||||
<button
|
||||
:class="{ 'bg-gray-200': activeState === UserCriteriaState.Done }"
|
||||
:class="{ 'bg-gray-200': activeState === 'success' }"
|
||||
class="flex flex-row items-center py-4 px-2 mr-6"
|
||||
@click="activeState = UserCriteriaState.Done"
|
||||
@click="activeState = 'success'"
|
||||
>
|
||||
<span class="inline-block mr-2">«Ja, ich kann das»</span>
|
||||
<span><it-icon-smiley-happy></it-icon-smiley-happy></span>
|
||||
</button>
|
||||
<button
|
||||
:class="{ 'bg-gray-200': activeState === UserCriteriaState.Open }"
|
||||
:class="{ 'bg-gray-200': activeState === 'unknown' }"
|
||||
class="flex flex-row items-center py-4 px-2"
|
||||
@click="activeState = UserCriteriaState.Open"
|
||||
@click="activeState = 'unknown'"
|
||||
>
|
||||
<span class="inline-block mr-2">Nicht eingeschätzt</span>
|
||||
<span><it-icon-smiley-neutral></it-icon-smiley-neutral></span>
|
||||
|
|
@ -139,10 +64,13 @@ const shownCriteria = computed(() => {
|
|||
<ul class="mb-6">
|
||||
<li
|
||||
v-for="criteria in shownCriteria"
|
||||
:key="criteria.title"
|
||||
:key="criteria.id"
|
||||
class="mb-4 pb-4 border-b border-gray-500"
|
||||
>
|
||||
<PerformanceCriteriaRow :criteria="criteria"> </PerformanceCriteriaRow>
|
||||
<PerformanceCriteriaRow
|
||||
:criteria="criteria"
|
||||
:show-state="true"
|
||||
></PerformanceCriteriaRow>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import * as log from "loglevel";
|
||||
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
import { itPost } from "@/fetchHelpers";
|
||||
import type { Circle } from "@/services/circle";
|
||||
import { useCompletionStore } from "@/stores/completion";
|
||||
import { useLearningPathStore } from "@/stores/learningPath";
|
||||
import type {
|
||||
CourseCompletionStatus,
|
||||
|
|
@ -11,6 +9,7 @@ import type {
|
|||
LearningUnit,
|
||||
LearningUnitPerformanceCriteria,
|
||||
} from "@/types";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export type CircleStoreState = {
|
||||
circle: Circle | undefined;
|
||||
|
|
@ -89,12 +88,11 @@ export const useCircleStore = defineStore({
|
|||
page: LearningContent | LearningUnitPerformanceCriteria,
|
||||
completion_status: CourseCompletionStatus = "success"
|
||||
) {
|
||||
const completionStore = useCompletionStore();
|
||||
|
||||
try {
|
||||
page.completion_status = completion_status;
|
||||
const completionData = await itPost("/api/course/completion/mark/", {
|
||||
page_key: page.translation_key,
|
||||
completion_status: page.completion_status,
|
||||
});
|
||||
const completionData = await completionStore.markPage(page);
|
||||
if (this.circle) {
|
||||
this.circle.parseCompletionData(completionData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { itGet } from "@/fetchHelpers";
|
||||
import { useCompletionStore } from "@/stores/completion";
|
||||
import type { CompetenceProfilePage } from "@/types";
|
||||
import _ from "lodash";
|
||||
import { defineStore } from "pinia";
|
||||
|
|
@ -38,6 +39,7 @@ export const useCompetenceStore = defineStore({
|
|||
actions: {
|
||||
async loadCompetenceProfilePage(slug: string, reload = false) {
|
||||
if (this.competenceProfilePage && !reload) {
|
||||
await this.parseCompletionData();
|
||||
return this.competenceProfilePage;
|
||||
}
|
||||
const competenceProfilePageData = await itGet(`/api/course/page/${slug}/`);
|
||||
|
|
@ -47,7 +49,32 @@ export const useCompetenceStore = defineStore({
|
|||
}
|
||||
|
||||
this.competenceProfilePage = competenceProfilePageData;
|
||||
await this.parseCompletionData();
|
||||
|
||||
return this.competenceProfilePage;
|
||||
},
|
||||
async parseCompletionData() {
|
||||
if (this.competenceProfilePage) {
|
||||
const completionStore = useCompletionStore();
|
||||
const completionData = await completionStore.loadCompletionData(
|
||||
this.competenceProfilePage.course.id
|
||||
);
|
||||
|
||||
if (completionData) {
|
||||
this.competenceProfilePage.children.forEach((competence) => {
|
||||
competence.children.forEach((performanceCriteria) => {
|
||||
const completion = completionData.find(
|
||||
(c) => c.page_key === performanceCriteria.translation_key
|
||||
);
|
||||
if (completion) {
|
||||
performanceCriteria.completion_status = completion.completion_status;
|
||||
} else {
|
||||
performanceCriteria.completion_status = "unknown";
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
import { itGet, itPost } from "@/fetchHelpers";
|
||||
import type { CourseCompletion, CourseWagtailPage } from "@/types";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export type CompletionStoreState = {
|
||||
completionData: CourseCompletion[] | undefined;
|
||||
};
|
||||
|
||||
export const useCompletionStore = defineStore({
|
||||
id: "completion",
|
||||
state: () => {
|
||||
return {
|
||||
completionData: undefined,
|
||||
} as CompletionStoreState;
|
||||
},
|
||||
getters: {},
|
||||
actions: {
|
||||
async loadCompletionData(courseId: number, reload = false) {
|
||||
if (this.completionData && !reload) {
|
||||
return this.completionData;
|
||||
}
|
||||
const completionData = await itGet(`/api/course/completion/${courseId}/`);
|
||||
|
||||
if (!completionData) {
|
||||
throw `No completionData found with: ${courseId}`;
|
||||
}
|
||||
|
||||
this.completionData = completionData;
|
||||
return this.completionData || [];
|
||||
},
|
||||
async markPage(page: CourseWagtailPage) {
|
||||
const completionData = await itPost("/api/course/completion/mark/", {
|
||||
page_key: page.translation_key,
|
||||
completion_status: page.completion_status,
|
||||
});
|
||||
|
||||
if (completionData) {
|
||||
this.completionData = completionData;
|
||||
}
|
||||
|
||||
return this.completionData || [];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import { itGet } from "@/fetchHelpers";
|
||||
import { LearningPath } from "@/services/learningPath";
|
||||
import { useCompletionStore } from "@/stores/completion";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export type LearningPathStoreState = {
|
||||
|
|
@ -18,12 +19,13 @@ export const useLearningPathStore = defineStore({
|
|||
getters: {},
|
||||
actions: {
|
||||
async loadLearningPath(slug: string, reload = false) {
|
||||
const completionStore = useCompletionStore();
|
||||
if (this.learningPath && !reload) {
|
||||
return this.learningPath;
|
||||
}
|
||||
const learningPathData = await itGet(`/api/course/page/${slug}/`);
|
||||
const completionData = await itGet(
|
||||
`/api/course/completion/${learningPathData.course.id}/`
|
||||
const completionData = await completionStore.loadCompletionData(
|
||||
learningPathData.course.id
|
||||
);
|
||||
|
||||
if (!learningPathData) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue