645 lines
38 KiB
JavaScript
645 lines
38 KiB
JavaScript
import {
|
|
EnrollmentService
|
|
} from "./chunk-AALWYTMW.js";
|
|
import {
|
|
getErrorMessage
|
|
} from "./chunk-QDZ3GX5R.js";
|
|
import {
|
|
CourseService
|
|
} from "./chunk-6K3TDILH.js";
|
|
import {
|
|
NzMessageService
|
|
} from "./chunk-GJYGTZ7J.js";
|
|
import {
|
|
ActivatedRoute,
|
|
AuthService,
|
|
NzIconDirective,
|
|
NzIconModule,
|
|
Router
|
|
} from "./chunk-2TRRHRR7.js";
|
|
import "./chunk-EDRPZB37.js";
|
|
import {
|
|
Component,
|
|
catchError,
|
|
computed,
|
|
forkJoin,
|
|
inject,
|
|
of,
|
|
setClassMetadata,
|
|
signal,
|
|
ɵsetClassDebugInfo,
|
|
ɵɵProvidersFeature,
|
|
ɵɵadvance,
|
|
ɵɵconditional,
|
|
ɵɵconditionalCreate,
|
|
ɵɵdefineComponent,
|
|
ɵɵelement,
|
|
ɵɵelementEnd,
|
|
ɵɵelementStart,
|
|
ɵɵgetCurrentView,
|
|
ɵɵlistener,
|
|
ɵɵnextContext,
|
|
ɵɵproperty,
|
|
ɵɵrepeater,
|
|
ɵɵrepeaterCreate,
|
|
ɵɵresetView,
|
|
ɵɵrestoreView,
|
|
ɵɵstyleProp,
|
|
ɵɵtext,
|
|
ɵɵtextInterpolate,
|
|
ɵɵtextInterpolate1,
|
|
ɵɵtextInterpolate2,
|
|
ɵɵtextInterpolate4
|
|
} from "./chunk-WI7WFVZR.js";
|
|
import "./chunk-WDMUDEB6.js";
|
|
|
|
// src/app/pages/course-viewer/course-viewer.ts
|
|
var _forTrack0 = ($index, $item) => $item.id;
|
|
function CourseViewerPage_Conditional_1_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275elementStart(0, "div", 1);
|
|
\u0275\u0275element(1, "span", 2);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_4_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
const _r3 = \u0275\u0275getCurrentView();
|
|
\u0275\u0275elementStart(0, "button", 20);
|
|
\u0275\u0275listener("click", function CourseViewerPage_Conditional_2_Conditional_4_Template_button_click_0_listener() {
|
|
\u0275\u0275restoreView(_r3);
|
|
const ctx_r1 = \u0275\u0275nextContext(2);
|
|
return \u0275\u0275resetView(ctx_r1.editCourse());
|
|
});
|
|
\u0275\u0275element(1, "span", 21);
|
|
\u0275\u0275text(2, " Modifier ");
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_20_Conditional_8_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275elementStart(0, "p", 27);
|
|
\u0275\u0275text(1);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
if (rf & 2) {
|
|
const ctx_r1 = \u0275\u0275nextContext(3);
|
|
\u0275\u0275advance();
|
|
\u0275\u0275textInterpolate4(" ", ctx_r1.progress().completedTopics, "/", ctx_r1.progress().totalTopics, " sujets \xB7 ", ctx_r1.progress().completedResources, "/", ctx_r1.progress().totalResources, " ressources ");
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_20_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275elementStart(0, "div", 15)(1, "div", 22)(2, "span", 23);
|
|
\u0275\u0275text(3, "Progression");
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(4, "span", 24);
|
|
\u0275\u0275text(5);
|
|
\u0275\u0275elementEnd()();
|
|
\u0275\u0275elementStart(6, "div", 25);
|
|
\u0275\u0275element(7, "div", 26);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275conditionalCreate(8, CourseViewerPage_Conditional_2_Conditional_20_Conditional_8_Template, 2, 4, "p", 27);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
if (rf & 2) {
|
|
const ctx_r1 = \u0275\u0275nextContext(2);
|
|
\u0275\u0275advance(5);
|
|
\u0275\u0275textInterpolate1("", ctx_r1.progressPercent(), "%");
|
|
\u0275\u0275advance(2);
|
|
\u0275\u0275styleProp("width", ctx_r1.progressPercent(), "%");
|
|
\u0275\u0275advance();
|
|
\u0275\u0275conditional(ctx_r1.progress() ? 8 : -1);
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_21_Conditional_1_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275element(0, "span", 29);
|
|
\u0275\u0275text(1, " Inscription... ");
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_21_Conditional_2_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275text(0, " Commencer ce cours \u2192 ");
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_21_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
const _r4 = \u0275\u0275getCurrentView();
|
|
\u0275\u0275elementStart(0, "button", 28);
|
|
\u0275\u0275listener("click", function CourseViewerPage_Conditional_2_Conditional_21_Template_button_click_0_listener() {
|
|
\u0275\u0275restoreView(_r4);
|
|
const ctx_r1 = \u0275\u0275nextContext(2);
|
|
return \u0275\u0275resetView(ctx_r1.enroll());
|
|
});
|
|
\u0275\u0275conditionalCreate(1, CourseViewerPage_Conditional_2_Conditional_21_Conditional_1_Template, 2, 0)(2, CourseViewerPage_Conditional_2_Conditional_21_Conditional_2_Template, 1, 0);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
if (rf & 2) {
|
|
const ctx_r1 = \u0275\u0275nextContext(2);
|
|
\u0275\u0275property("disabled", ctx_r1.enrolling());
|
|
\u0275\u0275advance();
|
|
\u0275\u0275conditional(ctx_r1.enrolling() ? 1 : 2);
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_25_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275elementStart(0, "div", 19)(1, "p");
|
|
\u0275\u0275text(2, "Ce cours ne contient pas encore de sujets.");
|
|
\u0275\u0275elementEnd()();
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_7_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275elementStart(0, "p", 35);
|
|
\u0275\u0275text(1);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
if (rf & 2) {
|
|
const topic_r6 = \u0275\u0275nextContext().$implicit;
|
|
\u0275\u0275advance();
|
|
\u0275\u0275textInterpolate(topic_r6.description);
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_11_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
const _r7 = \u0275\u0275getCurrentView();
|
|
\u0275\u0275elementStart(0, "button", 41);
|
|
\u0275\u0275listener("click", function CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_11_Template_button_click_0_listener($event) {
|
|
\u0275\u0275restoreView(_r7);
|
|
const topic_r6 = \u0275\u0275nextContext().$implicit;
|
|
const ctx_r1 = \u0275\u0275nextContext(3);
|
|
return \u0275\u0275resetView(ctx_r1.markTopicDone(topic_r6, $event));
|
|
});
|
|
\u0275\u0275element(1, "span", 42);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_13_For_2_Conditional_8_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
const _r8 = \u0275\u0275getCurrentView();
|
|
\u0275\u0275elementStart(0, "button", 50);
|
|
\u0275\u0275listener("click", function CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_13_For_2_Conditional_8_Template_button_click_0_listener($event) {
|
|
\u0275\u0275restoreView(_r8);
|
|
const resource_r9 = \u0275\u0275nextContext().$implicit;
|
|
const ctx_r1 = \u0275\u0275nextContext(5);
|
|
return \u0275\u0275resetView(ctx_r1.markResourceDone(resource_r9, $event));
|
|
});
|
|
\u0275\u0275element(1, "span", 51);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_13_For_2_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275elementStart(0, "div", 43)(1, "div", 44);
|
|
\u0275\u0275element(2, "span", 45);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(3, "div", 46)(4, "p", 47);
|
|
\u0275\u0275text(5);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(6, "span", 48);
|
|
\u0275\u0275text(7);
|
|
\u0275\u0275elementEnd()();
|
|
\u0275\u0275conditionalCreate(8, CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_13_For_2_Conditional_8_Template, 2, 0, "button", 49);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
if (rf & 2) {
|
|
const resource_r9 = ctx.$implicit;
|
|
const ctx_r1 = \u0275\u0275nextContext(5);
|
|
\u0275\u0275advance(2);
|
|
\u0275\u0275property("nzType", ctx_r1.getResourceIcon(resource_r9.type));
|
|
\u0275\u0275advance(3);
|
|
\u0275\u0275textInterpolate(resource_r9.title);
|
|
\u0275\u0275advance(2);
|
|
\u0275\u0275textInterpolate(resource_r9.type);
|
|
\u0275\u0275advance();
|
|
\u0275\u0275conditional(ctx_r1.isEnrolled() ? 8 : -1);
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_13_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275elementStart(0, "div", 40);
|
|
\u0275\u0275repeaterCreate(1, CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_13_For_2_Template, 9, 4, "div", 43, _forTrack0);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
if (rf & 2) {
|
|
const topic_r6 = \u0275\u0275nextContext().$implicit;
|
|
\u0275\u0275advance();
|
|
\u0275\u0275repeater(topic_r6.resources);
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_26_For_1_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
const _r5 = \u0275\u0275getCurrentView();
|
|
\u0275\u0275elementStart(0, "div", 30)(1, "div", 31);
|
|
\u0275\u0275listener("click", function CourseViewerPage_Conditional_2_Conditional_26_For_1_Template_div_click_1_listener() {
|
|
const topic_r6 = \u0275\u0275restoreView(_r5).$implicit;
|
|
const ctx_r1 = \u0275\u0275nextContext(3);
|
|
return \u0275\u0275resetView(ctx_r1.toggleTopic(topic_r6.id));
|
|
});
|
|
\u0275\u0275elementStart(2, "div", 32);
|
|
\u0275\u0275text(3);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(4, "div", 33)(5, "h3", 34);
|
|
\u0275\u0275text(6);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275conditionalCreate(7, CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_7_Template, 2, 1, "p", 35);
|
|
\u0275\u0275elementStart(8, "span", 36);
|
|
\u0275\u0275text(9);
|
|
\u0275\u0275elementEnd()();
|
|
\u0275\u0275elementStart(10, "div", 37);
|
|
\u0275\u0275conditionalCreate(11, CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_11_Template, 2, 0, "button", 38);
|
|
\u0275\u0275element(12, "span", 39);
|
|
\u0275\u0275elementEnd()();
|
|
\u0275\u0275conditionalCreate(13, CourseViewerPage_Conditional_2_Conditional_26_For_1_Conditional_13_Template, 3, 0, "div", 40);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
if (rf & 2) {
|
|
const topic_r6 = ctx.$implicit;
|
|
const ctx_r1 = \u0275\u0275nextContext(3);
|
|
\u0275\u0275advance(3);
|
|
\u0275\u0275textInterpolate(topic_r6.position);
|
|
\u0275\u0275advance(3);
|
|
\u0275\u0275textInterpolate(topic_r6.title);
|
|
\u0275\u0275advance();
|
|
\u0275\u0275conditional(topic_r6.description ? 7 : -1);
|
|
\u0275\u0275advance(2);
|
|
\u0275\u0275textInterpolate2(" ", topic_r6.resources.length, " ressource", topic_r6.resources.length !== 1 ? "s" : "", " ");
|
|
\u0275\u0275advance(2);
|
|
\u0275\u0275conditional(ctx_r1.isEnrolled() ? 11 : -1);
|
|
\u0275\u0275advance();
|
|
\u0275\u0275property("nzType", ctx_r1.isTopicExpanded(topic_r6.id) ? "menu-fold" : "menu-unfold");
|
|
\u0275\u0275advance();
|
|
\u0275\u0275conditional(ctx_r1.isTopicExpanded(topic_r6.id) && topic_r6.resources.length > 0 ? 13 : -1);
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Conditional_26_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275repeaterCreate(0, CourseViewerPage_Conditional_2_Conditional_26_For_1_Template, 14, 8, "div", 30, _forTrack0);
|
|
}
|
|
if (rf & 2) {
|
|
const ctx_r1 = \u0275\u0275nextContext(2);
|
|
\u0275\u0275repeater(ctx_r1.course().topics);
|
|
}
|
|
}
|
|
function CourseViewerPage_Conditional_2_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
const _r1 = \u0275\u0275getCurrentView();
|
|
\u0275\u0275elementStart(0, "div", 3)(1, "div", 4)(2, "button", 5);
|
|
\u0275\u0275listener("click", function CourseViewerPage_Conditional_2_Template_button_click_2_listener() {
|
|
\u0275\u0275restoreView(_r1);
|
|
const ctx_r1 = \u0275\u0275nextContext();
|
|
return \u0275\u0275resetView(ctx_r1.goBack());
|
|
});
|
|
\u0275\u0275element(3, "span", 6);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275conditionalCreate(4, CourseViewerPage_Conditional_2_Conditional_4_Template, 3, 0, "button", 7);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(5, "div", 8)(6, "span", 9);
|
|
\u0275\u0275text(7, "COMMUNAUT\xC9");
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(8, "h1", 10);
|
|
\u0275\u0275text(9);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(10, "p", 11);
|
|
\u0275\u0275text(11);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(12, "div", 12);
|
|
\u0275\u0275element(13, "span", 13);
|
|
\u0275\u0275elementStart(14, "span");
|
|
\u0275\u0275text(15);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(16, "span", 14);
|
|
\u0275\u0275text(17, "\xB7");
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(18, "span");
|
|
\u0275\u0275text(19);
|
|
\u0275\u0275elementEnd()()();
|
|
\u0275\u0275conditionalCreate(20, CourseViewerPage_Conditional_2_Conditional_20_Template, 9, 4, "div", 15);
|
|
\u0275\u0275conditionalCreate(21, CourseViewerPage_Conditional_2_Conditional_21_Template, 3, 2, "button", 16);
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275elementStart(22, "div", 17)(23, "h2", 18);
|
|
\u0275\u0275text(24, "Contenu du cours");
|
|
\u0275\u0275elementEnd();
|
|
\u0275\u0275conditionalCreate(25, CourseViewerPage_Conditional_2_Conditional_25_Template, 3, 0, "div", 19)(26, CourseViewerPage_Conditional_2_Conditional_26_Template, 2, 0);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
if (rf & 2) {
|
|
const ctx_r1 = \u0275\u0275nextContext();
|
|
\u0275\u0275advance(4);
|
|
\u0275\u0275conditional(ctx_r1.isOwnCourse() ? 4 : -1);
|
|
\u0275\u0275advance(5);
|
|
\u0275\u0275textInterpolate(ctx_r1.course().title);
|
|
\u0275\u0275advance(2);
|
|
\u0275\u0275textInterpolate(ctx_r1.course().description);
|
|
\u0275\u0275advance(4);
|
|
\u0275\u0275textInterpolate(ctx_r1.course().creatorName);
|
|
\u0275\u0275advance(4);
|
|
\u0275\u0275textInterpolate2("", ctx_r1.course().topicCount, " sujet", ctx_r1.course().topicCount !== 1 ? "s" : "");
|
|
\u0275\u0275advance();
|
|
\u0275\u0275conditional(ctx_r1.isEnrolled() ? 20 : -1);
|
|
\u0275\u0275advance();
|
|
\u0275\u0275conditional(!ctx_r1.isEnrolled() && !ctx_r1.isOwnCourse() ? 21 : -1);
|
|
\u0275\u0275advance(4);
|
|
\u0275\u0275conditional(ctx_r1.course().topics.length === 0 ? 25 : 26);
|
|
}
|
|
}
|
|
var CourseViewerPage = class _CourseViewerPage {
|
|
route = inject(ActivatedRoute);
|
|
router = inject(Router);
|
|
courseService = inject(CourseService);
|
|
enrollmentService = inject(EnrollmentService);
|
|
authService = inject(AuthService);
|
|
message = inject(NzMessageService);
|
|
course = signal(null, ...ngDevMode ? [{ debugName: "course" }] : []);
|
|
progress = signal(null, ...ngDevMode ? [{ debugName: "progress" }] : []);
|
|
loading = signal(true, ...ngDevMode ? [{ debugName: "loading" }] : []);
|
|
enrolling = signal(false, ...ngDevMode ? [{ debugName: "enrolling" }] : []);
|
|
isEnrolled = signal(false, ...ngDevMode ? [{ debugName: "isEnrolled" }] : []);
|
|
expandedTopicId = signal(null, ...ngDevMode ? [{ debugName: "expandedTopicId" }] : []);
|
|
get currentUser() {
|
|
return this.authService.currentUser();
|
|
}
|
|
isOwnCourse = computed(() => {
|
|
const user = this.currentUser;
|
|
const course = this.course();
|
|
return user && course ? course.creatorId === user.userId : false;
|
|
}, ...ngDevMode ? [{ debugName: "isOwnCourse" }] : []);
|
|
progressPercent = computed(() => {
|
|
const p = this.progress();
|
|
return p ? Math.round(p.progressPercentage) : 0;
|
|
}, ...ngDevMode ? [{ debugName: "progressPercent" }] : []);
|
|
ngOnInit() {
|
|
const id = this.route.snapshot.paramMap.get("id");
|
|
this.loadCourse(id);
|
|
}
|
|
loadCourse(id) {
|
|
this.loading.set(true);
|
|
const user = this.currentUser;
|
|
const course$ = this.courseService.getCourseById(id);
|
|
const enrollments$ = user ? this.enrollmentService.getEnrollments(user.userId).pipe(catchError(() => of([]))) : of([]);
|
|
const progress$ = user ? this.enrollmentService.getCourseProgress(id, user.userId).pipe(catchError(() => of(null))) : of(null);
|
|
forkJoin([course$, enrollments$, progress$]).subscribe({
|
|
next: ([course, enrollments, progress]) => {
|
|
this.course.set(course);
|
|
this.progress.set(progress);
|
|
if (enrollments.length > 0) {
|
|
this.isEnrolled.set(enrollments.some((e) => e.courseId === id));
|
|
}
|
|
if (course.topics.length > 0) {
|
|
this.expandedTopicId.set(course.topics[0].id);
|
|
}
|
|
this.loading.set(false);
|
|
},
|
|
error: () => {
|
|
this.loading.set(false);
|
|
this.message.error("Impossible de charger le cours");
|
|
this.router.navigate(["/catalog"]);
|
|
}
|
|
});
|
|
}
|
|
enroll() {
|
|
const user = this.currentUser;
|
|
const course = this.course();
|
|
if (!user || !course)
|
|
return;
|
|
this.enrolling.set(true);
|
|
this.enrollmentService.enroll(course.id, user.userId).subscribe({
|
|
next: () => {
|
|
this.isEnrolled.set(true);
|
|
this.enrolling.set(false);
|
|
this.message.success("Inscription r\xE9ussie !");
|
|
this.progress.set({ courseId: course.id, userId: user.userId, totalTopics: course.topics.length, completedTopics: 0, totalResources: 0, completedResources: 0, progressPercentage: 0 });
|
|
this.loadProgress(course.id, user.userId);
|
|
},
|
|
error: (err) => {
|
|
this.enrolling.set(false);
|
|
this.message.error(getErrorMessage(err, "Erreur lors de l'inscription"));
|
|
}
|
|
});
|
|
}
|
|
loadProgress(courseId, userId) {
|
|
this.enrollmentService.getCourseProgress(courseId, userId).subscribe({
|
|
next: (p) => this.progress.set(p),
|
|
error: () => {
|
|
}
|
|
});
|
|
}
|
|
toggleTopic(topicId) {
|
|
this.expandedTopicId.set(this.expandedTopicId() === topicId ? null : topicId);
|
|
}
|
|
isTopicExpanded(topicId) {
|
|
return this.expandedTopicId() === topicId;
|
|
}
|
|
markTopicDone(topic, event) {
|
|
event.stopPropagation();
|
|
const user = this.currentUser;
|
|
if (!user || !this.isEnrolled())
|
|
return;
|
|
this.enrollmentService.markTopicProgress(topic.id, user.userId, true).subscribe({
|
|
next: () => {
|
|
const course = this.course();
|
|
if (course)
|
|
this.loadProgress(course.id, user.userId);
|
|
},
|
|
error: () => {
|
|
}
|
|
});
|
|
}
|
|
markResourceDone(resource, event) {
|
|
event.stopPropagation();
|
|
const user = this.currentUser;
|
|
if (!user || !this.isEnrolled())
|
|
return;
|
|
this.enrollmentService.markResourceProgress(resource.id, user.userId, true).subscribe({
|
|
next: () => {
|
|
const course = this.course();
|
|
if (course)
|
|
this.loadProgress(course.id, user.userId);
|
|
},
|
|
error: () => {
|
|
}
|
|
});
|
|
}
|
|
editCourse() {
|
|
const course = this.course();
|
|
if (course)
|
|
this.router.navigate(["/courses", course.id, "edit"]);
|
|
}
|
|
goBack() {
|
|
this.router.navigate(["/catalog"]);
|
|
}
|
|
getResourceIcon(type) {
|
|
switch (type) {
|
|
case "Video":
|
|
return "video-camera";
|
|
case "Text":
|
|
return "file-text";
|
|
case "File":
|
|
return "file";
|
|
default:
|
|
return "link";
|
|
}
|
|
}
|
|
static \u0275fac = function CourseViewerPage_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _CourseViewerPage)();
|
|
};
|
|
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _CourseViewerPage, selectors: [["app-course-viewer"]], features: [\u0275\u0275ProvidersFeature([NzMessageService])], decls: 3, vars: 1, consts: [[1, "page-container", "course-viewer-page"], [1, "loading-screen"], ["nz-icon", "", "nzType", "loading", "nzTheme", "outline", 1, "loading-spin"], [1, "viewer-header"], [1, "header-row"], [1, "back-btn", 3, "click"], ["nz-icon", "", "nzType", "arrow-left", "nzTheme", "outline"], [1, "edit-btn"], [1, "course-hero"], [1, "community-badge"], [1, "course-title"], [1, "course-description"], [1, "course-meta"], ["nz-icon", "", "nzType", "user", "nzTheme", "outline"], [1, "meta-dot"], [1, "progress-card"], [1, "enroll-btn", 3, "disabled"], [1, "topics-section"], [1, "section-title"], [1, "empty-topics"], [1, "edit-btn", 3, "click"], ["nz-icon", "", "nzType", "edit", "nzTheme", "outline"], [1, "progress-row"], [1, "progress-label"], [1, "progress-value"], [1, "mc-progress-bar"], [1, "mc-progress-fill"], [1, "progress-detail"], [1, "enroll-btn", 3, "click", "disabled"], ["nz-icon", "", "nzType", "loading", "nzTheme", "outline"], [1, "topic-card"], [1, "topic-header", 3, "click"], [1, "topic-position"], [1, "topic-info"], [1, "topic-title"], [1, "topic-desc"], [1, "resource-count"], [1, "topic-actions"], ["title", "Marquer comme termin\xE9", 1, "done-btn"], ["nz-icon", "", "nzTheme", "outline", 1, "expand-icon", 3, "nzType"], [1, "resources-list"], ["title", "Marquer comme termin\xE9", 1, "done-btn", 3, "click"], ["nz-icon", "", "nzType", "check-circle", "nzTheme", "outline"], [1, "resource-item"], [1, "resource-icon"], ["nz-icon", "", "nzTheme", "outline", 3, "nzType"], [1, "resource-info"], [1, "resource-title"], [1, "resource-type"], ["title", "Marquer comme termin\xE9", 1, "done-btn", "small"], ["title", "Marquer comme termin\xE9", 1, "done-btn", "small", 3, "click"], ["nz-icon", "", "nzType", "check", "nzTheme", "outline"]], template: function CourseViewerPage_Template(rf, ctx) {
|
|
if (rf & 1) {
|
|
\u0275\u0275elementStart(0, "div", 0);
|
|
\u0275\u0275conditionalCreate(1, CourseViewerPage_Conditional_1_Template, 2, 0, "div", 1)(2, CourseViewerPage_Conditional_2_Template, 27, 9);
|
|
\u0275\u0275elementEnd();
|
|
}
|
|
if (rf & 2) {
|
|
\u0275\u0275advance();
|
|
\u0275\u0275conditional(ctx.loading() ? 1 : ctx.course() ? 2 : -1);
|
|
}
|
|
}, dependencies: [NzIconModule, NzIconDirective], styles: ["\n\n.course-viewer-page[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n padding-bottom: 100px;\n}\n.loading-screen[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n color: #1abc9c;\n}\n.loading-spin[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_spin 1s linear infinite;\n}\n@keyframes _ngcontent-%COMP%_spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n.viewer-header[_ngcontent-%COMP%] {\n padding: 16px 20px 20px;\n border-bottom: 1px solid var(--border);\n}\n.header-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 20px;\n}\n.back-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 18px;\n color: var(--text);\n}\n.edit-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 12px;\n padding: 8px 14px;\n font-size: 14px;\n font-weight: 600;\n color: var(--text);\n cursor: pointer;\n}\n.course-hero[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n.course-icon-wrap[_ngcontent-%COMP%] {\n width: 52px;\n height: 52px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 14px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 24px;\n color: var(--text);\n margin-bottom: 10px;\n}\n.community-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 700;\n color: var(--text-muted);\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n}\n.course-title[_ngcontent-%COMP%] {\n font-size: 22px;\n font-weight: 800;\n color: var(--text);\n margin: 0 0 8px;\n letter-spacing: -0.3px;\n line-height: 1.2;\n}\n.course-description[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--text-muted);\n margin: 0 0 12px;\n line-height: 1.5;\n}\n.course-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--text-muted);\n}\n.meta-dot[_ngcontent-%COMP%] {\n color: var(--border);\n}\n.progress-card[_ngcontent-%COMP%] {\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 14px;\n padding: 14px;\n margin-bottom: 12px;\n}\n.progress-row[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n margin-bottom: 8px;\n}\n.progress-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n}\n.progress-value[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 700;\n color: #1abc9c;\n}\n.progress-detail[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-muted);\n margin: 8px 0 0;\n}\n.enroll-btn[_ngcontent-%COMP%] {\n width: 100%;\n background-color: var(--primary);\n color: var(--primary-fg);\n border: none;\n border-radius: 14px;\n padding: 16px;\n font-size: 16px;\n font-weight: 700;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: opacity 0.2s;\n}\n.enroll-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n opacity: 0.85;\n}\n.enroll-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.topics-section[_ngcontent-%COMP%] {\n padding: 20px 20px 0;\n}\n.section-title[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 700;\n color: var(--text);\n margin: 0 0 12px;\n}\n.empty-topics[_ngcontent-%COMP%] {\n color: var(--text-muted);\n font-size: 14px;\n text-align: center;\n padding: 32px 0;\n}\n.topic-card[_ngcontent-%COMP%] {\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 14px;\n margin-bottom: 10px;\n overflow: hidden;\n}\n.topic-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 14px;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n}\n.topic-position[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n background: var(--bg);\n border: 1px solid var(--border);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 700;\n color: var(--text-muted);\n flex-shrink: 0;\n}\n.topic-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n.topic-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 700;\n color: var(--text);\n margin: 0 0 2px;\n}\n.topic-desc[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-muted);\n margin: 0 0 4px;\n line-height: 1.4;\n}\n.resource-count[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--text-muted);\n}\n.topic-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n.done-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: #1abc9c;\n font-size: 18px;\n display: flex;\n align-items: center;\n padding: 0;\n}\n.done-btn.small[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n.expand-icon[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--text-muted);\n}\n.resources-list[_ngcontent-%COMP%] {\n border-top: 1px solid var(--border);\n}\n.resource-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--border);\n}\n.resource-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n.resource-icon[_ngcontent-%COMP%] {\n width: 34px;\n height: 34px;\n background: var(--bg);\n border: 1px solid var(--border);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n color: var(--text-muted);\n flex-shrink: 0;\n}\n.resource-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n.resource-title[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n margin: 0 0 2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.resource-type[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--text-muted);\n}\n/*# sourceMappingURL=course-viewer.css.map */"] });
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CourseViewerPage, [{
|
|
type: Component,
|
|
args: [{ selector: "app-course-viewer", imports: [NzIconModule], providers: [NzMessageService], template: `<div class="page-container course-viewer-page">
|
|
@if (loading()) {
|
|
<div class="loading-screen">
|
|
<span nz-icon nzType="loading" nzTheme="outline" class="loading-spin"></span>
|
|
</div>
|
|
} @else if (course()) {
|
|
<!-- Header -->
|
|
<div class="viewer-header">
|
|
<div class="header-row">
|
|
<button class="back-btn" (click)="goBack()">
|
|
<span nz-icon nzType="arrow-left" nzTheme="outline"></span>
|
|
</button>
|
|
@if (isOwnCourse()) {
|
|
<button class="edit-btn" (click)="editCourse()">
|
|
<span nz-icon nzType="edit" nzTheme="outline"></span>
|
|
Modifier
|
|
</button>
|
|
}
|
|
</div>
|
|
|
|
<div class="course-hero">
|
|
<span class="community-badge">COMMUNAUT\xC9</span>
|
|
<h1 class="course-title">{{ course()!.title }}</h1>
|
|
<p class="course-description">{{ course()!.description }}</p>
|
|
<div class="course-meta">
|
|
<span nz-icon nzType="user" nzTheme="outline"></span>
|
|
<span>{{ course()!.creatorName }}</span>
|
|
<span class="meta-dot">\xB7</span>
|
|
<span>{{ course()!.topicCount }} sujet{{ course()!.topicCount !== 1 ? 's' : '' }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Progress (if enrolled) -->
|
|
@if (isEnrolled()) {
|
|
<div class="progress-card">
|
|
<div class="progress-row">
|
|
<span class="progress-label">Progression</span>
|
|
<span class="progress-value">{{ progressPercent() }}%</span>
|
|
</div>
|
|
<div class="mc-progress-bar">
|
|
<div class="mc-progress-fill" [style.width.%]="progressPercent()"></div>
|
|
</div>
|
|
@if (progress()) {
|
|
<p class="progress-detail">
|
|
{{ progress()!.completedTopics }}/{{ progress()!.totalTopics }} sujets \xB7
|
|
{{ progress()!.completedResources }}/{{ progress()!.totalResources }} ressources
|
|
</p>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
<!-- Enroll button -->
|
|
@if (!isEnrolled() && !isOwnCourse()) {
|
|
<button class="enroll-btn" (click)="enroll()" [disabled]="enrolling()">
|
|
@if (enrolling()) {
|
|
<span nz-icon nzType="loading" nzTheme="outline"></span> Inscription...
|
|
} @else {
|
|
Commencer ce cours →
|
|
}
|
|
</button>
|
|
}
|
|
</div>
|
|
|
|
<!-- Topics -->
|
|
<div class="topics-section">
|
|
<h2 class="section-title">Contenu du cours</h2>
|
|
|
|
@if (course()!.topics.length === 0) {
|
|
<div class="empty-topics">
|
|
<p>Ce cours ne contient pas encore de sujets.</p>
|
|
</div>
|
|
} @else {
|
|
@for (topic of course()!.topics; track topic.id) {
|
|
<div class="topic-card">
|
|
<!-- Topic header -->
|
|
<div class="topic-header" (click)="toggleTopic(topic.id)">
|
|
<div class="topic-position">{{ topic.position }}</div>
|
|
<div class="topic-info">
|
|
<h3 class="topic-title">{{ topic.title }}</h3>
|
|
@if (topic.description) {
|
|
<p class="topic-desc">{{ topic.description }}</p>
|
|
}
|
|
<span class="resource-count">
|
|
{{ topic.resources.length }} ressource{{ topic.resources.length !== 1 ? 's' : '' }}
|
|
</span>
|
|
</div>
|
|
<div class="topic-actions">
|
|
@if (isEnrolled()) {
|
|
<button class="done-btn" (click)="markTopicDone(topic, $event)" title="Marquer comme termin\xE9">
|
|
<span nz-icon nzType="check-circle" nzTheme="outline"></span>
|
|
</button>
|
|
}
|
|
<span
|
|
nz-icon
|
|
[nzType]="isTopicExpanded(topic.id) ? 'menu-fold' : 'menu-unfold'"
|
|
nzTheme="outline"
|
|
class="expand-icon"
|
|
></span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Resources -->
|
|
@if (isTopicExpanded(topic.id) && topic.resources.length > 0) {
|
|
<div class="resources-list">
|
|
@for (resource of topic.resources; track resource.id) {
|
|
<div class="resource-item">
|
|
<div class="resource-icon">
|
|
<span nz-icon [nzType]="getResourceIcon(resource.type)" nzTheme="outline"></span>
|
|
</div>
|
|
<div class="resource-info">
|
|
<p class="resource-title">{{ resource.title }}</p>
|
|
<span class="resource-type">{{ resource.type }}</span>
|
|
</div>
|
|
@if (isEnrolled()) {
|
|
<button class="done-btn small" (click)="markResourceDone(resource, $event)" title="Marquer comme termin\xE9">
|
|
<span nz-icon nzType="check" nzTheme="outline"></span>
|
|
</button>
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
`, styles: ["/* src/app/pages/course-viewer/course-viewer.css */\n.course-viewer-page {\n display: flex;\n flex-direction: column;\n padding-bottom: 100px;\n}\n.loading-screen {\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n color: #1abc9c;\n}\n.loading-spin {\n animation: spin 1s linear infinite;\n}\n@keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n.viewer-header {\n padding: 16px 20px 20px;\n border-bottom: 1px solid var(--border);\n}\n.header-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 20px;\n}\n.back-btn {\n width: 40px;\n height: 40px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 18px;\n color: var(--text);\n}\n.edit-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 12px;\n padding: 8px 14px;\n font-size: 14px;\n font-weight: 600;\n color: var(--text);\n cursor: pointer;\n}\n.course-hero {\n margin-bottom: 16px;\n}\n.course-icon-wrap {\n width: 52px;\n height: 52px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 14px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 24px;\n color: var(--text);\n margin-bottom: 10px;\n}\n.community-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 700;\n color: var(--text-muted);\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n}\n.course-title {\n font-size: 22px;\n font-weight: 800;\n color: var(--text);\n margin: 0 0 8px;\n letter-spacing: -0.3px;\n line-height: 1.2;\n}\n.course-description {\n font-size: 14px;\n color: var(--text-muted);\n margin: 0 0 12px;\n line-height: 1.5;\n}\n.course-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--text-muted);\n}\n.meta-dot {\n color: var(--border);\n}\n.progress-card {\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 14px;\n padding: 14px;\n margin-bottom: 12px;\n}\n.progress-row {\n display: flex;\n justify-content: space-between;\n margin-bottom: 8px;\n}\n.progress-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n}\n.progress-value {\n font-size: 13px;\n font-weight: 700;\n color: #1abc9c;\n}\n.progress-detail {\n font-size: 12px;\n color: var(--text-muted);\n margin: 8px 0 0;\n}\n.enroll-btn {\n width: 100%;\n background-color: var(--primary);\n color: var(--primary-fg);\n border: none;\n border-radius: 14px;\n padding: 16px;\n font-size: 16px;\n font-weight: 700;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: opacity 0.2s;\n}\n.enroll-btn:hover:not(:disabled) {\n opacity: 0.85;\n}\n.enroll-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.topics-section {\n padding: 20px 20px 0;\n}\n.section-title {\n font-size: 16px;\n font-weight: 700;\n color: var(--text);\n margin: 0 0 12px;\n}\n.empty-topics {\n color: var(--text-muted);\n font-size: 14px;\n text-align: center;\n padding: 32px 0;\n}\n.topic-card {\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 14px;\n margin-bottom: 10px;\n overflow: hidden;\n}\n.topic-header {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 14px;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n}\n.topic-position {\n width: 28px;\n height: 28px;\n background: var(--bg);\n border: 1px solid var(--border);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 700;\n color: var(--text-muted);\n flex-shrink: 0;\n}\n.topic-info {\n flex: 1;\n min-width: 0;\n}\n.topic-title {\n font-size: 14px;\n font-weight: 700;\n color: var(--text);\n margin: 0 0 2px;\n}\n.topic-desc {\n font-size: 12px;\n color: var(--text-muted);\n margin: 0 0 4px;\n line-height: 1.4;\n}\n.resource-count {\n font-size: 11px;\n color: var(--text-muted);\n}\n.topic-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n.done-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: #1abc9c;\n font-size: 18px;\n display: flex;\n align-items: center;\n padding: 0;\n}\n.done-btn.small {\n font-size: 14px;\n}\n.expand-icon {\n font-size: 16px;\n color: var(--text-muted);\n}\n.resources-list {\n border-top: 1px solid var(--border);\n}\n.resource-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--border);\n}\n.resource-item:last-child {\n border-bottom: none;\n}\n.resource-icon {\n width: 34px;\n height: 34px;\n background: var(--bg);\n border: 1px solid var(--border);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n color: var(--text-muted);\n flex-shrink: 0;\n}\n.resource-info {\n flex: 1;\n min-width: 0;\n}\n.resource-title {\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n margin: 0 0 2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.resource-type {\n font-size: 11px;\n color: var(--text-muted);\n}\n/*# sourceMappingURL=course-viewer.css.map */\n"] }]
|
|
}], null, null);
|
|
})();
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(CourseViewerPage, { className: "CourseViewerPage", filePath: "src/app/pages/course-viewer/course-viewer.ts", lineNumber: 20 });
|
|
})();
|
|
|
|
// src/app/pages/course-viewer/course-viewer.routes.ts
|
|
var COURSE_VIEWER_ROUTES = [
|
|
{ path: "", component: CourseViewerPage }
|
|
];
|
|
export {
|
|
COURSE_VIEWER_ROUTES
|
|
};
|
|
//# sourceMappingURL=chunk-UQBCWTZZ.js.map
|