@academy-sdk/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3315 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
32
+
33
+ // src/components/pages/MyLearningPage.tsx
34
+ import { useState as useState2 } from "react";
35
+ import { Search, X, ChevronDown } from "lucide-react";
36
+
37
+ // src/components/molecules/CourseCard.tsx
38
+ import { useState } from "react";
39
+ import { BookOpen, Clock, Grid2X2 } from "lucide-react";
40
+
41
+ // src/components/utils.ts
42
+ import { clsx } from "clsx";
43
+ import { twMerge } from "tailwind-merge";
44
+ function cn(...inputs) {
45
+ return twMerge(clsx(inputs));
46
+ }
47
+
48
+ // src/components/molecules/CourseCard.tsx
49
+ import { jsx, jsxs } from "react/jsx-runtime";
50
+ function CourseCard({
51
+ id,
52
+ title,
53
+ thumbnail,
54
+ thumbnails,
55
+ totalLessons,
56
+ progress,
57
+ status,
58
+ isFree,
59
+ price = 0,
60
+ currency = "USD",
61
+ description,
62
+ showPrice = true,
63
+ showProgress = true,
64
+ category,
65
+ duration,
66
+ instructorName,
67
+ instructorAvatar,
68
+ originalPrice,
69
+ isBundle = false,
70
+ onClick,
71
+ className
72
+ }) {
73
+ const [imageError, setImageError] = useState(false);
74
+ const clampedProgress = Math.min(Math.max(progress, 0), 100);
75
+ const stripHtml = (html) => {
76
+ if (typeof document === "undefined") return html;
77
+ const tmp = document.createElement("div");
78
+ tmp.innerHTML = html;
79
+ return tmp.textContent || tmp.innerText || "";
80
+ };
81
+ const displayCategory = category || "Design";
82
+ const displayDuration = duration || "3 Month";
83
+ const displayInstructorName = instructorName || (description ? stripHtml(description).slice(0, 15) : "Instructor");
84
+ return /* @__PURE__ */ jsxs(
85
+ "div",
86
+ {
87
+ className: cn(
88
+ "group overflow-hidden rounded-2xl border border-gray-100 bg-white shadow-sm hover:shadow-lg transition-all duration-300 hover:-translate-y-1 h-full flex flex-col min-w-0 w-full cursor-pointer",
89
+ className
90
+ ),
91
+ onClick,
92
+ children: [
93
+ /* @__PURE__ */ jsxs("div", { className: "relative h-[238.66px] w-full overflow-hidden mx-auto px-3 pt-3", children: [
94
+ /* @__PURE__ */ jsx("div", { className: "relative w-full h-full rounded-xl overflow-hidden bg-gray-100", children: isBundle && thumbnails && thumbnails.length > 0 && !imageError ? /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full flex", children: [
95
+ /* @__PURE__ */ jsx("div", { className: "relative h-full w-1/2", children: /* @__PURE__ */ jsx(
96
+ "img",
97
+ {
98
+ src: thumbnails[0],
99
+ alt: `${title} - image 1`,
100
+ className: "w-full h-full object-cover transition-transform duration-300 group-hover:scale-110",
101
+ onError: () => setImageError(true)
102
+ }
103
+ ) }),
104
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col w-1/2 h-full", children: [
105
+ thumbnails[1] && /* @__PURE__ */ jsx("div", { className: cn("relative w-full overflow-hidden", thumbnails.length > 2 ? "h-1/2" : "h-full"), children: /* @__PURE__ */ jsx(
106
+ "img",
107
+ {
108
+ src: thumbnails[1],
109
+ alt: `${title} - image 2`,
110
+ className: "w-full h-full object-cover transition-transform duration-300 group-hover:scale-110",
111
+ onError: () => setImageError(true)
112
+ }
113
+ ) }),
114
+ thumbnails.length > 2 && thumbnails[2] && /* @__PURE__ */ jsx("div", { className: "relative w-full h-1/2 overflow-hidden", children: /* @__PURE__ */ jsx(
115
+ "img",
116
+ {
117
+ src: thumbnails[2],
118
+ alt: `${title} - image 3`,
119
+ className: "w-full h-full object-cover transition-transform duration-300 group-hover:scale-110",
120
+ onError: () => setImageError(true)
121
+ }
122
+ ) })
123
+ ] })
124
+ ] }) : thumbnail && !imageError ? /* @__PURE__ */ jsx(
125
+ "img",
126
+ {
127
+ src: thumbnail,
128
+ alt: title,
129
+ className: "w-full h-full object-cover transition-transform duration-300 group-hover:scale-110",
130
+ onError: () => setImageError(true)
131
+ }
132
+ ) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center bg-gray-200", children: /* @__PURE__ */ jsx(BookOpen, { className: "w-12 h-12 text-gray-400" }) }) }),
133
+ status && /* @__PURE__ */ jsx("div", { className: "absolute right-6 top-5", children: /* @__PURE__ */ jsx(
134
+ "span",
135
+ {
136
+ className: `rounded-full px-3 py-1.5 text-xs font-medium text-white shadow-md ${status === "completed" ? "bg-green-500" : "bg-[rgb(var(--accent-primary))]"}`,
137
+ children: status
138
+ }
139
+ ) })
140
+ ] }),
141
+ /* @__PURE__ */ jsxs("div", { className: "p-5 space-y-3 flex-1 flex flex-col min-w-0", children: [
142
+ (displayCategory || displayDuration) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs text-gray-500", children: [
143
+ displayCategory && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
144
+ /* @__PURE__ */ jsx(Grid2X2, { className: "w-3.5 h-3.5 text-gray-400" }),
145
+ /* @__PURE__ */ jsx("span", { children: displayCategory })
146
+ ] }),
147
+ displayDuration && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
148
+ /* @__PURE__ */ jsx(Clock, { className: "w-3.5 h-3.5 text-gray-400" }),
149
+ /* @__PURE__ */ jsx("span", { children: displayDuration })
150
+ ] })
151
+ ] }),
152
+ /* @__PURE__ */ jsx("h3", { className: "text-base font-bold text-gray-900 line-clamp-2 leading-snug", children: title }),
153
+ description && /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 line-clamp-3 leading-relaxed", children: stripHtml(description) }),
154
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
155
+ showProgress && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
156
+ /* @__PURE__ */ jsx("div", { className: "h-2 overflow-hidden rounded-full bg-gray-100", children: /* @__PURE__ */ jsx(
157
+ "div",
158
+ {
159
+ className: "h-full rounded-full bg-[rgb(var(--accent-primary))] transition-all duration-300",
160
+ style: { width: `${clampedProgress}%` }
161
+ }
162
+ ) }),
163
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs", children: [
164
+ /* @__PURE__ */ jsx("span", { className: "text-gray-400" }),
165
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-500", children: [
166
+ isBundle ? "Course" : "Lesson",
167
+ " ",
168
+ Math.ceil(clampedProgress / 100 * totalLessons),
169
+ " of ",
170
+ totalLessons
171
+ ] })
172
+ ] })
173
+ ] }),
174
+ showPrice && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-3 border-t border-gray-100", children: [
175
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
176
+ instructorAvatar ? /* @__PURE__ */ jsx("div", { className: "w-7 h-7 rounded-full overflow-hidden flex-shrink-0", children: /* @__PURE__ */ jsx("img", { src: instructorAvatar, alt: displayInstructorName, className: "w-full h-full object-cover" }) }) : /* @__PURE__ */ jsx("div", { className: "w-7 h-7 rounded-full bg-gray-200 flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx("span", { className: "text-[10px] font-semibold text-gray-500", children: displayInstructorName.charAt(0).toUpperCase() }) }),
177
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-600 font-medium truncate max-w-[80px]", children: displayInstructorName })
178
+ ] }),
179
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
180
+ !isFree && originalPrice && originalPrice > price && /* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-400 line-through", children: [
181
+ "$",
182
+ originalPrice
183
+ ] }),
184
+ /* @__PURE__ */ jsx("span", { className: "text-lg font-bold text-[rgb(var(--accent-primary))]", children: isFree ? "Free" : `$${price}` })
185
+ ] })
186
+ ] })
187
+ ] })
188
+ ]
189
+ }
190
+ );
191
+ }
192
+
193
+ // src/components/molecules/Pagination.tsx
194
+ import { ChevronLeft, ChevronRight } from "lucide-react";
195
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
196
+ function Pagination({
197
+ currentPage,
198
+ totalPages,
199
+ total,
200
+ pageSize,
201
+ hasNextPage,
202
+ hasPreviousPage,
203
+ onPageChange,
204
+ maxVisiblePages = 5,
205
+ className
206
+ }) {
207
+ const renderPageNumbers = () => {
208
+ const pages = [];
209
+ let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
210
+ let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1);
211
+ if (endPage - startPage < maxVisiblePages - 1) {
212
+ startPage = Math.max(1, endPage - maxVisiblePages + 1);
213
+ }
214
+ for (let i = startPage; i <= endPage; i++) {
215
+ pages.push(
216
+ /* @__PURE__ */ jsx2(
217
+ "button",
218
+ {
219
+ onClick: () => onPageChange(i),
220
+ className: cn(
221
+ "px-3 py-1 rounded cursor-pointer transition-colors",
222
+ i === currentPage ? "bg-theme-accent-primary text-white" : "text-theme-text-primary border border-theme-border-primary hover:bg-theme-bg-tertiary"
223
+ ),
224
+ children: i
225
+ },
226
+ i
227
+ )
228
+ );
229
+ }
230
+ return pages;
231
+ };
232
+ return /* @__PURE__ */ jsxs2("div", { className: cn("flex items-center justify-between border-t border-theme-border-primary pt-4", className), children: [
233
+ /* @__PURE__ */ jsxs2("div", { className: "text-sm text-theme-text-secondary", children: [
234
+ "Showing ",
235
+ (currentPage - 1) * pageSize + 1,
236
+ " to ",
237
+ Math.min(currentPage * pageSize, total),
238
+ " of ",
239
+ total,
240
+ " results"
241
+ ] }),
242
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
243
+ /* @__PURE__ */ jsx2(
244
+ "button",
245
+ {
246
+ onClick: () => onPageChange(currentPage - 1),
247
+ disabled: !hasPreviousPage,
248
+ className: "p-2 rounded border border-theme-border-primary hover:bg-theme-bg-tertiary disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer transition-colors",
249
+ "aria-label": "Previous page",
250
+ children: /* @__PURE__ */ jsx2(ChevronLeft, { className: "h-4 w-4" })
251
+ }
252
+ ),
253
+ renderPageNumbers(),
254
+ /* @__PURE__ */ jsx2(
255
+ "button",
256
+ {
257
+ onClick: () => onPageChange(currentPage + 1),
258
+ disabled: !hasNextPage,
259
+ className: "p-2 rounded border border-theme-border-primary hover:bg-theme-bg-tertiary disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer transition-colors",
260
+ "aria-label": "Next page",
261
+ children: /* @__PURE__ */ jsx2(ChevronRight, { className: "h-4 w-4" })
262
+ }
263
+ )
264
+ ] })
265
+ ] });
266
+ }
267
+
268
+ // src/components/pages/MyLearningPage.tsx
269
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
270
+ function MyLearningPage(props) {
271
+ const noop = () => {
272
+ };
273
+ const {
274
+ courses = [],
275
+ coursesMeta,
276
+ coursesLoading,
277
+ coursesPage = 1,
278
+ onCoursesPageChange = noop,
279
+ bundles = [],
280
+ bundlesMeta,
281
+ bundlesLoading,
282
+ bundlesPage = 1,
283
+ onBundlesPageChange = noop,
284
+ searchQuery = "",
285
+ onSearchChange = noop,
286
+ activeTab = "courses",
287
+ onTabChange = noop,
288
+ statusFilter = "all",
289
+ onStatusFilterChange = noop,
290
+ onCourseClick = noop,
291
+ onBundleClick = noop
292
+ } = props;
293
+ const [showStatusDropdown, setShowStatusDropdown] = useState2(false);
294
+ const isLoading = activeTab === "courses" ? !!coursesLoading : !!bundlesLoading;
295
+ const currentPage = activeTab === "courses" ? coursesPage : bundlesPage;
296
+ const meta = activeTab === "courses" ? coursesMeta : bundlesMeta;
297
+ const onPageChange = activeTab === "courses" ? onCoursesPageChange : onBundlesPageChange;
298
+ const isSearchMode = Boolean(searchQuery.trim());
299
+ const getStatusLabel = () => {
300
+ switch (statusFilter) {
301
+ case "in-progress":
302
+ return "In Progress";
303
+ case "completed":
304
+ return "Completed";
305
+ default:
306
+ return "All Status";
307
+ }
308
+ };
309
+ const handleStatusFilterChange = (status) => {
310
+ onStatusFilterChange(status);
311
+ setShowStatusDropdown(false);
312
+ };
313
+ return /* @__PURE__ */ jsxs3("div", { className: "container mx-auto space-y-6", children: [
314
+ /* @__PURE__ */ jsxs3("div", { children: [
315
+ /* @__PURE__ */ jsx3("h1", { className: "text-3xl font-bold text-theme-text-primary", children: "My Learning Content" }),
316
+ /* @__PURE__ */ jsx3("p", { className: "mt-2 text-lg text-theme-text-secondary", children: "Continue your learning journey with courses and bundles" })
317
+ ] }),
318
+ /* @__PURE__ */ jsxs3("div", { className: "flex gap-4", children: [
319
+ /* @__PURE__ */ jsxs3("div", { className: "relative flex-1", children: [
320
+ /* @__PURE__ */ jsx3(Search, { className: "absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-theme-text-secondary z-10" }),
321
+ /* @__PURE__ */ jsx3(
322
+ "input",
323
+ {
324
+ type: "text",
325
+ placeholder: `Search ${activeTab}...`,
326
+ value: searchQuery,
327
+ onChange: (e) => onSearchChange(e.target.value),
328
+ className: "w-full rounded-lg border border-theme-border-primary bg-theme-bg-secondary pl-10 pr-10 py-2 text-sm text-theme-text-primary placeholder:text-theme-text-secondary focus:outline-none focus:ring-2 focus:ring-theme-accent-primary/30 focus:border-theme-accent-primary transition-all"
329
+ }
330
+ ),
331
+ searchQuery && /* @__PURE__ */ jsx3(
332
+ "button",
333
+ {
334
+ onClick: () => onSearchChange(""),
335
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-theme-text-secondary hover:text-theme-text-primary transition-colors",
336
+ children: /* @__PURE__ */ jsx3(X, { className: "h-5 w-5" })
337
+ }
338
+ )
339
+ ] }),
340
+ !isSearchMode && /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
341
+ /* @__PURE__ */ jsxs3(
342
+ "button",
343
+ {
344
+ onClick: () => setShowStatusDropdown(!showStatusDropdown),
345
+ className: "flex items-center gap-2 min-w-[150px] justify-between px-4 py-2 border border-theme-border-primary rounded-lg text-sm text-theme-text-primary bg-theme-bg-secondary hover:bg-theme-bg-tertiary transition-colors cursor-pointer",
346
+ children: [
347
+ getStatusLabel(),
348
+ /* @__PURE__ */ jsx3(ChevronDown, { className: "h-4 w-4" })
349
+ ]
350
+ }
351
+ ),
352
+ showStatusDropdown && /* @__PURE__ */ jsx3("div", { className: "absolute right-0 mt-2 w-48 rounded-lg border border-theme-border-primary bg-theme-bg-secondary shadow-lg z-10", children: ["all", "in-progress", "completed"].map((s) => /* @__PURE__ */ jsx3(
353
+ "button",
354
+ {
355
+ onClick: () => handleStatusFilterChange(s),
356
+ className: `w-full text-left px-4 py-2 hover:bg-theme-bg-tertiary transition-colors ${statusFilter === s ? "bg-theme-bg-tertiary text-theme-accent-primary font-medium" : "text-theme-text-primary"}`,
357
+ children: s === "all" ? "All Status" : s === "in-progress" ? "In Progress" : "Completed"
358
+ },
359
+ s
360
+ )) })
361
+ ] })
362
+ ] }),
363
+ /* @__PURE__ */ jsx3("div", { className: "flex gap-6 border-b border-theme-border-primary", children: ["courses", "bundles"].map((tab) => /* @__PURE__ */ jsx3(
364
+ "button",
365
+ {
366
+ onClick: () => {
367
+ onTabChange(tab);
368
+ onSearchChange("");
369
+ onStatusFilterChange("all");
370
+ },
371
+ className: `pb-3 px-0 bg-transparent border-0 font-medium text-sm cursor-pointer capitalize ${activeTab === tab ? "border-b-2 border-theme-accent-primary text-theme-accent-primary" : "text-theme-text-secondary hover:text-theme-text-primary border-b-2 border-transparent"}`,
372
+ children: tab.charAt(0).toUpperCase() + tab.slice(1)
373
+ },
374
+ tab
375
+ )) }),
376
+ isLoading && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center justify-center py-16", children: [
377
+ /* @__PURE__ */ jsx3("div", { className: "h-12 w-12 animate-spin rounded-full border-4 border-theme-border-primary border-t-theme-accent-primary" }),
378
+ /* @__PURE__ */ jsxs3("p", { className: "mt-4 text-theme-text-secondary", children: [
379
+ "Loading ",
380
+ activeTab,
381
+ "..."
382
+ ] })
383
+ ] }),
384
+ !isLoading && activeTab === "courses" && courses.length === 0 && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-theme-border-primary bg-theme-bg-secondary py-16 text-center", children: [
385
+ /* @__PURE__ */ jsx3("div", { className: "text-4xl mb-4", children: "\u{1F4DA}" }),
386
+ /* @__PURE__ */ jsx3("h3", { className: "text-xl font-semibold text-theme-text-primary", children: "No courses found" }),
387
+ /* @__PURE__ */ jsx3("p", { className: "mt-2 max-w-md text-theme-text-secondary", children: statusFilter === "all" ? "You don't have any enrolled courses yet" : `You don't have any ${statusFilter === "in-progress" ? "in progress" : "completed"} courses yet` })
388
+ ] }),
389
+ !isLoading && activeTab === "bundles" && bundles.length === 0 && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-theme-border-primary bg-theme-bg-secondary py-16 text-center", children: [
390
+ /* @__PURE__ */ jsx3("div", { className: "text-4xl mb-4", children: "\u{1F4E6}" }),
391
+ /* @__PURE__ */ jsx3("h3", { className: "text-xl font-semibold text-theme-text-primary", children: "No bundles found" }),
392
+ /* @__PURE__ */ jsx3("p", { className: "mt-2 max-w-md text-theme-text-secondary", children: statusFilter === "all" ? "You don't have any enrolled bundles yet" : `You don't have any ${statusFilter === "in-progress" ? "in progress" : "completed"} bundles yet` })
393
+ ] }),
394
+ !isLoading && activeTab === "courses" && courses.length > 0 && /* @__PURE__ */ jsxs3(Fragment, { children: [
395
+ /* @__PURE__ */ jsx3("div", { className: "grid gap-6 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4", children: courses.map((enrollment) => {
396
+ const course = enrollment.course || enrollment;
397
+ const title = (course == null ? void 0 : course.title) || enrollment.title || "";
398
+ const thumbnail = (course == null ? void 0 : course.thumbnail) || enrollment.thumbnail;
399
+ const totalLessons = enrollment.totalNumberOfActivities || enrollment.totalLessons || 0;
400
+ const progress = Math.min(enrollment.progressPercentage || enrollment.progress || 0, 100);
401
+ const status = enrollment.status === "COMPLETED" ? "completed" : enrollment.status === "IN_PROGRESS" ? "in-progress" : void 0;
402
+ const description = ((course == null ? void 0 : course.summary) || enrollment.description || "").replace(/<[^>]*>/g, "");
403
+ return /* @__PURE__ */ jsx3(
404
+ CourseCard,
405
+ {
406
+ id: enrollment.id,
407
+ title,
408
+ thumbnail,
409
+ totalLessons,
410
+ progress,
411
+ status,
412
+ isFree: true,
413
+ price: 0,
414
+ showPrice: false,
415
+ showProgress: true,
416
+ description,
417
+ onClick: () => onCourseClick((course == null ? void 0 : course.id) || enrollment.courseId || enrollment.id, enrollment.id)
418
+ },
419
+ enrollment.id
420
+ );
421
+ }) }),
422
+ meta && /* @__PURE__ */ jsx3(
423
+ Pagination,
424
+ {
425
+ currentPage,
426
+ totalPages: meta.totalPages,
427
+ total: meta.total,
428
+ pageSize: meta.limit || 12,
429
+ hasNextPage: currentPage < meta.totalPages,
430
+ hasPreviousPage: currentPage > 1,
431
+ onPageChange
432
+ }
433
+ )
434
+ ] }),
435
+ !isLoading && activeTab === "bundles" && bundles.length > 0 && /* @__PURE__ */ jsxs3(Fragment, { children: [
436
+ /* @__PURE__ */ jsx3("div", { className: "grid gap-6 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4", children: bundles.map((enrollment) => {
437
+ var _a, _b, _c;
438
+ const thumbnails = (_a = enrollment.courses) == null ? void 0 : _a.slice(0, 3).map((c) => c.thumbnail).filter(Boolean);
439
+ const description = ((_c = (_b = enrollment.courses) == null ? void 0 : _b[0]) == null ? void 0 : _c.summary) || "";
440
+ const status = enrollment.status === "COMPLETED" ? "completed" : enrollment.status === "IN_PROGRESS" ? "in-progress" : void 0;
441
+ return /* @__PURE__ */ jsx3(
442
+ CourseCard,
443
+ {
444
+ id: enrollment.id,
445
+ title: enrollment.bundleTitle || enrollment.title || "",
446
+ thumbnails,
447
+ totalLessons: enrollment.totalCourses || 0,
448
+ progress: Math.min(enrollment.progressPercentage || 0, 100),
449
+ status,
450
+ isFree: true,
451
+ price: 0,
452
+ showPrice: false,
453
+ showProgress: true,
454
+ description,
455
+ isBundle: true,
456
+ onClick: () => onBundleClick(enrollment.sourceBundleId || enrollment.bundleId || enrollment.id)
457
+ },
458
+ enrollment.id
459
+ );
460
+ }) }),
461
+ meta && /* @__PURE__ */ jsx3(
462
+ Pagination,
463
+ {
464
+ currentPage,
465
+ totalPages: meta.totalPages,
466
+ total: meta.total,
467
+ pageSize: meta.limit || 12,
468
+ hasNextPage: currentPage < meta.totalPages,
469
+ hasPreviousPage: currentPage > 1,
470
+ onPageChange
471
+ }
472
+ )
473
+ ] })
474
+ ] });
475
+ }
476
+
477
+ // src/components/pages/CatalogCoursesPage.tsx
478
+ import { useState as useState3 } from "react";
479
+ import { Search as Search2, BookOpen as BookOpen2, Package, Twitter, Facebook, Instagram } from "lucide-react";
480
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
481
+ var FILE_URL = "https://fe-academy-file.dev.magicai-testing-domain.work";
482
+ var FEATURES = [
483
+ "Free E-book, video & consolation",
484
+ "Top instructors from around world",
485
+ "Top courses from your team"
486
+ ];
487
+ var DEALS = [
488
+ { id: 1, discount: "50%", title: "Lorem ipsum dolor", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor", image: `${FILE_URL}/deal-1.png` },
489
+ { id: 2, discount: "10%", title: "Lorem ipsum dolor", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor", image: `${FILE_URL}/deal-2.png` },
490
+ { id: 3, discount: "50%", title: "Lorem ipsum dolor", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor", image: `${FILE_URL}/deal-3.png` }
491
+ ];
492
+ var RECOMMENDED = [
493
+ { id: "d87b963f", title: "testtgfsdfg dfs", thumbnail: `${FILE_URL}/uploads/4e2fd752-e8c0-440a-8622-3102d33e56e7-1771918805146.png`, totalLessons: 1, progress: 0, isFree: true, price: 0 },
494
+ { id: "30ceedf8", title: "tessst 11", thumbnail: `${FILE_URL}/uploads/ec2ebd93-f06e-48ce-914a-116b1b91c480-1771878020911.jpeg`, totalLessons: 1, progress: 0, isFree: true, price: 0 },
495
+ { id: "eae7f568", title: "React", thumbnail: `${FILE_URL}/uploads/ca3257ea-618c-4a61-a4b6-5560c2bf5ec1-1771488717244.png`, totalLessons: 2, progress: 0, isFree: true, price: 0 },
496
+ { id: "26a52485", title: "ll1", thumbnail: `${FILE_URL}/uploads/9bf7f1ca-214b-4a82-862d-f334801bcd53-1771486627052.png`, totalLessons: 1, progress: 0, isFree: true, price: 0 }
497
+ ];
498
+ var SIDE_AVATARS = [`${FILE_URL}/avatar-1.png`, `${FILE_URL}/avatar-2.png`, `${FILE_URL}/avatar-3.png`, `${FILE_URL}/avatar-4.png`];
499
+ function CatalogCoursesPage(props) {
500
+ const noop = (..._args) => {
501
+ };
502
+ const {
503
+ courses = [],
504
+ meta,
505
+ loading = false,
506
+ searchQuery = "",
507
+ page = 1,
508
+ onSearchChange = noop,
509
+ onPageChange = noop,
510
+ onCourseClick = noop,
511
+ activeTab = "courses",
512
+ onTabChange,
513
+ bundleCourses = [],
514
+ bundleMeta,
515
+ bundlesLoading = false,
516
+ bundlePage = 1,
517
+ onBundlePageChange = noop,
518
+ onBundleClick = noop
519
+ } = props;
520
+ const [localQuery, setLocalQuery] = useState3(searchQuery);
521
+ const defaultHeroImage = `${FILE_URL}/catalog-hero-banner.png`;
522
+ const handleSearchSubmit = (e) => {
523
+ e.preventDefault();
524
+ onSearchChange(localQuery);
525
+ };
526
+ const handleSearchChange = (val) => {
527
+ setLocalQuery(val);
528
+ onSearchChange(val);
529
+ };
530
+ const displayCourses = activeTab === "courses" ? courses : bundleCourses;
531
+ const displayMeta = activeTab === "courses" ? meta : bundleMeta;
532
+ const displayLoading = activeTab === "courses" ? loading : bundlesLoading;
533
+ const displayPage = activeTab === "courses" ? page : bundlePage;
534
+ const displayPageChange = activeTab === "courses" ? onPageChange : onBundlePageChange;
535
+ return /* @__PURE__ */ jsxs4("div", { className: "container mx-auto space-y-10", children: [
536
+ /* @__PURE__ */ jsxs4("div", { className: "relative w-full overflow-hidden rounded-2xl", children: [
537
+ /* @__PURE__ */ jsx4(
538
+ "div",
539
+ {
540
+ className: "absolute inset-0 z-0 bg-cover bg-center",
541
+ style: { backgroundImage: `var(--catalog-hero-image, url(${defaultHeroImage}))` },
542
+ children: /* @__PURE__ */ jsx4(
543
+ "div",
544
+ {
545
+ className: "absolute inset-0 backdrop-blur-[1px]",
546
+ style: { background: "linear-gradient(135deg, rgba(73,187,189,0.75) 0%, rgba(73,187,189,0.55) 50%, rgba(73,187,189,0.40) 100%)" }
547
+ }
548
+ )
549
+ }
550
+ ),
551
+ /* @__PURE__ */ jsx4("div", { className: "relative z-10 flex flex-col items-center justify-center px-4 py-8 sm:px-6 sm:py-10 gap-4", children: /* @__PURE__ */ jsxs4(
552
+ "form",
553
+ {
554
+ onSubmit: handleSearchSubmit,
555
+ className: "flex w-full max-w-[680px] bg-white rounded-2xl sm:rounded-full p-1 sm:p-[5px] sm:pl-0 shadow-lg flex-col sm:flex-row gap-1 sm:gap-0 sm:items-center",
556
+ children: [
557
+ /* @__PURE__ */ jsxs4("div", { className: "relative flex-1 flex items-center w-full", children: [
558
+ /* @__PURE__ */ jsx4(Search2, { className: "absolute left-4 sm:left-5 w-5 h-5 text-gray-400 pointer-events-none" }),
559
+ /* @__PURE__ */ jsx4(
560
+ "input",
561
+ {
562
+ type: "text",
563
+ placeholder: activeTab === "courses" ? "Search your favourite course" : "Search your favourite bundle",
564
+ value: localQuery,
565
+ onChange: (e) => handleSearchChange(e.target.value),
566
+ className: "w-full py-3 sm:py-3.5 pl-12 sm:pl-13 pr-4 bg-transparent text-gray-700 text-sm sm:text-[15px] rounded-full border-none outline-none placeholder:text-gray-400"
567
+ }
568
+ )
569
+ ] }),
570
+ /* @__PURE__ */ jsx4(
571
+ "button",
572
+ {
573
+ type: "submit",
574
+ className: "shrink-0 px-8 py-3 bg-theme-accent-primary text-white font-semibold text-sm sm:text-[15px] rounded-xl sm:rounded-full cursor-pointer transition-all duration-150 hover:brightness-110 hover:scale-[1.02] active:scale-[0.98] w-full sm:w-auto",
575
+ children: "Search"
576
+ }
577
+ )
578
+ ]
579
+ }
580
+ ) })
581
+ ] }),
582
+ /* @__PURE__ */ jsx4("div", { className: "flex gap-2", children: [{ id: "courses", label: "Courses", Icon: BookOpen2 }, { id: "bundles", label: "Bundles", Icon: Package }].map(({ id, label, Icon }) => /* @__PURE__ */ jsxs4(
583
+ "button",
584
+ {
585
+ onClick: () => onTabChange == null ? void 0 : onTabChange(id),
586
+ className: `flex items-center gap-2 px-4 py-2.5 font-medium transition-colors cursor-pointer ${activeTab === id ? "border-b-2 border-theme-accent-primary text-theme-accent-primary" : "text-theme-text-secondary hover:text-theme-text-primary"}`,
587
+ children: [
588
+ /* @__PURE__ */ jsx4(Icon, { className: "h-4 w-4" }),
589
+ label
590
+ ]
591
+ },
592
+ id
593
+ )) }),
594
+ displayLoading ? /* @__PURE__ */ jsxs4("div", { className: "flex flex-col items-center justify-center py-16", children: [
595
+ /* @__PURE__ */ jsx4("div", { className: "h-12 w-12 animate-spin rounded-full border-4 border-theme-border-primary border-t-theme-accent-primary" }),
596
+ /* @__PURE__ */ jsxs4("p", { className: "mt-4 text-theme-text-secondary", children: [
597
+ "Loading ",
598
+ activeTab,
599
+ "..."
600
+ ] })
601
+ ] }) : displayCourses.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-theme-border-primary bg-theme-bg-secondary py-16 text-center", children: [
602
+ /* @__PURE__ */ jsx4("div", { className: "text-4xl mb-4", children: activeTab === "courses" ? "\u{1F4DA}" : "\u{1F4E6}" }),
603
+ /* @__PURE__ */ jsxs4("h3", { className: "text-xl font-semibold text-theme-text-primary", children: [
604
+ "No ",
605
+ activeTab,
606
+ " found"
607
+ ] }),
608
+ /* @__PURE__ */ jsx4("p", { className: "mt-2 max-w-md text-theme-text-secondary", children: "Try adjusting your search query or check back later" })
609
+ ] }) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
610
+ /* @__PURE__ */ jsx4("div", { className: "grid gap-6 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4", children: displayCourses.map((course) => {
611
+ var _a;
612
+ const description = (course.summary || course.description || "").replace(/<[^>]*>/g, "");
613
+ const price = (_a = course.price) != null ? _a : 0;
614
+ const isFree = course.isFree !== void 0 ? course.isFree : price === 0;
615
+ return /* @__PURE__ */ jsx4(
616
+ CourseCard,
617
+ {
618
+ id: course.id,
619
+ title: course.title || "",
620
+ thumbnail: course.thumbnail || "",
621
+ totalLessons: course.totalLessons || 0,
622
+ progress: 0,
623
+ showProgress: false,
624
+ isFree,
625
+ price,
626
+ showPrice: true,
627
+ currency: course.currency,
628
+ description,
629
+ instructorName: course.instructorName,
630
+ instructorAvatar: course.instructorAvatar,
631
+ category: course.category,
632
+ originalPrice: course.originalPrice,
633
+ isBundle: activeTab === "bundles",
634
+ thumbnails: course.thumbnails,
635
+ onClick: () => activeTab === "courses" ? onCourseClick(course.id) : onBundleClick(course.id)
636
+ },
637
+ course.id
638
+ );
639
+ }) }),
640
+ displayMeta && displayMeta.totalPages > 1 && /* @__PURE__ */ jsx4(
641
+ Pagination,
642
+ {
643
+ currentPage: displayPage,
644
+ totalPages: displayMeta.totalPages,
645
+ total: displayMeta.total,
646
+ pageSize: displayMeta.limit || 8,
647
+ hasNextPage: displayPage < displayMeta.totalPages,
648
+ hasPreviousPage: displayPage > 1,
649
+ onPageChange: displayPageChange
650
+ }
651
+ )
652
+ ] }),
653
+ /* @__PURE__ */ jsx4("section", { className: "rounded-2xl bg-[#EEF4FA] p-6 sm:p-8 lg:p-10 overflow-hidden", children: /* @__PURE__ */ jsxs4("div", { className: "flex flex-col items-center gap-8 lg:flex-row lg:items-center lg:justify-between px-10", children: [
654
+ /* @__PURE__ */ jsxs4("div", { className: "space-y-6 lg:max-w-md shrink-0 py-4", children: [
655
+ /* @__PURE__ */ jsxs4("h2", { className: "text-2xl font-bold text-gray-900 sm:text-3xl leading-snug", children: [
656
+ "Know about learning",
657
+ /* @__PURE__ */ jsx4("br", {}),
658
+ "learning platform"
659
+ ] }),
660
+ /* @__PURE__ */ jsx4("ul", { className: "space-y-5", children: FEATURES.map((feature, i) => /* @__PURE__ */ jsxs4("li", { className: "flex items-center gap-4 text-sm text-gray-600 font-medium", children: [
661
+ /* @__PURE__ */ jsx4("span", { className: "h-4 w-4 rounded-full bg-[#B8F0E8] shrink-0" }),
662
+ feature
663
+ ] }, i)) }),
664
+ /* @__PURE__ */ jsx4("button", { className: "inline-block rounded-lg bg-theme-accent-primary px-8 py-3.5 text-sm font-bold text-white shadow-md transition-all hover:brightness-110 hover:scale-[1.02] active:scale-[0.98]", children: "Start learning now" })
665
+ ] }),
666
+ /* @__PURE__ */ jsx4("div", { className: "relative w-full max-w-[520px] lg:w-[55%]", children: /* @__PURE__ */ jsx4("div", { className: "aspect-[16/10] w-full flex items-center justify-center bg-[#dbeafe] rounded-xl", children: /* @__PURE__ */ jsx4("span", { className: "text-gray-400 text-sm", children: "Platform Preview" }) }) })
667
+ ] }) }),
668
+ /* @__PURE__ */ jsx4("div", { className: "relative w-screen left-1/2 right-1/2 -ml-[50vw] -mr-[50vw] bg-[#EEF4FA]", children: /* @__PURE__ */ jsx4("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-12", children: /* @__PURE__ */ jsxs4("section", { className: "space-y-6", children: [
669
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between", children: [
670
+ /* @__PURE__ */ jsx4("h2", { className: "text-xl font-bold text-gray-900 sm:text-2xl", children: "Recommended for you" }),
671
+ /* @__PURE__ */ jsx4("button", { className: "shrink-0 text-sm font-semibold text-[rgb(var(--accent-primary))] hover:underline cursor-pointer", children: "See all" })
672
+ ] }),
673
+ /* @__PURE__ */ jsx4("div", { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4", children: RECOMMENDED.map((course) => /* @__PURE__ */ jsx4(
674
+ CourseCard,
675
+ {
676
+ id: course.id,
677
+ title: course.title,
678
+ thumbnail: course.thumbnail,
679
+ totalLessons: course.totalLessons,
680
+ progress: course.progress,
681
+ showProgress: false,
682
+ isFree: course.isFree,
683
+ price: course.price,
684
+ showPrice: true,
685
+ onClick: () => onCourseClick(course.id)
686
+ },
687
+ course.id
688
+ )) })
689
+ ] }) }) }),
690
+ /* @__PURE__ */ jsx4("div", { className: "relative w-screen left-1/2 right-1/2 -ml-[50vw] -mr-[50vw] bg-[#EEF4FA]", children: /* @__PURE__ */ jsx4("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-12", children: /* @__PURE__ */ jsxs4("section", { className: "space-y-6", children: [
691
+ /* @__PURE__ */ jsx4("h2", { className: "text-xl font-bold text-gray-900 sm:text-2xl", children: "What our students have to say" }),
692
+ /* @__PURE__ */ jsx4("div", { className: "rounded-2xl bg-white p-6 sm:p-8 lg:p-14 shadow-sm relative overflow-hidden", children: /* @__PURE__ */ jsxs4("div", { className: "flex flex-col items-center gap-6 lg:flex-row lg:items-center lg:gap-16", children: [
693
+ /* @__PURE__ */ jsx4("div", { className: "relative shrink-0 w-48 h-48 sm:w-64 sm:h-64 bg-gray-100 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx4("img", { src: `${FILE_URL}/student.png`, alt: "Student", className: "w-full h-full object-cover rounded-full", onError: (e) => {
694
+ e.target.style.display = "none";
695
+ } }) }),
696
+ /* @__PURE__ */ jsxs4("div", { className: "flex-1 space-y-4 text-center lg:text-left min-w-0 z-10", children: [
697
+ /* @__PURE__ */ jsxs4("div", { className: "space-y-1", children: [
698
+ /* @__PURE__ */ jsx4("h3", { className: "text-xl font-bold text-gray-900", children: "Savannah Nguyen" }),
699
+ /* @__PURE__ */ jsx4("p", { className: "text-sm text-gray-500 font-medium tracking-wide", children: "tanya.hill@example.com" })
700
+ ] }),
701
+ /* @__PURE__ */ jsxs4("div", { className: "space-y-2 text-sm text-gray-500 leading-relaxed max-w-lg", children: [
702
+ /* @__PURE__ */ jsx4("p", { children: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor" }),
703
+ /* @__PURE__ */ jsx4("p", { children: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor" }),
704
+ /* @__PURE__ */ jsx4("p", { children: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor" })
705
+ ] }),
706
+ /* @__PURE__ */ jsx4("div", { className: "flex items-center gap-3 pt-2 justify-center lg:justify-start", children: [Twitter, Facebook, Instagram].map((Icon, i) => /* @__PURE__ */ jsx4("button", { className: "flex h-8 w-8 items-center justify-center rounded-full bg-theme-accent-primary text-white transition-all hover:scale-110 hover:shadow-md", children: /* @__PURE__ */ jsx4(Icon, { className: "h-4 w-4" }) }, i)) })
707
+ ] }),
708
+ /* @__PURE__ */ jsx4("div", { className: "hidden lg:flex flex-col gap-5 shrink-0 z-10", children: SIDE_AVATARS.map((avatar, i) => /* @__PURE__ */ jsx4("div", { className: "relative h-14 w-14 overflow-hidden rounded-full border-2 border-white shadow-md transition-all hover:scale-110 cursor-pointer hover:border-[#49BBBD]", children: /* @__PURE__ */ jsx4("img", { src: avatar, alt: `Student ${i + 1}`, className: "w-full h-full object-cover", onError: (e) => {
709
+ e.target.style.display = "none";
710
+ } }) }, i)) })
711
+ ] }) })
712
+ ] }) }) }),
713
+ /* @__PURE__ */ jsxs4("section", { className: "space-y-6", children: [
714
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between", children: [
715
+ /* @__PURE__ */ jsx4("h2", { className: "text-xl font-bold text-gray-900 sm:text-2xl", children: "Top Education offers and deals are listed here" }),
716
+ /* @__PURE__ */ jsx4("button", { className: "shrink-0 text-sm font-semibold text-[rgb(var(--accent-primary))] hover:underline cursor-pointer", children: "See all" })
717
+ ] }),
718
+ /* @__PURE__ */ jsx4("div", { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3", children: DEALS.map((deal) => /* @__PURE__ */ jsxs4("div", { className: "group relative overflow-hidden rounded-2xl cursor-pointer h-[320px] sm:h-[350px]", children: [
719
+ /* @__PURE__ */ jsx4("img", { src: deal.image, alt: deal.title, className: "absolute inset-0 w-full h-full object-cover transition-transform duration-500 group-hover:scale-110", onError: (e) => {
720
+ e.target.style.background = "#e5e7eb";
721
+ } }),
722
+ /* @__PURE__ */ jsx4("div", { className: "absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-black/10" }),
723
+ /* @__PURE__ */ jsxs4("div", { className: "absolute inset-0 flex flex-col justify-between p-5 sm:p-6", children: [
724
+ /* @__PURE__ */ jsx4("div", { children: /* @__PURE__ */ jsx4("span", { className: "inline-block rounded-lg bg-[rgb(var(--accent-primary))] px-4 py-2 text-xl font-bold text-white sm:text-2xl", children: deal.discount }) }),
725
+ /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
726
+ /* @__PURE__ */ jsx4("h3", { className: "text-lg font-bold text-white sm:text-xl", children: deal.title }),
727
+ /* @__PURE__ */ jsx4("p", { className: "text-sm text-white/80 leading-relaxed line-clamp-2", children: deal.description })
728
+ ] })
729
+ ] })
730
+ ] }, deal.id)) })
731
+ ] })
732
+ ] });
733
+ }
734
+
735
+ // src/components/pages/CatalogBundlesPage.tsx
736
+ import { Search as Search3, X as X2 } from "lucide-react";
737
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
738
+ function CatalogBundlesPage(props) {
739
+ const noop = (..._args) => {
740
+ };
741
+ const { bundles = [], meta, loading = false, searchQuery = "", page = 1, onSearchChange = noop, onPageChange = noop, onBundleClick = noop } = props;
742
+ return /* @__PURE__ */ jsxs5("div", { className: "space-y-6", children: [
743
+ /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
744
+ /* @__PURE__ */ jsx5(Search3, { className: "absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-theme-text-secondary z-10" }),
745
+ /* @__PURE__ */ jsx5(
746
+ "input",
747
+ {
748
+ type: "text",
749
+ placeholder: "Search bundles...",
750
+ value: searchQuery,
751
+ onChange: (e) => onSearchChange(e.target.value),
752
+ className: "w-full rounded-lg border border-theme-border-primary bg-theme-bg-secondary pl-10 pr-10 py-2 text-sm text-theme-text-primary placeholder:text-theme-text-secondary focus:outline-none focus:ring-2 focus:ring-theme-accent-primary/30 focus:border-theme-accent-primary transition-all"
753
+ }
754
+ ),
755
+ searchQuery && /* @__PURE__ */ jsx5(
756
+ "button",
757
+ {
758
+ onClick: () => onSearchChange(""),
759
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-theme-text-secondary hover:text-theme-text-primary transition-colors",
760
+ children: /* @__PURE__ */ jsx5(X2, { className: "h-5 w-5" })
761
+ }
762
+ )
763
+ ] }),
764
+ loading ? /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center justify-center py-16", children: [
765
+ /* @__PURE__ */ jsx5("div", { className: "h-12 w-12 animate-spin rounded-full border-4 border-theme-border-primary border-t-theme-accent-primary" }),
766
+ /* @__PURE__ */ jsx5("p", { className: "mt-4 text-theme-text-secondary", children: "Loading bundles..." })
767
+ ] }) : bundles.length === 0 ? /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-theme-border-primary bg-theme-bg-secondary py-16 text-center", children: [
768
+ /* @__PURE__ */ jsx5("div", { className: "text-4xl mb-4", children: "\u{1F4E6}" }),
769
+ /* @__PURE__ */ jsx5("h3", { className: "text-xl font-semibold text-theme-text-primary", children: "No bundles found" }),
770
+ /* @__PURE__ */ jsx5("p", { className: "mt-2 max-w-md text-theme-text-secondary", children: "Try adjusting your search query or check back later for new bundles" })
771
+ ] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
772
+ /* @__PURE__ */ jsx5("div", { className: "grid gap-6 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4", children: bundles.map((bundle) => {
773
+ var _a, _b, _c;
774
+ const priceValue = bundle.price !== void 0 && bundle.price !== null ? bundle.price : ((_a = bundle.settings) == null ? void 0 : _a.price) || 0;
775
+ const pricingType = bundle.pricingType || ((_b = bundle.settings) == null ? void 0 : _b.pricingType);
776
+ const isFree = pricingType === "FREE" || !priceValue || priceValue === 0;
777
+ const thumbnails = bundle.courses && bundle.courses.length > 0 ? bundle.courses.sort((a, b) => a.orderIndex - b.orderIndex).slice(0, 3).map((c) => c.thumbnail) : bundle.thumbnails || [];
778
+ return /* @__PURE__ */ jsx5(
779
+ CourseCard,
780
+ {
781
+ id: bundle.id,
782
+ title: bundle.title || "",
783
+ thumbnail: thumbnails[0],
784
+ thumbnails,
785
+ totalLessons: bundle.totalCourses || ((_c = bundle.courses) == null ? void 0 : _c.length) || 0,
786
+ progress: 0,
787
+ showProgress: false,
788
+ isFree,
789
+ price: priceValue,
790
+ showPrice: true,
791
+ currency: bundle.currency,
792
+ description: bundle.description || "",
793
+ isBundle: true,
794
+ onClick: () => onBundleClick(bundle.id)
795
+ },
796
+ bundle.id
797
+ );
798
+ }) }),
799
+ meta && meta.totalPages > 1 && /* @__PURE__ */ jsx5(
800
+ Pagination,
801
+ {
802
+ currentPage: page,
803
+ totalPages: meta.totalPages,
804
+ total: meta.total,
805
+ pageSize: meta.limit || 12,
806
+ hasNextPage: page < meta.totalPages,
807
+ hasPreviousPage: page > 1,
808
+ onPageChange
809
+ }
810
+ )
811
+ ] })
812
+ ] });
813
+ }
814
+
815
+ // src/components/pages/CourseDetailPage.tsx
816
+ import { useState as useState4 } from "react";
817
+ import {
818
+ CheckCircle2,
819
+ ChevronDown as ChevronDown2,
820
+ ChevronRight as ChevronRight2,
821
+ PlayCircle,
822
+ Download,
823
+ FileText,
824
+ Clock as Clock2,
825
+ Monitor,
826
+ Tag,
827
+ X as X3,
828
+ Check,
829
+ BookOpen as BookOpen3
830
+ } from "lucide-react";
831
+
832
+ // src/components/molecules/LoadingSpinner.tsx
833
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
834
+ var sizeClasses = {
835
+ sm: "h-4 w-4",
836
+ md: "h-8 w-8",
837
+ lg: "h-12 w-12"
838
+ };
839
+ function LoadingSpinner({ size = "md", className, text }) {
840
+ return /* @__PURE__ */ jsxs6("div", { className: cn("flex flex-col items-center justify-center gap-3", className), children: [
841
+ /* @__PURE__ */ jsx6(
842
+ "div",
843
+ {
844
+ className: cn(
845
+ "animate-spin rounded-full border-2 border-theme-bg-tertiary border-t-theme-accent-primary",
846
+ sizeClasses[size]
847
+ )
848
+ }
849
+ ),
850
+ text && /* @__PURE__ */ jsx6("p", { className: "text-sm text-theme-text-secondary", children: text })
851
+ ] });
852
+ }
853
+
854
+ // src/components/molecules/EmptyState.tsx
855
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
856
+ function EmptyState({ icon, title, description, action, className }) {
857
+ return /* @__PURE__ */ jsxs7("div", { className: cn("flex flex-col items-center justify-center py-12 text-center", className), children: [
858
+ icon && /* @__PURE__ */ jsx7("div", { className: "mb-4 text-theme-text-muted", children: icon }),
859
+ /* @__PURE__ */ jsx7("h3", { className: "text-lg font-semibold text-theme-text-primary", children: title }),
860
+ description && /* @__PURE__ */ jsx7("p", { className: "mt-2 text-sm text-theme-text-secondary max-w-md", children: description }),
861
+ action && /* @__PURE__ */ jsx7("div", { className: "mt-4", children: action })
862
+ ] });
863
+ }
864
+
865
+ // src/components/pages/CourseDetailPage.tsx
866
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
867
+ function formatCoursePrice(price, isFree, currency = "USD") {
868
+ if (isFree || price === 0) return "Free";
869
+ try {
870
+ return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(price);
871
+ } catch (e) {
872
+ return `${currency} ${price.toFixed(2)}`;
873
+ }
874
+ }
875
+ function formatDuration(seconds) {
876
+ const mins = Math.floor(seconds / 60);
877
+ if (mins >= 60) {
878
+ const hours = Math.floor(mins / 60);
879
+ const remainMins = mins % 60;
880
+ return `${hours}h ${remainMins}m`;
881
+ }
882
+ const secs = seconds % 60;
883
+ return `${mins}:${secs.toString().padStart(2, "0")}`;
884
+ }
885
+ function CourseDetailPage(props) {
886
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
887
+ const noop = (..._args) => {
888
+ };
889
+ const {
890
+ course,
891
+ isLoading = false,
892
+ notFound = false,
893
+ isEnrolled = false,
894
+ enrollmentId = null,
895
+ onEnroll = noop,
896
+ onStartLearning = noop,
897
+ isProcessingEnrollment = false,
898
+ paymentProviders = [],
899
+ onCheckout = noop,
900
+ isProcessingCheckout = false,
901
+ couponCode = "",
902
+ onCouponCodeChange = noop,
903
+ onApplyCoupon = noop,
904
+ appliedCoupon = null,
905
+ couponError = null,
906
+ isApplyingCoupon = false,
907
+ discountedPrice,
908
+ activeTab = "overview",
909
+ onTabChange = noop,
910
+ relatedCourses = [],
911
+ isRelatedLoading = false,
912
+ onRelatedCourseClick = noop,
913
+ ratings,
914
+ ratingSummary
915
+ } = props;
916
+ const [expandedSections, setExpandedSections] = useState4(/* @__PURE__ */ new Set());
917
+ const [selectedLesson, setSelectedLesson] = useState4(null);
918
+ const [showCouponInput, setShowCouponInput] = useState4(false);
919
+ const [imgError, setImgError] = useState4(false);
920
+ if (isLoading) return /* @__PURE__ */ jsx8(LoadingSpinner, { className: "py-20", text: "Loading course..." });
921
+ if (notFound || !course) {
922
+ return /* @__PURE__ */ jsx8(
923
+ EmptyState,
924
+ {
925
+ icon: /* @__PURE__ */ jsx8(BookOpen3, { className: "w-16 h-16" }),
926
+ title: "Course not found",
927
+ description: "The course you're looking for doesn't exist."
928
+ }
929
+ );
930
+ }
931
+ const pricingType = ((_a = course.settings) == null ? void 0 : _a.pricingType) || course.pricingType || "FREE";
932
+ const price = (_d = (_c = (_b = course.settings) == null ? void 0 : _b.price) != null ? _c : course.price) != null ? _d : 0;
933
+ const currency = (_g = (_f = (_e = course.settings) == null ? void 0 : _e.currency) != null ? _f : course.currency) != null ? _g : "USD";
934
+ const isFree = pricingType === "FREE" || price === 0;
935
+ const bannerImage = ((_h = course.settings) == null ? void 0 : _h.banner) || course.bannerImage;
936
+ const thumbnail = course.thumbnail || "";
937
+ const totalLessons = (course.sections || []).reduce(
938
+ (sum, s) => {
939
+ var _a2;
940
+ return sum + (((_a2 = s.activities) == null ? void 0 : _a2.length) || 0);
941
+ },
942
+ 0
943
+ );
944
+ const sections = course.sections || [];
945
+ const hasBanner = bannerImage && bannerImage.trim();
946
+ const toggleSection = (sectionId) => {
947
+ const next = new Set(expandedSections);
948
+ if (next.has(sectionId)) next.delete(sectionId);
949
+ else next.add(sectionId);
950
+ setExpandedSections(next);
951
+ };
952
+ const getButtonText = () => {
953
+ if (isEnrolled) return "Continue Learning";
954
+ if (isFree) return "Enroll for Free";
955
+ if (pricingType === "SUBSCRIPTION") return "Subscribe to Access";
956
+ if (pricingType === "INSTALLMENT") return "Make a Payment";
957
+ return "Buy Course";
958
+ };
959
+ const handleEnrollClick = () => {
960
+ if (isEnrolled && enrollmentId) {
961
+ onStartLearning(enrollmentId);
962
+ return;
963
+ }
964
+ if (isFree) {
965
+ onEnroll();
966
+ return;
967
+ }
968
+ if (paymentProviders.length === 1) {
969
+ const p = paymentProviders[0];
970
+ onCheckout(p.paymentProvider || p.id);
971
+ return;
972
+ }
973
+ onEnroll();
974
+ };
975
+ const renderEnrollmentCard = () => /* @__PURE__ */ jsxs8("div", { className: "bg-white p-4 rounded-xl shadow-lg border border-gray-100", children: [
976
+ thumbnail && !imgError && /* @__PURE__ */ jsx8(
977
+ "img",
978
+ {
979
+ src: thumbnail,
980
+ alt: course.title,
981
+ className: "w-full h-48 object-cover rounded-lg mb-4",
982
+ onError: () => setImgError(true)
983
+ }
984
+ ),
985
+ isEnrolled && /* @__PURE__ */ jsxs8("div", { className: "mb-4 flex items-center justify-center gap-2 text-green-600", children: [
986
+ /* @__PURE__ */ jsx8(Check, { className: "h-5 w-5" }),
987
+ /* @__PURE__ */ jsx8("span", { className: "font-semibold text-sm", children: "You're enrolled" })
988
+ ] }),
989
+ /* @__PURE__ */ jsx8("div", { className: "text-center mb-4", children: appliedCoupon && discountedPrice !== void 0 ? /* @__PURE__ */ jsxs8("div", { className: "space-y-1", children: [
990
+ /* @__PURE__ */ jsx8("div", { className: "text-2xl font-bold text-gray-900", children: formatCoursePrice(discountedPrice, false, currency) }),
991
+ /* @__PURE__ */ jsx8("div", { className: "text-base line-through text-gray-400", children: formatCoursePrice(price, isFree, currency) }),
992
+ /* @__PURE__ */ jsx8("div", { className: "text-sm font-semibold text-gray-900", children: appliedCoupon.discountType === "PERCENTAGE" ? `${appliedCoupon.discountValue}% Off` : formatCoursePrice(appliedCoupon.discountValue, false, currency) })
993
+ ] }) : /* @__PURE__ */ jsxs8("div", { className: "text-2xl font-bold text-gray-900", children: [
994
+ formatCoursePrice(price, isFree, currency),
995
+ pricingType === "SUBSCRIPTION" && /* @__PURE__ */ jsx8("span", { className: "text-lg font-normal text-gray-500", children: " / month" })
996
+ ] }) }),
997
+ /* @__PURE__ */ jsx8(
998
+ "button",
999
+ {
1000
+ onClick: handleEnrollClick,
1001
+ disabled: isProcessingEnrollment || isProcessingCheckout,
1002
+ className: "w-full bg-theme-accent-primary hover:bg-[#3da5a7] text-white font-semibold py-3 px-6 rounded-md transition-colors mb-4 cursor-pointer disabled:opacity-50",
1003
+ children: isProcessingEnrollment || isProcessingCheckout ? "Processing..." : getButtonText()
1004
+ }
1005
+ ),
1006
+ !isEnrolled && !isFree && paymentProviders.length > 1 && paymentProviders.map((provider) => /* @__PURE__ */ jsxs8(
1007
+ "button",
1008
+ {
1009
+ onClick: () => onCheckout(provider.paymentProvider || provider.id),
1010
+ disabled: isProcessingCheckout,
1011
+ className: "w-full bg-theme-accent-primary hover:bg-[#3da5a7] text-white font-semibold py-3 px-6 rounded-md transition-colors mb-2 cursor-pointer disabled:opacity-50",
1012
+ children: [
1013
+ "Pay with ",
1014
+ provider.paymentProvider
1015
+ ]
1016
+ },
1017
+ provider.paymentProvider || provider.id
1018
+ )),
1019
+ !isFree && !isEnrolled && /* @__PURE__ */ jsx8("div", { className: "mb-6", children: appliedCoupon ? /* @__PURE__ */ jsx8("div", { className: "p-3 bg-theme-accent-primary/10 border border-[#49BBBD]/20 rounded-lg", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between", children: [
1020
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
1021
+ /* @__PURE__ */ jsx8(Tag, { className: "h-4 w-4 text-[#49BBBD]" }),
1022
+ /* @__PURE__ */ jsxs8("span", { className: "text-sm font-medium text-[#49BBBD]", children: [
1023
+ 'Coupon "',
1024
+ appliedCoupon.code,
1025
+ '" applied'
1026
+ ] })
1027
+ ] }),
1028
+ /* @__PURE__ */ jsx8(
1029
+ "button",
1030
+ {
1031
+ onClick: () => {
1032
+ onCouponCodeChange("");
1033
+ },
1034
+ className: "text-[#49BBBD] hover:text-[#3da5a7] transition-colors cursor-pointer",
1035
+ children: /* @__PURE__ */ jsx8(X3, { className: "h-4 w-4" })
1036
+ }
1037
+ )
1038
+ ] }) }) : showCouponInput ? /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
1039
+ /* @__PURE__ */ jsxs8("div", { className: "flex gap-2", children: [
1040
+ /* @__PURE__ */ jsx8(
1041
+ "input",
1042
+ {
1043
+ type: "text",
1044
+ placeholder: "Enter coupon code",
1045
+ value: couponCode,
1046
+ onChange: (e) => onCouponCodeChange(e.target.value.toUpperCase()),
1047
+ className: `flex-1 text-sm border rounded-md px-3 py-2 focus:outline-none focus:border-[#49BBBD] ${couponError ? "border-red-500" : "border-gray-300"}`
1048
+ }
1049
+ ),
1050
+ /* @__PURE__ */ jsx8(
1051
+ "button",
1052
+ {
1053
+ onClick: onApplyCoupon,
1054
+ disabled: !couponCode || isApplyingCoupon,
1055
+ className: "px-3 py-2 text-sm bg-theme-accent-primary text-white rounded-md hover:bg-[#3da5a7] disabled:opacity-50 cursor-pointer",
1056
+ children: isApplyingCoupon ? "Applying..." : "Apply"
1057
+ }
1058
+ )
1059
+ ] }),
1060
+ couponError && /* @__PURE__ */ jsx8("p", { className: "text-xs text-red-600", children: couponError })
1061
+ ] }) : /* @__PURE__ */ jsx8(
1062
+ "a",
1063
+ {
1064
+ href: "#",
1065
+ onClick: (e) => {
1066
+ e.preventDefault();
1067
+ setShowCouponInput(true);
1068
+ },
1069
+ className: "block text-center text-sm font-medium text-[#49BBBD] hover:text-[#3da5a7] hover:underline cursor-pointer",
1070
+ children: "Apply Coupon"
1071
+ }
1072
+ ) }),
1073
+ /* @__PURE__ */ jsxs8("div", { className: "border-t border-gray-200 pt-4", children: [
1074
+ /* @__PURE__ */ jsx8("h3", { className: "font-semibold text-gray-900 mb-3 text-sm", children: "This course included" }),
1075
+ /* @__PURE__ */ jsxs8("div", { className: "space-y-2.5", children: [
1076
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2.5 text-gray-700", children: [
1077
+ /* @__PURE__ */ jsx8("div", { className: "w-4 h-4 rounded-full bg-theme-accent-primary flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx8(FileText, { className: "h-2.5 w-2.5 text-white" }) }),
1078
+ /* @__PURE__ */ jsxs8("span", { className: "text-sm", children: [
1079
+ totalLessons,
1080
+ " lessons"
1081
+ ] })
1082
+ ] }),
1083
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2.5 text-gray-700", children: [
1084
+ /* @__PURE__ */ jsx8("div", { className: "w-4 h-4 rounded-full bg-theme-accent-primary flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx8(Clock2, { className: "h-2.5 w-2.5 text-white" }) }),
1085
+ /* @__PURE__ */ jsx8("span", { className: "text-sm", children: "Self-paced learning" })
1086
+ ] }),
1087
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2.5 text-gray-700", children: [
1088
+ /* @__PURE__ */ jsx8("div", { className: "w-4 h-4 rounded-full bg-theme-accent-primary flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx8(Monitor, { className: "h-2.5 w-2.5 text-white" }) }),
1089
+ /* @__PURE__ */ jsx8("span", { className: "text-sm", children: "Access on mobile and desktop" })
1090
+ ] })
1091
+ ] })
1092
+ ] })
1093
+ ] });
1094
+ return /* @__PURE__ */ jsxs8("div", { className: "-mx-4 sm:-mx-4 md:-mx-4 lg:-mx-6 xl:-mx-6", children: [
1095
+ /* @__PURE__ */ jsxs8(
1096
+ "div",
1097
+ {
1098
+ className: "relative text-white px-4 lg:px-8 py-8 lg:py-40 mb-8",
1099
+ style: hasBanner ? { backgroundImage: `url(${bannerImage})`, backgroundSize: "cover", backgroundPosition: "center" } : { backgroundColor: "#1a2332" },
1100
+ children: [
1101
+ hasBanner && /* @__PURE__ */ jsx8("div", { className: "absolute inset-0 bg-gradient-to-r from-black/60 via-black/50 to-black/40" }),
1102
+ /* @__PURE__ */ jsxs8("div", { className: "relative z-10", children: [
1103
+ /* @__PURE__ */ jsxs8("div", { className: "max-w-7xl lg:pr-110", children: [
1104
+ /* @__PURE__ */ jsx8("h1", { className: "text-3xl lg:text-4xl font-bold mb-2", children: course.title }),
1105
+ course.brief && /* @__PURE__ */ jsx8("p", { className: "text-base lg:text-lg text-gray-300 mb-4 leading-relaxed", children: course.brief }),
1106
+ course.creator && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 mt-4 lg:mt-6", children: [
1107
+ /* @__PURE__ */ jsx8("div", { className: "w-10 h-10 rounded-full bg-theme-accent-primary flex items-center justify-center text-white font-semibold", children: (course.creator.name || "C").charAt(0).toUpperCase() }),
1108
+ /* @__PURE__ */ jsx8("span", { className: "text-sm", children: course.creator.name })
1109
+ ] })
1110
+ ] }),
1111
+ /* @__PURE__ */ jsx8("div", { className: "lg:hidden mt-6", children: renderEnrollmentCard() })
1112
+ ] }),
1113
+ /* @__PURE__ */ jsx8("div", { className: "hidden lg:block absolute right-8 top-15 w-80 z-20", children: renderEnrollmentCard() })
1114
+ ]
1115
+ }
1116
+ ),
1117
+ /* @__PURE__ */ jsx8("div", { className: "px-4 lg:px-6 mb-6", children: /* @__PURE__ */ jsx8("div", { className: "flex gap-3", children: ["overview", "curriculum"].map((tab) => /* @__PURE__ */ jsx8(
1118
+ "button",
1119
+ {
1120
+ onClick: () => onTabChange(tab),
1121
+ className: `px-6 py-2.5 rounded-full text-sm font-medium transition-all cursor-pointer ${activeTab === tab ? "bg-theme-accent-primary text-white shadow-md" : "bg-white text-gray-600 border border-gray-200 hover:border-[#49BBBD] hover:text-[#49BBBD]"}`,
1122
+ children: tab.charAt(0).toUpperCase() + tab.slice(1)
1123
+ },
1124
+ tab
1125
+ )) }) }),
1126
+ /* @__PURE__ */ jsxs8("div", { className: "px-4 lg:px-6", children: [
1127
+ activeTab === "overview" && /* @__PURE__ */ jsxs8("div", { className: "lg:pr-110", children: [
1128
+ /* @__PURE__ */ jsxs8("div", { className: "mb-8 pb-8 border-b border-gray-300", children: [
1129
+ /* @__PURE__ */ jsx8("h2", { className: "text-xl font-bold text-gray-900 mb-4", children: "About This Course" }),
1130
+ course.summary && /* @__PURE__ */ jsx8(
1131
+ "div",
1132
+ {
1133
+ className: "text-gray-700 text-sm leading-relaxed mb-6",
1134
+ dangerouslySetInnerHTML: { __html: course.summary }
1135
+ }
1136
+ ),
1137
+ course.description && /* @__PURE__ */ jsx8(
1138
+ "div",
1139
+ {
1140
+ className: "text-gray-700 text-sm leading-relaxed",
1141
+ dangerouslySetInnerHTML: { __html: course.description }
1142
+ }
1143
+ )
1144
+ ] }),
1145
+ course.whatYouWillLearn && course.whatYouWillLearn.length > 0 && /* @__PURE__ */ jsxs8("div", { className: "mb-8 pb-8 border-b border-gray-300", children: [
1146
+ /* @__PURE__ */ jsx8("h2", { className: "text-xl font-bold text-gray-900 mb-4", children: "What You'll Learn" }),
1147
+ /* @__PURE__ */ jsx8("div", { className: "grid md:grid-cols-2 gap-3", children: course.whatYouWillLearn.map((item, i) => /* @__PURE__ */ jsxs8("div", { className: "flex items-start gap-3", children: [
1148
+ /* @__PURE__ */ jsx8(CheckCircle2, { className: "h-5 w-5 text-green-600 flex-shrink-0" }),
1149
+ /* @__PURE__ */ jsx8("span", { className: "text-sm text-gray-700", children: item })
1150
+ ] }, i)) })
1151
+ ] }),
1152
+ course.requirements && course.requirements.length > 0 && /* @__PURE__ */ jsxs8("div", { className: "mb-8 pb-8 border-b border-gray-300", children: [
1153
+ /* @__PURE__ */ jsx8("h2", { className: "text-xl font-bold text-gray-900 mb-4", children: "Requirements" }),
1154
+ /* @__PURE__ */ jsx8("ul", { className: "space-y-2", children: course.requirements.map((item, i) => /* @__PURE__ */ jsxs8("li", { className: "flex items-start gap-2", children: [
1155
+ /* @__PURE__ */ jsx8("span", { className: "text-gray-400 text-sm", children: "\u2022" }),
1156
+ /* @__PURE__ */ jsx8("span", { className: "text-sm text-gray-700", children: item })
1157
+ ] }, i)) })
1158
+ ] }),
1159
+ course.targetAudience && course.targetAudience.length > 0 && /* @__PURE__ */ jsxs8("div", { className: "mb-8 pb-8 border-b border-gray-300", children: [
1160
+ /* @__PURE__ */ jsx8("h2", { className: "text-xl font-bold text-gray-900 mb-4", children: "Who This Course Is For" }),
1161
+ /* @__PURE__ */ jsx8("ul", { className: "space-y-2", children: course.targetAudience.map((item, i) => /* @__PURE__ */ jsxs8("li", { className: "flex items-start gap-2", children: [
1162
+ /* @__PURE__ */ jsx8("span", { className: "text-gray-400 text-sm", children: "\u2022" }),
1163
+ /* @__PURE__ */ jsx8("span", { className: "text-sm text-gray-700", children: item })
1164
+ ] }, i)) })
1165
+ ] }),
1166
+ ratingSummary && /* @__PURE__ */ jsxs8("div", { className: "mb-8", children: [
1167
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-4 mb-6", children: [
1168
+ /* @__PURE__ */ jsx8("div", { className: "text-5xl font-bold text-yellow-500", children: (_i = ratingSummary.averageRating) == null ? void 0 : _i.toFixed(1) }),
1169
+ /* @__PURE__ */ jsxs8("div", { children: [
1170
+ /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-1 mb-1", children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx8(
1171
+ "svg",
1172
+ {
1173
+ className: `w-4 h-4 ${star <= Math.round(ratingSummary.averageRating || 0) ? "text-yellow-400 fill-yellow-400" : "text-gray-300 fill-gray-300"}`,
1174
+ viewBox: "0 0 24 24",
1175
+ children: /* @__PURE__ */ jsx8("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" })
1176
+ },
1177
+ star
1178
+ )) }),
1179
+ /* @__PURE__ */ jsxs8("p", { className: "text-sm text-gray-600", children: [
1180
+ "Course Rating \u2022 ",
1181
+ ratingSummary.totalRatings,
1182
+ " ratings"
1183
+ ] })
1184
+ ] })
1185
+ ] }),
1186
+ ratings && ratings.slice(0, 2).map((review) => /* @__PURE__ */ jsxs8("div", { className: "mb-4 p-4 border border-gray-200 rounded-lg", children: [
1187
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 mb-2", children: [
1188
+ /* @__PURE__ */ jsx8("div", { className: "w-9 h-9 rounded-full bg-theme-accent-primary flex items-center justify-center text-white font-semibold text-sm", children: (review.reviewerName || "U").charAt(0) }),
1189
+ /* @__PURE__ */ jsxs8("div", { children: [
1190
+ /* @__PURE__ */ jsx8("p", { className: "font-medium text-sm", children: review.reviewerName }),
1191
+ /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-1", children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx8(
1192
+ "svg",
1193
+ {
1194
+ className: `w-3 h-3 ${star <= (review.rating || 0) ? "text-yellow-400 fill-yellow-400" : "text-gray-300 fill-gray-300"}`,
1195
+ viewBox: "0 0 24 24",
1196
+ children: /* @__PURE__ */ jsx8("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" })
1197
+ },
1198
+ star
1199
+ )) })
1200
+ ] })
1201
+ ] }),
1202
+ review.review && /* @__PURE__ */ jsx8("p", { className: "text-sm text-gray-700", children: review.review })
1203
+ ] }, review.id))
1204
+ ] })
1205
+ ] }),
1206
+ activeTab === "curriculum" && /* @__PURE__ */ jsxs8("div", { className: "mb-8", children: [
1207
+ /* @__PURE__ */ jsx8("h2", { className: "text-xl font-bold text-gray-900 mb-4", children: "Curriculum" }),
1208
+ /* @__PURE__ */ jsx8("div", { className: "space-y-1", children: sections.map((section) => {
1209
+ var _a2, _b2;
1210
+ return /* @__PURE__ */ jsxs8("div", { className: "border border-gray-200 rounded overflow-hidden", children: [
1211
+ /* @__PURE__ */ jsxs8(
1212
+ "button",
1213
+ {
1214
+ onClick: () => toggleSection(section.id),
1215
+ className: "w-full flex items-center justify-between p-3 hover:bg-gray-50 transition-colors text-left cursor-pointer",
1216
+ children: [
1217
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
1218
+ expandedSections.has(section.id) ? /* @__PURE__ */ jsx8(ChevronDown2, { className: "h-4 w-4 text-gray-600" }) : /* @__PURE__ */ jsx8(ChevronRight2, { className: "h-4 w-4 text-gray-600" }),
1219
+ /* @__PURE__ */ jsxs8("div", { children: [
1220
+ /* @__PURE__ */ jsx8("span", { className: "text-sm font-medium text-gray-900", children: section.title }),
1221
+ section.description && /* @__PURE__ */ jsx8("p", { className: "text-xs text-gray-500 mt-0.5", children: section.description })
1222
+ ] })
1223
+ ] }),
1224
+ /* @__PURE__ */ jsxs8("span", { className: "text-xs text-gray-500", children: [
1225
+ ((_a2 = section.activities) == null ? void 0 : _a2.length) || 0,
1226
+ " lessons"
1227
+ ] })
1228
+ ]
1229
+ }
1230
+ ),
1231
+ expandedSections.has(section.id) && /* @__PURE__ */ jsx8("div", { className: "bg-gray-50 border-t border-gray-200", children: (_b2 = section.activities) == null ? void 0 : _b2.map((activity) => {
1232
+ const isSelected = selectedLesson === activity.id;
1233
+ return /* @__PURE__ */ jsxs8(
1234
+ "button",
1235
+ {
1236
+ onClick: () => setSelectedLesson(activity.id),
1237
+ className: `w-full flex items-start justify-between gap-3 px-10 py-3 border-b border-gray-100 last:border-b-0 transition-colors text-left cursor-pointer ${isSelected ? "bg-blue-50 border-l-4 border-l-blue-600" : "hover:bg-gray-100"}`,
1238
+ children: [
1239
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-start gap-3 flex-1", children: [
1240
+ /* @__PURE__ */ jsx8(
1241
+ PlayCircle,
1242
+ {
1243
+ className: `h-4 w-4 flex-shrink-0 mt-0.5 ${isSelected ? "text-blue-600" : "text-gray-400"}`
1244
+ }
1245
+ ),
1246
+ /* @__PURE__ */ jsx8("div", { className: "flex-1", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
1247
+ /* @__PURE__ */ jsx8("span", { className: `text-xs font-medium ${isSelected ? "text-blue-600" : "text-gray-700"}`, children: activity.title }),
1248
+ activity.freePreview && /* @__PURE__ */ jsx8("span", { className: "text-xs px-2 py-0.5 bg-blue-100 text-blue-700 rounded", children: "Preview" })
1249
+ ] }) })
1250
+ ] }),
1251
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 flex-shrink-0", children: [
1252
+ activity.downloadable && /* @__PURE__ */ jsx8(Download, { className: "h-3 w-3 text-gray-400" }),
1253
+ activity.duration && /* @__PURE__ */ jsx8("span", { className: "text-xs text-gray-500", children: typeof activity.duration === "number" ? formatDuration(activity.duration) : activity.duration })
1254
+ ] })
1255
+ ]
1256
+ },
1257
+ activity.id
1258
+ );
1259
+ }) })
1260
+ ] }, section.id);
1261
+ }) })
1262
+ ] })
1263
+ ] }),
1264
+ activeTab === "overview" && (relatedCourses.length > 0 || isRelatedLoading) && /* @__PURE__ */ jsx8("div", { className: "mt-8 bg-[#EEF4FA] border-t border-gray-200 pb-8", children: /* @__PURE__ */ jsx8("div", { className: "px-4 lg:px-6", children: /* @__PURE__ */ jsxs8("section", { className: "py-10", children: [
1265
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between mb-6", children: [
1266
+ /* @__PURE__ */ jsx8("h2", { className: "text-xl font-bold text-gray-900", children: "Related Courses" }),
1267
+ /* @__PURE__ */ jsx8("button", { className: "text-sm font-medium text-[#49BBBD] hover:underline cursor-pointer", children: "See all" })
1268
+ ] }),
1269
+ isRelatedLoading ? /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6", children: [...Array(4)].map((_, i) => /* @__PURE__ */ jsx8("div", { className: "rounded-2xl bg-gray-100 animate-pulse h-64" }, i)) }) : /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6", children: relatedCourses.map((c) => {
1270
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2;
1271
+ const cIsFree = ((_a2 = c.settings) == null ? void 0 : _a2.pricingType) === "FREE" || !((_b2 = c.settings) == null ? void 0 : _b2.price) && !c.price;
1272
+ const cPrice = (_e2 = (_d2 = (_c2 = c.settings) == null ? void 0 : _c2.price) != null ? _d2 : c.price) != null ? _e2 : 0;
1273
+ const cCurrency = (_h2 = (_g2 = (_f2 = c.settings) == null ? void 0 : _f2.currency) != null ? _g2 : c.currency) != null ? _h2 : "USD";
1274
+ return /* @__PURE__ */ jsxs8(
1275
+ "div",
1276
+ {
1277
+ onClick: () => onRelatedCourseClick(c.id),
1278
+ className: "bg-white rounded-2xl overflow-hidden shadow-sm border border-gray-100 hover:shadow-md transition-shadow cursor-pointer",
1279
+ children: [
1280
+ /* @__PURE__ */ jsx8("div", { className: "h-40 bg-gray-100 overflow-hidden", children: c.thumbnail && /* @__PURE__ */ jsx8(
1281
+ "img",
1282
+ {
1283
+ src: c.thumbnail,
1284
+ alt: c.title,
1285
+ className: "w-full h-full object-cover"
1286
+ }
1287
+ ) }),
1288
+ /* @__PURE__ */ jsxs8("div", { className: "p-4", children: [
1289
+ /* @__PURE__ */ jsx8("h3", { className: "font-semibold text-gray-900 text-sm mb-2 line-clamp-2", children: c.title }),
1290
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between text-xs text-gray-500", children: [
1291
+ /* @__PURE__ */ jsxs8("span", { children: [
1292
+ (_i2 = c.totalLessons) != null ? _i2 : 0,
1293
+ " lessons"
1294
+ ] }),
1295
+ /* @__PURE__ */ jsx8("span", { className: cIsFree ? "text-green-600 font-medium" : "font-semibold text-gray-900", children: cIsFree ? "Free" : formatCoursePrice(cPrice, false, cCurrency) })
1296
+ ] })
1297
+ ] })
1298
+ ]
1299
+ },
1300
+ c.id
1301
+ );
1302
+ }) })
1303
+ ] }) }) })
1304
+ ] });
1305
+ }
1306
+
1307
+ // src/components/pages/BundleDetailPage.tsx
1308
+ import { useState as useState5 } from "react";
1309
+ import {
1310
+ Check as Check2,
1311
+ Tag as Tag2,
1312
+ X as X4,
1313
+ FileText as FileText2,
1314
+ Clock as Clock3,
1315
+ Monitor as Monitor2,
1316
+ BookOpen as BookOpen4,
1317
+ ChevronDown as ChevronDown3,
1318
+ ChevronRight as ChevronRight3,
1319
+ Package as Package2
1320
+ } from "lucide-react";
1321
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1322
+ function formatCoursePrice2(price, isFree, currency = "USD") {
1323
+ if (isFree || price === 0) return "Free";
1324
+ try {
1325
+ return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(price);
1326
+ } catch (e) {
1327
+ return `${currency} ${price.toFixed(2)}`;
1328
+ }
1329
+ }
1330
+ function BundleDetailPage(props) {
1331
+ var _a, _b, _c, _d;
1332
+ const noop = (..._args) => {
1333
+ };
1334
+ const {
1335
+ bundle,
1336
+ isLoading = false,
1337
+ notFound = false,
1338
+ isEnrolled = false,
1339
+ onEnroll = noop,
1340
+ isProcessingEnrollment = false,
1341
+ paymentProviders = [],
1342
+ onCheckout = noop,
1343
+ isProcessingCheckout = false,
1344
+ couponCode = "",
1345
+ onCouponCodeChange = noop,
1346
+ onApplyCoupon = noop,
1347
+ appliedCoupon = null,
1348
+ couponError = null,
1349
+ onCourseClick = noop
1350
+ } = props;
1351
+ const [expandedCourses, setExpandedCourses] = useState5(/* @__PURE__ */ new Set());
1352
+ const [showCouponInput, setShowCouponInput] = useState5(false);
1353
+ const [imgErrors, setImgErrors] = useState5({});
1354
+ if (isLoading) return /* @__PURE__ */ jsx9(LoadingSpinner, { className: "py-20", text: "Loading bundle..." });
1355
+ if (notFound || !bundle) {
1356
+ return /* @__PURE__ */ jsx9(
1357
+ EmptyState,
1358
+ {
1359
+ icon: /* @__PURE__ */ jsx9(Package2, { className: "w-16 h-16" }),
1360
+ title: "Bundle not found",
1361
+ description: "The bundle you're looking for doesn't exist."
1362
+ }
1363
+ );
1364
+ }
1365
+ const b = bundle;
1366
+ const pricingType = b.pricingType || "FREE";
1367
+ const price = (_a = b.price) != null ? _a : 0;
1368
+ const currency = (_b = b.currency) != null ? _b : "USD";
1369
+ const isFree = pricingType === "FREE" || price === 0;
1370
+ const totalCourses = ((_c = b.courses) == null ? void 0 : _c.length) || 0;
1371
+ const creatorName = ((_d = b.creator) == null ? void 0 : _d.name) || "Academy Team";
1372
+ const courses = b.courses || [];
1373
+ const toggleCourse = (courseId) => {
1374
+ const next = new Set(expandedCourses);
1375
+ if (next.has(courseId)) next.delete(courseId);
1376
+ else next.add(courseId);
1377
+ setExpandedCourses(next);
1378
+ };
1379
+ const getButtonText = () => {
1380
+ if (isEnrolled) return "You are enrolled";
1381
+ if (isFree) return "Enroll for free";
1382
+ if (pricingType === "SUBSCRIPTION") return "Subscribe to access";
1383
+ if (pricingType === "INSTALLMENT") return "Make a payment";
1384
+ return "Buy bundle";
1385
+ };
1386
+ const handleEnrollClick = () => {
1387
+ if (isEnrolled) return;
1388
+ if (isFree) {
1389
+ onEnroll();
1390
+ return;
1391
+ }
1392
+ if (paymentProviders.length === 1) {
1393
+ const p = paymentProviders[0];
1394
+ onCheckout(p.paymentProvider || p.id);
1395
+ return;
1396
+ }
1397
+ onEnroll();
1398
+ };
1399
+ const thumbnails = courses.slice(0, 3).map((c) => {
1400
+ var _a2;
1401
+ return c.thumbnail || ((_a2 = c.course) == null ? void 0 : _a2.thumbnail);
1402
+ }).filter(Boolean);
1403
+ const renderEnrollmentCard = () => /* @__PURE__ */ jsxs9("div", { className: "bg-white p-4 rounded-xl shadow-lg border border-gray-100", children: [
1404
+ thumbnails.length > 0 ? /* @__PURE__ */ jsxs9("div", { className: "relative w-full h-48 flex mb-4 rounded-lg overflow-hidden", children: [
1405
+ /* @__PURE__ */ jsx9("div", { className: "relative h-full w-1/2 bg-gray-100", children: /* @__PURE__ */ jsx9(
1406
+ "img",
1407
+ {
1408
+ src: thumbnails[0],
1409
+ alt: "Bundle course 1",
1410
+ className: "w-full h-full object-cover",
1411
+ onError: () => setImgErrors((p) => __spreadProps(__spreadValues({}, p), { t0: true }))
1412
+ }
1413
+ ) }),
1414
+ /* @__PURE__ */ jsxs9("div", { className: "flex flex-col w-1/2 h-full", children: [
1415
+ /* @__PURE__ */ jsx9("div", { className: `relative w-full overflow-hidden bg-gray-100 ${thumbnails.length > 1 ? "h-1/2" : "h-full"}`, children: thumbnails[1] && /* @__PURE__ */ jsx9(
1416
+ "img",
1417
+ {
1418
+ src: thumbnails[1],
1419
+ alt: "Bundle course 2",
1420
+ className: "w-full h-full object-cover",
1421
+ onError: () => setImgErrors((p) => __spreadProps(__spreadValues({}, p), { t1: true }))
1422
+ }
1423
+ ) }),
1424
+ thumbnails.length > 2 && /* @__PURE__ */ jsx9("div", { className: "relative w-full h-1/2 overflow-hidden bg-gray-100", children: /* @__PURE__ */ jsx9(
1425
+ "img",
1426
+ {
1427
+ src: thumbnails[2],
1428
+ alt: "Bundle course 3",
1429
+ className: "w-full h-full object-cover",
1430
+ onError: () => setImgErrors((p) => __spreadProps(__spreadValues({}, p), { t2: true }))
1431
+ }
1432
+ ) })
1433
+ ] })
1434
+ ] }) : /* @__PURE__ */ jsx9("div", { className: "w-full h-48 bg-gray-100 rounded-lg mb-4 flex items-center justify-center", children: /* @__PURE__ */ jsx9(Package2, { className: "w-16 h-16 text-gray-300" }) }),
1435
+ isEnrolled && /* @__PURE__ */ jsxs9("div", { className: "mb-4 flex items-center gap-2 text-green-600", children: [
1436
+ /* @__PURE__ */ jsx9(Check2, { className: "h-5 w-5" }),
1437
+ /* @__PURE__ */ jsx9("span", { className: "font-semibold text-sm", children: "Enrolled in this bundle" })
1438
+ ] }),
1439
+ /* @__PURE__ */ jsxs9("div", { className: "text-center mb-4", children: [
1440
+ /* @__PURE__ */ jsxs9("div", { className: "text-2xl font-bold text-gray-900", children: [
1441
+ formatCoursePrice2(price, isFree, currency),
1442
+ pricingType === "SUBSCRIPTION" && /* @__PURE__ */ jsx9("span", { className: "text-lg font-normal text-gray-500", children: " / month" })
1443
+ ] }),
1444
+ !isFree && !isEnrolled && /* @__PURE__ */ jsx9("p", { className: "text-sm text-[#49BBBD] font-medium mt-1", children: "Bundle Deal" })
1445
+ ] }),
1446
+ !isEnrolled && /* @__PURE__ */ jsx9(
1447
+ "button",
1448
+ {
1449
+ onClick: handleEnrollClick,
1450
+ disabled: isProcessingEnrollment || isProcessingCheckout,
1451
+ className: "w-full bg-theme-accent-primary hover:bg-[#3da5a7] text-white font-semibold py-3 px-6 rounded-md transition-colors mb-4 cursor-pointer disabled:opacity-50",
1452
+ children: isProcessingEnrollment || isProcessingCheckout ? "Processing..." : getButtonText()
1453
+ }
1454
+ ),
1455
+ !isEnrolled && !isFree && paymentProviders.length > 1 && paymentProviders.map((provider) => /* @__PURE__ */ jsxs9(
1456
+ "button",
1457
+ {
1458
+ onClick: () => onCheckout(provider.paymentProvider || provider.id),
1459
+ disabled: isProcessingCheckout,
1460
+ className: "w-full bg-theme-accent-primary hover:bg-[#3da5a7] text-white font-semibold py-3 px-6 rounded-md transition-colors mb-2 cursor-pointer disabled:opacity-50",
1461
+ children: [
1462
+ "Pay with ",
1463
+ provider.paymentProvider
1464
+ ]
1465
+ },
1466
+ provider.paymentProvider || provider.id
1467
+ )),
1468
+ !isFree && !isEnrolled && /* @__PURE__ */ jsx9("div", { className: "mb-6", children: appliedCoupon ? /* @__PURE__ */ jsx9("div", { className: "p-3 bg-theme-accent-primary/10 border border-[#49BBBD]/20 rounded-lg", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
1469
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
1470
+ /* @__PURE__ */ jsx9(Tag2, { className: "h-4 w-4 text-[#49BBBD]" }),
1471
+ /* @__PURE__ */ jsxs9("span", { className: "text-sm font-medium text-[#49BBBD]", children: [
1472
+ 'Coupon "',
1473
+ appliedCoupon.code,
1474
+ '" applied'
1475
+ ] })
1476
+ ] }),
1477
+ /* @__PURE__ */ jsx9(
1478
+ "button",
1479
+ {
1480
+ onClick: () => onCouponCodeChange(""),
1481
+ className: "text-[#49BBBD] hover:text-[#3da5a7] transition-colors cursor-pointer",
1482
+ children: /* @__PURE__ */ jsx9(X4, { className: "h-4 w-4" })
1483
+ }
1484
+ )
1485
+ ] }) }) : showCouponInput ? /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
1486
+ /* @__PURE__ */ jsxs9("div", { className: "flex gap-2", children: [
1487
+ /* @__PURE__ */ jsx9(
1488
+ "input",
1489
+ {
1490
+ type: "text",
1491
+ placeholder: "Enter coupon code",
1492
+ value: couponCode,
1493
+ onChange: (e) => onCouponCodeChange(e.target.value.toUpperCase()),
1494
+ className: `flex-1 text-sm border rounded-md px-3 py-2 focus:outline-none focus:border-[#49BBBD] ${couponError ? "border-red-500" : "border-gray-300"}`
1495
+ }
1496
+ ),
1497
+ /* @__PURE__ */ jsx9(
1498
+ "button",
1499
+ {
1500
+ onClick: onApplyCoupon,
1501
+ disabled: !couponCode,
1502
+ className: "px-3 py-2 text-sm bg-theme-accent-primary text-white rounded-md hover:bg-[#3da5a7] disabled:opacity-50 cursor-pointer",
1503
+ children: "Apply"
1504
+ }
1505
+ )
1506
+ ] }),
1507
+ couponError && /* @__PURE__ */ jsx9("p", { className: "text-xs text-red-600", children: couponError })
1508
+ ] }) : /* @__PURE__ */ jsx9(
1509
+ "a",
1510
+ {
1511
+ href: "#",
1512
+ onClick: (e) => {
1513
+ e.preventDefault();
1514
+ setShowCouponInput(true);
1515
+ },
1516
+ className: "block text-center text-sm font-medium text-[#49BBBD] hover:text-[#3da5a7] hover:underline cursor-pointer",
1517
+ children: "Apply Coupon"
1518
+ }
1519
+ ) }),
1520
+ /* @__PURE__ */ jsxs9("div", { className: "border-t border-gray-200 pt-4", children: [
1521
+ /* @__PURE__ */ jsx9("h3", { className: "font-semibold text-gray-900 mb-3 text-sm", children: "This bundle included" }),
1522
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2.5", children: [
1523
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2.5 text-gray-700", children: [
1524
+ /* @__PURE__ */ jsx9("div", { className: "w-4 h-4 rounded-full bg-theme-accent-primary flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx9(FileText2, { className: "h-2.5 w-2.5 text-white" }) }),
1525
+ /* @__PURE__ */ jsxs9("span", { className: "text-sm", children: [
1526
+ totalCourses,
1527
+ " courses"
1528
+ ] })
1529
+ ] }),
1530
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2.5 text-gray-700", children: [
1531
+ /* @__PURE__ */ jsx9("div", { className: "w-4 h-4 rounded-full bg-theme-accent-primary flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx9(Clock3, { className: "h-2.5 w-2.5 text-white" }) }),
1532
+ /* @__PURE__ */ jsx9("span", { className: "text-sm", children: "Self-paced learning" })
1533
+ ] }),
1534
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2.5 text-gray-700", children: [
1535
+ /* @__PURE__ */ jsx9("div", { className: "w-4 h-4 rounded-full bg-theme-accent-primary flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx9(Monitor2, { className: "h-2.5 w-2.5 text-white" }) }),
1536
+ /* @__PURE__ */ jsx9("span", { className: "text-sm", children: "Access on mobile and desktop" })
1537
+ ] })
1538
+ ] })
1539
+ ] })
1540
+ ] });
1541
+ return /* @__PURE__ */ jsxs9("div", { className: "-mx-4 sm:-mx-4 md:-mx-4 lg:-mx-6 xl:-mx-6", children: [
1542
+ /* @__PURE__ */ jsxs9("div", { className: "relative bg-[#1a2332] text-white px-4 lg:px-8 py-8 lg:py-12 mb-8", children: [
1543
+ /* @__PURE__ */ jsxs9("div", { className: "max-w-7xl lg:pr-110", children: [
1544
+ /* @__PURE__ */ jsx9("h1", { className: "text-3xl lg:text-4xl font-bold mb-2", children: b.title }),
1545
+ b.description && /* @__PURE__ */ jsx9("p", { className: "text-base lg:text-lg text-gray-300 mb-4 leading-relaxed", children: b.description }),
1546
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3 mt-4 lg:mt-6 mb-6 lg:mb-0", children: [
1547
+ /* @__PURE__ */ jsx9("div", { className: "w-10 h-10 rounded-full bg-theme-accent-primary flex items-center justify-center text-white font-semibold", children: creatorName.charAt(0).toUpperCase() }),
1548
+ /* @__PURE__ */ jsx9("span", { className: "text-sm", children: creatorName })
1549
+ ] })
1550
+ ] }),
1551
+ /* @__PURE__ */ jsx9("div", { className: "lg:hidden mt-6", children: renderEnrollmentCard() }),
1552
+ /* @__PURE__ */ jsx9("div", { className: "hidden lg:block absolute right-30 top-15 w-80 z-10", children: renderEnrollmentCard() })
1553
+ ] }),
1554
+ /* @__PURE__ */ jsxs9("div", { className: "px-4 lg:px-6", children: [
1555
+ /* @__PURE__ */ jsxs9("div", { className: "lg:pr-110 pr-4 mb-8 pb-8 border-b border-gray-300", children: [
1556
+ /* @__PURE__ */ jsx9("h2", { className: "text-xl font-bold text-gray-900 mb-4", children: "About This Bundle" }),
1557
+ /* @__PURE__ */ jsx9("div", { className: "text-gray-700 text-sm leading-relaxed", children: b.description || "This comprehensive bundle includes multiple courses designed to help you master your learning goals." })
1558
+ ] }),
1559
+ /* @__PURE__ */ jsxs9("div", { className: "mb-8", children: [
1560
+ /* @__PURE__ */ jsxs9("h2", { className: "text-xl font-bold text-gray-900 mb-4", children: [
1561
+ "Included Courses",
1562
+ totalCourses > 0 ? ` (${totalCourses})` : ""
1563
+ ] }),
1564
+ courses.length === 0 ? /* @__PURE__ */ jsx9("div", { className: "text-center py-8 text-gray-500", children: "No courses included in this bundle yet." }) : /* @__PURE__ */ jsx9("div", { className: "space-y-1 lg:max-w-[70%] md:max-w-[100%]", children: courses.sort((a, b2) => {
1565
+ var _a2, _b2;
1566
+ return ((_a2 = a.orderIndex) != null ? _a2 : 0) - ((_b2 = b2.orderIndex) != null ? _b2 : 0);
1567
+ }).map((bundleCourse, index) => {
1568
+ const course = bundleCourse.course || bundleCourse;
1569
+ const courseId = bundleCourse.courseId || bundleCourse.id || course.id;
1570
+ const courseThumbnail = course.thumbnail || bundleCourse.thumbnail;
1571
+ const isExpanded = expandedCourses.has(courseId);
1572
+ const isCompleted = bundleCourse.isCompleted;
1573
+ return /* @__PURE__ */ jsxs9("div", { className: "border border-gray-200 rounded overflow-hidden", children: [
1574
+ /* @__PURE__ */ jsxs9(
1575
+ "button",
1576
+ {
1577
+ onClick: () => toggleCourse(courseId),
1578
+ className: "w-full flex items-center justify-between p-3 hover:bg-gray-50 transition-colors text-left cursor-pointer",
1579
+ children: [
1580
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3", children: [
1581
+ isExpanded ? /* @__PURE__ */ jsx9(ChevronDown3, { className: "h-4 w-4 text-gray-600 flex-shrink-0" }) : /* @__PURE__ */ jsx9(ChevronRight3, { className: "h-4 w-4 text-gray-600 flex-shrink-0" }),
1582
+ /* @__PURE__ */ jsx9("div", { className: "w-8 h-8 rounded-full bg-purple-100 text-purple-700 flex items-center justify-center font-bold text-sm flex-shrink-0", children: index + 1 }),
1583
+ courseThumbnail && !imgErrors[`c-${courseId}`] && /* @__PURE__ */ jsx9(
1584
+ "img",
1585
+ {
1586
+ src: courseThumbnail,
1587
+ alt: course.title,
1588
+ className: "w-12 h-8 object-cover rounded flex-shrink-0",
1589
+ onError: () => setImgErrors((p) => __spreadProps(__spreadValues({}, p), { [`c-${courseId}`]: true }))
1590
+ }
1591
+ ),
1592
+ /* @__PURE__ */ jsxs9("div", { className: "flex-1 min-w-0", children: [
1593
+ /* @__PURE__ */ jsx9("span", { className: "text-sm font-medium text-gray-900 truncate block", children: course.title || bundleCourse.title || "Course" }),
1594
+ course.summary && /* @__PURE__ */ jsx9("p", { className: "text-xs text-gray-500 truncate", children: course.summary })
1595
+ ] })
1596
+ ] }),
1597
+ /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-2 flex-shrink-0 ml-2", children: isCompleted && /* @__PURE__ */ jsx9(Check2, { className: "h-4 w-4 text-green-600" }) })
1598
+ ]
1599
+ }
1600
+ ),
1601
+ isExpanded && /* @__PURE__ */ jsxs9("div", { className: "px-4 py-3 bg-gray-50 border-t border-gray-200", children: [
1602
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-4 text-xs text-gray-500 mb-3", children: [
1603
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1", children: [
1604
+ /* @__PURE__ */ jsx9(BookOpen4, { className: "h-4 w-4" }),
1605
+ /* @__PURE__ */ jsxs9("span", { children: [
1606
+ "Course ",
1607
+ index + 1
1608
+ ] })
1609
+ ] }),
1610
+ course.status && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1", children: [
1611
+ /* @__PURE__ */ jsx9("div", { className: `w-2 h-2 rounded-full ${course.status === "PUBLISHED" ? "bg-green-500" : "bg-gray-400"}` }),
1612
+ /* @__PURE__ */ jsx9("span", { className: "capitalize", children: course.status.toLowerCase() })
1613
+ ] })
1614
+ ] }),
1615
+ /* @__PURE__ */ jsx9(
1616
+ "button",
1617
+ {
1618
+ onClick: () => onCourseClick(courseId, bundleCourse.enrollmentId),
1619
+ className: "text-sm font-medium text-[#49BBBD] hover:text-[#3da5a7] hover:underline cursor-pointer",
1620
+ children: isEnrolled ? "Go to course \u2192" : "View course \u2192"
1621
+ }
1622
+ )
1623
+ ] })
1624
+ ] }, courseId);
1625
+ }) })
1626
+ ] })
1627
+ ] })
1628
+ ] });
1629
+ }
1630
+
1631
+ // src/components/pages/CoursePlayerPage.tsx
1632
+ import { useState as useState7, useMemo as useMemo2 } from "react";
1633
+ import {
1634
+ ChevronLeft as ChevronLeft2,
1635
+ ChevronRight as ChevronRight5,
1636
+ FileText as FileText3,
1637
+ StickyNote,
1638
+ Bookmark,
1639
+ FileAudio,
1640
+ FolderOpen,
1641
+ HelpCircle,
1642
+ List,
1643
+ X as X6,
1644
+ Clock3 as Clock32,
1645
+ CheckCircle2 as CheckCircle22,
1646
+ PlayCircle as PlayCircle2,
1647
+ Lock as Lock2
1648
+ } from "lucide-react";
1649
+
1650
+ // src/components/organisms/CourseSidebar.tsx
1651
+ import { useState as useState6, useMemo } from "react";
1652
+ import { ArrowLeft, Search as Search4, X as X5, Lock, ClipboardList, Award, Check as Check3, ChevronRight as ChevronRight4 } from "lucide-react";
1653
+
1654
+ // src/components/atoms/Button.tsx
1655
+ import * as React from "react";
1656
+ import { cva } from "class-variance-authority";
1657
+ import { jsx as jsx10 } from "react/jsx-runtime";
1658
+ var buttonVariants = cva(
1659
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 cursor-pointer",
1660
+ {
1661
+ variants: {
1662
+ variant: {
1663
+ default: "bg-theme-accent-primary text-white hover:opacity-90",
1664
+ destructive: "bg-red-600 text-white hover:bg-red-700",
1665
+ outline: "border border-theme-border-primary bg-theme-bg-secondary hover:bg-theme-bg-tertiary text-theme-text-primary",
1666
+ secondary: "bg-theme-bg-tertiary text-theme-text-primary hover:opacity-80",
1667
+ ghost: "hover:bg-theme-bg-tertiary text-theme-text-primary",
1668
+ link: "text-[rgb(var(--accent-primary))] underline-offset-4 hover:underline"
1669
+ },
1670
+ size: {
1671
+ default: "h-10 px-4 py-2",
1672
+ sm: "h-9 rounded-md px-3",
1673
+ lg: "h-11 rounded-md px-8",
1674
+ icon: "h-10 w-10"
1675
+ }
1676
+ },
1677
+ defaultVariants: {
1678
+ variant: "default",
1679
+ size: "default"
1680
+ }
1681
+ }
1682
+ );
1683
+ var Button = React.forwardRef(
1684
+ (_a, ref) => {
1685
+ var _b = _a, { className, variant, size } = _b, props = __objRest(_b, ["className", "variant", "size"]);
1686
+ return /* @__PURE__ */ jsx10(
1687
+ "button",
1688
+ __spreadValues({
1689
+ className: cn(buttonVariants({ variant, size, className })),
1690
+ ref
1691
+ }, props)
1692
+ );
1693
+ }
1694
+ );
1695
+ Button.displayName = "Button";
1696
+
1697
+ // src/components/atoms/ProgressBar.tsx
1698
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1699
+ var sizeClasses2 = {
1700
+ sm: "h-1.5",
1701
+ md: "h-2.5",
1702
+ lg: "h-3.5"
1703
+ };
1704
+ var variantClasses = {
1705
+ default: "bg-theme-accent-primary",
1706
+ success: "bg-green-600",
1707
+ warning: "bg-yellow-500",
1708
+ error: "bg-red-600"
1709
+ };
1710
+ function ProgressBar(_a) {
1711
+ var _b = _a, {
1712
+ value,
1713
+ max = 100,
1714
+ showLabel = false,
1715
+ size = "md",
1716
+ variant = "default",
1717
+ className
1718
+ } = _b, props = __objRest(_b, [
1719
+ "value",
1720
+ "max",
1721
+ "showLabel",
1722
+ "size",
1723
+ "variant",
1724
+ "className"
1725
+ ]);
1726
+ const percentage = Math.min(Math.max(value / max * 100, 0), 100);
1727
+ return /* @__PURE__ */ jsxs10("div", __spreadProps(__spreadValues({ className: cn("w-full", className) }, props), { children: [
1728
+ showLabel && /* @__PURE__ */ jsxs10("div", { className: "mb-1 flex items-center justify-between text-sm", children: [
1729
+ /* @__PURE__ */ jsx11("span", { className: "text-theme-text-secondary", children: "Progress" }),
1730
+ /* @__PURE__ */ jsxs10("span", { className: "font-medium text-theme-text-primary", children: [
1731
+ Math.round(percentage),
1732
+ "%"
1733
+ ] })
1734
+ ] }),
1735
+ /* @__PURE__ */ jsx11("div", { className: cn("w-full overflow-hidden rounded-full bg-theme-bg-tertiary", sizeClasses2[size]), children: /* @__PURE__ */ jsx11(
1736
+ "div",
1737
+ {
1738
+ className: cn("h-full transition-all duration-300 ease-in-out", variantClasses[variant]),
1739
+ style: { width: `${percentage}%` }
1740
+ }
1741
+ ) })
1742
+ ] }));
1743
+ }
1744
+
1745
+ // src/components/organisms/CourseSidebar.tsx
1746
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1747
+ var lessonColors = [
1748
+ "bg-[#E2F0FF] border-l-4 border-[#3aa3a5]",
1749
+ "bg-[#fcddb5] border-l-4 border-[#d67a05]",
1750
+ "bg-[#FAD1CE] border-l-4 border-[#7ab3f0]"
1751
+ ];
1752
+ function CourseSidebar({
1753
+ courseTitle,
1754
+ modules,
1755
+ currentLessonId,
1756
+ expandedModules,
1757
+ completedCount,
1758
+ totalCount,
1759
+ onToggleModule,
1760
+ onSelectLesson,
1761
+ hideProgress = false,
1762
+ hideSearch = false,
1763
+ certificateEnabled = false,
1764
+ isCompleted = false,
1765
+ onDownloadCertificate,
1766
+ isDownloadingCertificate = false,
1767
+ onBack,
1768
+ showBackButton = true,
1769
+ className
1770
+ }) {
1771
+ const [searchQuery, setSearchQuery] = useState6("");
1772
+ const filteredModules = useMemo(() => {
1773
+ if (!searchQuery.trim()) return modules;
1774
+ const query = searchQuery.toLowerCase();
1775
+ return modules.map((mod) => __spreadProps(__spreadValues({}, mod), {
1776
+ lessons: mod.lessons.filter((l) => l.title.toLowerCase().includes(query))
1777
+ })).filter((mod) => mod.lessons.length > 0);
1778
+ }, [modules, searchQuery]);
1779
+ const totalResults = filteredModules.reduce((sum, m) => sum + m.lessons.length, 0);
1780
+ const progressPct = totalCount > 0 ? completedCount / totalCount * 100 : 0;
1781
+ const formatDuration2 = (duration) => {
1782
+ if (!duration) return "";
1783
+ const text = duration.trim();
1784
+ if (!text) return "";
1785
+ if (/[a-zA-Z]/.test(text)) return text;
1786
+ const parts = text.split(":").map(Number);
1787
+ if (parts.some(isNaN)) return text;
1788
+ if (parts.length === 3) {
1789
+ const [hrs, mins] = parts;
1790
+ if (hrs > 0 && mins > 0) return `${hrs} ${hrs === 1 ? "hour" : "hours"} ${mins} min`;
1791
+ if (hrs > 0) return `${hrs} ${hrs === 1 ? "hour" : "hours"}`;
1792
+ return `${mins} min`;
1793
+ }
1794
+ if (parts.length === 2) {
1795
+ const [mins, secs] = parts;
1796
+ return `${mins > 0 ? mins : secs > 0 ? 1 : 0} min`;
1797
+ }
1798
+ return `${Math.max(1, Math.round(parts[0] / 60))} min`;
1799
+ };
1800
+ let globalLessonIndex = 0;
1801
+ return /* @__PURE__ */ jsxs11("div", { className: cn("w-full lg:w-[350px] bg-white flex-shrink-0 flex flex-col border-r border-gray-100 lg:h-screen lg:sticky lg:top-0 overflow-y-auto", className), children: [
1802
+ /* @__PURE__ */ jsxs11("div", { className: "p-6", children: [
1803
+ showBackButton && onBack && /* @__PURE__ */ jsx12(
1804
+ "button",
1805
+ {
1806
+ onClick: onBack,
1807
+ className: "w-10 h-10 bg-[#4ecdc4] rounded-md flex items-center justify-center text-white hover:bg-[#3dbdb4] transition-colors mb-6 cursor-pointer",
1808
+ "aria-label": "Go back",
1809
+ children: /* @__PURE__ */ jsx12(ArrowLeft, { className: "w-5 h-5" })
1810
+ }
1811
+ ),
1812
+ /* @__PURE__ */ jsx12("h3", { className: "text-3xl font-semibold text-[#1f2937] leading-tight", children: courseTitle ? `${courseTitle.charAt(0).toUpperCase()}${courseTitle.slice(1)}` : "" }),
1813
+ !hideProgress && /* @__PURE__ */ jsxs11("div", { className: "mt-4", children: [
1814
+ /* @__PURE__ */ jsx12(ProgressBar, { value: progressPct, size: "sm" }),
1815
+ /* @__PURE__ */ jsxs11("p", { className: "text-xs text-gray-400 mt-1 text-right", children: [
1816
+ completedCount,
1817
+ " / ",
1818
+ totalCount,
1819
+ " lessons \xB7 ",
1820
+ Math.round(progressPct),
1821
+ "%"
1822
+ ] })
1823
+ ] }),
1824
+ certificateEnabled && isCompleted && onDownloadCertificate && completedCount === totalCount && totalCount > 0 && /* @__PURE__ */ jsxs11(
1825
+ Button,
1826
+ {
1827
+ onClick: onDownloadCertificate,
1828
+ disabled: isDownloadingCertificate,
1829
+ className: "w-full mt-3 bg-green-600 hover:bg-green-700 disabled:opacity-50 text-white",
1830
+ children: [
1831
+ /* @__PURE__ */ jsx12(Award, { className: "w-4 h-4 mr-2" }),
1832
+ isDownloadingCertificate ? "Downloading..." : "Download Certificate"
1833
+ ]
1834
+ }
1835
+ ),
1836
+ !hideSearch && /* @__PURE__ */ jsxs11("div", { className: "mt-3 relative", children: [
1837
+ /* @__PURE__ */ jsx12(Search4, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" }),
1838
+ /* @__PURE__ */ jsx12(
1839
+ "input",
1840
+ {
1841
+ type: "text",
1842
+ placeholder: "Search lessons...",
1843
+ value: searchQuery,
1844
+ onChange: (e) => setSearchQuery(e.target.value),
1845
+ className: "w-full pl-9 pr-9 py-2 text-sm bg-gray-50 border border-gray-200 text-gray-700 placeholder:text-gray-400 rounded-lg focus:outline-none focus:border-[#49BBBD] transition-colors"
1846
+ }
1847
+ ),
1848
+ searchQuery && /* @__PURE__ */ jsxs11(Fragment4, { children: [
1849
+ /* @__PURE__ */ jsx12(
1850
+ "button",
1851
+ {
1852
+ onClick: () => setSearchQuery(""),
1853
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 cursor-pointer",
1854
+ "aria-label": "Clear search",
1855
+ children: /* @__PURE__ */ jsx12(X5, { className: "w-4 h-4" })
1856
+ }
1857
+ ),
1858
+ /* @__PURE__ */ jsxs11("p", { className: "text-xs text-gray-400 mt-1", children: [
1859
+ totalResults,
1860
+ " ",
1861
+ totalResults === 1 ? "lesson" : "lessons",
1862
+ " found"
1863
+ ] })
1864
+ ] })
1865
+ ] })
1866
+ ] }),
1867
+ /* @__PURE__ */ jsx12("div", { className: "flex-1 px-4 space-y-8 pb-10", children: filteredModules.length === 0 ? /* @__PURE__ */ jsxs11("div", { className: "text-center py-8", children: [
1868
+ /* @__PURE__ */ jsx12(Search4, { className: "w-10 h-10 text-gray-300 mx-auto mb-2" }),
1869
+ /* @__PURE__ */ jsxs11("p", { className: "text-sm text-gray-400", children: [
1870
+ "No lessons found for \u201C",
1871
+ searchQuery,
1872
+ "\u201D"
1873
+ ] }),
1874
+ /* @__PURE__ */ jsx12("button", { onClick: () => setSearchQuery(""), className: "mt-2 text-sm text-[#49BBBD] hover:underline font-medium cursor-pointer", children: "Clear search" })
1875
+ ] }) : filteredModules.map((module) => {
1876
+ const isExpanded = expandedModules.has(module.id) || !!searchQuery.trim();
1877
+ return /* @__PURE__ */ jsxs11("div", { children: [
1878
+ /* @__PURE__ */ jsxs11(
1879
+ "button",
1880
+ {
1881
+ type: "button",
1882
+ onClick: () => onToggleModule(module.id),
1883
+ "aria-expanded": isExpanded,
1884
+ className: "w-full flex items-center justify-between text-left mb-3 px-2 cursor-pointer",
1885
+ children: [
1886
+ /* @__PURE__ */ jsx12("h3", { className: "text-sm font-bold text-gray-500 uppercase tracking-wider", children: module.title }),
1887
+ /* @__PURE__ */ jsx12(ChevronRight4, { className: cn("w-4 h-4 transition-transform", isExpanded ? "rotate-90 text-[#49BBBD]" : "text-gray-400") })
1888
+ ]
1889
+ }
1890
+ ),
1891
+ isExpanded && /* @__PURE__ */ jsx12("div", { className: "space-y-3", children: module.lessons.map((lesson) => {
1892
+ const isCurrent = currentLessonId === lesson.id;
1893
+ const isLocked = lesson.locked === true;
1894
+ const colorClass = lessonColors[globalLessonIndex % lessonColors.length];
1895
+ globalLessonIndex++;
1896
+ let availabilityText = "";
1897
+ if (isLocked) {
1898
+ if (lesson.availableAt) {
1899
+ const diffDays = Math.ceil((new Date(lesson.availableAt).getTime() - Date.now()) / 864e5);
1900
+ availabilityText = diffDays > 0 ? `Available in ${diffDays}d` : `Available on ${new Date(lesson.availableAt).toLocaleDateString()}`;
1901
+ } else if (lesson.hasPrerequisite) {
1902
+ availabilityText = "Complete previous lesson";
1903
+ }
1904
+ }
1905
+ return /* @__PURE__ */ jsxs11(
1906
+ "button",
1907
+ {
1908
+ title: lesson.title,
1909
+ onClick: () => !isLocked && onSelectLesson(lesson.id),
1910
+ disabled: isLocked,
1911
+ className: cn(
1912
+ "w-full text-left p-4 rounded-lg flex items-center justify-between transition-transform",
1913
+ isLocked ? "opacity-50 cursor-not-allowed" : "hover:scale-[1.02] active:scale-[0.98] cursor-pointer",
1914
+ isCurrent ? "bg-[#49BBBD] text-white shadow-md ring-2 ring-[#2a9ea0]/40" : colorClass
1915
+ ),
1916
+ children: [
1917
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-3 overflow-hidden", children: [
1918
+ lesson.completed ? /* @__PURE__ */ jsx12("div", { className: "w-5 h-5 rounded-full border-2 bg-green-500 border-green-500 flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx12(Check3, { className: "w-3 h-3 text-white" }) }) : isLocked ? /* @__PURE__ */ jsx12("div", { className: "w-5 h-5 rounded-full border-2 border-gray-400 flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx12(Lock, { className: "w-2.5 h-2.5 text-gray-500" }) }) : /* @__PURE__ */ jsx12("div", { className: cn("w-5 h-5 rounded-full border-2 flex items-center justify-center flex-shrink-0", isCurrent ? "border-white/60" : "border-gray-400"), children: /* @__PURE__ */ jsx12("div", { className: cn("w-2.5 h-2.5 rounded-sm", isCurrent ? "bg-white/80" : "bg-[#1f2a44]") }) }),
1919
+ /* @__PURE__ */ jsxs11("div", { className: "overflow-hidden", children: [
1920
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5", children: [
1921
+ lesson.type === "ASSESSMENT" ? /* @__PURE__ */ jsx12(ClipboardList, { className: cn("w-3.5 h-3.5 flex-shrink-0", isCurrent ? "text-white" : "text-gray-600") }) : null,
1922
+ /* @__PURE__ */ jsx12("span", { className: cn("text-sm font-medium truncate", isCurrent ? "text-white" : "text-gray-800"), children: lesson.title })
1923
+ ] }),
1924
+ isLocked && availabilityText && /* @__PURE__ */ jsx12("p", { className: "text-xs text-gray-600 mt-0.5 truncate", children: availabilityText })
1925
+ ] })
1926
+ ] }),
1927
+ lesson.type === "ASSESSMENT" ? /* @__PURE__ */ jsx12("span", { className: cn("text-xs font-semibold flex-shrink-0 ml-2", isCurrent ? "text-white/90" : "text-gray-600"), children: "Quiz" }) : lesson.duration ? /* @__PURE__ */ jsx12("span", { className: cn("text-xs font-semibold flex-shrink-0 ml-2", isCurrent ? "text-white/90" : "text-gray-600"), children: formatDuration2(lesson.duration) }) : null
1928
+ ]
1929
+ },
1930
+ lesson.id
1931
+ );
1932
+ }) })
1933
+ ] }, module.id);
1934
+ }) })
1935
+ ] });
1936
+ }
1937
+
1938
+ // src/components/pages/CoursePlayerPage.tsx
1939
+ import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
1940
+ function formatHeaderDuration(duration) {
1941
+ if (!duration) return "";
1942
+ const text = duration.trim();
1943
+ if (!text) return "";
1944
+ if (/[a-zA-Z]/.test(text)) return text;
1945
+ const parts = text.split(":").map(Number);
1946
+ if (parts.some(isNaN)) return text;
1947
+ if (parts.length === 3) {
1948
+ const [h, m] = parts;
1949
+ if (h > 0 && m > 0) return `${h} ${h === 1 ? "hour" : "hours"} ${m} min`;
1950
+ if (h > 0) return `${h} ${h === 1 ? "hour" : "hours"}`;
1951
+ return `${m} min`;
1952
+ }
1953
+ if (parts.length === 2) {
1954
+ const [m, s2] = parts;
1955
+ return `${m > 0 ? m : s2 > 0 ? 1 : 0} min`;
1956
+ }
1957
+ const s = parts[0];
1958
+ return `${s > 0 ? Math.max(1, Math.round(s / 60)) : 0} min`;
1959
+ }
1960
+ function CoursePlayerPage(props) {
1961
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
1962
+ const {
1963
+ course,
1964
+ isLoading = false,
1965
+ courseNotFound = false,
1966
+ onBack,
1967
+ onNavigateToLesson
1968
+ } = props;
1969
+ const allLessons = useMemo2(
1970
+ () => {
1971
+ var _a2;
1972
+ return ((_a2 = course == null ? void 0 : course.modules) != null ? _a2 : []).flatMap((m) => m.lessons);
1973
+ },
1974
+ [course]
1975
+ );
1976
+ const [currentLessonIdx, setCurrentLessonIdx] = useState7(0);
1977
+ const [expandedModules, setExpandedModules] = useState7(
1978
+ () => {
1979
+ var _a2, _b2;
1980
+ return new Set(((_b2 = (_a2 = course == null ? void 0 : course.modules) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.id) ? [course.modules[0].id] : []);
1981
+ }
1982
+ );
1983
+ const [activeTab, setActiveTab] = useState7("overview");
1984
+ const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState7(false);
1985
+ const currentLesson = (_a = allLessons[currentLessonIdx]) != null ? _a : null;
1986
+ const completedCount = allLessons.filter((l) => l.completed).length;
1987
+ const totalCount = allLessons.length;
1988
+ const goToLesson = (lessonId) => {
1989
+ const idx = allLessons.findIndex((l) => l.id === lessonId);
1990
+ if (idx === -1) return;
1991
+ const lesson = allLessons[idx];
1992
+ if (lesson == null ? void 0 : lesson.locked) return;
1993
+ setCurrentLessonIdx(idx);
1994
+ setIsMobileSidebarOpen(false);
1995
+ onNavigateToLesson == null ? void 0 : onNavigateToLesson(lessonId);
1996
+ };
1997
+ const goPrev = () => {
1998
+ if (currentLessonIdx > 0) {
1999
+ setCurrentLessonIdx((i) => i - 1);
2000
+ onNavigateToLesson == null ? void 0 : onNavigateToLesson(allLessons[currentLessonIdx - 1].id);
2001
+ }
2002
+ };
2003
+ const goNext = () => {
2004
+ if (currentLessonIdx < allLessons.length - 1) {
2005
+ setCurrentLessonIdx((i) => i + 1);
2006
+ onNavigateToLesson == null ? void 0 : onNavigateToLesson(allLessons[currentLessonIdx + 1].id);
2007
+ }
2008
+ };
2009
+ const toggleModule = (id) => {
2010
+ setExpandedModules((prev) => {
2011
+ const s = new Set(prev);
2012
+ s.has(id) ? s.delete(id) : s.add(id);
2013
+ return s;
2014
+ });
2015
+ };
2016
+ if (isLoading) return /* @__PURE__ */ jsx13(LoadingSpinner, { className: "py-20", text: "Loading course..." });
2017
+ if (courseNotFound || !course) {
2018
+ return /* @__PURE__ */ jsx13("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs12("div", { className: "text-center space-y-4", children: [
2019
+ /* @__PURE__ */ jsx13("div", { className: "text-6xl", children: "\u{1F4DA}" }),
2020
+ /* @__PURE__ */ jsx13("h1", { className: "text-3xl font-bold text-theme-text-primary", children: "Course Not Found" }),
2021
+ /* @__PURE__ */ jsx13("p", { className: "text-theme-text-secondary max-w-md mx-auto", children: "The course you're looking for doesn't exist or has been removed." }),
2022
+ /* @__PURE__ */ jsx13(
2023
+ "button",
2024
+ {
2025
+ onClick: onBack != null ? onBack : () => window.history.back(),
2026
+ className: "mt-4 px-6 py-2.5 rounded-lg bg-theme-accent-primary text-white font-medium hover:opacity-90 transition-opacity cursor-pointer",
2027
+ children: "Go Back"
2028
+ }
2029
+ )
2030
+ ] }) });
2031
+ }
2032
+ const sidebarProps = {
2033
+ courseTitle: course.title,
2034
+ modules: course.modules,
2035
+ currentLessonId: (_b = currentLesson == null ? void 0 : currentLesson.id) != null ? _b : "",
2036
+ expandedModules,
2037
+ completedCount,
2038
+ totalCount,
2039
+ onToggleModule: toggleModule,
2040
+ onSelectLesson: goToLesson,
2041
+ onBack: onBack != null ? onBack : () => window.history.back()
2042
+ };
2043
+ const tabs = [
2044
+ { id: "overview", label: "Overview", icon: /* @__PURE__ */ jsx13(FileText3, { className: "w-4 h-4" }) },
2045
+ { id: "notes", label: "Notes", icon: /* @__PURE__ */ jsx13(StickyNote, { className: "w-4 h-4" }) },
2046
+ { id: "bookmarks", label: "Bookmarks", icon: /* @__PURE__ */ jsx13(Bookmark, { className: "w-4 h-4" }) },
2047
+ { id: "transcript", label: "Transcript", icon: /* @__PURE__ */ jsx13(FileAudio, { className: "w-4 h-4" }) },
2048
+ { id: "resources", label: "Resources", icon: /* @__PURE__ */ jsx13(FolderOpen, { className: "w-4 h-4" }) },
2049
+ { id: "faq", label: "FAQ", icon: /* @__PURE__ */ jsx13(HelpCircle, { className: "w-4 h-4" }) }
2050
+ ];
2051
+ const videoUrl = (_c = currentLesson == null ? void 0 : currentLesson.videoUrl) != null ? _c : "";
2052
+ const videoProvider = (_d = currentLesson == null ? void 0 : currentLesson.videoProvider) != null ? _d : "YOUTUBE";
2053
+ const getEmbedSrc = () => {
2054
+ if (!videoUrl) return null;
2055
+ if (videoProvider === "YOUTUBE") return `https://www.youtube.com/embed/${videoUrl}?rel=0`;
2056
+ if (videoProvider === "VIMEO") return `https://player.vimeo.com/video/${videoUrl}`;
2057
+ if (videoProvider === "LOOM") return `https://www.loom.com/embed/${videoUrl}`;
2058
+ return videoUrl;
2059
+ };
2060
+ const embedSrc = getEmbedSrc();
2061
+ const lessonLocked = (_e = currentLesson == null ? void 0 : currentLesson.locked) != null ? _e : false;
2062
+ const lessonType = currentLesson == null ? void 0 : currentLesson.type;
2063
+ const duration = formatHeaderDuration(currentLesson == null ? void 0 : currentLesson.duration);
2064
+ const summary = (_g = (_f = currentLesson == null ? void 0 : currentLesson.summary) != null ? _f : course.description) != null ? _g : "";
2065
+ const learningObjectives = (_h = course.learningObjectives) != null ? _h : [];
2066
+ const faqs = (_j = (_i = currentLesson == null ? void 0 : currentLesson.settings) == null ? void 0 : _i.faqs) != null ? _j : [];
2067
+ const secondaryResources = (_k = currentLesson == null ? void 0 : currentLesson.secondaryResources) != null ? _k : [];
2068
+ return /* @__PURE__ */ jsxs12("div", { className: "min-h-screen bg-[#f7f9fc] flex lg:flex-row lg:-mx-6", children: [
2069
+ /* @__PURE__ */ jsx13("div", { className: "hidden lg:block", children: /* @__PURE__ */ jsx13(CourseSidebar, __spreadValues({}, sidebarProps)) }),
2070
+ isMobileSidebarOpen && /* @__PURE__ */ jsxs12("div", { className: "lg:hidden fixed inset-0 z-50", children: [
2071
+ /* @__PURE__ */ jsx13(
2072
+ "button",
2073
+ {
2074
+ onClick: () => setIsMobileSidebarOpen(false),
2075
+ className: "absolute inset-0 bg-black/40 cursor-pointer",
2076
+ "aria-label": "Close lessons drawer"
2077
+ }
2078
+ ),
2079
+ /* @__PURE__ */ jsxs12("div", { className: "relative h-full w-[88vw] max-w-[360px] bg-white shadow-xl overflow-y-auto", children: [
2080
+ /* @__PURE__ */ jsx13(
2081
+ "button",
2082
+ {
2083
+ onClick: () => setIsMobileSidebarOpen(false),
2084
+ className: "absolute top-3 right-3 z-10 w-9 h-9 rounded-full bg-white/90 border border-gray-200 text-gray-700 flex items-center justify-center cursor-pointer",
2085
+ "aria-label": "Close",
2086
+ children: /* @__PURE__ */ jsx13(X6, { className: "w-4 h-4" })
2087
+ }
2088
+ ),
2089
+ /* @__PURE__ */ jsx13(CourseSidebar, __spreadProps(__spreadValues({}, sidebarProps), { onSelectLesson: (id) => {
2090
+ goToLesson(id);
2091
+ setIsMobileSidebarOpen(false);
2092
+ } }))
2093
+ ] })
2094
+ ] }),
2095
+ /* @__PURE__ */ jsxs12("div", { className: "flex-1 flex flex-col min-w-0 bg-[#dce8f5]", children: [
2096
+ /* @__PURE__ */ jsxs12("div", { className: "lg:hidden sticky top-0 z-20 bg-white/95 backdrop-blur border-b border-gray-200 px-4 py-3 flex items-center justify-between", children: [
2097
+ /* @__PURE__ */ jsxs12(
2098
+ "button",
2099
+ {
2100
+ onClick: () => setIsMobileSidebarOpen(true),
2101
+ className: "inline-flex items-center gap-2 px-3 py-2 rounded-md bg-theme-accent-primary text-white text-sm font-medium cursor-pointer",
2102
+ children: [
2103
+ /* @__PURE__ */ jsx13(List, { className: "w-4 h-4" }),
2104
+ "Lessons"
2105
+ ]
2106
+ }
2107
+ ),
2108
+ /* @__PURE__ */ jsxs12("span", { className: "text-xs text-gray-600 font-medium", children: [
2109
+ "Lesson ",
2110
+ currentLessonIdx + 1,
2111
+ " / ",
2112
+ allLessons.length
2113
+ ] })
2114
+ ] }),
2115
+ lessonLocked ? /* @__PURE__ */ jsx13("div", { className: "flex items-center justify-center min-h-[70vh] p-4", children: /* @__PURE__ */ jsxs12("div", { className: "max-w-lg w-full bg-white rounded-2xl border border-gray-200 p-12 text-center space-y-6", children: [
2116
+ /* @__PURE__ */ jsx13("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx13(Lock2, { className: "w-16 h-16 text-orange-500" }) }),
2117
+ /* @__PURE__ */ jsx13("h1", { className: "text-2xl font-bold text-theme-text-primary", children: "Lesson Locked" }),
2118
+ /* @__PURE__ */ jsx13("p", { className: "text-theme-text-secondary", children: "Complete the previous lesson to unlock this content." }),
2119
+ /* @__PURE__ */ jsx13("p", { className: "text-lg font-semibold text-theme-text-primary", children: currentLesson == null ? void 0 : currentLesson.title })
2120
+ ] }) }) : /* @__PURE__ */ jsxs12(Fragment5, { children: [
2121
+ /* @__PURE__ */ jsx13("div", { className: "bg-theme-accent-primary px-4 sm:px-6 lg:px-8 py-4 sm:py-6 text-white", children: /* @__PURE__ */ jsx13("div", { className: "flex items-start", children: /* @__PURE__ */ jsxs12("div", { className: "flex-1 min-w-0", children: [
2122
+ /* @__PURE__ */ jsx13("h2", { className: "text-2xl lg:text-3xl font-bold", children: (currentLesson == null ? void 0 : currentLesson.title) ? `${currentLesson.title.charAt(0).toUpperCase()}${currentLesson.title.slice(1)}` : "Select a lesson" }),
2123
+ /* @__PURE__ */ jsxs12("div", { className: "mt-1 flex items-center gap-3", children: [
2124
+ /* @__PURE__ */ jsx13("p", { className: "text-white/90 text-sm lg:text-base opacity-90 line-clamp-1 flex-1 min-w-0", children: summary }),
2125
+ duration && /* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1.5 whitespace-nowrap text-white/90 text-sm lg:text-base shrink-0", children: [
2126
+ /* @__PURE__ */ jsx13(Clock32, { className: "w-4 h-4" }),
2127
+ duration
2128
+ ] })
2129
+ ] })
2130
+ ] }) }) }),
2131
+ /* @__PURE__ */ jsxs12("div", { className: "p-4 lg:p-8 space-y-6 lg:space-y-8 max-w-5xl w-full", children: [
2132
+ /* @__PURE__ */ jsxs12("div", { className: "bg-white rounded-2xl shadow-sm", children: [
2133
+ /* @__PURE__ */ jsxs12("div", { className: "relative group", children: [
2134
+ /* @__PURE__ */ jsx13("div", { className: "overflow-hidden rounded-t-2xl", children: embedSrc ? /* @__PURE__ */ jsx13("div", { className: "relative w-full", style: { paddingBottom: "56.25%" }, children: /* @__PURE__ */ jsx13(
2135
+ "iframe",
2136
+ {
2137
+ src: embedSrc,
2138
+ className: "absolute inset-0 w-full h-full",
2139
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
2140
+ allowFullScreen: true,
2141
+ title: (_l = currentLesson == null ? void 0 : currentLesson.title) != null ? _l : "Lesson video"
2142
+ }
2143
+ ) }) : /* @__PURE__ */ jsx13("div", { className: "relative w-full bg-gray-900 flex items-center justify-center", style: { paddingBottom: "56.25%" }, children: /* @__PURE__ */ jsxs12("div", { className: "absolute inset-0 flex flex-col items-center justify-center gap-3 text-white/60", children: [
2144
+ /* @__PURE__ */ jsx13(PlayCircle2, { className: "w-16 h-16 opacity-40" }),
2145
+ /* @__PURE__ */ jsx13("p", { className: "text-sm", children: "No video available for this lesson" })
2146
+ ] }) }) }),
2147
+ /* @__PURE__ */ jsx13(
2148
+ "button",
2149
+ {
2150
+ onClick: goPrev,
2151
+ disabled: currentLessonIdx === 0,
2152
+ className: "hidden md:flex absolute -left-5 top-1/2 -translate-y-1/2 z-10 w-10 h-10 items-center justify-center rounded-full bg-[#F48C06] text-white opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed",
2153
+ title: "Previous lesson",
2154
+ children: /* @__PURE__ */ jsx13(ChevronLeft2, { className: "w-5 h-5" })
2155
+ }
2156
+ ),
2157
+ /* @__PURE__ */ jsx13(
2158
+ "button",
2159
+ {
2160
+ onClick: goNext,
2161
+ disabled: currentLessonIdx >= allLessons.length - 1,
2162
+ className: "hidden md:flex absolute -right-5 top-1/2 -translate-y-1/2 z-10 w-10 h-10 items-center justify-center rounded-full bg-[#F48C06] text-white opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed",
2163
+ title: "Next lesson",
2164
+ children: /* @__PURE__ */ jsx13(ChevronRight5, { className: "w-5 h-5" })
2165
+ }
2166
+ )
2167
+ ] }),
2168
+ /* @__PURE__ */ jsxs12("div", { className: "px-4 sm:px-6 py-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 border-t border-gray-100", children: [
2169
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
2170
+ (currentLesson == null ? void 0 : currentLesson.completed) && /* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1 text-xs text-green-600 font-medium", children: [
2171
+ /* @__PURE__ */ jsx13(CheckCircle22, { className: "w-4 h-4" }),
2172
+ " Completed"
2173
+ ] }),
2174
+ /* @__PURE__ */ jsxs12("span", { className: "text-sm text-gray-500", children: [
2175
+ "Lesson ",
2176
+ currentLessonIdx + 1,
2177
+ " of ",
2178
+ allLessons.length
2179
+ ] })
2180
+ ] }),
2181
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
2182
+ /* @__PURE__ */ jsxs12(
2183
+ "button",
2184
+ {
2185
+ onClick: goPrev,
2186
+ disabled: currentLessonIdx === 0,
2187
+ className: "inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-gray-200 text-sm text-gray-700 hover:bg-gray-50 transition-colors disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer",
2188
+ children: [
2189
+ /* @__PURE__ */ jsx13(ChevronLeft2, { className: "w-4 h-4" }),
2190
+ " Prev"
2191
+ ]
2192
+ }
2193
+ ),
2194
+ /* @__PURE__ */ jsxs12(
2195
+ "button",
2196
+ {
2197
+ onClick: goNext,
2198
+ disabled: currentLessonIdx >= allLessons.length - 1,
2199
+ className: "inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-theme-accent-primary text-white text-sm hover:opacity-90 transition-opacity disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer",
2200
+ children: [
2201
+ "Next ",
2202
+ /* @__PURE__ */ jsx13(ChevronRight5, { className: "w-4 h-4" })
2203
+ ]
2204
+ }
2205
+ )
2206
+ ] })
2207
+ ] })
2208
+ ] }),
2209
+ /* @__PURE__ */ jsxs12("div", { className: "bg-white border border-gray-200 rounded-lg overflow-hidden", children: [
2210
+ /* @__PURE__ */ jsx13("div", { className: "flex overflow-x-auto border-b border-gray-200 scrollbar-hide", children: tabs.map((tab) => /* @__PURE__ */ jsxs12(
2211
+ "button",
2212
+ {
2213
+ onClick: () => setActiveTab(tab.id),
2214
+ className: `flex items-center gap-2 px-4 py-3 text-sm font-medium whitespace-nowrap border-b-2 transition-colors cursor-pointer ${activeTab === tab.id ? "border-theme-accent-primary text-theme-accent-primary" : "border-transparent text-gray-500 hover:text-gray-700"}`,
2215
+ children: [
2216
+ tab.icon,
2217
+ tab.label
2218
+ ]
2219
+ },
2220
+ tab.id
2221
+ )) }),
2222
+ /* @__PURE__ */ jsxs12("div", { className: "px-6 py-6", style: { minHeight: 480 }, children: [
2223
+ activeTab === "overview" && /* @__PURE__ */ jsxs12("div", { className: "space-y-6", children: [
2224
+ /* @__PURE__ */ jsxs12("div", { children: [
2225
+ /* @__PURE__ */ jsx13("h3", { className: "text-base font-semibold text-gray-900 mb-2", children: "About This Lesson" }),
2226
+ summary ? /* @__PURE__ */ jsx13("p", { className: "text-sm text-gray-700 leading-relaxed", children: summary }) : /* @__PURE__ */ jsx13("p", { className: "text-sm text-gray-400 italic", children: "No description available." })
2227
+ ] }),
2228
+ learningObjectives.length > 0 && /* @__PURE__ */ jsxs12("div", { children: [
2229
+ /* @__PURE__ */ jsx13("h3", { className: "text-base font-semibold text-gray-900 mb-3", children: "What You'll Learn" }),
2230
+ /* @__PURE__ */ jsx13("ul", { className: "space-y-2", children: learningObjectives.map((obj, i) => /* @__PURE__ */ jsxs12("li", { className: "flex items-start gap-2.5 text-sm text-gray-700", children: [
2231
+ /* @__PURE__ */ jsx13(CheckCircle22, { className: "w-4 h-4 text-green-500 flex-shrink-0 mt-0.5" }),
2232
+ obj
2233
+ ] }, i)) })
2234
+ ] })
2235
+ ] }),
2236
+ activeTab === "notes" && /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center py-12 text-center gap-3", children: [
2237
+ /* @__PURE__ */ jsx13(StickyNote, { className: "w-12 h-12 text-gray-300" }),
2238
+ /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-gray-500", children: "Your notes will appear here" }),
2239
+ /* @__PURE__ */ jsx13("p", { className: "text-xs text-gray-400", children: "Take notes while watching to revisit key points later." })
2240
+ ] }),
2241
+ activeTab === "bookmarks" && /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center py-12 text-center gap-3", children: [
2242
+ /* @__PURE__ */ jsx13(Bookmark, { className: "w-12 h-12 text-gray-300" }),
2243
+ /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-gray-500", children: "No bookmarks yet" }),
2244
+ /* @__PURE__ */ jsx13("p", { className: "text-xs text-gray-400", children: "Bookmark key moments in the video to revisit them." })
2245
+ ] }),
2246
+ activeTab === "transcript" && /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center py-12 text-center gap-3", children: [
2247
+ /* @__PURE__ */ jsx13(FileAudio, { className: "w-12 h-12 text-gray-300" }),
2248
+ /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-gray-500", children: "Transcript not available" }),
2249
+ /* @__PURE__ */ jsx13("p", { className: "text-xs text-gray-400", children: "The transcript for this lesson has not been generated yet." })
2250
+ ] }),
2251
+ activeTab === "resources" && /* @__PURE__ */ jsx13("div", { children: secondaryResources.length > 0 ? /* @__PURE__ */ jsx13("div", { className: "space-y-3", children: secondaryResources.map((res, i) => {
2252
+ var _a2, _b2, _c2, _d2, _e2;
2253
+ return /* @__PURE__ */ jsxs12(
2254
+ "a",
2255
+ {
2256
+ href: (_c2 = (_b2 = res.url) != null ? _b2 : (_a2 = res.metadataJson) == null ? void 0 : _a2.url) != null ? _c2 : "#",
2257
+ target: "_blank",
2258
+ rel: "noopener noreferrer",
2259
+ className: "flex items-center gap-3 p-3 rounded-lg border border-gray-200 hover:border-theme-accent-primary hover:bg-theme-accent-primary/5 transition-colors",
2260
+ children: [
2261
+ /* @__PURE__ */ jsx13(FolderOpen, { className: "w-5 h-5 text-theme-accent-primary flex-shrink-0" }),
2262
+ /* @__PURE__ */ jsx13("span", { className: "text-sm text-gray-700", children: (_e2 = (_d2 = res.title) != null ? _d2 : res.name) != null ? _e2 : `Resource ${i + 1}` })
2263
+ ]
2264
+ },
2265
+ i
2266
+ );
2267
+ }) }) : /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center py-12 text-center gap-3", children: [
2268
+ /* @__PURE__ */ jsx13(FolderOpen, { className: "w-12 h-12 text-gray-300" }),
2269
+ /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-gray-500", children: "No resources available" }),
2270
+ /* @__PURE__ */ jsx13("p", { className: "text-xs text-gray-400", children: "Downloadable files and links will appear here." })
2271
+ ] }) }),
2272
+ activeTab === "faq" && /* @__PURE__ */ jsx13("div", { children: faqs.length > 0 ? /* @__PURE__ */ jsx13(FAQAccordion, { faqs }) : /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center py-12 text-center gap-3", children: [
2273
+ /* @__PURE__ */ jsx13(HelpCircle, { className: "w-12 h-12 text-gray-300" }),
2274
+ /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-gray-500", children: "No FAQs for this lesson" })
2275
+ ] }) })
2276
+ ] })
2277
+ ] })
2278
+ ] })
2279
+ ] })
2280
+ ] })
2281
+ ] });
2282
+ }
2283
+ function FAQAccordion({ faqs }) {
2284
+ const [openIdx, setOpenIdx] = useState7(null);
2285
+ return /* @__PURE__ */ jsx13("div", { className: "space-y-2", children: faqs.map((faq, i) => /* @__PURE__ */ jsxs12("div", { className: "border border-gray-200 rounded-lg overflow-hidden", children: [
2286
+ /* @__PURE__ */ jsxs12(
2287
+ "button",
2288
+ {
2289
+ onClick: () => setOpenIdx(openIdx === i ? null : i),
2290
+ className: "w-full flex items-center justify-between px-4 py-3 text-left text-sm font-medium text-gray-800 hover:bg-gray-50 transition-colors cursor-pointer",
2291
+ children: [
2292
+ faq.question,
2293
+ /* @__PURE__ */ jsx13(ChevronLeft2, { className: `w-4 h-4 text-gray-400 transition-transform duration-200 ${openIdx === i ? "-rotate-90" : "rotate-180"}` })
2294
+ ]
2295
+ }
2296
+ ),
2297
+ openIdx === i && /* @__PURE__ */ jsx13("div", { className: "px-4 pb-4 text-sm text-gray-600 border-t border-gray-100 pt-3", children: faq.answer })
2298
+ ] }, i)) });
2299
+ }
2300
+
2301
+ // src/components/pages/MessagesPage.tsx
2302
+ import { useState as useState8, useRef, useEffect } from "react";
2303
+ import { MessageSquare, Send, ArrowLeft as ArrowLeft2, Plus, ChevronUp, Loader2, Search as Search6 } from "lucide-react";
2304
+ import { Fragment as Fragment6, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2305
+ function formatTime(timestamp) {
2306
+ try {
2307
+ const date = new Date(timestamp);
2308
+ const now = /* @__PURE__ */ new Date();
2309
+ const diffDays = Math.floor((now.getTime() - date.getTime()) / (1e3 * 60 * 60 * 24));
2310
+ if (diffDays === 0) return date.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" });
2311
+ if (diffDays === 1) return "Yesterday";
2312
+ if (diffDays < 7) return date.toLocaleDateString("en-US", { weekday: "short" });
2313
+ return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
2314
+ } catch (e) {
2315
+ return "";
2316
+ }
2317
+ }
2318
+ function timeAgo(timestamp) {
2319
+ try {
2320
+ const diff = Date.now() - new Date(timestamp).getTime();
2321
+ const mins = Math.floor(diff / 6e4);
2322
+ if (mins < 1) return "just now";
2323
+ if (mins < 60) return `${mins}m`;
2324
+ const hrs = Math.floor(mins / 60);
2325
+ if (hrs < 24) return `${hrs}h`;
2326
+ return `${Math.floor(hrs / 24)}d`;
2327
+ } catch (e) {
2328
+ return "";
2329
+ }
2330
+ }
2331
+ function MessagesPage(props) {
2332
+ var _a, _b;
2333
+ const noop = (..._args) => {
2334
+ };
2335
+ const {
2336
+ conversations = [],
2337
+ isLoadingConversations = false,
2338
+ selectedConversation,
2339
+ onSelectConversation = noop,
2340
+ messages = [],
2341
+ isLoadingMessages = false,
2342
+ isLoadingMore = false,
2343
+ hasMoreMessages = false,
2344
+ onLoadMoreMessages = noop,
2345
+ onSendMessage = noop,
2346
+ isSending = false,
2347
+ searchQuery = "",
2348
+ onSearchChange = noop,
2349
+ showNewMessageDialog = false,
2350
+ onNewMessageDialogChange = noop,
2351
+ mobileView = "list",
2352
+ onMobileViewChange = noop,
2353
+ currentUserId = "student-current"
2354
+ } = props;
2355
+ const [messageText, setMessageText] = useState8("");
2356
+ const messagesEndRef = useRef(null);
2357
+ useEffect(() => {
2358
+ var _a2;
2359
+ (_a2 = messagesEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth" });
2360
+ }, [messages]);
2361
+ const handleSend = async () => {
2362
+ if (!messageText.trim()) return;
2363
+ const text = messageText.trim();
2364
+ setMessageText("");
2365
+ await onSendMessage(text);
2366
+ };
2367
+ const selectedName = ((_a = selectedConversation == null ? void 0 : selectedConversation.participant) == null ? void 0 : _a.name) || (selectedConversation == null ? void 0 : selectedConversation.name) || "Conversation";
2368
+ const selectedCourse = ((_b = selectedConversation == null ? void 0 : selectedConversation.courseContext) == null ? void 0 : _b.courseName) || "";
2369
+ return /* @__PURE__ */ jsxs13("div", { className: "flex h-[calc(100vh-4rem)] -mx-4 lg:-mx-6 lg:-my-4 pt-3 overflow-hidden bg-theme-bg-secondary", children: [
2370
+ /* @__PURE__ */ jsxs13("div", { className: cn(
2371
+ "w-full lg:w-80 shrink-0 border-r border-theme-border-primary flex flex-col bg-theme-bg-secondary",
2372
+ mobileView === "chat" ? "hidden lg:flex" : "flex"
2373
+ ), children: [
2374
+ /* @__PURE__ */ jsxs13("div", { className: "px-4 pt-5 pb-3", children: [
2375
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between mb-4", children: [
2376
+ /* @__PURE__ */ jsx14("h1", { className: "text-xl font-bold text-theme-text-primary", children: "Messages" }),
2377
+ /* @__PURE__ */ jsx14(
2378
+ "button",
2379
+ {
2380
+ onClick: () => onNewMessageDialogChange(true),
2381
+ title: "New message",
2382
+ className: "inline-flex items-center justify-center w-8 h-8 rounded-full bg-[rgb(var(--accent-primary))] text-white hover:opacity-90 transition-opacity shadow-sm cursor-pointer",
2383
+ children: /* @__PURE__ */ jsx14(Plus, { className: "h-4 w-4" })
2384
+ }
2385
+ )
2386
+ ] }),
2387
+ /* @__PURE__ */ jsxs13("div", { className: "relative", children: [
2388
+ /* @__PURE__ */ jsx14(Search6, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-theme-text-secondary" }),
2389
+ /* @__PURE__ */ jsx14(
2390
+ "input",
2391
+ {
2392
+ type: "text",
2393
+ value: searchQuery,
2394
+ onChange: (e) => onSearchChange(e.target.value),
2395
+ placeholder: "Search messages...",
2396
+ className: "w-full rounded-lg border border-theme-border-primary bg-theme-bg-primary pl-10 pr-4 py-2.5 text-sm text-theme-text-primary placeholder:text-theme-text-secondary focus:outline-none focus:ring-2 focus:ring-theme-accent-primary/30 focus:border-theme-accent-primary transition-colors"
2397
+ }
2398
+ )
2399
+ ] })
2400
+ ] }),
2401
+ /* @__PURE__ */ jsx14("div", { className: "flex-1 overflow-y-auto", children: isLoadingConversations ? /* @__PURE__ */ jsx14("div", { className: "flex justify-center py-8", children: /* @__PURE__ */ jsx14("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-theme-border-primary border-t-theme-accent-primary" }) }) : conversations.length === 0 ? /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2402
+ /* @__PURE__ */ jsx14("div", { className: "w-16 h-16 rounded-full bg-theme-bg-tertiary flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx14(MessageSquare, { className: "w-8 h-8 text-theme-text-secondary" }) }),
2403
+ /* @__PURE__ */ jsx14("p", { className: "text-sm text-theme-text-secondary", children: "No conversations found" })
2404
+ ] }) : conversations.map((conv) => {
2405
+ var _a2, _b2, _c, _d, _e;
2406
+ const convId = conv.id || conv.conversationId;
2407
+ const isSelected = (selectedConversation == null ? void 0 : selectedConversation.id) === convId;
2408
+ const name = ((_a2 = conv.participant) == null ? void 0 : _a2.name) || conv.name || ((_b2 = conv.courseContext) == null ? void 0 : _b2.courseName) || "Conversation";
2409
+ const initials = name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
2410
+ const lastMsg = ((_c = conv.lastMessage) == null ? void 0 : _c.content) || "";
2411
+ const lastTime = (_d = conv.lastMessage) == null ? void 0 : _d.timestamp;
2412
+ const courseName = (_e = conv.courseContext) == null ? void 0 : _e.courseName;
2413
+ const unread = conv.unreadCount || 0;
2414
+ return /* @__PURE__ */ jsxs13(
2415
+ "button",
2416
+ {
2417
+ onClick: () => {
2418
+ onSelectConversation(conv);
2419
+ onMobileViewChange("chat");
2420
+ },
2421
+ className: cn(
2422
+ "w-full flex items-start gap-3 px-4 py-3.5 text-left transition-colors border-l-[3px] border-transparent hover:bg-theme-bg-tertiary/50 cursor-pointer",
2423
+ isSelected && "bg-theme-accent-primary/5 border-l-[rgb(var(--accent-primary))]"
2424
+ ),
2425
+ children: [
2426
+ /* @__PURE__ */ jsxs13("div", { className: "relative shrink-0", children: [
2427
+ /* @__PURE__ */ jsx14("div", { className: "w-10 h-10 rounded-full bg-theme-accent-primary/10 flex items-center justify-center", children: /* @__PURE__ */ jsx14("span", { className: "text-sm font-semibold text-[rgb(var(--accent-primary))]", children: initials }) }),
2428
+ unread > 0 && /* @__PURE__ */ jsx14("span", { className: "absolute -top-1 -right-1 w-5 h-5 rounded-full bg-[rgb(var(--accent-primary))] text-white text-[10px] font-bold flex items-center justify-center", children: unread > 9 ? "9+" : unread })
2429
+ ] }),
2430
+ /* @__PURE__ */ jsxs13("div", { className: "flex-1 min-w-0", children: [
2431
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between gap-2", children: [
2432
+ /* @__PURE__ */ jsx14("span", { className: "text-sm font-semibold text-theme-text-primary truncate", children: name }),
2433
+ lastTime && /* @__PURE__ */ jsx14("span", { className: "text-xs text-theme-text-secondary whitespace-nowrap", children: timeAgo(lastTime) })
2434
+ ] }),
2435
+ /* @__PURE__ */ jsx14("p", { className: "text-xs text-theme-text-secondary truncate mt-0.5", children: lastMsg }),
2436
+ courseName && /* @__PURE__ */ jsx14("p", { className: "text-xs text-[rgb(var(--accent-primary))] mt-1 truncate", children: courseName })
2437
+ ] })
2438
+ ]
2439
+ },
2440
+ convId
2441
+ );
2442
+ }) })
2443
+ ] }),
2444
+ /* @__PURE__ */ jsx14("div", { className: cn(
2445
+ "flex-1 min-w-0 flex flex-col bg-theme-bg-primary",
2446
+ mobileView === "list" ? "hidden lg:flex" : "flex"
2447
+ ), children: !selectedConversation ? /* @__PURE__ */ jsxs13("div", { className: "flex-1 flex flex-col items-center justify-center gap-3 text-center px-4", children: [
2448
+ /* @__PURE__ */ jsx14("div", { className: "w-20 h-20 rounded-full bg-theme-bg-tertiary flex items-center justify-center", children: /* @__PURE__ */ jsx14(MessageSquare, { className: "w-10 h-10 text-theme-text-secondary" }) }),
2449
+ /* @__PURE__ */ jsx14("h2", { className: "text-lg font-semibold text-theme-text-primary", children: "Select a conversation" }),
2450
+ /* @__PURE__ */ jsx14("p", { className: "text-sm text-theme-text-secondary max-w-xs", children: "Choose a conversation from the list or start a new one" }),
2451
+ /* @__PURE__ */ jsxs13(
2452
+ "button",
2453
+ {
2454
+ onClick: () => onNewMessageDialogChange(true),
2455
+ className: "mt-2 inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-[rgb(var(--accent-primary))] text-white text-sm font-medium hover:opacity-90 transition-opacity cursor-pointer",
2456
+ children: [
2457
+ /* @__PURE__ */ jsx14(Plus, { className: "w-4 h-4" }),
2458
+ "New Message"
2459
+ ]
2460
+ }
2461
+ )
2462
+ ] }) : /* @__PURE__ */ jsxs13(Fragment6, { children: [
2463
+ /* @__PURE__ */ jsxs13("div", { className: "px-4 py-3 border-b border-theme-border-primary flex items-center gap-3 bg-theme-bg-secondary", children: [
2464
+ /* @__PURE__ */ jsx14(
2465
+ "button",
2466
+ {
2467
+ onClick: () => onMobileViewChange("list"),
2468
+ className: "lg:hidden text-theme-text-secondary hover:text-theme-text-primary cursor-pointer",
2469
+ children: /* @__PURE__ */ jsx14(ArrowLeft2, { className: "w-5 h-5" })
2470
+ }
2471
+ ),
2472
+ /* @__PURE__ */ jsx14("div", { className: "w-9 h-9 rounded-full bg-theme-accent-primary/10 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsx14("span", { className: "text-sm font-semibold text-[rgb(var(--accent-primary))]", children: selectedName.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) }) }),
2473
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
2474
+ /* @__PURE__ */ jsx14("p", { className: "font-semibold text-sm text-theme-text-primary truncate", children: selectedName }),
2475
+ selectedCourse && /* @__PURE__ */ jsx14("p", { className: "text-xs text-[rgb(var(--accent-primary))] truncate", children: selectedCourse })
2476
+ ] })
2477
+ ] }),
2478
+ /* @__PURE__ */ jsxs13("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-3", children: [
2479
+ hasMoreMessages && /* @__PURE__ */ jsx14("div", { className: "flex justify-center pb-2", children: /* @__PURE__ */ jsxs13(
2480
+ "button",
2481
+ {
2482
+ onClick: onLoadMoreMessages,
2483
+ disabled: isLoadingMore,
2484
+ className: "inline-flex items-center gap-1 text-xs text-[rgb(var(--accent-primary))] hover:opacity-80 cursor-pointer disabled:opacity-50",
2485
+ children: [
2486
+ isLoadingMore ? /* @__PURE__ */ jsx14(Loader2, { className: "w-3 h-3 animate-spin" }) : /* @__PURE__ */ jsx14(ChevronUp, { className: "w-3 h-3" }),
2487
+ "Load older messages"
2488
+ ]
2489
+ }
2490
+ ) }),
2491
+ isLoadingMessages ? /* @__PURE__ */ jsx14("div", { className: "flex justify-center py-8", children: /* @__PURE__ */ jsx14("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-theme-border-primary border-t-theme-accent-primary" }) }) : messages.length === 0 ? /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
2492
+ /* @__PURE__ */ jsx14(MessageSquare, { className: "w-10 h-10 text-theme-text-secondary mb-3" }),
2493
+ /* @__PURE__ */ jsx14("p", { className: "text-sm text-theme-text-secondary", children: "No messages yet. Say hello!" })
2494
+ ] }) : messages.map((msg) => {
2495
+ const isOwn = msg.senderId === currentUserId || msg.senderRole === "STUDENT";
2496
+ return /* @__PURE__ */ jsx14("div", { className: cn("flex", isOwn ? "justify-end" : "justify-start"), children: /* @__PURE__ */ jsxs13("div", { className: cn("flex items-end gap-2 max-w-[75%]", isOwn && "flex-row-reverse"), children: [
2497
+ !isOwn && /* @__PURE__ */ jsx14("div", { className: "w-7 h-7 rounded-full bg-theme-accent-primary/10 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsx14("span", { className: "text-[10px] font-semibold text-[rgb(var(--accent-primary))]", children: selectedName.charAt(0).toUpperCase() }) }),
2498
+ /* @__PURE__ */ jsxs13("div", { children: [
2499
+ /* @__PURE__ */ jsx14("div", { className: cn(
2500
+ "rounded-2xl px-4 py-2.5 text-sm leading-relaxed",
2501
+ isOwn ? "bg-[rgb(var(--accent-primary))] text-white rounded-br-md" : "bg-theme-bg-tertiary text-theme-text-primary rounded-bl-md"
2502
+ ), children: msg.content }),
2503
+ /* @__PURE__ */ jsx14("p", { className: cn("text-[10px] text-theme-text-muted mt-1", isOwn ? "text-right" : "text-left"), children: msg.timestamp ? formatTime(msg.timestamp) : "" })
2504
+ ] })
2505
+ ] }) }, msg.id);
2506
+ }),
2507
+ /* @__PURE__ */ jsx14("div", { ref: messagesEndRef })
2508
+ ] }),
2509
+ /* @__PURE__ */ jsx14("div", { className: "px-4 py-3 border-t border-theme-border-primary bg-theme-bg-secondary", children: /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
2510
+ /* @__PURE__ */ jsx14(
2511
+ "input",
2512
+ {
2513
+ type: "text",
2514
+ value: messageText,
2515
+ onChange: (e) => setMessageText(e.target.value),
2516
+ onKeyDown: (e) => {
2517
+ if (e.key === "Enter" && !e.shiftKey) {
2518
+ e.preventDefault();
2519
+ handleSend();
2520
+ }
2521
+ },
2522
+ placeholder: "Type a message...",
2523
+ className: "flex-1 h-10 px-4 text-sm rounded-full border border-theme-border-primary bg-theme-bg-primary text-theme-text-primary placeholder:text-theme-text-muted focus:outline-none focus:border-theme-accent-primary transition-colors"
2524
+ }
2525
+ ),
2526
+ /* @__PURE__ */ jsx14(
2527
+ "button",
2528
+ {
2529
+ onClick: handleSend,
2530
+ disabled: isSending || !messageText.trim(),
2531
+ className: "flex items-center justify-center w-10 h-10 rounded-full bg-[rgb(var(--accent-primary))] text-white hover:opacity-90 disabled:opacity-50 transition-opacity shrink-0 cursor-pointer",
2532
+ children: isSending ? /* @__PURE__ */ jsx14(Loader2, { className: "w-4 h-4 animate-spin" }) : /* @__PURE__ */ jsx14(Send, { className: "w-4 h-4" })
2533
+ }
2534
+ )
2535
+ ] }) })
2536
+ ] }) })
2537
+ ] });
2538
+ }
2539
+
2540
+ // src/components/pages/ManualReviewPage.tsx
2541
+ import { ClipboardList as ClipboardList2, CheckCircle, AlertCircle, FileText as FileText4, Calendar, Search as Search7 } from "lucide-react";
2542
+
2543
+ // src/components/atoms/Badge.tsx
2544
+ import { cva as cva2 } from "class-variance-authority";
2545
+ import { jsx as jsx15 } from "react/jsx-runtime";
2546
+ var badgeVariants = cva2(
2547
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2",
2548
+ {
2549
+ variants: {
2550
+ variant: {
2551
+ default: "bg-theme-accent-primary text-white",
2552
+ secondary: "bg-theme-bg-tertiary text-theme-text-primary",
2553
+ success: "border-transparent bg-green-600 text-white",
2554
+ warning: "border-transparent bg-yellow-500 text-white",
2555
+ destructive: "border-transparent bg-red-600 text-white",
2556
+ outline: "text-theme-text-primary border-theme-border-primary"
2557
+ }
2558
+ },
2559
+ defaultVariants: {
2560
+ variant: "default"
2561
+ }
2562
+ }
2563
+ );
2564
+ function Badge(_a) {
2565
+ var _b = _a, { className, variant } = _b, props = __objRest(_b, ["className", "variant"]);
2566
+ return /* @__PURE__ */ jsx15("div", __spreadValues({ className: cn(badgeVariants({ variant }), className) }, props));
2567
+ }
2568
+
2569
+ // src/components/atoms/Input.tsx
2570
+ import * as React2 from "react";
2571
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
2572
+ var Input = React2.forwardRef(
2573
+ (_a, ref) => {
2574
+ var _b = _a, { className, type, label } = _b, props = __objRest(_b, ["className", "type", "label"]);
2575
+ const inputElement = /* @__PURE__ */ jsx16(
2576
+ "input",
2577
+ __spreadValues({
2578
+ type,
2579
+ className: cn(
2580
+ "flex h-10 w-full rounded-md border border-theme-border-primary bg-theme-bg-primary px-3 py-2 text-sm text-theme-text-primary file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-[rgb(var(--text-muted))] focus-visible:outline-none focus-visible:border-theme-accent-primary transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2581
+ className
2582
+ ),
2583
+ ref
2584
+ }, props)
2585
+ );
2586
+ if (label) {
2587
+ return /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
2588
+ /* @__PURE__ */ jsxs14("label", { className: "text-sm font-medium text-theme-text-primary", children: [
2589
+ label,
2590
+ props.required && /* @__PURE__ */ jsx16("span", { className: "text-red-500 ml-1", children: "*" })
2591
+ ] }),
2592
+ inputElement
2593
+ ] });
2594
+ }
2595
+ return inputElement;
2596
+ }
2597
+ );
2598
+ Input.displayName = "Input";
2599
+
2600
+ // src/components/pages/ManualReviewPage.tsx
2601
+ import { Fragment as Fragment7, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
2602
+ var statusDisplay = {
2603
+ IN_REVIEW: { label: "Pending Review", variant: "warning" },
2604
+ REQUEST_CHANGE: { label: "Changes Requested", variant: "destructive" },
2605
+ GRADED: { label: "Approved", variant: "success" }
2606
+ };
2607
+ function formatDate(dateString) {
2608
+ return new Date(dateString).toLocaleDateString("en-US", {
2609
+ month: "short",
2610
+ day: "numeric",
2611
+ year: "numeric"
2612
+ });
2613
+ }
2614
+ function ManualReviewPage(props) {
2615
+ var _a, _b, _c, _d;
2616
+ const noop = (..._args) => {
2617
+ };
2618
+ const {
2619
+ submissions = [],
2620
+ summary,
2621
+ pagination,
2622
+ isLoading = false,
2623
+ filterStatus = "ALL",
2624
+ onFilterStatusChange = noop,
2625
+ searchQuery = "",
2626
+ onSearchChange = noop,
2627
+ currentPage = 1,
2628
+ onPageChange = noop,
2629
+ onSubmissionClick = noop
2630
+ } = props;
2631
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-6", children: [
2632
+ /* @__PURE__ */ jsx17("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs15("div", { children: [
2633
+ /* @__PURE__ */ jsx17("h1", { className: "text-3xl font-bold text-theme-text-primary", children: "Manual Review" }),
2634
+ /* @__PURE__ */ jsx17("p", { className: "text-theme-text-secondary mt-1", children: "Track your assignment submissions and review status" })
2635
+ ] }) }),
2636
+ /* @__PURE__ */ jsxs15("div", { className: "grid grid-cols-2 gap-6 md:grid-cols-4", children: [
2637
+ /* @__PURE__ */ jsxs15(
2638
+ "button",
2639
+ {
2640
+ onClick: () => {
2641
+ onFilterStatusChange("IN_REVIEW");
2642
+ onPageChange(1);
2643
+ },
2644
+ className: cn(
2645
+ "relative rounded-lg border-2 p-4 text-left transition-all duration-300 ease-in-out hover:scale-105 hover:shadow-md hover:z-20 cursor-pointer",
2646
+ filterStatus === "IN_REVIEW" ? "border-yellow-500 bg-yellow-50 dark:bg-yellow-900/20 scale-105 shadow-md z-20" : "border-theme-border-primary hover:border-yellow-500"
2647
+ ),
2648
+ children: [
2649
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between", children: [
2650
+ /* @__PURE__ */ jsxs15("div", { children: [
2651
+ /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-theme-text-muted", children: "Pending Review" }),
2652
+ /* @__PURE__ */ jsx17("p", { className: "text-2xl font-bold text-yellow-600", children: (_a = summary == null ? void 0 : summary.inReviewSubmissions) != null ? _a : 0 })
2653
+ ] }),
2654
+ /* @__PURE__ */ jsx17(ClipboardList2, { className: "h-6 w-6 text-yellow-600" })
2655
+ ] }),
2656
+ /* @__PURE__ */ jsx17("p", { className: "mt-1 text-xs text-theme-text-muted", children: "Awaiting review" })
2657
+ ]
2658
+ }
2659
+ ),
2660
+ /* @__PURE__ */ jsxs15(
2661
+ "button",
2662
+ {
2663
+ onClick: () => {
2664
+ onFilterStatusChange("REQUEST_CHANGE");
2665
+ onPageChange(1);
2666
+ },
2667
+ className: cn(
2668
+ "relative rounded-lg border-2 p-4 text-left transition-all duration-300 ease-in-out hover:scale-105 hover:shadow-md hover:z-20 cursor-pointer",
2669
+ filterStatus === "REQUEST_CHANGE" ? "border-red-500 bg-red-50 dark:bg-red-900/20 scale-105 shadow-md z-20" : "border-theme-border-primary hover:border-red-500"
2670
+ ),
2671
+ children: [
2672
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between", children: [
2673
+ /* @__PURE__ */ jsxs15("div", { children: [
2674
+ /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-theme-text-muted", children: "Changes Requested" }),
2675
+ /* @__PURE__ */ jsx17("p", { className: "text-2xl font-bold text-red-600", children: (_b = summary == null ? void 0 : summary.requestChangeSubmissions) != null ? _b : 0 })
2676
+ ] }),
2677
+ /* @__PURE__ */ jsx17(AlertCircle, { className: "h-6 w-6 text-red-600" })
2678
+ ] }),
2679
+ /* @__PURE__ */ jsx17("p", { className: "mt-1 text-xs text-theme-text-muted", children: "Needs revision" })
2680
+ ]
2681
+ }
2682
+ ),
2683
+ /* @__PURE__ */ jsxs15(
2684
+ "button",
2685
+ {
2686
+ onClick: () => {
2687
+ onFilterStatusChange("GRADED");
2688
+ onPageChange(1);
2689
+ },
2690
+ className: cn(
2691
+ "relative rounded-lg border-2 p-4 text-left transition-all duration-300 ease-in-out hover:scale-105 hover:shadow-md hover:z-20 cursor-pointer",
2692
+ filterStatus === "GRADED" ? "border-green-500 bg-green-50 dark:bg-green-900/20 scale-105 shadow-md z-20" : "border-theme-border-primary hover:border-green-500"
2693
+ ),
2694
+ children: [
2695
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between", children: [
2696
+ /* @__PURE__ */ jsxs15("div", { children: [
2697
+ /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-theme-text-muted", children: "Approved" }),
2698
+ /* @__PURE__ */ jsx17("p", { className: "text-2xl font-bold text-green-600", children: (_c = summary == null ? void 0 : summary.gradedSubmissions) != null ? _c : 0 })
2699
+ ] }),
2700
+ /* @__PURE__ */ jsx17(CheckCircle, { className: "h-6 w-6 text-green-600" })
2701
+ ] }),
2702
+ /* @__PURE__ */ jsx17("p", { className: "mt-1 text-xs text-theme-text-muted", children: "Completed" })
2703
+ ]
2704
+ }
2705
+ ),
2706
+ /* @__PURE__ */ jsxs15(
2707
+ "button",
2708
+ {
2709
+ onClick: () => {
2710
+ onFilterStatusChange("ALL");
2711
+ onPageChange(1);
2712
+ },
2713
+ className: cn(
2714
+ "relative rounded-lg border-2 p-4 text-left transition-all duration-300 ease-in-out hover:scale-105 hover:shadow-md hover:z-20 cursor-pointer",
2715
+ filterStatus === "ALL" ? "border-blue-500 bg-blue-50 dark:bg-blue-900/20 scale-105 shadow-md z-20" : "border-theme-border-primary hover:border-blue-500"
2716
+ ),
2717
+ children: [
2718
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between", children: [
2719
+ /* @__PURE__ */ jsxs15("div", { children: [
2720
+ /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-theme-text-muted", children: "Total" }),
2721
+ /* @__PURE__ */ jsx17("p", { className: "text-2xl font-bold text-blue-600", children: (_d = summary == null ? void 0 : summary.totalSubmissions) != null ? _d : 0 })
2722
+ ] }),
2723
+ /* @__PURE__ */ jsx17(FileText4, { className: "h-6 w-6 text-blue-600" })
2724
+ ] }),
2725
+ /* @__PURE__ */ jsx17("p", { className: "mt-1 text-xs text-theme-text-muted", children: "All submissions" })
2726
+ ]
2727
+ }
2728
+ )
2729
+ ] }),
2730
+ /* @__PURE__ */ jsx17("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-3 sm:flex-row", children: [
2731
+ /* @__PURE__ */ jsxs15("div", { className: "relative flex-1", children: [
2732
+ /* @__PURE__ */ jsx17(Search7, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-theme-text-tertiary z-10 pointer-events-none" }),
2733
+ /* @__PURE__ */ jsx17(
2734
+ Input,
2735
+ {
2736
+ type: "text",
2737
+ placeholder: "Search learner, course, or assignment...",
2738
+ value: searchQuery,
2739
+ onChange: (e) => onSearchChange(e.target.value),
2740
+ className: "pl-10"
2741
+ }
2742
+ )
2743
+ ] }),
2744
+ /* @__PURE__ */ jsx17("div", { className: "w-full sm:w-auto", children: /* @__PURE__ */ jsxs15(
2745
+ "select",
2746
+ {
2747
+ value: filterStatus,
2748
+ onChange: (e) => {
2749
+ onFilterStatusChange(e.target.value);
2750
+ onPageChange(1);
2751
+ },
2752
+ className: "w-full h-10 px-3 rounded-md border border-theme-border-primary bg-theme-bg-primary text-theme-text-primary text-sm focus:outline-none focus:ring-2 focus:ring-theme-accent-primary cursor-pointer",
2753
+ children: [
2754
+ /* @__PURE__ */ jsx17("option", { value: "ALL", children: "All Statuses" }),
2755
+ /* @__PURE__ */ jsx17("option", { value: "IN_REVIEW", children: "Pending Review" }),
2756
+ /* @__PURE__ */ jsx17("option", { value: "REQUEST_CHANGE", children: "Changes Requested" }),
2757
+ /* @__PURE__ */ jsx17("option", { value: "GRADED", children: "Approved" })
2758
+ ]
2759
+ }
2760
+ ) })
2761
+ ] }) }),
2762
+ isLoading ? /* @__PURE__ */ jsx17(LoadingSpinner, { className: "py-20", text: "Loading submissions..." }) : submissions.length === 0 ? /* @__PURE__ */ jsx17(
2763
+ EmptyState,
2764
+ {
2765
+ icon: /* @__PURE__ */ jsx17(ClipboardList2, { className: "w-16 h-16" }),
2766
+ title: "No submissions found",
2767
+ description: "You haven't submitted anything for manual review yet."
2768
+ }
2769
+ ) : /* @__PURE__ */ jsxs15(Fragment7, { children: [
2770
+ /* @__PURE__ */ jsxs15("div", { className: "bg-theme-bg-primary rounded-lg border border-theme-border-primary", children: [
2771
+ /* @__PURE__ */ jsxs15("div", { className: "hidden sm:grid grid-cols-12 gap-4 px-5 py-3 bg-theme-bg-secondary text-xs font-semibold text-theme-text-muted uppercase tracking-wider border-b border-theme-border-primary rounded-t-lg", children: [
2772
+ /* @__PURE__ */ jsx17("div", { className: "col-span-5", children: "Assignment" }),
2773
+ /* @__PURE__ */ jsx17("div", { className: "col-span-2", children: "Submitted" }),
2774
+ /* @__PURE__ */ jsx17("div", { className: "col-span-3", children: "Status" }),
2775
+ /* @__PURE__ */ jsx17("div", { className: "col-span-2 text-right", children: "Score" })
2776
+ ] }),
2777
+ /* @__PURE__ */ jsx17("div", { className: "divide-y divide-theme-border-primary", children: submissions.map((sub) => {
2778
+ var _a2, _b2, _c2, _d2, _e, _f;
2779
+ return /* @__PURE__ */ jsxs15(
2780
+ "div",
2781
+ {
2782
+ onClick: () => onSubmissionClick(sub.id),
2783
+ className: "grid grid-cols-1 sm:grid-cols-12 gap-2 sm:gap-4 px-5 py-4 hover:bg-theme-bg-secondary/50 transition-colors cursor-pointer group",
2784
+ children: [
2785
+ /* @__PURE__ */ jsxs15("div", { className: "sm:col-span-5", children: [
2786
+ /* @__PURE__ */ jsx17("div", { className: "font-medium text-theme-text-primary group-hover:text-theme-accent-primary transition-colors truncate max-w-xs", children: ((_a2 = sub.assignment) == null ? void 0 : _a2.title) || sub.lessonTitle || sub.title || "Submission" }),
2787
+ /* @__PURE__ */ jsx17("div", { className: "text-xs text-theme-text-tertiary", children: ((_b2 = sub.assignment) == null ? void 0 : _b2.courseName) || sub.courseName || "" })
2788
+ ] }),
2789
+ /* @__PURE__ */ jsxs15("div", { className: "sm:col-span-2 flex items-center gap-1 text-sm text-theme-text-secondary", children: [
2790
+ /* @__PURE__ */ jsx17(Calendar, { className: "h-4 w-4" }),
2791
+ sub.submittedAt ? formatDate(sub.submittedAt) : "\u2014"
2792
+ ] }),
2793
+ /* @__PURE__ */ jsx17("div", { className: "sm:col-span-3 flex items-center", children: /* @__PURE__ */ jsx17(Badge, { variant: ((_c2 = statusDisplay[sub.status]) == null ? void 0 : _c2.variant) || "secondary", children: ((_d2 = statusDisplay[sub.status]) == null ? void 0 : _d2.label) || sub.status }) }),
2794
+ /* @__PURE__ */ jsx17("div", { className: "sm:col-span-2 flex items-center justify-end", children: /* @__PURE__ */ jsxs15("span", { className: "font-medium text-theme-text-primary", children: [
2795
+ (_e = sub.score) != null ? _e : 0,
2796
+ "/",
2797
+ (_f = sub.totalPoints) != null ? _f : 0
2798
+ ] }) })
2799
+ ]
2800
+ },
2801
+ sub.id
2802
+ );
2803
+ }) })
2804
+ ] }),
2805
+ pagination && pagination.totalPages > 1 && /* @__PURE__ */ jsx17(
2806
+ Pagination,
2807
+ {
2808
+ currentPage,
2809
+ totalPages: pagination.totalPages,
2810
+ total: pagination.totalItems,
2811
+ pageSize: pagination.itemsPerPage || 10,
2812
+ hasNextPage: pagination.hasNextPage,
2813
+ hasPreviousPage: pagination.hasPreviousPage,
2814
+ onPageChange,
2815
+ className: "mt-4"
2816
+ }
2817
+ )
2818
+ ] })
2819
+ ] });
2820
+ }
2821
+
2822
+ // src/components/pages/ManualReviewDetailPage.tsx
2823
+ import { ArrowLeft as ArrowLeft3, Calendar as Calendar2, BookOpen as BookOpen5, Award as Award3, AlertCircle as AlertCircle2, CheckCircle as CheckCircle3, Clock as Clock4, FileText as FileText5 } from "lucide-react";
2824
+
2825
+ // src/components/atoms/Card.tsx
2826
+ import { jsx as jsx18 } from "react/jsx-runtime";
2827
+ function Card(_a) {
2828
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
2829
+ return /* @__PURE__ */ jsx18(
2830
+ "div",
2831
+ __spreadValues({
2832
+ className: cn("rounded-lg border border-theme-border-primary bg-theme-bg-primary shadow-sm", className)
2833
+ }, props)
2834
+ );
2835
+ }
2836
+ function CardHeader(_a) {
2837
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
2838
+ return /* @__PURE__ */ jsx18("div", __spreadValues({ className: cn("flex flex-col space-y-1.5 p-6", className) }, props));
2839
+ }
2840
+ function CardTitle(_a) {
2841
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
2842
+ return /* @__PURE__ */ jsx18("h3", __spreadValues({ className: cn("text-2xl font-semibold leading-none tracking-tight", className) }, props));
2843
+ }
2844
+ function CardContent(_a) {
2845
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
2846
+ return /* @__PURE__ */ jsx18("div", __spreadValues({ className: cn("p-6 pt-0", className) }, props));
2847
+ }
2848
+
2849
+ // src/components/pages/ManualReviewDetailPage.tsx
2850
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
2851
+ function formatDate2(dateString) {
2852
+ return new Date(dateString).toLocaleDateString("en-US", {
2853
+ month: "long",
2854
+ day: "numeric",
2855
+ year: "numeric",
2856
+ hour: "2-digit",
2857
+ minute: "2-digit"
2858
+ });
2859
+ }
2860
+ function formatQuestionType(type) {
2861
+ switch (type) {
2862
+ case "TRUE_FALSE":
2863
+ return "True/False";
2864
+ case "SINGLE_CHOICE":
2865
+ return "Single Choice";
2866
+ case "MULTIPLE_SELECT":
2867
+ return "Multiple Select";
2868
+ case "TEXT":
2869
+ return "Short Answer";
2870
+ case "ESSAY":
2871
+ return "Essay";
2872
+ default:
2873
+ return type;
2874
+ }
2875
+ }
2876
+ function getStatusBadge(status) {
2877
+ switch (status) {
2878
+ case "IN_REVIEW":
2879
+ return /* @__PURE__ */ jsxs16(Badge, { variant: "warning", className: "flex items-center gap-1", children: [
2880
+ /* @__PURE__ */ jsx19(Clock4, { className: "h-3 w-3" }),
2881
+ "Pending Review"
2882
+ ] });
2883
+ case "REQUEST_CHANGE":
2884
+ return /* @__PURE__ */ jsxs16(Badge, { variant: "destructive", className: "flex items-center gap-1", children: [
2885
+ /* @__PURE__ */ jsx19(AlertCircle2, { className: "h-3 w-3" }),
2886
+ "Changes Requested"
2887
+ ] });
2888
+ case "GRADED":
2889
+ return /* @__PURE__ */ jsxs16(Badge, { variant: "success", className: "flex items-center gap-1", children: [
2890
+ /* @__PURE__ */ jsx19(CheckCircle3, { className: "h-3 w-3" }),
2891
+ "Approved"
2892
+ ] });
2893
+ default:
2894
+ return /* @__PURE__ */ jsx19(Badge, { variant: "secondary", children: status });
2895
+ }
2896
+ }
2897
+ function ManualReviewDetailPage(props) {
2898
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
2899
+ const noop = (..._args) => {
2900
+ };
2901
+ const { submission, isLoading = false, notFound = false, onBack = noop } = props;
2902
+ if (isLoading) return /* @__PURE__ */ jsx19(LoadingSpinner, { className: "py-20", text: "Loading submission..." });
2903
+ if (notFound || !submission) {
2904
+ return /* @__PURE__ */ jsx19("div", { className: "container mx-auto p-6", children: /* @__PURE__ */ jsxs16("div", { className: "text-center py-12", children: [
2905
+ /* @__PURE__ */ jsx19(AlertCircle2, { className: "h-12 w-12 text-theme-text-tertiary mx-auto mb-4" }),
2906
+ /* @__PURE__ */ jsx19("h2", { className: "text-xl font-semibold text-theme-text-primary mb-2", children: "Submission Not Found" }),
2907
+ /* @__PURE__ */ jsx19("p", { className: "text-theme-text-secondary mb-4", children: "The submission you're looking for doesn't exist or has been removed." }),
2908
+ /* @__PURE__ */ jsx19(Button, { onClick: onBack, children: "Back to Manual Review" })
2909
+ ] }) });
2910
+ }
2911
+ const detail = submission;
2912
+ const status = ((_a = detail.context) == null ? void 0 : _a.status) || detail.status || "IN_REVIEW";
2913
+ const assignmentTitle = ((_c = (_b = detail.context) == null ? void 0 : _b.assignment) == null ? void 0 : _c.title) || detail.lessonTitle || "Submission Detail";
2914
+ const courseName = ((_e = (_d = detail.context) == null ? void 0 : _d.course) == null ? void 0 : _e.name) || detail.courseName || "";
2915
+ const submittedAt = ((_f = detail.context) == null ? void 0 : _f.submittedAt) || detail.submittedAt || "";
2916
+ const totalQuestions = ((_h = (_g = detail.context) == null ? void 0 : _g.assignment) == null ? void 0 : _h.totalQuestions) || 0;
2917
+ const totalPoints = ((_j = (_i = detail.context) == null ? void 0 : _i.assignment) == null ? void 0 : _j.totalPoints) || 0;
2918
+ const score = (_n = (_m = (_k = detail.latestReview) == null ? void 0 : _k.score) != null ? _m : (_l = detail.answers) == null ? void 0 : _l.reduce((sum, a) => sum + (a.pointsAwarded || 0), 0)) != null ? _n : 0;
2919
+ const answers = detail.answers || [];
2920
+ return /* @__PURE__ */ jsxs16("div", { className: "container mx-auto space-y-6 max-w-6xl", children: [
2921
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-4", children: [
2922
+ /* @__PURE__ */ jsx19(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ jsx19(ArrowLeft3, { className: "h-5 w-5" }) }),
2923
+ /* @__PURE__ */ jsxs16("div", { className: "flex-1", children: [
2924
+ /* @__PURE__ */ jsx19("h1", { className: "text-3xl font-bold text-theme-text-primary", children: assignmentTitle }),
2925
+ courseName && /* @__PURE__ */ jsx19("p", { className: "text-theme-text-secondary mt-1", children: courseName })
2926
+ ] }),
2927
+ getStatusBadge(status)
2928
+ ] }),
2929
+ /* @__PURE__ */ jsxs16("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4", children: [
2930
+ /* @__PURE__ */ jsx19(Card, { children: /* @__PURE__ */ jsxs16(CardContent, { className: "pt-6", children: [
2931
+ /* @__PURE__ */ jsx19(Calendar2, { className: "h-5 w-5 text-purple-600 dark:text-purple-400 mb-3" }),
2932
+ /* @__PURE__ */ jsxs16("div", { children: [
2933
+ /* @__PURE__ */ jsx19("p", { className: "text-sm text-theme-text-secondary", children: "Submitted" }),
2934
+ /* @__PURE__ */ jsx19("p", { className: "font-medium text-theme-text-primary", children: submittedAt ? formatDate2(submittedAt) : "\u2014" })
2935
+ ] })
2936
+ ] }) }),
2937
+ /* @__PURE__ */ jsx19(Card, { children: /* @__PURE__ */ jsxs16(CardContent, { className: "pt-6", children: [
2938
+ /* @__PURE__ */ jsx19(BookOpen5, { className: "h-5 w-5 text-green-600 dark:text-green-400 mb-3" }),
2939
+ /* @__PURE__ */ jsxs16("div", { children: [
2940
+ /* @__PURE__ */ jsx19("p", { className: "text-sm text-theme-text-secondary", children: "Assignment Info" }),
2941
+ /* @__PURE__ */ jsxs16("p", { className: "font-medium text-theme-text-primary", children: [
2942
+ totalQuestions,
2943
+ " Questions"
2944
+ ] })
2945
+ ] })
2946
+ ] }) }),
2947
+ status === "IN_REVIEW" ? /* @__PURE__ */ jsx19(Card, { children: /* @__PURE__ */ jsxs16(CardContent, { className: "pt-6", children: [
2948
+ /* @__PURE__ */ jsx19(Clock4, { className: "h-5 w-5 text-yellow-600 dark:text-yellow-400 mb-3" }),
2949
+ /* @__PURE__ */ jsxs16("div", { children: [
2950
+ /* @__PURE__ */ jsx19("p", { className: "text-sm text-theme-text-secondary", children: "Status" }),
2951
+ /* @__PURE__ */ jsx19("p", { className: "font-medium text-theme-text-primary", children: "Waiting for Review" }),
2952
+ /* @__PURE__ */ jsx19("p", { className: "text-xs text-theme-text-tertiary mt-1", children: "Your submission is being reviewed by the instructor." })
2953
+ ] })
2954
+ ] }) }) : /* @__PURE__ */ jsx19(Card, { children: /* @__PURE__ */ jsxs16(CardContent, { className: "pt-6", children: [
2955
+ /* @__PURE__ */ jsx19(Award3, { className: "h-5 w-5 text-blue-600 dark:text-blue-400 mb-3" }),
2956
+ /* @__PURE__ */ jsxs16("div", { children: [
2957
+ /* @__PURE__ */ jsx19("p", { className: "text-sm text-theme-text-secondary", children: "Score" }),
2958
+ /* @__PURE__ */ jsxs16("p", { className: "text-2xl font-bold text-theme-accent-primary", children: [
2959
+ score,
2960
+ "/",
2961
+ totalPoints
2962
+ ] }),
2963
+ status === "REQUEST_CHANGE" && /* @__PURE__ */ jsx19("p", { className: "text-xs text-theme-text-tertiary mt-1", children: "Score is provisional until review completes." })
2964
+ ] })
2965
+ ] }) })
2966
+ ] }),
2967
+ status === "REQUEST_CHANGE" && /* @__PURE__ */ jsx19(Card, { className: "border-red-200 dark:border-red-800 bg-red-50 dark:bg-red-900/10", children: /* @__PURE__ */ jsx19(CardContent, { className: "pt-6", children: /* @__PURE__ */ jsxs16("div", { className: "flex items-start gap-4", children: [
2968
+ /* @__PURE__ */ jsx19(AlertCircle2, { className: "h-6 w-6 text-red-600 dark:text-red-400 flex-shrink-0 mt-1" }),
2969
+ /* @__PURE__ */ jsxs16("div", { className: "flex-1", children: [
2970
+ /* @__PURE__ */ jsx19("h3", { className: "font-semibold text-theme-text-primary mb-2", children: "Changes Requested" }),
2971
+ /* @__PURE__ */ jsx19("p", { className: "text-sm text-theme-text-secondary", children: "Your instructor has requested changes to your submission. Please review the feedback below and resubmit your assignment through the course player." })
2972
+ ] })
2973
+ ] }) }) }),
2974
+ answers.length > 0 && /* @__PURE__ */ jsxs16(Card, { children: [
2975
+ /* @__PURE__ */ jsx19(CardHeader, { children: /* @__PURE__ */ jsxs16(CardTitle, { className: "flex items-center gap-2", children: [
2976
+ /* @__PURE__ */ jsx19(FileText5, { className: "h-5 w-5" }),
2977
+ "Submitted Answers (",
2978
+ answers.length,
2979
+ ")"
2980
+ ] }) }),
2981
+ /* @__PURE__ */ jsx19(CardContent, { className: "space-y-6", children: answers.map((answer, index) => /* @__PURE__ */ jsx19(
2982
+ "div",
2983
+ {
2984
+ className: "pb-6 border-b border-theme-border-primary last:border-b-0 last:pb-0",
2985
+ children: /* @__PURE__ */ jsxs16("div", { className: "flex items-start gap-3 mb-3", children: [
2986
+ /* @__PURE__ */ jsx19("div", { className: "flex-shrink-0 w-8 h-8 rounded-full bg-theme-accent-primary text-white flex items-center justify-center font-semibold text-sm", children: index + 1 }),
2987
+ /* @__PURE__ */ jsxs16("div", { className: "flex-1", children: [
2988
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-start justify-between gap-4 mb-2", children: [
2989
+ /* @__PURE__ */ jsx19("h4", { className: "font-medium text-theme-text-primary", children: answer.questionText }),
2990
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
2991
+ /* @__PURE__ */ jsx19(Badge, { variant: "secondary", className: "text-xs", children: formatQuestionType(answer.questionType) }),
2992
+ /* @__PURE__ */ jsxs16("span", { className: "text-sm text-theme-text-secondary", children: [
2993
+ answer.questionPoints,
2994
+ " pts"
2995
+ ] })
2996
+ ] })
2997
+ ] }),
2998
+ /* @__PURE__ */ jsxs16("div", { className: "mt-3 space-y-3", children: [
2999
+ answer.selectedOptionText && /* @__PURE__ */ jsxs16("div", { className: "p-4 bg-theme-bg-secondary rounded-lg border border-theme-border-primary", children: [
3000
+ /* @__PURE__ */ jsx19("p", { className: "text-xs font-medium text-theme-text-secondary mb-2", children: "Your Answer:" }),
3001
+ /* @__PURE__ */ jsx19("p", { className: "text-theme-text-primary font-medium", children: answer.selectedOptionText })
3002
+ ] }),
3003
+ answer.selectedOptionIds && answer.selectedOptionIds.length > 0 && !answer.selectedOptionText && /* @__PURE__ */ jsxs16("div", { className: "p-4 bg-theme-bg-secondary rounded-lg border border-theme-border-primary", children: [
3004
+ /* @__PURE__ */ jsx19("p", { className: "text-xs font-medium text-theme-text-secondary mb-2", children: "Selected Options:" }),
3005
+ /* @__PURE__ */ jsx19("div", { className: "space-y-2", children: answer.selectedOptions && answer.selectedOptions.length > 0 ? answer.selectedOptions.map((option, idx) => /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
3006
+ /* @__PURE__ */ jsx19("div", { className: "h-2 w-2 rounded-full bg-theme-accent-primary" }),
3007
+ /* @__PURE__ */ jsx19("span", { className: "text-theme-text-primary", children: option.text })
3008
+ ] }, idx)) : /* @__PURE__ */ jsxs16("p", { className: "text-theme-text-secondary text-sm", children: [
3009
+ answer.selectedOptionIds.length,
3010
+ " option",
3011
+ answer.selectedOptionIds.length !== 1 ? "s" : "",
3012
+ " selected"
3013
+ ] }) })
3014
+ ] }),
3015
+ answer.answerText && /* @__PURE__ */ jsxs16("div", { className: "p-4 bg-theme-bg-secondary rounded-lg border border-theme-border-primary", children: [
3016
+ /* @__PURE__ */ jsx19("p", { className: "text-xs font-medium text-theme-text-secondary mb-2", children: "Your Answer:" }),
3017
+ /* @__PURE__ */ jsx19("p", { className: "text-theme-text-primary whitespace-pre-wrap", children: answer.answerText })
3018
+ ] })
3019
+ ] })
3020
+ ] })
3021
+ ] })
3022
+ },
3023
+ answer.questionId || index
3024
+ )) })
3025
+ ] })
3026
+ ] });
3027
+ }
3028
+
3029
+ // src/components/pages/LearnerSettingsPage.tsx
3030
+ import { useState as useState9 } from "react";
3031
+ import { Mail } from "lucide-react";
3032
+ import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
3033
+ function LearnerSettingsPage(props) {
3034
+ const [marketingEmails, setMarketingEmails] = useState9(true);
3035
+ return /* @__PURE__ */ jsxs17("div", { className: "space-y-8", children: [
3036
+ /* @__PURE__ */ jsxs17("div", { children: [
3037
+ /* @__PURE__ */ jsx20("h1", { className: "text-3xl font-bold text-theme-text-primary", children: "Settings" }),
3038
+ /* @__PURE__ */ jsx20("p", { className: "mt-2 text-lg text-theme-text-secondary", children: "Manage your account settings and preferences" })
3039
+ ] }),
3040
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
3041
+ /* @__PURE__ */ jsxs17("div", { children: [
3042
+ /* @__PURE__ */ jsx20("h2", { className: "text-2xl font-bold text-theme-text-primary", children: "Email Preferences" }),
3043
+ /* @__PURE__ */ jsx20("p", { className: "mt-1 text-theme-text-secondary", children: "Control what emails you receive from us" })
3044
+ ] }),
3045
+ /* @__PURE__ */ jsx20("div", { className: "p-6 w-full max-w-2xl rounded-lg border border-theme-border-primary bg-theme-bg-secondary", children: /* @__PURE__ */ jsxs17("div", { className: "flex items-start justify-between", children: [
3046
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-4", children: [
3047
+ /* @__PURE__ */ jsx20("div", { className: "rounded-lg bg-theme-bg-tertiary p-3", children: /* @__PURE__ */ jsx20(Mail, { className: "h-5 w-5 text-theme-accent-primary" }) }),
3048
+ /* @__PURE__ */ jsxs17("div", { children: [
3049
+ /* @__PURE__ */ jsx20("h3", { className: "text-base font-semibold text-theme-text-primary", children: "Marketing Emails" }),
3050
+ /* @__PURE__ */ jsx20("p", { className: "mt-1 text-sm text-theme-text-secondary", children: "Receive promotional updates, new courses, and special offers about our academy" })
3051
+ ] })
3052
+ ] }),
3053
+ /* @__PURE__ */ jsx20(
3054
+ "button",
3055
+ {
3056
+ onClick: () => setMarketingEmails(!marketingEmails),
3057
+ className: `relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${marketingEmails ? "bg-theme-accent-primary" : "bg-gray-200"}`,
3058
+ role: "switch",
3059
+ "aria-checked": marketingEmails,
3060
+ children: /* @__PURE__ */ jsx20(
3061
+ "span",
3062
+ {
3063
+ className: `pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200 ${marketingEmails ? "translate-x-5" : "translate-x-0"}`
3064
+ }
3065
+ )
3066
+ }
3067
+ )
3068
+ ] }) })
3069
+ ] })
3070
+ ] });
3071
+ }
3072
+
3073
+ // src/components/pages/PaymentSuccessPage.tsx
3074
+ import { useEffect as useEffect2, useState as useState10 } from "react";
3075
+ import { CheckCircle as CheckCircle4, Loader2 as Loader22 } from "lucide-react";
3076
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
3077
+ function PaymentSuccessPage({ onContinueLearning = () => {
3078
+ } }) {
3079
+ const [countdown, setCountdown] = useState10(5);
3080
+ const [isRedirecting, setIsRedirecting] = useState10(false);
3081
+ useEffect2(() => {
3082
+ const timer = setInterval(() => {
3083
+ setCountdown((prev) => {
3084
+ if (prev <= 1) {
3085
+ clearInterval(timer);
3086
+ setIsRedirecting(true);
3087
+ onContinueLearning();
3088
+ return 0;
3089
+ }
3090
+ return prev - 1;
3091
+ });
3092
+ }, 1e3);
3093
+ return () => clearInterval(timer);
3094
+ }, []);
3095
+ return /* @__PURE__ */ jsx21("div", { className: "min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 flex items-center justify-center px-4 py-12", children: /* @__PURE__ */ jsx21("div", { className: "max-w-lg w-full", children: /* @__PURE__ */ jsxs18("div", { children: [
3096
+ /* @__PURE__ */ jsx21("div", { className: "mb-8 flex justify-center", children: /* @__PURE__ */ jsxs18("div", { className: "relative", children: [
3097
+ /* @__PURE__ */ jsx21("div", { className: "absolute inset-0 bg-green-400 rounded-full animate-ping opacity-20" }),
3098
+ /* @__PURE__ */ jsx21("div", { className: "relative bg-gradient-to-br from-green-400 to-green-500 rounded-full p-5 shadow-lg", children: /* @__PURE__ */ jsx21(CheckCircle4, { className: "h-16 w-16 text-white", strokeWidth: 2.5 }) })
3099
+ ] }) }),
3100
+ /* @__PURE__ */ jsx21("h1", { className: "text-2xl font-bold text-gray-900 mb-3 text-center", children: "Payment Successful!" }),
3101
+ /* @__PURE__ */ jsx21("p", { className: "text-gray-600 text-sm mb-8 text-center leading-relaxed", children: "Thank you for your purchase. You're now enrolled in the course and can start learning immediately." }),
3102
+ /* @__PURE__ */ jsx21("div", { className: "mb-8 p-4 bg-blue-50 rounded-xl border border-blue-100", children: isRedirecting ? /* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-center gap-2 text-blue-600", children: [
3103
+ /* @__PURE__ */ jsx21(Loader22, { className: "h-5 w-5 animate-spin" }),
3104
+ /* @__PURE__ */ jsx21("span", { className: "text-sm font-medium", children: "Redirecting..." })
3105
+ ] }) : /* @__PURE__ */ jsxs18("p", { className: "text-sm text-blue-600 text-center font-medium", children: [
3106
+ "Redirecting to course page in ",
3107
+ countdown,
3108
+ " second",
3109
+ countdown !== 1 ? "s" : "",
3110
+ "..."
3111
+ ] }) }),
3112
+ /* @__PURE__ */ jsx21("div", { className: "text-center", children: /* @__PURE__ */ jsx21(
3113
+ "button",
3114
+ {
3115
+ onClick: onContinueLearning,
3116
+ className: "inline-flex items-center gap-2 px-6 py-2 bg-green-500 text-white rounded-lg font-medium hover:bg-green-600 transition-colors cursor-pointer",
3117
+ children: "Continue Learning"
3118
+ }
3119
+ ) })
3120
+ ] }) }) });
3121
+ }
3122
+
3123
+ // src/components/pages/PaymentCancelPage.tsx
3124
+ import { useEffect as useEffect3, useState as useState11 } from "react";
3125
+ import { XCircle } from "lucide-react";
3126
+ import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
3127
+ function PaymentCancelPage({ onRetry = () => {
3128
+ }, onGoBack = () => {
3129
+ } }) {
3130
+ const [countdown, setCountdown] = useState11(10);
3131
+ useEffect3(() => {
3132
+ const timer = setInterval(() => {
3133
+ setCountdown((prev) => {
3134
+ if (prev <= 1) {
3135
+ clearInterval(timer);
3136
+ onGoBack();
3137
+ return 0;
3138
+ }
3139
+ return prev - 1;
3140
+ });
3141
+ }, 1e3);
3142
+ return () => clearInterval(timer);
3143
+ }, []);
3144
+ return /* @__PURE__ */ jsx22("div", { className: "min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 flex items-center justify-center px-4 py-12", children: /* @__PURE__ */ jsx22("div", { className: "max-w-lg w-full", children: /* @__PURE__ */ jsxs19("div", { children: [
3145
+ /* @__PURE__ */ jsx22("div", { className: "mb-8 flex justify-center", children: /* @__PURE__ */ jsx22("div", { className: "bg-gradient-to-br from-orange-400 to-orange-500 rounded-full p-5 shadow-lg", children: /* @__PURE__ */ jsx22(XCircle, { className: "h-16 w-16 text-white", strokeWidth: 2.5 }) }) }),
3146
+ /* @__PURE__ */ jsx22("h1", { className: "text-2xl font-bold text-gray-900 mb-3 text-center", children: "Payment Cancelled" }),
3147
+ /* @__PURE__ */ jsx22("p", { className: "text-gray-600 text-sm mb-8 text-center leading-relaxed", children: "Your payment was cancelled. No charges have been made to your account." }),
3148
+ /* @__PURE__ */ jsx22("div", { className: "mb-6 p-4 bg-blue-50 rounded-xl border border-blue-100", children: /* @__PURE__ */ jsx22("p", { className: "text-sm text-blue-600 text-center font-medium leading-relaxed", children: "You can complete your purchase anytime. The course will be waiting for you!" }) }),
3149
+ /* @__PURE__ */ jsx22("div", { className: "mb-8 p-4 bg-gradient-to-br from-gray-50 to-gray-100 rounded-xl border border-gray-200", children: /* @__PURE__ */ jsxs19("p", { className: "text-sm text-gray-600 text-center font-medium", children: [
3150
+ "Redirecting in ",
3151
+ countdown,
3152
+ " second",
3153
+ countdown !== 1 ? "s" : "",
3154
+ "..."
3155
+ ] }) }),
3156
+ /* @__PURE__ */ jsxs19("div", { className: "flex gap-4 justify-center", children: [
3157
+ /* @__PURE__ */ jsx22(
3158
+ "button",
3159
+ {
3160
+ onClick: onRetry,
3161
+ className: "px-6 py-2 bg-theme-accent-primary text-white rounded-lg font-medium hover:opacity-90 transition-opacity cursor-pointer",
3162
+ children: "Try Again"
3163
+ }
3164
+ ),
3165
+ /* @__PURE__ */ jsx22(
3166
+ "button",
3167
+ {
3168
+ onClick: onGoBack,
3169
+ className: "px-6 py-2 border border-theme-border-primary rounded-lg font-medium text-theme-text-primary hover:bg-theme-bg-secondary transition-colors cursor-pointer",
3170
+ children: "Go Back"
3171
+ }
3172
+ )
3173
+ ] })
3174
+ ] }) }) });
3175
+ }
3176
+
3177
+ // src/components/pages/CreatorProfilePage.tsx
3178
+ import { Mail as Mail2, BookOpen as BookOpen6, Award as Award4 } from "lucide-react";
3179
+ import { User } from "lucide-react";
3180
+ import { Fragment as Fragment8, jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
3181
+ function CreatorProfilePage(props) {
3182
+ var _a;
3183
+ const noop = (..._args) => {
3184
+ };
3185
+ const { creator, courses = [], isLoading = false, onCourseClick = noop } = props;
3186
+ if (isLoading) return /* @__PURE__ */ jsx23(LoadingSpinner, { className: "py-20" });
3187
+ if (!creator) return /* @__PURE__ */ jsx23(EmptyState, { icon: /* @__PURE__ */ jsx23(User, { className: "w-16 h-16" }), title: "Creator not found" });
3188
+ const name = creator.name || "Course Creator";
3189
+ const email = creator.email || "";
3190
+ const bio = creator.bio || "An experienced educator and software developer with expertise in modern web development and software engineering. With years of industry experience, they create comprehensive courses that help students master cutting-edge technologies and build real-world applications.";
3191
+ const expertise = creator.expertise || [];
3192
+ const avatarInitial = name.charAt(0).toUpperCase();
3193
+ const totalCourses = (_a = creator.totalCourses) != null ? _a : courses.length;
3194
+ const totalLessons = creator.totalLessons;
3195
+ const totalStudents = creator.totalStudents;
3196
+ return /* @__PURE__ */ jsx23("div", { className: "min-h-screen", children: /* @__PURE__ */ jsxs20("div", { children: [
3197
+ /* @__PURE__ */ jsx23("div", { className: "mb-12", children: /* @__PURE__ */ jsxs20("div", { className: "flex flex-col md:flex-row items-center gap-10", children: [
3198
+ /* @__PURE__ */ jsxs20("div", { className: "flex-1 text-gray-900 text-center md:text-left space-y-4", children: [
3199
+ /* @__PURE__ */ jsxs20("div", { className: "inline-flex items-center gap-2 bg-indigo-100 px-4 py-2 rounded-full text-sm font-medium text-indigo-700", children: [
3200
+ /* @__PURE__ */ jsx23(Award4, { className: "h-4 w-4" }),
3201
+ "Professional Creator"
3202
+ ] }),
3203
+ /* @__PURE__ */ jsx23("h1", { className: "text-5xl md:text-6xl font-bold tracking-tight", children: name }),
3204
+ email && /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 text-gray-600 justify-center md:justify-start", children: [
3205
+ /* @__PURE__ */ jsx23(Mail2, { className: "h-4 w-4" }),
3206
+ /* @__PURE__ */ jsx23("span", { className: "text-lg", children: email })
3207
+ ] }),
3208
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-6 pt-4 justify-center md:justify-start", children: [
3209
+ /* @__PURE__ */ jsxs20("div", { className: "text-center", children: [
3210
+ /* @__PURE__ */ jsx23("div", { className: "text-3xl font-bold text-gray-900", children: totalCourses }),
3211
+ /* @__PURE__ */ jsx23("div", { className: "text-sm text-gray-600", children: "Courses" })
3212
+ ] }),
3213
+ totalLessons != null && /* @__PURE__ */ jsxs20(Fragment8, { children: [
3214
+ /* @__PURE__ */ jsx23("div", { className: "w-px h-12 bg-gray-300" }),
3215
+ /* @__PURE__ */ jsxs20("div", { className: "text-center", children: [
3216
+ /* @__PURE__ */ jsx23("div", { className: "text-3xl font-bold text-gray-900", children: totalLessons }),
3217
+ /* @__PURE__ */ jsx23("div", { className: "text-sm text-gray-600", children: "Lessons" })
3218
+ ] })
3219
+ ] }),
3220
+ totalStudents != null && /* @__PURE__ */ jsxs20(Fragment8, { children: [
3221
+ /* @__PURE__ */ jsx23("div", { className: "w-px h-12 bg-gray-300" }),
3222
+ /* @__PURE__ */ jsxs20("div", { className: "text-center", children: [
3223
+ /* @__PURE__ */ jsx23("div", { className: "text-3xl font-bold text-gray-900", children: totalStudents }),
3224
+ /* @__PURE__ */ jsx23("div", { className: "text-sm text-gray-600", children: "Students" })
3225
+ ] })
3226
+ ] })
3227
+ ] })
3228
+ ] }),
3229
+ /* @__PURE__ */ jsx23("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxs20("div", { className: "relative", children: [
3230
+ creator.profileImage ? /* @__PURE__ */ jsx23(
3231
+ "img",
3232
+ {
3233
+ src: creator.profileImage,
3234
+ alt: name,
3235
+ className: "w-48 h-48 rounded-full object-cover shadow-2xl"
3236
+ }
3237
+ ) : /* @__PURE__ */ jsx23("div", { className: "w-48 h-48 rounded-full bg-gradient-to-br from-indigo-600 to-purple-600 flex items-center justify-center text-white text-7xl font-bold shadow-2xl", children: avatarInitial }),
3238
+ /* @__PURE__ */ jsx23("div", { className: "absolute -bottom-2 -right-2 bg-green-500 h-12 w-12 rounded-full border-4 border-white shadow-lg" })
3239
+ ] }) })
3240
+ ] }) }),
3241
+ /* @__PURE__ */ jsxs20("div", { className: "mb-12", children: [
3242
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-3 mb-6", children: [
3243
+ /* @__PURE__ */ jsx23("div", { className: "h-1 w-12 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-full" }),
3244
+ /* @__PURE__ */ jsx23("h2", { className: "text-3xl font-bold text-gray-900", children: "About" })
3245
+ ] }),
3246
+ /* @__PURE__ */ jsx23("p", { className: "text-gray-700 leading-relaxed text-lg", children: bio })
3247
+ ] }),
3248
+ expertise.length > 0 && /* @__PURE__ */ jsxs20("div", { className: "mb-12", children: [
3249
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-3 mb-6", children: [
3250
+ /* @__PURE__ */ jsx23("div", { className: "h-1 w-12 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-full" }),
3251
+ /* @__PURE__ */ jsx23("h2", { className: "text-3xl font-bold text-gray-900", children: "Expertise" })
3252
+ ] }),
3253
+ /* @__PURE__ */ jsx23("div", { className: "flex flex-wrap gap-3", children: expertise.map((skill) => /* @__PURE__ */ jsx23(
3254
+ "span",
3255
+ {
3256
+ className: "px-4 py-2 bg-indigo-50 text-indigo-700 rounded-full text-sm font-medium",
3257
+ children: skill
3258
+ },
3259
+ skill
3260
+ )) })
3261
+ ] }),
3262
+ /* @__PURE__ */ jsxs20("div", { children: [
3263
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between mb-8", children: [
3264
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-3", children: [
3265
+ /* @__PURE__ */ jsx23("div", { className: "h-1 w-12 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-full" }),
3266
+ /* @__PURE__ */ jsx23("h2", { className: "text-3xl font-bold text-gray-900", children: "Featured Courses" })
3267
+ ] }),
3268
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 bg-indigo-50 px-4 py-2 rounded-full", children: [
3269
+ /* @__PURE__ */ jsx23(BookOpen6, { className: "h-5 w-5 text-indigo-600" }),
3270
+ /* @__PURE__ */ jsxs20("span", { className: "font-semibold text-indigo-600", children: [
3271
+ courses.length,
3272
+ " Courses"
3273
+ ] })
3274
+ ] })
3275
+ ] }),
3276
+ courses.length === 0 ? /* @__PURE__ */ jsx23(EmptyState, { title: "No courses yet" }) : /* @__PURE__ */ jsx23("div", { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3", children: courses.map((course) => {
3277
+ var _a2, _b;
3278
+ return /* @__PURE__ */ jsx23(
3279
+ CourseCard,
3280
+ {
3281
+ id: course.id,
3282
+ title: course.title || "",
3283
+ thumbnail: course.thumbnail,
3284
+ totalLessons: course.totalLessons || 0,
3285
+ progress: 0,
3286
+ isFree: (_a2 = course.isFree) != null ? _a2 : false,
3287
+ price: course.price,
3288
+ showProgress: false,
3289
+ showPrice: true,
3290
+ description: course.description || ((_b = course.summary) == null ? void 0 : _b.replace(/<[^>]*>/g, "")) || "",
3291
+ instructorName: creator.name,
3292
+ category: course.category,
3293
+ onClick: () => onCourseClick(course.id)
3294
+ },
3295
+ course.id
3296
+ );
3297
+ }) })
3298
+ ] })
3299
+ ] }) });
3300
+ }
3301
+ export {
3302
+ BundleDetailPage,
3303
+ CatalogBundlesPage,
3304
+ CatalogCoursesPage,
3305
+ CourseDetailPage,
3306
+ CoursePlayerPage,
3307
+ CreatorProfilePage,
3308
+ LearnerSettingsPage,
3309
+ ManualReviewDetailPage,
3310
+ ManualReviewPage,
3311
+ MessagesPage,
3312
+ MyLearningPage,
3313
+ PaymentCancelPage,
3314
+ PaymentSuccessPage
3315
+ };