Use circle filter on competence page

This commit is contained in:
Daniel Egger 2022-10-10 18:23:41 +02:00
parent cf873e6f23
commit 64b5c5a825
6 changed files with 103 additions and 34 deletions

View File

@ -34,12 +34,16 @@ const togglePerformanceCriteria = () => {
</button>
</div>
<ComptenceProgress
:status-count="competenceStore.calcStatusCount(competence.children)"
:status-count="
competenceStore.calcStatusCount(
competenceStore.criteriaByCompetence(competence)
)
"
></ComptenceProgress>
</div>
<ul v-if="isOpen">
<li
v-for="performanceCriteria in competence.children"
v-for="performanceCriteria in competenceStore.criteriaByCompetence(competence)"
:key="performanceCriteria.id"
class="mb-4 pb-4 border-b border-gray-500"
>

View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import CompetenceProgress from "@/components/competences/CompetenceProgress.vue";
import PerformanceCriteriaRow from "@/components/competences/PerformanceCriteriaRow.vue";
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
import { useCompetenceStore } from "@/stores/competence";
import _ from "lodash";
import * as log from "loglevel";
@ -19,22 +20,26 @@ const failedCriteria = computed(() => {
});
const lastUpdatedCompetences = computed(() => {
if (competenceStore.competenceProfilePage?.children.length) {
return _.orderBy(
competenceStore.competenceProfilePage.children,
[
(competence) => {
return (
_.maxBy(competence.children, "completion_status_updated_at")
?.completion_status_updated_at || ""
);
},
],
["desc"]
).slice(0, 3);
}
return [];
return _.orderBy(
competenceStore.competences,
[
(competence) => {
let criteria = competence.children;
if (competenceStore.selectedCircle.id != "all") {
criteria = criteria.filter((criteria) => {
return (
criteria.circle.translation_key === competenceStore.selectedCircle.id
);
});
}
return (
_.maxBy(criteria, "completion_status_updated_at")
?.completion_status_updated_at || ""
);
},
],
["desc"]
).slice(0, 3);
});
const countStatus = computed(() => {
@ -49,9 +54,10 @@ const countStatus = computed(() => {
class="flex flex-col lg:flex-row items-center justify-between mb-10"
>
<h1>Kompetenzprofil</h1>
<!-- <ItDropdownSelect-->
<!-- v-model="dropdownSelected"-->
<!-- :items="mediaStore.availableLearningPaths"></ItDropdownSelect>-->
<ItDropdownSelect
v-model="competenceStore.selectedCircle"
:items="competenceStore.availableCircles"
></ItDropdownSelect>
</div>
<div class="bg-white p-8 mb-8">
<div>
@ -66,7 +72,11 @@ const countStatus = computed(() => {
{{ competence.competence_id }} {{ competence.title }}
</p>
<CompetenceProgress
:status-count="competenceStore.calcStatusCount(competence.children)"
:status-count="
competenceStore.calcStatusCount(
competenceStore.criteriaByCompetence(competence)
)
"
></CompetenceProgress>
</li>
</ul>

View File

@ -1,5 +1,6 @@
<script setup lang="ts">
import CompetenceDetail from "@/components/competences/CompetenceDetail.vue";
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
import { useCompetenceStore } from "@/stores/competence";
import * as log from "loglevel";
@ -21,13 +22,14 @@ const competenceStore = useCompetenceStore();
</nav>
<div class="flex flex-col lg:flex-row items-center justify-between mb-10">
<h1>Kompetenzen</h1>
<!-- <ItDropdownSelect-->
<!-- v-model="dropdownSelected"-->
<!-- :items="mediaStore.availableLearningPaths"></ItDropdownSelect>-->
<ItDropdownSelect
v-model="competenceStore.selectedCircle"
:items="competenceStore.availableCircles"
></ItDropdownSelect>
</div>
<ul v-if="competenceStore.competenceProfilePage">
<li
v-for="competence in competenceStore.competenceProfilePage.children"
v-for="competence in competenceStore.competences"
:key="competence.id"
class="bg-white p-8 mb-8"
>

View File

@ -1,5 +1,6 @@
<script setup lang="ts">
import { default as PerformanceCriteriaRow } from "@/components/competences/PerformanceCriteriaRow.vue";
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
import { useCompetenceStore } from "@/stores/competence";
import type { CourseCompletionStatus } from "@/types";
import * as log from "loglevel";
@ -31,9 +32,10 @@ const shownCriteria = computed(() => {
</nav>
<div class="flex flex-col lg:flex-row items-center justify-between mb-10">
<h1>Einschätzungen</h1>
<!-- <ItDropdownSelect-->
<!-- v-model="dropdownSelected"-->
<!-- :items="mediaStore.availableLearningPaths"></ItDropdownSelect>-->
<ItDropdownSelect
v-model="competenceStore.selectedCircle"
:items="competenceStore.availableCircles"
></ItDropdownSelect>
</div>
<div class="bg-white p-8">
<div

View File

@ -1,11 +1,18 @@
import { itGet } from "@/fetchHelpers";
import { useCompletionStore } from "@/stores/completion";
import type { CompetenceProfilePage, PerformanceCriteria } from "@/types";
import type {
CompetencePage,
CompetenceProfilePage,
CourseWagtailPage,
PerformanceCriteria,
} from "@/types";
import _ from "lodash";
import { defineStore } from "pinia";
export type CompetenceStoreState = {
competenceProfilePage: CompetenceProfilePage | undefined;
selectedCircle: { id: string; name: string };
availableCircles: { id: string; name: string }[];
};
export const useCompetenceStore = defineStore({
@ -13,10 +20,12 @@ export const useCompetenceStore = defineStore({
state: () => {
return {
competenceProfilePage: undefined,
selectedCircle: { id: "all", name: "Circle: Alle" },
availableCircles: [],
} as CompetenceStoreState;
},
getters: {
flatPerformanceCriteria: (state, circleTitle = "") => {
flatPerformanceCriteria: (state) => {
if (!state.competenceProfilePage) {
return [];
}
@ -29,12 +38,40 @@ export const useCompetenceStore = defineStore({
["asc"]
);
if (circleTitle) {
criteria = criteria.filter((c) => c.circle === circleTitle);
if (state.selectedCircle.id !== "all") {
criteria = criteria.filter(
(c) => c.circle.translation_key === state.selectedCircle.id
);
}
return criteria;
},
competences: (state) => {
if (state.competenceProfilePage?.children.length) {
return state.competenceProfilePage.children.filter((competence) => {
let criteria = competence.children;
if (state.selectedCircle.id != "all") {
criteria = criteria.filter((criteria) => {
return criteria.circle.translation_key === state.selectedCircle.id;
});
}
return criteria.length > 0;
});
}
return [];
},
criteriaByCompetence: (state) => {
return (competence: CompetencePage) => {
return competence.children.filter((criteria) => {
if (state.selectedCircle.id != "all") {
return criteria.circle.translation_key === state.selectedCircle.id;
}
return competence.children;
});
};
},
},
actions: {
calcStatusCount(criteria: PerformanceCriteria[]) {
@ -65,6 +102,12 @@ export const useCompetenceStore = defineStore({
}
this.competenceProfilePage = competenceProfilePageData;
const circles = competenceProfilePageData.circles.map((c: CourseWagtailPage) => {
return { id: c.translation_key, name: `Circle: ${c.title}` };
});
this.availableCircles = [{ id: "all", name: "Circle: Alle" }, ...circles];
await this.parseCompletionData();
return this.competenceProfilePage;

View File

@ -125,6 +125,13 @@ export interface CourseWagtailPage {
completion_status_updated_at: string;
}
export interface CircleLight {
readonly id: number;
readonly title: string;
readonly slug: string;
readonly translation_key: string;
}
export interface LearningContent extends CourseWagtailPage {
type: "learnpath.LearningContent";
minutes: number;
@ -296,7 +303,7 @@ export interface MediaLibraryPage extends CourseWagtailPage {
export interface PerformanceCriteria extends CourseWagtailPage {
type: "competence.PerformanceCriteria";
competence_id: string;
circle: string;
circle: CircleLight;
course_category: CourseCategory;
learning_unit: CourseWagtailPage;
}
@ -310,5 +317,6 @@ export interface CompetencePage extends CourseWagtailPage {
export interface CompetenceProfilePage extends CourseWagtailPage {
type: "competence.CompetenceProfilePage";
course: Course;
circles: CircleLight[];
children: CompetencePage[];
}