vbv/client/src/services/learningPath.ts

129 lines
3.5 KiB
TypeScript

import * as _ from "lodash";
import { Circle } from "@/services/circle";
import type {
CourseCompletion,
CourseCompletionStatus,
CourseWagtailPage,
LearningContent,
LearningPathChild,
Topic,
} from "@/types";
function getLastCompleted(courseId: number, completionData: CourseCompletion[]) {
return _.orderBy(completionData, ["updated_at"], "desc").find(
(c: CourseCompletion) => {
return (
c.completion_status === "success" &&
c.course === courseId &&
c.page_type === "learnpath.LearningContent"
);
}
);
}
export class LearningPath implements CourseWagtailPage {
readonly type = "learnpath.LearningPath";
public topics: Topic[];
public circles: Circle[];
public nextLearningContent?: LearningContent;
readonly completion_status: CourseCompletionStatus = "unknown";
public static fromJson(json: any, completionData: CourseCompletion[]): LearningPath {
return new LearningPath(
json.id,
json.slug,
json.course.title,
json.translation_key,
json.frontend_url,
json.course.id,
json.children,
completionData
);
}
constructor(
public readonly id: number,
public readonly slug: string,
public readonly title: string,
public readonly translation_key: string,
public readonly frontend_url: string,
public readonly courseId: number,
public children: LearningPathChild[],
completionData?: CourseCompletion[]
) {
// parse children
this.topics = [];
this.circles = [];
let topic: Topic | undefined;
this.children.forEach((page) => {
if (page.type === "learnpath.Topic") {
if (topic) {
this.topics.push(topic);
}
topic = Object.assign(page, { circles: [] });
}
if (page.type === "learnpath.Circle") {
const circle = Circle.fromJson(page, this);
if (completionData) {
circle.parseCompletionData(completionData);
}
if (topic) {
topic.circles.push(circle);
}
circle.previousCircle = this.circles[this.circles.length - 1];
if (circle.previousCircle) {
circle.previousCircle.nextCircle = circle;
}
this.circles.push(circle);
}
});
if (topic) {
this.topics.push(topic);
}
if (completionData) {
this.calcNextLearningContent(completionData);
}
}
public calcNextLearningContent(completionData: CourseCompletion[]): void {
this.nextLearningContent = undefined;
const lastCompletedLearningContent = getLastCompleted(
this.courseId,
completionData
);
if (lastCompletedLearningContent) {
const lastCircle = this.circles.find((circle) => {
return circle.flatLearningContents.find(
(learningContent) =>
learningContent.translation_key === lastCompletedLearningContent.page_key
);
});
if (lastCircle) {
const lastLearningContent = lastCircle.flatLearningContents.find(
(learningContent) =>
learningContent.translation_key === lastCompletedLearningContent.page_key
);
if (lastLearningContent && lastLearningContent.nextLearningContent) {
this.nextLearningContent = lastLearningContent.nextLearningContent;
} else {
if (lastCircle.nextCircle) {
this.nextLearningContent = lastCircle.nextCircle.flatLearningContents[0];
}
}
}
} else {
if (this.circles[0]) {
this.nextLearningContent = this.circles[0].flatLearningContents[0];
}
}
}
}