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]; } } } }