Files
2026-05-05 10:53:52 +02:00

401 lines
24 KiB
JavaScript

import {
BottomNav
} from "./chunk-JDU3HACN.js";
import {
DefaultValueAccessor,
FormsModule,
NgControlStatus,
NgModel
} from "./chunk-VD6QIYHN.js";
import {
CourseService
} from "./chunk-6K3TDILH.js";
import {
NzMessageService
} from "./chunk-GJYGTZ7J.js";
import {
AuthService,
NzIconDirective,
NzIconModule,
Router
} from "./chunk-2TRRHRR7.js";
import "./chunk-EDRPZB37.js";
import {
Component,
Input,
Output,
Subject,
debounceTime,
distinctUntilChanged,
inject,
input,
output,
setClassMetadata,
signal,
takeUntil,
ɵsetClassDebugInfo,
ɵɵProvidersFeature,
ɵɵadvance,
ɵɵconditional,
ɵɵconditionalCreate,
ɵɵdefineComponent,
ɵɵelement,
ɵɵelementEnd,
ɵɵelementStart,
ɵɵgetCurrentView,
ɵɵlistener,
ɵɵnextContext,
ɵɵproperty,
ɵɵpureFunction0,
ɵɵrepeater,
ɵɵrepeaterCreate,
ɵɵrepeaterTrackByIndex,
ɵɵresetView,
ɵɵrestoreView,
ɵɵtext,
ɵɵtextInterpolate,
ɵɵtextInterpolate2
} from "./chunk-WI7WFVZR.js";
import "./chunk-WDMUDEB6.js";
// src/app/components/course-card/course-card.ts
function CourseCard_Conditional_13_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "span", 9);
\u0275\u0275text(1);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r0 = \u0275\u0275nextContext();
\u0275\u0275advance();
\u0275\u0275textInterpolate2("\xB7 ", ctx_r0.course().topicCount, " sujet", ctx_r0.course().topicCount > 1 ? "s" : "");
}
}
var CourseCard = class _CourseCard {
course = input.required(...ngDevMode ? [{ debugName: "course" }] : []);
clicked = output();
onClick() {
this.clicked.emit(this.course());
}
static \u0275fac = function CourseCard_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CourseCard)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _CourseCard, selectors: [["app-course-card"]], inputs: { course: [1, "course"] }, outputs: { clicked: "clicked" }, decls: 14, vars: 4, consts: [[1, "course-card", 3, "click"], [1, "card-header"], [1, "community-badge"], [1, "card-body"], [1, "course-title"], [1, "course-description"], [1, "card-footer"], ["nz-icon", "", "nzType", "user", "nzTheme", "outline", 1, "author-icon"], [1, "author-name"], [1, "topic-count"]], template: function CourseCard_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 0);
\u0275\u0275listener("click", function CourseCard_Template_div_click_0_listener() {
return ctx.onClick();
});
\u0275\u0275elementStart(1, "div", 1)(2, "span", 2);
\u0275\u0275text(3, "COMMUNAUT\xC9");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(4, "div", 3)(5, "h3", 4);
\u0275\u0275text(6);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(7, "p", 5);
\u0275\u0275text(8);
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(9, "div", 6);
\u0275\u0275element(10, "span", 7);
\u0275\u0275elementStart(11, "span", 8);
\u0275\u0275text(12);
\u0275\u0275elementEnd();
\u0275\u0275conditionalCreate(13, CourseCard_Conditional_13_Template, 2, 2, "span", 9);
\u0275\u0275elementEnd()();
}
if (rf & 2) {
\u0275\u0275advance(6);
\u0275\u0275textInterpolate(ctx.course().title);
\u0275\u0275advance(2);
\u0275\u0275textInterpolate(ctx.course().description);
\u0275\u0275advance(4);
\u0275\u0275textInterpolate(ctx.course().creatorName);
\u0275\u0275advance();
\u0275\u0275conditional(ctx.course().topicCount > 0 ? 13 : -1);
}
}, dependencies: [NzIconModule, NzIconDirective], styles: ["\n\n.course-card[_ngcontent-%COMP%] {\n background-color: var(--card);\n border: 1px solid var(--border);\n border-radius: 16px;\n padding: 16px;\n cursor: pointer;\n transition: transform 0.15s, box-shadow 0.15s;\n margin-bottom: 12px;\n}\n.course-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);\n}\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 12px;\n}\n.book-icon-wrapper[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n background-color: var(--bg);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--border);\n}\n.book-icon[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--text);\n}\n.community-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.08em;\n color: var(--text-muted);\n background-color: var(--bg);\n border: 1px solid var(--border);\n border-radius: 6px;\n padding: 3px 8px;\n}\n.card-body[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n.course-title[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 700;\n color: var(--text);\n margin: 0 0 6px 0;\n line-height: 1.3;\n}\n.course-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-muted);\n margin: 0;\n line-height: 1.5;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.card-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n.author-icon[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-muted);\n}\n.author-name[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-muted);\n font-weight: 500;\n}\n.topic-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-muted);\n}\n/*# sourceMappingURL=course-card.css.map */"] });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CourseCard, [{
type: Component,
args: [{ selector: "app-course-card", imports: [NzIconModule], template: `<div class="course-card" (click)="onClick()">
<div class="card-header">
<span class="community-badge">COMMUNAUT\xC9</span>
</div>
<div class="card-body">
<h3 class="course-title">{{ course().title }}</h3>
<p class="course-description">{{ course().description }}</p>
</div>
<div class="card-footer">
<span nz-icon nzType="user" nzTheme="outline" class="author-icon"></span>
<span class="author-name">{{ course().creatorName }}</span>
@if (course().topicCount > 0) {
<span class="topic-count">\xB7 {{ course().topicCount }} sujet{{ course().topicCount > 1 ? 's' : '' }}</span>
}
</div>
</div>
`, styles: ["/* src/app/components/course-card/course-card.css */\n.course-card {\n background-color: var(--card);\n border: 1px solid var(--border);\n border-radius: 16px;\n padding: 16px;\n cursor: pointer;\n transition: transform 0.15s, box-shadow 0.15s;\n margin-bottom: 12px;\n}\n.course-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);\n}\n.card-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 12px;\n}\n.book-icon-wrapper {\n width: 44px;\n height: 44px;\n background-color: var(--bg);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--border);\n}\n.book-icon {\n font-size: 20px;\n color: var(--text);\n}\n.community-badge {\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.08em;\n color: var(--text-muted);\n background-color: var(--bg);\n border: 1px solid var(--border);\n border-radius: 6px;\n padding: 3px 8px;\n}\n.card-body {\n margin-bottom: 12px;\n}\n.course-title {\n font-size: 15px;\n font-weight: 700;\n color: var(--text);\n margin: 0 0 6px 0;\n line-height: 1.3;\n}\n.course-description {\n font-size: 13px;\n color: var(--text-muted);\n margin: 0;\n line-height: 1.5;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.card-footer {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n.author-icon {\n font-size: 13px;\n color: var(--text-muted);\n}\n.author-name {\n font-size: 12px;\n color: var(--text-muted);\n font-weight: 500;\n}\n.topic-count {\n font-size: 12px;\n color: var(--text-muted);\n}\n/*# sourceMappingURL=course-card.css.map */\n"] }]
}], null, { course: [{ type: Input, args: [{ isSignal: true, alias: "course", required: true }] }], clicked: [{ type: Output, args: ["clicked"] }] });
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(CourseCard, { className: "CourseCard", filePath: "src/app/components/course-card/course-card.ts", lineNumber: 11 });
})();
// src/app/pages/catalog/catalog.ts
var _c0 = () => [1, 2, 3];
var _forTrack0 = ($index, $item) => $item.id;
function CatalogPage_Conditional_20_For_2_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275element(0, "div", 20);
}
}
function CatalogPage_Conditional_20_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 17);
\u0275\u0275repeaterCreate(1, CatalogPage_Conditional_20_For_2_Template, 1, 0, "div", 20, \u0275\u0275repeaterTrackByIndex);
\u0275\u0275elementEnd();
}
if (rf & 2) {
\u0275\u0275advance();
\u0275\u0275repeater(\u0275\u0275pureFunction0(0, _c0));
}
}
function CatalogPage_Conditional_21_Conditional_4_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "p", 23);
\u0275\u0275text(1, "Essayez un autre terme de recherche");
\u0275\u0275elementEnd();
}
}
function CatalogPage_Conditional_21_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 18);
\u0275\u0275element(1, "span", 21);
\u0275\u0275elementStart(2, "p", 22);
\u0275\u0275text(3, "Aucun cours trouv\xE9");
\u0275\u0275elementEnd();
\u0275\u0275conditionalCreate(4, CatalogPage_Conditional_21_Conditional_4_Template, 2, 0, "p", 23);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r0 = \u0275\u0275nextContext();
\u0275\u0275advance(4);
\u0275\u0275conditional(ctx_r0.searchQuery() ? 4 : -1);
}
}
function CatalogPage_Conditional_22_For_2_Template(rf, ctx) {
if (rf & 1) {
const _r2 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "app-course-card", 25);
\u0275\u0275listener("clicked", function CatalogPage_Conditional_22_For_2_Template_app_course_card_clicked_0_listener($event) {
\u0275\u0275restoreView(_r2);
const ctx_r0 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r0.onCourseClicked($event));
});
\u0275\u0275elementEnd();
}
if (rf & 2) {
const course_r3 = ctx.$implicit;
\u0275\u0275property("course", course_r3);
}
}
function CatalogPage_Conditional_22_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 19);
\u0275\u0275repeaterCreate(1, CatalogPage_Conditional_22_For_2_Template, 1, 1, "app-course-card", 24, _forTrack0);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r0 = \u0275\u0275nextContext();
\u0275\u0275advance();
\u0275\u0275repeater(ctx_r0.courses());
}
}
var CatalogPage = class _CatalogPage {
courseService = inject(CourseService);
authService = inject(AuthService);
router = inject(Router);
message = inject(NzMessageService);
destroy$ = new Subject();
search$ = new Subject();
courses = signal([], ...ngDevMode ? [{ debugName: "courses" }] : []);
loading = signal(false, ...ngDevMode ? [{ debugName: "loading" }] : []);
searchQuery = signal("", ...ngDevMode ? [{ debugName: "searchQuery" }] : []);
isDark = signal(true, ...ngDevMode ? [{ debugName: "isDark" }] : []);
get currentUser() {
return this.authService.currentUser();
}
ngOnInit() {
this.search$.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$)).subscribe((query) => {
this.loadCourses(query);
});
this.loadCourses("");
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
onSearchChange(value) {
this.searchQuery.set(value);
this.search$.next(value);
}
loadCourses(search) {
this.loading.set(true);
this.courseService.getCourses(search).subscribe({
next: (courses) => {
this.courses.set(courses);
this.loading.set(false);
},
error: () => {
this.loading.set(false);
this.message.error("Impossible de charger les cours");
}
});
}
onCourseClicked(course) {
this.router.navigate(["/courses", course.id]);
}
toggleTheme() {
const html = document.documentElement;
if (html.classList.contains("dark")) {
html.classList.remove("dark");
this.isDark.set(false);
} else {
html.classList.add("dark");
this.isDark.set(true);
}
}
logout() {
this.authService.logout();
this.router.navigate(["/auth"]);
}
static \u0275fac = function CatalogPage_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CatalogPage)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _CatalogPage, selectors: [["app-catalog"]], features: [\u0275\u0275ProvidersFeature([NzMessageService])], decls: 24, vars: 4, consts: [[1, "page-container", "catalog-page"], [1, "catalog-header"], [1, "header-top"], [1, "header-logo"], [1, "logo-text"], [1, "header-actions"], ["aria-label", "Toggle theme", 1, "icon-btn", 3, "click"], ["nz-icon", "", 3, "nzType", "nzTheme"], ["aria-label", "D\xE9connexion", 1, "icon-btn", 3, "click"], ["nz-icon", "", "nzType", "logout", "nzTheme", "outline"], [1, "catalog-title-section"], [1, "catalog-title"], [1, "catalog-subtitle"], [1, "search-wrapper"], ["nz-icon", "", "nzType", "search", "nzTheme", "outline", 1, "search-icon"], ["type", "search", "placeholder", "Rechercher des sujets, auteurs...", 1, "search-input", 3, "ngModelChange", "ngModel"], [1, "catalog-content"], [1, "loading-list"], [1, "empty-state"], [1, "courses-list"], [1, "skeleton-card"], ["nz-icon", "", "nzType", "read", "nzTheme", "outline", 1, "empty-icon"], [1, "empty-text"], [1, "empty-hint"], [3, "course"], [3, "clicked", "course"]], template: function CatalogPage_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "div", 3)(4, "span", 4);
\u0275\u0275text(5, "MetaCourse");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(6, "div", 5)(7, "button", 6);
\u0275\u0275listener("click", function CatalogPage_Template_button_click_7_listener() {
return ctx.toggleTheme();
});
\u0275\u0275element(8, "span", 7);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(9, "button", 8);
\u0275\u0275listener("click", function CatalogPage_Template_button_click_9_listener() {
return ctx.logout();
});
\u0275\u0275element(10, "span", 9);
\u0275\u0275elementEnd()()();
\u0275\u0275elementStart(11, "div", 10)(12, "h1", 11);
\u0275\u0275text(13, "Explorer les Cours");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(14, "p", 12);
\u0275\u0275text(15, "D\xE9couvrez de nouvelles comp\xE9tences.");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(16, "div", 13);
\u0275\u0275element(17, "span", 14);
\u0275\u0275elementStart(18, "input", 15);
\u0275\u0275listener("ngModelChange", function CatalogPage_Template_input_ngModelChange_18_listener($event) {
return ctx.onSearchChange($event);
});
\u0275\u0275elementEnd()()();
\u0275\u0275elementStart(19, "div", 16);
\u0275\u0275conditionalCreate(20, CatalogPage_Conditional_20_Template, 3, 1, "div", 17)(21, CatalogPage_Conditional_21_Template, 5, 1, "div", 18)(22, CatalogPage_Conditional_22_Template, 3, 0, "div", 19);
\u0275\u0275elementEnd();
\u0275\u0275element(23, "app-bottom-nav");
\u0275\u0275elementEnd();
}
if (rf & 2) {
\u0275\u0275advance(8);
\u0275\u0275property("nzType", ctx.isDark() ? "bulb" : "bulb")("nzTheme", ctx.isDark() ? "fill" : "outline");
\u0275\u0275advance(10);
\u0275\u0275property("ngModel", ctx.searchQuery());
\u0275\u0275advance(2);
\u0275\u0275conditional(ctx.loading() ? 20 : ctx.courses().length === 0 ? 21 : 22);
}
}, dependencies: [FormsModule, DefaultValueAccessor, NgControlStatus, NgModel, NzIconModule, NzIconDirective, CourseCard, BottomNav], styles: ["\n\n.catalog-page[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n padding-bottom: 80px;\n}\n.catalog-header[_ngcontent-%COMP%] {\n padding: 16px 20px 0;\n background-color: var(--bg);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n.header-top[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 20px;\n}\n.header-logo[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.logo-icon[_ngcontent-%COMP%] {\n font-size: 22px;\n color: var(--text);\n}\n.logo-text[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 800;\n color: var(--text);\n letter-spacing: -0.3px;\n}\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n.icon-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 16px;\n color: var(--text);\n}\n.catalog-title-section[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n.catalog-title[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 800;\n color: var(--text);\n margin: 0 0 4px;\n letter-spacing: -0.5px;\n}\n.catalog-subtitle[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--text-muted);\n margin: 0 0 16px;\n}\n.search-wrapper[_ngcontent-%COMP%] {\n position: relative;\n margin-bottom: 16px;\n}\n.search-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 14px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--text-muted);\n font-size: 16px;\n z-index: 1;\n}\n.search-input[_ngcontent-%COMP%] {\n width: 100%;\n background-color: var(--card);\n border: 1px solid var(--border);\n border-radius: 12px;\n padding: 12px 16px 12px 42px;\n color: var(--text);\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s;\n}\n.search-input[_ngcontent-%COMP%]:focus {\n border-color: #1abc9c;\n}\n.search-input[_ngcontent-%COMP%]::placeholder {\n color: var(--text-muted);\n}\n.catalog-content[_ngcontent-%COMP%] {\n padding: 4px 20px 0;\n}\n.courses-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.loading-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.skeleton-card[_ngcontent-%COMP%] {\n height: 160px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 16px;\n animation: _ngcontent-%COMP%_skeleton-pulse 1.5s ease-in-out infinite;\n}\n@keyframes _ngcontent-%COMP%_skeleton-pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.4;\n }\n}\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n text-align: center;\n}\n.empty-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n color: var(--text-muted);\n margin-bottom: 16px;\n}\n.empty-text[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 600;\n color: var(--text);\n margin: 0 0 8px;\n}\n.empty-hint[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--text-muted);\n margin: 0;\n}\n/*# sourceMappingURL=catalog.css.map */"] });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CatalogPage, [{
type: Component,
args: [{ selector: "app-catalog", imports: [FormsModule, NzIconModule, CourseCard, BottomNav], providers: [NzMessageService], template: `<div class="page-container catalog-page">
<!-- Header -->
<div class="catalog-header">
<div class="header-top">
<div class="header-logo">
<span class="logo-text">MetaCourse</span>
</div>
<div class="header-actions">
<button class="icon-btn" (click)="toggleTheme()" aria-label="Toggle theme">
<span nz-icon [nzType]="isDark() ? 'bulb' : 'bulb'" [nzTheme]="isDark() ? 'fill' : 'outline'"></span>
</button>
<button class="icon-btn" (click)="logout()" aria-label="D\xE9connexion">
<span nz-icon nzType="logout" nzTheme="outline"></span>
</button>
</div>
</div>
<div class="catalog-title-section">
<h1 class="catalog-title">Explorer les Cours</h1>
<p class="catalog-subtitle">D\xE9couvrez de nouvelles comp\xE9tences.</p>
</div>
<!-- Search -->
<div class="search-wrapper">
<span nz-icon nzType="search" nzTheme="outline" class="search-icon"></span>
<input
type="search"
class="search-input"
placeholder="Rechercher des sujets, auteurs..."
[ngModel]="searchQuery()"
(ngModelChange)="onSearchChange($event)"
/>
</div>
</div>
<!-- Course list -->
<div class="catalog-content">
@if (loading()) {
<div class="loading-list">
@for (_ of [1, 2, 3]; track $index) {
<div class="skeleton-card"></div>
}
</div>
} @else if (courses().length === 0) {
<div class="empty-state">
<span nz-icon nzType="read" nzTheme="outline" class="empty-icon"></span>
<p class="empty-text">Aucun cours trouv\xE9</p>
@if (searchQuery()) {
<p class="empty-hint">Essayez un autre terme de recherche</p>
}
</div>
} @else {
<div class="courses-list">
@for (course of courses(); track course.id) {
<app-course-card [course]="course" (clicked)="onCourseClicked($event)" />
}
</div>
}
</div>
<app-bottom-nav />
</div>
`, styles: ["/* src/app/pages/catalog/catalog.css */\n.catalog-page {\n display: flex;\n flex-direction: column;\n padding-bottom: 80px;\n}\n.catalog-header {\n padding: 16px 20px 0;\n background-color: var(--bg);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n.header-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 20px;\n}\n.header-logo {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.logo-icon {\n font-size: 22px;\n color: var(--text);\n}\n.logo-text {\n font-size: 18px;\n font-weight: 800;\n color: var(--text);\n letter-spacing: -0.3px;\n}\n.header-actions {\n display: flex;\n gap: 8px;\n}\n.icon-btn {\n width: 36px;\n height: 36px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 16px;\n color: var(--text);\n}\n.catalog-title-section {\n margin-bottom: 16px;\n}\n.catalog-title {\n font-size: 28px;\n font-weight: 800;\n color: var(--text);\n margin: 0 0 4px;\n letter-spacing: -0.5px;\n}\n.catalog-subtitle {\n font-size: 14px;\n color: var(--text-muted);\n margin: 0 0 16px;\n}\n.search-wrapper {\n position: relative;\n margin-bottom: 16px;\n}\n.search-icon {\n position: absolute;\n left: 14px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--text-muted);\n font-size: 16px;\n z-index: 1;\n}\n.search-input {\n width: 100%;\n background-color: var(--card);\n border: 1px solid var(--border);\n border-radius: 12px;\n padding: 12px 16px 12px 42px;\n color: var(--text);\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s;\n}\n.search-input:focus {\n border-color: #1abc9c;\n}\n.search-input::placeholder {\n color: var(--text-muted);\n}\n.catalog-content {\n padding: 4px 20px 0;\n}\n.courses-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.loading-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.skeleton-card {\n height: 160px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 16px;\n animation: skeleton-pulse 1.5s ease-in-out infinite;\n}\n@keyframes skeleton-pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.4;\n }\n}\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n text-align: center;\n}\n.empty-icon {\n font-size: 48px;\n color: var(--text-muted);\n margin-bottom: 16px;\n}\n.empty-text {\n font-size: 18px;\n font-weight: 600;\n color: var(--text);\n margin: 0 0 8px;\n}\n.empty-hint {\n font-size: 14px;\n color: var(--text-muted);\n margin: 0;\n}\n/*# sourceMappingURL=catalog.css.map */\n"] }]
}], null, null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(CatalogPage, { className: "CatalogPage", filePath: "src/app/pages/catalog/catalog.ts", lineNumber: 20 });
})();
// src/app/pages/catalog/catalog.routes.ts
var CATALOG_ROUTES = [
{ path: "", component: CatalogPage }
];
export {
CATALOG_ROUTES
};
//# sourceMappingURL=chunk-IM6TR7DF.js.map