vbv/client/src/stores/learningPath.ts

118 lines
3.2 KiB
TypeScript

import { itGetCached } from "@/fetchHelpers";
import { LearningPath } from "@/services/learningPath";
import { useCompletionStore } from "@/stores/completion";
import { useCourseSessionsStore } from "@/stores/courseSessions";
import { useUserStore } from "@/stores/user";
import type { CourseCompletion } from "@/types";
import eventBus from "@/utils/eventBus";
import cloneDeep from "lodash/cloneDeep";
import log from "loglevel";
import { defineStore } from "pinia";
import { computed, reactive } from "vue";
export type LearningPathStoreState = {
learningPaths: Map<string, LearningPath>;
page: "INDEX" | "OVERVIEW";
};
type LearningPathKey = string;
function getLearningPathKey(
slug: string,
userId: string | number | undefined
): LearningPathKey {
return `${slug}-${userId}`;
}
export const useLearningPathStore = defineStore("learningPath", () => {
const state: LearningPathStoreState = reactive({
learningPaths: new Map<LearningPathKey, LearningPath>(),
page: "INDEX",
});
const learningPathForUser = computed(() => {
return (courseSlug: string, userId: string | number | undefined) => {
if (state.learningPaths.size > 0) {
const learningPathKey = getLearningPathKey(`${courseSlug}-lp`, userId);
return state.learningPaths.get(learningPathKey);
}
return undefined;
};
});
async function loadCompletionData(
courseSlug: string,
userId: number | undefined = undefined
) {
const completionStore = useCompletionStore();
let completionData: CourseCompletion[] = [];
if (userId) {
const courseSessionsStore = useCourseSessionsStore();
const courseSession = courseSessionsStore.courseSessionForCourse(courseSlug);
if (courseSession) {
completionData = await completionStore.loadCompletionData(
courseSession.id,
userId
);
return completionData;
}
}
return [];
}
async function loadLearningPath(
slug: string,
userId: number | undefined = undefined,
reload = false,
fail = true
) {
if (!userId) {
const userStore = useUserStore();
userId = userStore.id;
}
const key = getLearningPathKey(slug, userId);
if (state.learningPaths.has(key) && !reload) {
return state.learningPaths.get(key);
}
const learningPathData = await itGetCached(`/api/course/page/${slug}/`);
if (!learningPathData && fail) {
throw `No learning path found with: ${slug}`;
}
const completionData = await loadCompletionData(
learningPathData.course.slug,
userId
);
const learningPath = LearningPath.fromJson(
cloneDeep(learningPathData),
completionData,
userId
);
state.learningPaths.set(key, learningPath);
return learningPath;
}
function reloadCompletionData() {
state.learningPaths.forEach((lp) => {
if (lp.userId) {
lp.reloadCompletionData();
}
});
}
eventBus.on("switchedCourseSession", (courseSession) => {
log.debug("handle switchedCourseSession", courseSession);
// FIXME: clean up with VBV-305
reloadCompletionData();
});
return { state, learningPathForUser, loadCompletionData, loadLearningPath };
});