@academy-sdk/sdk 0.1.1 → 0.2.1
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.
- package/dist/academy-sdk-sdk-v1.0.0.zip +0 -0
- package/dist/bundle.js +70 -0
- package/dist/manifest.json +5 -0
- package/dist/styles.css +3307 -0
- package/package.json +41 -46
- package/src/components/atoms/Avatar.tsx +38 -0
- package/src/components/atoms/Badge.tsx +32 -0
- package/src/components/atoms/Button.tsx +48 -0
- package/src/components/atoms/Card.tsx +33 -0
- package/src/components/atoms/Input.tsx +39 -0
- package/src/components/atoms/ProgressBar.tsx +52 -0
- package/src/components/atoms/Tabs.tsx +47 -0
- package/{dist/components/atoms/index.d.ts → src/components/atoms/index.ts} +0 -1
- package/{dist/components/index.d.ts → src/components/index.ts} +7 -1
- package/src/components/molecules/CourseCard.tsx +215 -0
- package/src/components/molecules/EmptyState.tsx +23 -0
- package/src/components/molecules/LoadingSpinner.tsx +27 -0
- package/src/components/molecules/PageHeader.tsx +22 -0
- package/src/components/molecules/Pagination.tsx +82 -0
- package/src/components/molecules/SearchInput.tsx +35 -0
- package/{dist/components/molecules/index.d.ts → src/components/molecules/index.ts} +0 -1
- package/src/components/organisms/CourseSidebar.tsx +276 -0
- package/src/components/organisms/LearnerNavbar.tsx +129 -0
- package/src/components/organisms/LearnerSidebar.tsx +148 -0
- package/src/components/organisms/LessonBookmarks.tsx +128 -0
- package/src/components/organisms/LessonNotes.tsx +153 -0
- package/{dist/components/organisms/index.d.ts → src/components/organisms/index.ts} +0 -1
- package/src/components/pages/BundleDetailPage.tsx +388 -0
- package/src/components/pages/CatalogBundlesPage.tsx +96 -0
- package/src/components/pages/CatalogCoursesPage.tsx +299 -0
- package/src/components/pages/CourseDetailPage.tsx +582 -0
- package/src/components/pages/CoursePlayerPage.tsx +481 -0
- package/src/components/pages/CreatorProfilePage.tsx +161 -0
- package/src/components/pages/LearnerSettingsPage.tsx +58 -0
- package/src/components/pages/ManualReviewDetailPage.tsx +254 -0
- package/src/components/pages/ManualReviewPage.tsx +228 -0
- package/src/components/pages/MessagesPage.tsx +285 -0
- package/src/components/pages/MyLearningPage.tsx +239 -0
- package/src/components/pages/PaymentCancelPage.tsx +74 -0
- package/src/components/pages/PaymentSuccessPage.tsx +73 -0
- package/{dist/components/pages/index.d.ts → src/components/pages/index.ts} +0 -1
- package/src/components/utils.ts +6 -0
- package/src/contracts/components.contract.ts +89 -0
- package/{dist/contracts/index.d.ts → src/contracts/index.ts} +0 -1
- package/src/contracts/layout.contract.ts +36 -0
- package/src/contracts/pages.contract.ts +275 -0
- package/src/contracts/template.contract.ts +100 -0
- package/src/default-template.tsx +52 -0
- package/{dist/hooks/index.d.ts → src/hooks/index.ts} +15 -1
- package/src/hooks/sdk-context.tsx +152 -0
- package/src/hooks/useAiCoach.ts +27 -0
- package/src/hooks/useBookmarks.ts +35 -0
- package/{dist/hooks/useCourseSearch.d.ts → src/hooks/useCourseSearch.ts} +8 -5
- package/{dist/hooks/useDebounce.d.ts → src/hooks/useDebounce.ts} +8 -2
- package/{dist/hooks/useMyBundles.d.ts → src/hooks/useMyBundles.ts} +8 -6
- package/{dist/hooks/useMyCourses.d.ts → src/hooks/useMyCourses.ts} +8 -6
- package/src/hooks/useNotes.ts +35 -0
- package/src/hooks/useNotifications.ts +16 -0
- package/{dist/hooks/useTheme.d.ts → src/hooks/useTheme.ts} +8 -5
- package/src/hooks/useToast.ts +17 -0
- package/{dist/hooks/useUser.d.ts → src/hooks/useUser.ts} +13 -9
- package/src/index.ts +33 -0
- package/src/layouts/DefaultLayout.tsx +58 -0
- package/src/manifest.json +5 -0
- package/src/styles.css +43 -0
- package/src/types/ai-coach.ts +25 -0
- package/src/types/bookmarks.ts +20 -0
- package/src/types/bundle.ts +119 -0
- package/src/types/common.ts +24 -0
- package/src/types/course.ts +135 -0
- package/src/types/enrollment.ts +35 -0
- package/{dist/types/index.d.ts → src/types/index.ts} +0 -1
- package/src/types/lesson.ts +106 -0
- package/src/types/manual-review.ts +116 -0
- package/src/types/messaging.ts +109 -0
- package/src/types/notification.ts +30 -0
- package/src/types/payment.ts +40 -0
- package/src/types/progress.ts +19 -0
- package/src/types/rating.ts +20 -0
- package/src/types/search.ts +31 -0
- package/src/types/user.ts +16 -0
- package/src/utils/formatters.ts +74 -0
- package/src/utils/index.ts +8 -0
- package/dist/components/atoms/Avatar.d.ts +0 -9
- package/dist/components/atoms/Avatar.d.ts.map +0 -1
- package/dist/components/atoms/Badge.d.ts +0 -10
- package/dist/components/atoms/Badge.d.ts.map +0 -1
- package/dist/components/atoms/Button.d.ts +0 -11
- package/dist/components/atoms/Button.d.ts.map +0 -1
- package/dist/components/atoms/Card.d.ts +0 -11
- package/dist/components/atoms/Card.d.ts.map +0 -1
- package/dist/components/atoms/Input.d.ts +0 -7
- package/dist/components/atoms/Input.d.ts.map +0 -1
- package/dist/components/atoms/ProgressBar.d.ts +0 -11
- package/dist/components/atoms/ProgressBar.d.ts.map +0 -1
- package/dist/components/atoms/Tabs.d.ts +0 -16
- package/dist/components/atoms/Tabs.d.ts.map +0 -1
- package/dist/components/atoms/index.cjs +0 -318
- package/dist/components/atoms/index.d.ts.map +0 -1
- package/dist/components/atoms/index.js +0 -288
- package/dist/components/index.cjs +0 -1275
- package/dist/components/index.d.ts.map +0 -1
- package/dist/components/index.js +0 -1245
- package/dist/components/molecules/CourseCard.d.ts +0 -25
- package/dist/components/molecules/CourseCard.d.ts.map +0 -1
- package/dist/components/molecules/EmptyState.d.ts +0 -10
- package/dist/components/molecules/EmptyState.d.ts.map +0 -1
- package/dist/components/molecules/LoadingSpinner.d.ts +0 -7
- package/dist/components/molecules/LoadingSpinner.d.ts.map +0 -1
- package/dist/components/molecules/PageHeader.d.ts +0 -8
- package/dist/components/molecules/PageHeader.d.ts.map +0 -1
- package/dist/components/molecules/Pagination.d.ts +0 -13
- package/dist/components/molecules/Pagination.d.ts.map +0 -1
- package/dist/components/molecules/SearchInput.d.ts +0 -8
- package/dist/components/molecules/SearchInput.d.ts.map +0 -1
- package/dist/components/molecules/index.cjs +0 -334
- package/dist/components/molecules/index.d.ts.map +0 -1
- package/dist/components/molecules/index.js +0 -311
- package/dist/components/organisms/CourseSidebar.d.ts +0 -37
- package/dist/components/organisms/CourseSidebar.d.ts.map +0 -1
- package/dist/components/organisms/LearnerNavbar.d.ts +0 -8
- package/dist/components/organisms/LearnerNavbar.d.ts.map +0 -1
- package/dist/components/organisms/LearnerSidebar.d.ts +0 -16
- package/dist/components/organisms/LearnerSidebar.d.ts.map +0 -1
- package/dist/components/organisms/LessonBookmarks.d.ts +0 -8
- package/dist/components/organisms/LessonBookmarks.d.ts.map +0 -1
- package/dist/components/organisms/LessonNotes.d.ts +0 -8
- package/dist/components/organisms/LessonNotes.d.ts.map +0 -1
- package/dist/components/organisms/index.cjs +0 -855
- package/dist/components/organisms/index.d.ts.map +0 -1
- package/dist/components/organisms/index.js +0 -825
- package/dist/components/pages/BundleDetailPage.d.ts +0 -3
- package/dist/components/pages/BundleDetailPage.d.ts.map +0 -1
- package/dist/components/pages/CatalogBundlesPage.d.ts +0 -3
- package/dist/components/pages/CatalogBundlesPage.d.ts.map +0 -1
- package/dist/components/pages/CatalogCoursesPage.d.ts +0 -3
- package/dist/components/pages/CatalogCoursesPage.d.ts.map +0 -1
- package/dist/components/pages/CourseDetailPage.d.ts +0 -3
- package/dist/components/pages/CourseDetailPage.d.ts.map +0 -1
- package/dist/components/pages/CoursePlayerPage.d.ts +0 -8
- package/dist/components/pages/CoursePlayerPage.d.ts.map +0 -1
- package/dist/components/pages/CreatorProfilePage.d.ts +0 -3
- package/dist/components/pages/CreatorProfilePage.d.ts.map +0 -1
- package/dist/components/pages/LearnerSettingsPage.d.ts +0 -3
- package/dist/components/pages/LearnerSettingsPage.d.ts.map +0 -1
- package/dist/components/pages/ManualReviewDetailPage.d.ts +0 -3
- package/dist/components/pages/ManualReviewDetailPage.d.ts.map +0 -1
- package/dist/components/pages/ManualReviewPage.d.ts +0 -3
- package/dist/components/pages/ManualReviewPage.d.ts.map +0 -1
- package/dist/components/pages/MessagesPage.d.ts +0 -3
- package/dist/components/pages/MessagesPage.d.ts.map +0 -1
- package/dist/components/pages/MyLearningPage.d.ts +0 -3
- package/dist/components/pages/MyLearningPage.d.ts.map +0 -1
- package/dist/components/pages/PaymentCancelPage.d.ts +0 -3
- package/dist/components/pages/PaymentCancelPage.d.ts.map +0 -1
- package/dist/components/pages/PaymentSuccessPage.d.ts +0 -3
- package/dist/components/pages/PaymentSuccessPage.d.ts.map +0 -1
- package/dist/components/pages/index.cjs +0 -3306
- package/dist/components/pages/index.d.ts.map +0 -1
- package/dist/components/pages/index.js +0 -3315
- package/dist/components/utils.d.ts +0 -3
- package/dist/components/utils.d.ts.map +0 -1
- package/dist/contracts/components.contract.d.ts +0 -87
- package/dist/contracts/components.contract.d.ts.map +0 -1
- package/dist/contracts/index.cjs +0 -52
- package/dist/contracts/index.d.ts.map +0 -1
- package/dist/contracts/index.js +0 -29
- package/dist/contracts/layout.contract.d.ts +0 -35
- package/dist/contracts/layout.contract.d.ts.map +0 -1
- package/dist/contracts/pages.contract.d.ts +0 -192
- package/dist/contracts/pages.contract.d.ts.map +0 -1
- package/dist/contracts/template.contract.d.ts +0 -49
- package/dist/contracts/template.contract.d.ts.map +0 -1
- package/dist/hooks/index.cjs +0 -165
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js +0 -142
- package/dist/hooks/sdk-context.d.ts +0 -125
- package/dist/hooks/sdk-context.d.ts.map +0 -1
- package/dist/hooks/useAiCoach.d.ts +0 -32
- package/dist/hooks/useAiCoach.d.ts.map +0 -1
- package/dist/hooks/useBookmarks.d.ts +0 -31
- package/dist/hooks/useBookmarks.d.ts.map +0 -1
- package/dist/hooks/useCourseSearch.d.ts.map +0 -1
- package/dist/hooks/useDebounce.d.ts.map +0 -1
- package/dist/hooks/useMyBundles.d.ts.map +0 -1
- package/dist/hooks/useMyCourses.d.ts.map +0 -1
- package/dist/hooks/useNotes.d.ts +0 -31
- package/dist/hooks/useNotes.d.ts.map +0 -1
- package/dist/hooks/useNotifications.d.ts +0 -19
- package/dist/hooks/useNotifications.d.ts.map +0 -1
- package/dist/hooks/useTheme.d.ts.map +0 -1
- package/dist/hooks/useToast.d.ts +0 -17
- package/dist/hooks/useToast.d.ts.map +0 -1
- package/dist/hooks/useUser.d.ts.map +0 -1
- package/dist/index.cjs +0 -630
- package/dist/index.d.ts +0 -17
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -600
- package/dist/layouts/DefaultLayout.d.ts +0 -9
- package/dist/layouts/DefaultLayout.d.ts.map +0 -1
- package/dist/types/ai-coach.d.ts +0 -22
- package/dist/types/ai-coach.d.ts.map +0 -1
- package/dist/types/bookmarks.d.ts +0 -19
- package/dist/types/bookmarks.d.ts.map +0 -1
- package/dist/types/bundle.d.ts +0 -114
- package/dist/types/bundle.d.ts.map +0 -1
- package/dist/types/common.d.ts +0 -23
- package/dist/types/common.d.ts.map +0 -1
- package/dist/types/course.d.ts +0 -127
- package/dist/types/course.d.ts.map +0 -1
- package/dist/types/enrollment.d.ts +0 -34
- package/dist/types/enrollment.d.ts.map +0 -1
- package/dist/types/index.cjs +0 -18
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -0
- package/dist/types/lesson.d.ts +0 -105
- package/dist/types/lesson.d.ts.map +0 -1
- package/dist/types/manual-review.d.ts +0 -123
- package/dist/types/manual-review.d.ts.map +0 -1
- package/dist/types/messaging.d.ts +0 -101
- package/dist/types/messaging.d.ts.map +0 -1
- package/dist/types/notification.d.ts +0 -28
- package/dist/types/notification.d.ts.map +0 -1
- package/dist/types/payment.d.ts +0 -38
- package/dist/types/payment.d.ts.map +0 -1
- package/dist/types/progress.d.ts +0 -18
- package/dist/types/progress.d.ts.map +0 -1
- package/dist/types/rating.d.ts +0 -20
- package/dist/types/rating.d.ts.map +0 -1
- package/dist/types/search.d.ts +0 -28
- package/dist/types/search.d.ts.map +0 -1
- package/dist/types/user.d.ts +0 -15
- package/dist/types/user.d.ts.map +0 -1
- package/dist/utils/formatters.d.ts +0 -25
- package/dist/utils/formatters.d.ts.map +0 -1
- package/dist/utils/index.cjs +0 -80
- package/dist/utils/index.d.ts +0 -2
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -57
|
@@ -1,825 +0,0 @@
|
|
|
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/organisms/LearnerNavbar.tsx
|
|
34
|
-
import { useEffect, useRef, useState } from "react";
|
|
35
|
-
import { User, Menu, ChevronDown, LogOut } from "lucide-react";
|
|
36
|
-
|
|
37
|
-
// src/components/utils.ts
|
|
38
|
-
import { clsx } from "clsx";
|
|
39
|
-
import { twMerge } from "tailwind-merge";
|
|
40
|
-
function cn(...inputs) {
|
|
41
|
-
return twMerge(clsx(inputs));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// src/hooks/sdk-context.tsx
|
|
45
|
-
import { createContext, useContext } from "react";
|
|
46
|
-
import { jsx } from "react/jsx-runtime";
|
|
47
|
-
var SDKContext = createContext(null);
|
|
48
|
-
function useSDK() {
|
|
49
|
-
const ctx = useContext(SDKContext);
|
|
50
|
-
if (!ctx) {
|
|
51
|
-
throw new Error(
|
|
52
|
-
"useSDK must be used within an SDKProvider. Make sure your learner routes are wrapped with <SDKProvider>."
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
return ctx;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// src/components/organisms/LearnerNavbar.tsx
|
|
59
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
60
|
-
function LearnerNavbar({ hideMenuButton = false, onMenuClick, onProfileClick, onLogoClick }) {
|
|
61
|
-
var _a;
|
|
62
|
-
const sdk = useSDK();
|
|
63
|
-
const { user } = sdk.useUser();
|
|
64
|
-
const { logout } = sdk.useLogout();
|
|
65
|
-
const [profileDropdownOpen, setProfileDropdownOpen] = useState(false);
|
|
66
|
-
const closeTimeoutRef = useRef(null);
|
|
67
|
-
useEffect(() => {
|
|
68
|
-
return () => {
|
|
69
|
-
if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current);
|
|
70
|
-
};
|
|
71
|
-
}, []);
|
|
72
|
-
const openDropdown = () => {
|
|
73
|
-
if (closeTimeoutRef.current) {
|
|
74
|
-
clearTimeout(closeTimeoutRef.current);
|
|
75
|
-
closeTimeoutRef.current = null;
|
|
76
|
-
}
|
|
77
|
-
setProfileDropdownOpen(true);
|
|
78
|
-
};
|
|
79
|
-
const closeDropdownWithDelay = () => {
|
|
80
|
-
if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current);
|
|
81
|
-
closeTimeoutRef.current = setTimeout(() => {
|
|
82
|
-
setProfileDropdownOpen(false);
|
|
83
|
-
closeTimeoutRef.current = null;
|
|
84
|
-
}, 150);
|
|
85
|
-
};
|
|
86
|
-
return /* @__PURE__ */ jsx2("header", { style: { top: "var(--preview-toolbar-h, 0px)" }, className: "fixed left-0 right-0 z-30 h-20 border-b border-theme-border-primary bg-theme-bg-secondary", children: /* @__PURE__ */ jsxs("div", { className: "flex h-full items-center justify-between px-4 sm:px-6 lg:px-10 xl:px-12 2xl:px-16", children: [
|
|
87
|
-
/* @__PURE__ */ jsx2("div", { className: "flex items-center gap-4", children: !hideMenuButton && /* @__PURE__ */ jsx2(
|
|
88
|
-
"button",
|
|
89
|
-
{
|
|
90
|
-
onClick: onMenuClick,
|
|
91
|
-
className: "rounded-lg p-2 hover:bg-theme-bg-tertiary lg:hidden",
|
|
92
|
-
children: /* @__PURE__ */ jsx2(Menu, { className: "h-5 w-5 text-theme-text-primary" })
|
|
93
|
-
}
|
|
94
|
-
) }),
|
|
95
|
-
/* @__PURE__ */ jsx2("div", { className: "ml-auto flex items-center", children: /* @__PURE__ */ jsxs(
|
|
96
|
-
"div",
|
|
97
|
-
{
|
|
98
|
-
className: "relative group ml-2 sm:ml-4 border-l border-theme-border-primary pl-3 sm:pl-5",
|
|
99
|
-
onMouseEnter: openDropdown,
|
|
100
|
-
onMouseLeave: closeDropdownWithDelay,
|
|
101
|
-
children: [
|
|
102
|
-
/* @__PURE__ */ jsxs(
|
|
103
|
-
"button",
|
|
104
|
-
{
|
|
105
|
-
onClick: () => setProfileDropdownOpen((o) => !o),
|
|
106
|
-
className: "flex items-center gap-2 sm:gap-3 hover:opacity-80 cursor-pointer transition-opacity",
|
|
107
|
-
children: [
|
|
108
|
-
/* @__PURE__ */ jsx2("div", { className: "relative flex h-8 w-8 sm:h-10 sm:w-10 items-center justify-center rounded-full bg-theme-accent-primary text-sm font-semibold text-white overflow-hidden", children: (user == null ? void 0 : user.profileImage) ? /* @__PURE__ */ jsx2("img", { src: user.profileImage, alt: "Profile", className: "w-full h-full object-cover" }) : ((_a = user == null ? void 0 : user.name) == null ? void 0 : _a.charAt(0)) || "S" }),
|
|
109
|
-
user && /* @__PURE__ */ jsxs("div", { className: "hidden md:flex items-center gap-3", children: [
|
|
110
|
-
/* @__PURE__ */ jsx2("div", { className: "text-sm font-medium text-theme-text-primary", children: user.name }),
|
|
111
|
-
/* @__PURE__ */ jsx2(
|
|
112
|
-
ChevronDown,
|
|
113
|
-
{
|
|
114
|
-
className: cn(
|
|
115
|
-
"h-4 w-4 text-theme-text-secondary transition-transform group-hover:rotate-180",
|
|
116
|
-
profileDropdownOpen && "rotate-180"
|
|
117
|
-
)
|
|
118
|
-
}
|
|
119
|
-
)
|
|
120
|
-
] })
|
|
121
|
-
]
|
|
122
|
-
}
|
|
123
|
-
),
|
|
124
|
-
profileDropdownOpen && /* @__PURE__ */ jsxs(
|
|
125
|
-
"div",
|
|
126
|
-
{
|
|
127
|
-
className: "absolute right-0 top-full z-50 mt-2 w-56 rounded-lg border border-theme-border-primary bg-theme-bg-secondary shadow-lg",
|
|
128
|
-
onMouseEnter: openDropdown,
|
|
129
|
-
onMouseLeave: closeDropdownWithDelay,
|
|
130
|
-
children: [
|
|
131
|
-
/* @__PURE__ */ jsxs("div", { className: "border-b border-theme-border-primary p-3", children: [
|
|
132
|
-
/* @__PURE__ */ jsx2("p", { className: "text-sm font-medium text-theme-text-primary", children: user == null ? void 0 : user.name }),
|
|
133
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs text-theme-text-muted", children: user == null ? void 0 : user.email })
|
|
134
|
-
] }),
|
|
135
|
-
/* @__PURE__ */ jsx2("div", { className: "p-2", children: /* @__PURE__ */ jsxs(
|
|
136
|
-
"button",
|
|
137
|
-
{
|
|
138
|
-
onClick: () => {
|
|
139
|
-
onProfileClick == null ? void 0 : onProfileClick();
|
|
140
|
-
setProfileDropdownOpen(false);
|
|
141
|
-
},
|
|
142
|
-
className: "flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-theme-text-secondary transition-colors hover:bg-[rgb(var(--accent-primary))]/15 hover:text-[rgb(var(--accent-primary))] cursor-pointer",
|
|
143
|
-
children: [
|
|
144
|
-
/* @__PURE__ */ jsx2(User, { className: "h-4 w-4" }),
|
|
145
|
-
"My Profile"
|
|
146
|
-
]
|
|
147
|
-
}
|
|
148
|
-
) }),
|
|
149
|
-
/* @__PURE__ */ jsx2("div", { className: "border-t border-theme-border-primary p-2", children: /* @__PURE__ */ jsxs(
|
|
150
|
-
"button",
|
|
151
|
-
{
|
|
152
|
-
onClick: () => {
|
|
153
|
-
logout();
|
|
154
|
-
setProfileDropdownOpen(false);
|
|
155
|
-
},
|
|
156
|
-
className: "flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-theme-text-secondary transition-colors hover:bg-[rgb(var(--accent-primary))]/15 hover:text-[rgb(var(--accent-primary))] cursor-pointer",
|
|
157
|
-
children: [
|
|
158
|
-
/* @__PURE__ */ jsx2(LogOut, { className: "h-4 w-4" }),
|
|
159
|
-
"Logout"
|
|
160
|
-
]
|
|
161
|
-
}
|
|
162
|
-
) })
|
|
163
|
-
]
|
|
164
|
-
}
|
|
165
|
-
)
|
|
166
|
-
]
|
|
167
|
-
}
|
|
168
|
-
) })
|
|
169
|
-
] }) });
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// src/components/organisms/LearnerSidebar.tsx
|
|
173
|
-
import { BookOpen as BookOpen2, GraduationCap, MessageSquare, ClipboardCheck, UserCircle, Settings, LogOut as LogOut2, ChevronLeft, ChevronRight } from "lucide-react";
|
|
174
|
-
|
|
175
|
-
// src/components/atoms/Button.tsx
|
|
176
|
-
import * as React from "react";
|
|
177
|
-
import { cva } from "class-variance-authority";
|
|
178
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
179
|
-
var buttonVariants = cva(
|
|
180
|
-
"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",
|
|
181
|
-
{
|
|
182
|
-
variants: {
|
|
183
|
-
variant: {
|
|
184
|
-
default: "bg-theme-accent-primary text-white hover:opacity-90",
|
|
185
|
-
destructive: "bg-red-600 text-white hover:bg-red-700",
|
|
186
|
-
outline: "border border-theme-border-primary bg-theme-bg-secondary hover:bg-theme-bg-tertiary text-theme-text-primary",
|
|
187
|
-
secondary: "bg-theme-bg-tertiary text-theme-text-primary hover:opacity-80",
|
|
188
|
-
ghost: "hover:bg-theme-bg-tertiary text-theme-text-primary",
|
|
189
|
-
link: "text-[rgb(var(--accent-primary))] underline-offset-4 hover:underline"
|
|
190
|
-
},
|
|
191
|
-
size: {
|
|
192
|
-
default: "h-10 px-4 py-2",
|
|
193
|
-
sm: "h-9 rounded-md px-3",
|
|
194
|
-
lg: "h-11 rounded-md px-8",
|
|
195
|
-
icon: "h-10 w-10"
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
defaultVariants: {
|
|
199
|
-
variant: "default",
|
|
200
|
-
size: "default"
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
);
|
|
204
|
-
var Button = React.forwardRef(
|
|
205
|
-
(_a, ref) => {
|
|
206
|
-
var _b = _a, { className, variant, size } = _b, props = __objRest(_b, ["className", "variant", "size"]);
|
|
207
|
-
return /* @__PURE__ */ jsx3(
|
|
208
|
-
"button",
|
|
209
|
-
__spreadValues({
|
|
210
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
211
|
-
ref
|
|
212
|
-
}, props)
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
);
|
|
216
|
-
Button.displayName = "Button";
|
|
217
|
-
|
|
218
|
-
// src/components/organisms/LearnerSidebar.tsx
|
|
219
|
-
import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
220
|
-
var defaultItems = [
|
|
221
|
-
{ label: "My Learning", href: "/my-learning", icon: BookOpen2 },
|
|
222
|
-
{ label: "Catalog", href: "/catalog/courses", icon: GraduationCap },
|
|
223
|
-
{ label: "Messages", href: "/messages", icon: MessageSquare },
|
|
224
|
-
{ label: "Manual Review", href: "/manual-review", icon: ClipboardCheck },
|
|
225
|
-
{ label: "Account", href: "/account", icon: UserCircle }
|
|
226
|
-
];
|
|
227
|
-
function LearnerSidebar({
|
|
228
|
-
isOpen,
|
|
229
|
-
isCollapsed,
|
|
230
|
-
onClose,
|
|
231
|
-
onToggle,
|
|
232
|
-
currentPath,
|
|
233
|
-
onNavigate,
|
|
234
|
-
items = defaultItems
|
|
235
|
-
}) {
|
|
236
|
-
const sdk = useSDK();
|
|
237
|
-
const { user } = sdk.useUser();
|
|
238
|
-
const { logout } = sdk.useLogout();
|
|
239
|
-
const isActive = (href, label) => {
|
|
240
|
-
if (label === "Catalog" && currentPath.startsWith("/catalog")) return true;
|
|
241
|
-
return currentPath === href || currentPath.startsWith(href + "/");
|
|
242
|
-
};
|
|
243
|
-
const handleNav = (href) => {
|
|
244
|
-
onNavigate(href);
|
|
245
|
-
onClose();
|
|
246
|
-
};
|
|
247
|
-
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
248
|
-
/* @__PURE__ */ jsxs2(
|
|
249
|
-
"aside",
|
|
250
|
-
{
|
|
251
|
-
style: { top: "var(--preview-toolbar-h, 0px)", height: "calc(100vh - var(--preview-toolbar-h, 0px))" },
|
|
252
|
-
className: cn(
|
|
253
|
-
"fixed left-0 z-40 border-r border-theme-border-primary bg-theme-bg-secondary transition-all duration-300 flex flex-col",
|
|
254
|
-
isOpen ? "translate-x-0" : "-translate-x-full lg:translate-x-0",
|
|
255
|
-
isCollapsed ? "w-16" : "w-64"
|
|
256
|
-
),
|
|
257
|
-
children: [
|
|
258
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex h-20 items-center justify-between border-b border-theme-border-primary px-4 bg-theme-bg-secondary/50 backdrop-blur-sm", children: [
|
|
259
|
-
!isCollapsed && /* @__PURE__ */ jsxs2(
|
|
260
|
-
"button",
|
|
261
|
-
{
|
|
262
|
-
onClick: () => handleNav("/my-learning"),
|
|
263
|
-
className: "flex items-center gap-2 sm:gap-3 hover:opacity-80 transition-opacity cursor-pointer",
|
|
264
|
-
children: [
|
|
265
|
-
/* @__PURE__ */ jsx4("div", { className: "flex h-8 w-8 items-center justify-center rounded bg-theme-accent-primary", children: /* @__PURE__ */ jsx4(BookOpen2, { className: "h-5 w-5 text-white" }) }),
|
|
266
|
-
/* @__PURE__ */ jsx4("span", { className: "text-xl font-bold text-theme-text-primary leading-none whitespace-nowrap", children: "Academy" })
|
|
267
|
-
]
|
|
268
|
-
}
|
|
269
|
-
),
|
|
270
|
-
/* @__PURE__ */ jsx4(
|
|
271
|
-
Button,
|
|
272
|
-
{
|
|
273
|
-
variant: "ghost",
|
|
274
|
-
size: "icon",
|
|
275
|
-
onClick: onToggle,
|
|
276
|
-
className: cn("hover:bg-theme-bg-tertiary rounded-lg transition-colors", isCollapsed && "mx-auto"),
|
|
277
|
-
children: isCollapsed ? /* @__PURE__ */ jsx4(ChevronRight, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx4(ChevronLeft, { className: "h-5 w-5" })
|
|
278
|
-
}
|
|
279
|
-
)
|
|
280
|
-
] }),
|
|
281
|
-
/* @__PURE__ */ jsx4("nav", { className: "flex-1 overflow-y-auto p-4 space-y-1", children: items.map((item) => {
|
|
282
|
-
const Icon = item.icon;
|
|
283
|
-
const active = isActive(item.href, item.label);
|
|
284
|
-
return /* @__PURE__ */ jsxs2(
|
|
285
|
-
"button",
|
|
286
|
-
{
|
|
287
|
-
onClick: () => handleNav(item.href),
|
|
288
|
-
className: cn(
|
|
289
|
-
"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors cursor-pointer",
|
|
290
|
-
active ? "bg-theme-accent-primary text-white hover:opacity-90" : "text-theme-text-secondary hover:bg-theme-bg-tertiary hover:text-theme-text-primary",
|
|
291
|
-
isCollapsed && "justify-center"
|
|
292
|
-
),
|
|
293
|
-
title: isCollapsed ? item.label : void 0,
|
|
294
|
-
children: [
|
|
295
|
-
/* @__PURE__ */ jsx4(Icon, { className: "h-5 w-5 shrink-0" }),
|
|
296
|
-
!isCollapsed && /* @__PURE__ */ jsx4("span", { className: "whitespace-nowrap", children: item.label })
|
|
297
|
-
]
|
|
298
|
-
},
|
|
299
|
-
item.href
|
|
300
|
-
);
|
|
301
|
-
}) }),
|
|
302
|
-
user && /* @__PURE__ */ jsx4("div", { className: "border-t border-theme-border-primary p-4", children: /* @__PURE__ */ jsxs2("div", { className: "space-y-1", children: [
|
|
303
|
-
/* @__PURE__ */ jsxs2(
|
|
304
|
-
"button",
|
|
305
|
-
{
|
|
306
|
-
onClick: () => handleNav("/learner-settings"),
|
|
307
|
-
className: cn(
|
|
308
|
-
"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors cursor-pointer",
|
|
309
|
-
currentPath === "/learner-settings" ? "bg-theme-accent-primary text-white" : "text-theme-text-secondary hover:bg-theme-bg-tertiary hover:text-theme-text-primary",
|
|
310
|
-
isCollapsed && "justify-center"
|
|
311
|
-
),
|
|
312
|
-
title: isCollapsed ? "Settings" : void 0,
|
|
313
|
-
children: [
|
|
314
|
-
/* @__PURE__ */ jsx4(Settings, { className: "h-5 w-5 shrink-0" }),
|
|
315
|
-
!isCollapsed && /* @__PURE__ */ jsx4("span", { className: "whitespace-nowrap", children: "Settings" })
|
|
316
|
-
]
|
|
317
|
-
}
|
|
318
|
-
),
|
|
319
|
-
/* @__PURE__ */ jsxs2(
|
|
320
|
-
"button",
|
|
321
|
-
{
|
|
322
|
-
onClick: logout,
|
|
323
|
-
className: cn(
|
|
324
|
-
"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors hover:bg-red-50 hover:text-red-600 text-theme-text-secondary cursor-pointer",
|
|
325
|
-
isCollapsed && "justify-center"
|
|
326
|
-
),
|
|
327
|
-
children: [
|
|
328
|
-
/* @__PURE__ */ jsx4(LogOut2, { className: "h-5 w-5 shrink-0" }),
|
|
329
|
-
!isCollapsed && /* @__PURE__ */ jsx4("span", { className: "whitespace-nowrap", children: "Logout" })
|
|
330
|
-
]
|
|
331
|
-
}
|
|
332
|
-
)
|
|
333
|
-
] }) })
|
|
334
|
-
]
|
|
335
|
-
}
|
|
336
|
-
),
|
|
337
|
-
isOpen && /* @__PURE__ */ jsx4("div", { className: "fixed inset-0 z-30 bg-black/50 lg:hidden", onClick: onClose })
|
|
338
|
-
] });
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// src/components/organisms/CourseSidebar.tsx
|
|
342
|
-
import { useState as useState2, useMemo } from "react";
|
|
343
|
-
import { ArrowLeft, Search, X, Lock, ClipboardList, Award, Check, ChevronRight as ChevronRight2 } from "lucide-react";
|
|
344
|
-
|
|
345
|
-
// src/components/atoms/ProgressBar.tsx
|
|
346
|
-
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
347
|
-
var sizeClasses = {
|
|
348
|
-
sm: "h-1.5",
|
|
349
|
-
md: "h-2.5",
|
|
350
|
-
lg: "h-3.5"
|
|
351
|
-
};
|
|
352
|
-
var variantClasses = {
|
|
353
|
-
default: "bg-theme-accent-primary",
|
|
354
|
-
success: "bg-green-600",
|
|
355
|
-
warning: "bg-yellow-500",
|
|
356
|
-
error: "bg-red-600"
|
|
357
|
-
};
|
|
358
|
-
function ProgressBar(_a) {
|
|
359
|
-
var _b = _a, {
|
|
360
|
-
value,
|
|
361
|
-
max = 100,
|
|
362
|
-
showLabel = false,
|
|
363
|
-
size = "md",
|
|
364
|
-
variant = "default",
|
|
365
|
-
className
|
|
366
|
-
} = _b, props = __objRest(_b, [
|
|
367
|
-
"value",
|
|
368
|
-
"max",
|
|
369
|
-
"showLabel",
|
|
370
|
-
"size",
|
|
371
|
-
"variant",
|
|
372
|
-
"className"
|
|
373
|
-
]);
|
|
374
|
-
const percentage = Math.min(Math.max(value / max * 100, 0), 100);
|
|
375
|
-
return /* @__PURE__ */ jsxs3("div", __spreadProps(__spreadValues({ className: cn("w-full", className) }, props), { children: [
|
|
376
|
-
showLabel && /* @__PURE__ */ jsxs3("div", { className: "mb-1 flex items-center justify-between text-sm", children: [
|
|
377
|
-
/* @__PURE__ */ jsx5("span", { className: "text-theme-text-secondary", children: "Progress" }),
|
|
378
|
-
/* @__PURE__ */ jsxs3("span", { className: "font-medium text-theme-text-primary", children: [
|
|
379
|
-
Math.round(percentage),
|
|
380
|
-
"%"
|
|
381
|
-
] })
|
|
382
|
-
] }),
|
|
383
|
-
/* @__PURE__ */ jsx5("div", { className: cn("w-full overflow-hidden rounded-full bg-theme-bg-tertiary", sizeClasses[size]), children: /* @__PURE__ */ jsx5(
|
|
384
|
-
"div",
|
|
385
|
-
{
|
|
386
|
-
className: cn("h-full transition-all duration-300 ease-in-out", variantClasses[variant]),
|
|
387
|
-
style: { width: `${percentage}%` }
|
|
388
|
-
}
|
|
389
|
-
) })
|
|
390
|
-
] }));
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// src/components/organisms/CourseSidebar.tsx
|
|
394
|
-
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
395
|
-
var lessonColors = [
|
|
396
|
-
"bg-[#E2F0FF] border-l-4 border-[#3aa3a5]",
|
|
397
|
-
"bg-[#fcddb5] border-l-4 border-[#d67a05]",
|
|
398
|
-
"bg-[#FAD1CE] border-l-4 border-[#7ab3f0]"
|
|
399
|
-
];
|
|
400
|
-
function CourseSidebar({
|
|
401
|
-
courseTitle,
|
|
402
|
-
modules,
|
|
403
|
-
currentLessonId,
|
|
404
|
-
expandedModules,
|
|
405
|
-
completedCount,
|
|
406
|
-
totalCount,
|
|
407
|
-
onToggleModule,
|
|
408
|
-
onSelectLesson,
|
|
409
|
-
hideProgress = false,
|
|
410
|
-
hideSearch = false,
|
|
411
|
-
certificateEnabled = false,
|
|
412
|
-
isCompleted = false,
|
|
413
|
-
onDownloadCertificate,
|
|
414
|
-
isDownloadingCertificate = false,
|
|
415
|
-
onBack,
|
|
416
|
-
showBackButton = true,
|
|
417
|
-
className
|
|
418
|
-
}) {
|
|
419
|
-
const [searchQuery, setSearchQuery] = useState2("");
|
|
420
|
-
const filteredModules = useMemo(() => {
|
|
421
|
-
if (!searchQuery.trim()) return modules;
|
|
422
|
-
const query = searchQuery.toLowerCase();
|
|
423
|
-
return modules.map((mod) => __spreadProps(__spreadValues({}, mod), {
|
|
424
|
-
lessons: mod.lessons.filter((l) => l.title.toLowerCase().includes(query))
|
|
425
|
-
})).filter((mod) => mod.lessons.length > 0);
|
|
426
|
-
}, [modules, searchQuery]);
|
|
427
|
-
const totalResults = filteredModules.reduce((sum, m) => sum + m.lessons.length, 0);
|
|
428
|
-
const progressPct = totalCount > 0 ? completedCount / totalCount * 100 : 0;
|
|
429
|
-
const formatDuration = (duration) => {
|
|
430
|
-
if (!duration) return "";
|
|
431
|
-
const text = duration.trim();
|
|
432
|
-
if (!text) return "";
|
|
433
|
-
if (/[a-zA-Z]/.test(text)) return text;
|
|
434
|
-
const parts = text.split(":").map(Number);
|
|
435
|
-
if (parts.some(isNaN)) return text;
|
|
436
|
-
if (parts.length === 3) {
|
|
437
|
-
const [hrs, mins] = parts;
|
|
438
|
-
if (hrs > 0 && mins > 0) return `${hrs} ${hrs === 1 ? "hour" : "hours"} ${mins} min`;
|
|
439
|
-
if (hrs > 0) return `${hrs} ${hrs === 1 ? "hour" : "hours"}`;
|
|
440
|
-
return `${mins} min`;
|
|
441
|
-
}
|
|
442
|
-
if (parts.length === 2) {
|
|
443
|
-
const [mins, secs] = parts;
|
|
444
|
-
return `${mins > 0 ? mins : secs > 0 ? 1 : 0} min`;
|
|
445
|
-
}
|
|
446
|
-
return `${Math.max(1, Math.round(parts[0] / 60))} min`;
|
|
447
|
-
};
|
|
448
|
-
let globalLessonIndex = 0;
|
|
449
|
-
return /* @__PURE__ */ jsxs4("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: [
|
|
450
|
-
/* @__PURE__ */ jsxs4("div", { className: "p-6", children: [
|
|
451
|
-
showBackButton && onBack && /* @__PURE__ */ jsx6(
|
|
452
|
-
"button",
|
|
453
|
-
{
|
|
454
|
-
onClick: onBack,
|
|
455
|
-
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",
|
|
456
|
-
"aria-label": "Go back",
|
|
457
|
-
children: /* @__PURE__ */ jsx6(ArrowLeft, { className: "w-5 h-5" })
|
|
458
|
-
}
|
|
459
|
-
),
|
|
460
|
-
/* @__PURE__ */ jsx6("h3", { className: "text-3xl font-semibold text-[#1f2937] leading-tight", children: courseTitle ? `${courseTitle.charAt(0).toUpperCase()}${courseTitle.slice(1)}` : "" }),
|
|
461
|
-
!hideProgress && /* @__PURE__ */ jsxs4("div", { className: "mt-4", children: [
|
|
462
|
-
/* @__PURE__ */ jsx6(ProgressBar, { value: progressPct, size: "sm" }),
|
|
463
|
-
/* @__PURE__ */ jsxs4("p", { className: "text-xs text-gray-400 mt-1 text-right", children: [
|
|
464
|
-
completedCount,
|
|
465
|
-
" / ",
|
|
466
|
-
totalCount,
|
|
467
|
-
" lessons \xB7 ",
|
|
468
|
-
Math.round(progressPct),
|
|
469
|
-
"%"
|
|
470
|
-
] })
|
|
471
|
-
] }),
|
|
472
|
-
certificateEnabled && isCompleted && onDownloadCertificate && completedCount === totalCount && totalCount > 0 && /* @__PURE__ */ jsxs4(
|
|
473
|
-
Button,
|
|
474
|
-
{
|
|
475
|
-
onClick: onDownloadCertificate,
|
|
476
|
-
disabled: isDownloadingCertificate,
|
|
477
|
-
className: "w-full mt-3 bg-green-600 hover:bg-green-700 disabled:opacity-50 text-white",
|
|
478
|
-
children: [
|
|
479
|
-
/* @__PURE__ */ jsx6(Award, { className: "w-4 h-4 mr-2" }),
|
|
480
|
-
isDownloadingCertificate ? "Downloading..." : "Download Certificate"
|
|
481
|
-
]
|
|
482
|
-
}
|
|
483
|
-
),
|
|
484
|
-
!hideSearch && /* @__PURE__ */ jsxs4("div", { className: "mt-3 relative", children: [
|
|
485
|
-
/* @__PURE__ */ jsx6(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" }),
|
|
486
|
-
/* @__PURE__ */ jsx6(
|
|
487
|
-
"input",
|
|
488
|
-
{
|
|
489
|
-
type: "text",
|
|
490
|
-
placeholder: "Search lessons...",
|
|
491
|
-
value: searchQuery,
|
|
492
|
-
onChange: (e) => setSearchQuery(e.target.value),
|
|
493
|
-
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"
|
|
494
|
-
}
|
|
495
|
-
),
|
|
496
|
-
searchQuery && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
497
|
-
/* @__PURE__ */ jsx6(
|
|
498
|
-
"button",
|
|
499
|
-
{
|
|
500
|
-
onClick: () => setSearchQuery(""),
|
|
501
|
-
className: "absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 cursor-pointer",
|
|
502
|
-
"aria-label": "Clear search",
|
|
503
|
-
children: /* @__PURE__ */ jsx6(X, { className: "w-4 h-4" })
|
|
504
|
-
}
|
|
505
|
-
),
|
|
506
|
-
/* @__PURE__ */ jsxs4("p", { className: "text-xs text-gray-400 mt-1", children: [
|
|
507
|
-
totalResults,
|
|
508
|
-
" ",
|
|
509
|
-
totalResults === 1 ? "lesson" : "lessons",
|
|
510
|
-
" found"
|
|
511
|
-
] })
|
|
512
|
-
] })
|
|
513
|
-
] })
|
|
514
|
-
] }),
|
|
515
|
-
/* @__PURE__ */ jsx6("div", { className: "flex-1 px-4 space-y-8 pb-10", children: filteredModules.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "text-center py-8", children: [
|
|
516
|
-
/* @__PURE__ */ jsx6(Search, { className: "w-10 h-10 text-gray-300 mx-auto mb-2" }),
|
|
517
|
-
/* @__PURE__ */ jsxs4("p", { className: "text-sm text-gray-400", children: [
|
|
518
|
-
"No lessons found for \u201C",
|
|
519
|
-
searchQuery,
|
|
520
|
-
"\u201D"
|
|
521
|
-
] }),
|
|
522
|
-
/* @__PURE__ */ jsx6("button", { onClick: () => setSearchQuery(""), className: "mt-2 text-sm text-[#49BBBD] hover:underline font-medium cursor-pointer", children: "Clear search" })
|
|
523
|
-
] }) : filteredModules.map((module) => {
|
|
524
|
-
const isExpanded = expandedModules.has(module.id) || !!searchQuery.trim();
|
|
525
|
-
return /* @__PURE__ */ jsxs4("div", { children: [
|
|
526
|
-
/* @__PURE__ */ jsxs4(
|
|
527
|
-
"button",
|
|
528
|
-
{
|
|
529
|
-
type: "button",
|
|
530
|
-
onClick: () => onToggleModule(module.id),
|
|
531
|
-
"aria-expanded": isExpanded,
|
|
532
|
-
className: "w-full flex items-center justify-between text-left mb-3 px-2 cursor-pointer",
|
|
533
|
-
children: [
|
|
534
|
-
/* @__PURE__ */ jsx6("h3", { className: "text-sm font-bold text-gray-500 uppercase tracking-wider", children: module.title }),
|
|
535
|
-
/* @__PURE__ */ jsx6(ChevronRight2, { className: cn("w-4 h-4 transition-transform", isExpanded ? "rotate-90 text-[#49BBBD]" : "text-gray-400") })
|
|
536
|
-
]
|
|
537
|
-
}
|
|
538
|
-
),
|
|
539
|
-
isExpanded && /* @__PURE__ */ jsx6("div", { className: "space-y-3", children: module.lessons.map((lesson) => {
|
|
540
|
-
const isCurrent = currentLessonId === lesson.id;
|
|
541
|
-
const isLocked = lesson.locked === true;
|
|
542
|
-
const colorClass = lessonColors[globalLessonIndex % lessonColors.length];
|
|
543
|
-
globalLessonIndex++;
|
|
544
|
-
let availabilityText = "";
|
|
545
|
-
if (isLocked) {
|
|
546
|
-
if (lesson.availableAt) {
|
|
547
|
-
const diffDays = Math.ceil((new Date(lesson.availableAt).getTime() - Date.now()) / 864e5);
|
|
548
|
-
availabilityText = diffDays > 0 ? `Available in ${diffDays}d` : `Available on ${new Date(lesson.availableAt).toLocaleDateString()}`;
|
|
549
|
-
} else if (lesson.hasPrerequisite) {
|
|
550
|
-
availabilityText = "Complete previous lesson";
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
return /* @__PURE__ */ jsxs4(
|
|
554
|
-
"button",
|
|
555
|
-
{
|
|
556
|
-
title: lesson.title,
|
|
557
|
-
onClick: () => !isLocked && onSelectLesson(lesson.id),
|
|
558
|
-
disabled: isLocked,
|
|
559
|
-
className: cn(
|
|
560
|
-
"w-full text-left p-4 rounded-lg flex items-center justify-between transition-transform",
|
|
561
|
-
isLocked ? "opacity-50 cursor-not-allowed" : "hover:scale-[1.02] active:scale-[0.98] cursor-pointer",
|
|
562
|
-
isCurrent ? "bg-[#49BBBD] text-white shadow-md ring-2 ring-[#2a9ea0]/40" : colorClass
|
|
563
|
-
),
|
|
564
|
-
children: [
|
|
565
|
-
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-3 overflow-hidden", children: [
|
|
566
|
-
lesson.completed ? /* @__PURE__ */ jsx6("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__ */ jsx6(Check, { className: "w-3 h-3 text-white" }) }) : isLocked ? /* @__PURE__ */ jsx6("div", { className: "w-5 h-5 rounded-full border-2 border-gray-400 flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx6(Lock, { className: "w-2.5 h-2.5 text-gray-500" }) }) : /* @__PURE__ */ jsx6("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__ */ jsx6("div", { className: cn("w-2.5 h-2.5 rounded-sm", isCurrent ? "bg-white/80" : "bg-[#1f2a44]") }) }),
|
|
567
|
-
/* @__PURE__ */ jsxs4("div", { className: "overflow-hidden", children: [
|
|
568
|
-
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5", children: [
|
|
569
|
-
lesson.type === "ASSESSMENT" ? /* @__PURE__ */ jsx6(ClipboardList, { className: cn("w-3.5 h-3.5 flex-shrink-0", isCurrent ? "text-white" : "text-gray-600") }) : null,
|
|
570
|
-
/* @__PURE__ */ jsx6("span", { className: cn("text-sm font-medium truncate", isCurrent ? "text-white" : "text-gray-800"), children: lesson.title })
|
|
571
|
-
] }),
|
|
572
|
-
isLocked && availabilityText && /* @__PURE__ */ jsx6("p", { className: "text-xs text-gray-600 mt-0.5 truncate", children: availabilityText })
|
|
573
|
-
] })
|
|
574
|
-
] }),
|
|
575
|
-
lesson.type === "ASSESSMENT" ? /* @__PURE__ */ jsx6("span", { className: cn("text-xs font-semibold flex-shrink-0 ml-2", isCurrent ? "text-white/90" : "text-gray-600"), children: "Quiz" }) : lesson.duration ? /* @__PURE__ */ jsx6("span", { className: cn("text-xs font-semibold flex-shrink-0 ml-2", isCurrent ? "text-white/90" : "text-gray-600"), children: formatDuration(lesson.duration) }) : null
|
|
576
|
-
]
|
|
577
|
-
},
|
|
578
|
-
lesson.id
|
|
579
|
-
);
|
|
580
|
-
}) })
|
|
581
|
-
] }, module.id);
|
|
582
|
-
}) })
|
|
583
|
-
] });
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// src/components/organisms/LessonNotes.tsx
|
|
587
|
-
import { useState as useState3, useEffect as useEffect2 } from "react";
|
|
588
|
-
import { Pencil, Trash2 } from "lucide-react";
|
|
589
|
-
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
590
|
-
function formatTimestamp(seconds) {
|
|
591
|
-
if (seconds === void 0 || seconds === null) return "";
|
|
592
|
-
const total = Math.floor(seconds);
|
|
593
|
-
const hrs = Math.floor(total / 3600);
|
|
594
|
-
const mins = Math.floor(total % 3600 / 60);
|
|
595
|
-
const secs = Math.floor(total % 60);
|
|
596
|
-
if (hrs > 0) return `${String(hrs).padStart(2, "0")}:${String(mins).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
|
|
597
|
-
return `${String(mins).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
|
|
598
|
-
}
|
|
599
|
-
function LessonNotes({ activityId, currentVideoTime, getLiveCurrentTime, onTimestampClick }) {
|
|
600
|
-
const sdk = useSDK();
|
|
601
|
-
const { data: apiNotes, isLoading, refetch } = sdk.useLessonNotes(activityId);
|
|
602
|
-
const { createNote, isLoading: isCreating } = sdk.useCreateNote();
|
|
603
|
-
const { updateNote, isLoading: isUpdating } = sdk.useUpdateNote();
|
|
604
|
-
const { deleteNote, isLoading: isDeleting } = sdk.useDeleteNote();
|
|
605
|
-
const [noteText, setNoteText] = useState3("");
|
|
606
|
-
const [editingNoteId, setEditingNoteId] = useState3(null);
|
|
607
|
-
const [editingText, setEditingText] = useState3("");
|
|
608
|
-
const notes = Array.isArray(apiNotes) ? apiNotes : [];
|
|
609
|
-
useEffect2(() => {
|
|
610
|
-
setNoteText("");
|
|
611
|
-
setEditingNoteId(null);
|
|
612
|
-
setEditingText("");
|
|
613
|
-
}, [activityId]);
|
|
614
|
-
const handleSaveNote = async () => {
|
|
615
|
-
if (!noteText.trim()) return;
|
|
616
|
-
const effectiveTime = getLiveCurrentTime ? getLiveCurrentTime() : currentVideoTime;
|
|
617
|
-
const result = await createNote({
|
|
618
|
-
activityId,
|
|
619
|
-
text: noteText.trim(),
|
|
620
|
-
timestamp: effectiveTime !== void 0 ? Math.floor(effectiveTime) : void 0
|
|
621
|
-
});
|
|
622
|
-
if (result) {
|
|
623
|
-
setNoteText("");
|
|
624
|
-
refetch();
|
|
625
|
-
}
|
|
626
|
-
};
|
|
627
|
-
const handleSaveEdit = async (noteId) => {
|
|
628
|
-
if (!editingText.trim()) return;
|
|
629
|
-
const result = await updateNote(noteId, { text: editingText.trim() });
|
|
630
|
-
if (result) {
|
|
631
|
-
setEditingNoteId(null);
|
|
632
|
-
setEditingText("");
|
|
633
|
-
refetch();
|
|
634
|
-
}
|
|
635
|
-
};
|
|
636
|
-
const handleDeleteNote = async (noteId) => {
|
|
637
|
-
const success = await deleteNote(noteId);
|
|
638
|
-
if (success) refetch();
|
|
639
|
-
};
|
|
640
|
-
const handleTimestampClick = (timestamp) => {
|
|
641
|
-
onTimestampClick == null ? void 0 : onTimestampClick(timestamp);
|
|
642
|
-
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
643
|
-
};
|
|
644
|
-
return /* @__PURE__ */ jsx7("div", { className: "space-y-6", children: isLoading ? /* @__PURE__ */ jsx7("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx7("div", { className: "text-theme-text-secondary", children: "Loading notes..." }) }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
645
|
-
/* @__PURE__ */ jsxs5("div", { className: "space-y-3", children: [
|
|
646
|
-
/* @__PURE__ */ jsx7(
|
|
647
|
-
"textarea",
|
|
648
|
-
{
|
|
649
|
-
placeholder: "Write a note...",
|
|
650
|
-
value: noteText,
|
|
651
|
-
onChange: (e) => setNoteText(e.target.value),
|
|
652
|
-
rows: notes.length === 0 ? 6 : 4,
|
|
653
|
-
className: "w-full resize-none rounded-md border border-theme-border-primary bg-theme-bg-primary px-3 py-2 text-sm text-theme-text-primary placeholder:text-[rgb(var(--text-muted))] focus-visible:outline-none focus-visible:border-theme-accent-primary transition-colors"
|
|
654
|
-
}
|
|
655
|
-
),
|
|
656
|
-
/* @__PURE__ */ jsx7("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx7(
|
|
657
|
-
Button,
|
|
658
|
-
{
|
|
659
|
-
onClick: handleSaveNote,
|
|
660
|
-
disabled: !noteText.trim() || isCreating,
|
|
661
|
-
className: "bg-theme-accent-primary hover:bg-theme-accent-primary/90 text-white",
|
|
662
|
-
children: isCreating ? "Saving..." : "Save note"
|
|
663
|
-
}
|
|
664
|
-
) })
|
|
665
|
-
] }),
|
|
666
|
-
notes.length === 0 ? /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
|
|
667
|
-
/* @__PURE__ */ jsx7("h3", { className: "text-xl font-bold text-theme-text-primary", children: "No notes yet" }),
|
|
668
|
-
/* @__PURE__ */ jsx7("p", { className: "text-base text-theme-text-secondary", children: "Add notes for this lesson to remember key points." })
|
|
669
|
-
] }) : /* @__PURE__ */ jsxs5("div", { className: "space-y-4", children: [
|
|
670
|
-
/* @__PURE__ */ jsx7("h3", { className: "text-lg font-bold text-theme-text-primary", children: "Your notes for this lesson" }),
|
|
671
|
-
/* @__PURE__ */ jsx7("div", { className: "space-y-3", children: notes.map((note) => /* @__PURE__ */ jsxs5("div", { className: "border border-theme-border-primary bg-theme-bg-secondary rounded-lg p-3 md:p-4 space-y-2 relative w-full", children: [
|
|
672
|
-
editingNoteId !== note.id && /* @__PURE__ */ jsxs5("div", { className: "absolute top-3 right-3 flex gap-2", children: [
|
|
673
|
-
/* @__PURE__ */ jsx7(Button, { variant: "ghost", size: "sm", onClick: () => {
|
|
674
|
-
setEditingNoteId(note.id);
|
|
675
|
-
setEditingText(note.text);
|
|
676
|
-
}, disabled: isDeleting, className: "text-theme-accent-primary hover:text-theme-accent-primary/80 p-1 h-auto", children: /* @__PURE__ */ jsx7(Pencil, { className: "w-4 h-4" }) }),
|
|
677
|
-
/* @__PURE__ */ jsx7(Button, { variant: "ghost", size: "sm", onClick: () => handleDeleteNote(note.id), disabled: isDeleting, className: "text-red-600 hover:text-red-800 p-1 h-auto", children: /* @__PURE__ */ jsx7(Trash2, { className: "w-4 h-4" }) })
|
|
678
|
-
] }),
|
|
679
|
-
note.timestamp !== void 0 && note.timestamp !== null && /* @__PURE__ */ jsx7("button", { onClick: () => handleTimestampClick(note.timestamp), className: "text-theme-accent-primary font-mono font-semibold hover:underline text-sm", disabled: !onTimestampClick, children: note.formattedTimestamp || formatTimestamp(note.timestamp) }),
|
|
680
|
-
editingNoteId === note.id ? /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
|
|
681
|
-
/* @__PURE__ */ jsx7("textarea", { value: editingText, onChange: (e) => setEditingText(e.target.value), rows: 3, className: "w-full resize-none rounded-md border border-theme-border-primary bg-theme-bg-primary px-3 py-2 text-sm text-theme-text-primary focus-visible:outline-none focus-visible:border-theme-accent-primary transition-colors" }),
|
|
682
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex gap-2 justify-end", children: [
|
|
683
|
-
/* @__PURE__ */ jsx7(Button, { variant: "outline", onClick: () => {
|
|
684
|
-
setEditingNoteId(null);
|
|
685
|
-
setEditingText("");
|
|
686
|
-
}, disabled: isUpdating, children: "Cancel" }),
|
|
687
|
-
/* @__PURE__ */ jsx7(Button, { onClick: () => handleSaveEdit(note.id), disabled: !editingText.trim() || isUpdating, className: "bg-theme-accent-primary hover:bg-theme-accent-primary/90 text-white", children: isUpdating ? "Saving..." : "Save" })
|
|
688
|
-
] })
|
|
689
|
-
] }) : /* @__PURE__ */ jsx7("p", { className: "text-theme-text-primary", children: note.text })
|
|
690
|
-
] }, note.id)) })
|
|
691
|
-
] })
|
|
692
|
-
] }) });
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
// src/components/organisms/LessonBookmarks.tsx
|
|
696
|
-
import { useState as useState4, useEffect as useEffect3 } from "react";
|
|
697
|
-
import { Pencil as Pencil2, Trash2 as Trash22, Bookmark as BookmarkIcon } from "lucide-react";
|
|
698
|
-
|
|
699
|
-
// src/components/atoms/Input.tsx
|
|
700
|
-
import * as React2 from "react";
|
|
701
|
-
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
702
|
-
var Input = React2.forwardRef(
|
|
703
|
-
(_a, ref) => {
|
|
704
|
-
var _b = _a, { className, type, label } = _b, props = __objRest(_b, ["className", "type", "label"]);
|
|
705
|
-
const inputElement = /* @__PURE__ */ jsx8(
|
|
706
|
-
"input",
|
|
707
|
-
__spreadValues({
|
|
708
|
-
type,
|
|
709
|
-
className: cn(
|
|
710
|
-
"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",
|
|
711
|
-
className
|
|
712
|
-
),
|
|
713
|
-
ref
|
|
714
|
-
}, props)
|
|
715
|
-
);
|
|
716
|
-
if (label) {
|
|
717
|
-
return /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
|
|
718
|
-
/* @__PURE__ */ jsxs6("label", { className: "text-sm font-medium text-theme-text-primary", children: [
|
|
719
|
-
label,
|
|
720
|
-
props.required && /* @__PURE__ */ jsx8("span", { className: "text-red-500 ml-1", children: "*" })
|
|
721
|
-
] }),
|
|
722
|
-
inputElement
|
|
723
|
-
] });
|
|
724
|
-
}
|
|
725
|
-
return inputElement;
|
|
726
|
-
}
|
|
727
|
-
);
|
|
728
|
-
Input.displayName = "Input";
|
|
729
|
-
|
|
730
|
-
// src/components/organisms/LessonBookmarks.tsx
|
|
731
|
-
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
732
|
-
function formatTime(seconds) {
|
|
733
|
-
const hrs = Math.floor(seconds / 3600);
|
|
734
|
-
const mins = Math.floor(seconds % 3600 / 60);
|
|
735
|
-
const secs = Math.floor(seconds % 60);
|
|
736
|
-
if (hrs > 0) return `${hrs}:${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
|
|
737
|
-
return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
|
|
738
|
-
}
|
|
739
|
-
function LessonBookmarks({ activityId, currentVideoTime, getLiveCurrentTime, onTimestampClick }) {
|
|
740
|
-
const sdk = useSDK();
|
|
741
|
-
const { data: apiBookmarks, isLoading, refetch } = sdk.useLessonBookmarks(activityId);
|
|
742
|
-
const { createBookmark, isLoading: isCreating } = sdk.useCreateBookmark();
|
|
743
|
-
const { updateBookmark, isLoading: isUpdating } = sdk.useUpdateBookmark();
|
|
744
|
-
const { deleteBookmark, isLoading: isDeleting } = sdk.useDeleteBookmark();
|
|
745
|
-
const [label, setLabel] = useState4("");
|
|
746
|
-
const [editingId, setEditingId] = useState4(null);
|
|
747
|
-
const [editingLabel, setEditingLabel] = useState4("");
|
|
748
|
-
const bookmarks = Array.isArray(apiBookmarks) ? [...apiBookmarks].sort((a, b) => a.second - b.second) : [];
|
|
749
|
-
useEffect3(() => {
|
|
750
|
-
setLabel("");
|
|
751
|
-
setEditingId(null);
|
|
752
|
-
setEditingLabel("");
|
|
753
|
-
}, [activityId]);
|
|
754
|
-
const handleAdd = async () => {
|
|
755
|
-
const effectiveTime = getLiveCurrentTime ? getLiveCurrentTime() : currentVideoTime;
|
|
756
|
-
if (effectiveTime === void 0) return;
|
|
757
|
-
const result = await createBookmark({ activityId, second: Math.floor(effectiveTime), label: label.trim() || void 0 });
|
|
758
|
-
if (result) {
|
|
759
|
-
setLabel("");
|
|
760
|
-
await refetch();
|
|
761
|
-
}
|
|
762
|
-
};
|
|
763
|
-
const handleSaveEdit = async (id) => {
|
|
764
|
-
const result = await updateBookmark(id, { label: editingLabel.trim() || void 0 });
|
|
765
|
-
if (result) {
|
|
766
|
-
setEditingId(null);
|
|
767
|
-
setEditingLabel("");
|
|
768
|
-
refetch();
|
|
769
|
-
}
|
|
770
|
-
};
|
|
771
|
-
const handleDelete = async (id) => {
|
|
772
|
-
const success = await deleteBookmark(id);
|
|
773
|
-
if (success) refetch();
|
|
774
|
-
};
|
|
775
|
-
const handleClick = (second) => {
|
|
776
|
-
onTimestampClick == null ? void 0 : onTimestampClick(second);
|
|
777
|
-
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
778
|
-
};
|
|
779
|
-
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col h-full", children: [
|
|
780
|
-
/* @__PURE__ */ jsxs7("div", { className: "p-4 border-b border-theme-border-primary bg-theme-bg-secondary sticky top-0 z-10", children: [
|
|
781
|
-
/* @__PURE__ */ jsx9("h3", { className: "text-lg font-bold text-theme-text-primary mb-2", children: "Bookmarks for this lesson" }),
|
|
782
|
-
/* @__PURE__ */ jsx9("p", { className: "text-base text-theme-text-secondary mb-4", children: "Save key moments in the video for quick access" }),
|
|
783
|
-
/* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
|
|
784
|
-
/* @__PURE__ */ jsx9(Input, { value: label, onChange: (e) => setLabel(e.target.value), placeholder: "Optional label...", className: "w-full" }),
|
|
785
|
-
/* @__PURE__ */ jsx9("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs7(Button, { onClick: handleAdd, disabled: isCreating || currentVideoTime === void 0, className: "bg-theme-accent-primary hover:bg-theme-accent-primary/90 text-white", children: [
|
|
786
|
-
/* @__PURE__ */ jsx9(BookmarkIcon, { className: "h-4 w-4 mr-2" }),
|
|
787
|
-
"Add Bookmark"
|
|
788
|
-
] }) })
|
|
789
|
-
] })
|
|
790
|
-
] }),
|
|
791
|
-
/* @__PURE__ */ jsx9("div", { className: "flex-1 overflow-y-auto p-4", children: isLoading ? /* @__PURE__ */ jsx9("div", { className: "text-theme-text-secondary", children: "Loading bookmarks..." }) : bookmarks.length === 0 ? /* @__PURE__ */ jsxs7("div", { className: "text-center py-8", children: [
|
|
792
|
-
/* @__PURE__ */ jsx9(BookmarkIcon, { className: "h-12 w-12 mx-auto text-theme-text-muted mb-3" }),
|
|
793
|
-
/* @__PURE__ */ jsx9("h3", { className: "text-xl font-bold text-theme-text-primary", children: "No bookmarks yet" }),
|
|
794
|
-
/* @__PURE__ */ jsx9("p", { className: "text-base text-theme-text-secondary mt-2", children: "Click \u201CAdd Bookmark\u201D to save important moments" })
|
|
795
|
-
] }) : /* @__PURE__ */ jsx9("div", { className: "space-y-3", children: bookmarks.map((bm) => /* @__PURE__ */ jsx9("div", { className: "rounded-lg border border-theme-border-primary bg-theme-bg-secondary p-3 hover:border-theme-accent-primary transition-colors", children: editingId === bm.id ? /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
|
|
796
|
-
/* @__PURE__ */ jsx9(Input, { value: editingLabel, onChange: (e) => setEditingLabel(e.target.value), placeholder: "Label...", className: "w-full", autoFocus: true }),
|
|
797
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex gap-2 justify-end", children: [
|
|
798
|
-
/* @__PURE__ */ jsx9(Button, { onClick: () => handleSaveEdit(bm.id), disabled: isUpdating, className: "bg-theme-accent-primary hover:bg-theme-accent-primary/90 text-white", children: "Save" }),
|
|
799
|
-
/* @__PURE__ */ jsx9(Button, { variant: "outline", onClick: () => {
|
|
800
|
-
setEditingId(null);
|
|
801
|
-
setEditingLabel("");
|
|
802
|
-
}, disabled: isUpdating, children: "Cancel" })
|
|
803
|
-
] })
|
|
804
|
-
] }) : /* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-3", children: [
|
|
805
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex-1 min-w-0", children: [
|
|
806
|
-
/* @__PURE__ */ jsx9("button", { onClick: () => handleClick(bm.second), className: "text-theme-accent-primary font-mono font-semibold hover:underline text-sm", children: formatTime(bm.second) }),
|
|
807
|
-
bm.label && /* @__PURE__ */ jsx9("p", { className: "text-theme-text-secondary text-sm mt-1 break-words", children: bm.label })
|
|
808
|
-
] }),
|
|
809
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex gap-1 flex-shrink-0", children: [
|
|
810
|
-
/* @__PURE__ */ jsx9(Button, { onClick: () => {
|
|
811
|
-
setEditingId(bm.id);
|
|
812
|
-
setEditingLabel(bm.label || "");
|
|
813
|
-
}, variant: "ghost", size: "icon", className: "text-theme-accent-primary hover:text-theme-accent-primary/80 h-8 w-8", title: "Edit", children: /* @__PURE__ */ jsx9(Pencil2, { className: "h-4 w-4" }) }),
|
|
814
|
-
/* @__PURE__ */ jsx9(Button, { onClick: () => handleDelete(bm.id), disabled: isDeleting, variant: "ghost", size: "icon", className: "text-red-600 hover:text-red-800 h-8 w-8", title: "Delete", children: /* @__PURE__ */ jsx9(Trash22, { className: "h-4 w-4" }) })
|
|
815
|
-
] })
|
|
816
|
-
] }) }, bm.id)) }) })
|
|
817
|
-
] });
|
|
818
|
-
}
|
|
819
|
-
export {
|
|
820
|
-
CourseSidebar,
|
|
821
|
-
LearnerNavbar,
|
|
822
|
-
LearnerSidebar,
|
|
823
|
-
LessonBookmarks,
|
|
824
|
-
LessonNotes
|
|
825
|
-
};
|