@burdenoff/microfe-technospam 2026.1101.4 → 2026.1101.5

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.
Files changed (34) hide show
  1. package/dist/technospam/TechnoSpamRoutes.d.ts.map +1 -1
  2. package/dist/technospam/TechnoSpamRoutes.js +91 -90
  3. package/dist/technospam/TechnoSpamRoutes.js.map +1 -1
  4. package/dist/technospam/api/technospamApi.d.ts +21 -7
  5. package/dist/technospam/api/technospamApi.d.ts.map +1 -1
  6. package/dist/technospam/api/technospamApi.js +317 -284
  7. package/dist/technospam/api/technospamApi.js.map +1 -1
  8. package/dist/technospam/components/lesson/OfflineProgressSync.d.ts +9 -0
  9. package/dist/technospam/components/lesson/OfflineProgressSync.d.ts.map +1 -0
  10. package/dist/technospam/components/lesson/OfflineProgressSync.js +20 -0
  11. package/dist/technospam/components/lesson/OfflineProgressSync.js.map +1 -0
  12. package/dist/technospam/components/lesson/SaveCourseOffline.d.ts +17 -0
  13. package/dist/technospam/components/lesson/SaveCourseOffline.d.ts.map +1 -0
  14. package/dist/technospam/components/lesson/SaveCourseOffline.js +73 -0
  15. package/dist/technospam/components/lesson/SaveCourseOffline.js.map +1 -0
  16. package/dist/technospam/components/lesson/SavedCourseOutline.d.ts +17 -0
  17. package/dist/technospam/components/lesson/SavedCourseOutline.d.ts.map +1 -0
  18. package/dist/technospam/components/lesson/SavedCourseOutline.js +77 -0
  19. package/dist/technospam/components/lesson/SavedCourseOutline.js.map +1 -0
  20. package/dist/technospam/hooks/useOfflineLessons.d.ts +26 -0
  21. package/dist/technospam/hooks/useOfflineLessons.d.ts.map +1 -0
  22. package/dist/technospam/hooks/useOfflineLessons.js +70 -0
  23. package/dist/technospam/hooks/useOfflineLessons.js.map +1 -0
  24. package/dist/technospam/lib/offlineLessons.d.ts +97 -0
  25. package/dist/technospam/lib/offlineLessons.d.ts.map +1 -0
  26. package/dist/technospam/lib/offlineLessons.js +168 -0
  27. package/dist/technospam/lib/offlineLessons.js.map +1 -0
  28. package/dist/technospam/pages/CoursesCourseDetailsPagePage.d.ts.map +1 -1
  29. package/dist/technospam/pages/CoursesCourseDetailsPagePage.js +235 -197
  30. package/dist/technospam/pages/CoursesCourseDetailsPagePage.js.map +1 -1
  31. package/dist/technospam/pages/CoursesLessonPlayerPagePage.d.ts.map +1 -1
  32. package/dist/technospam/pages/CoursesLessonPlayerPagePage.js +216 -138
  33. package/dist/technospam/pages/CoursesLessonPlayerPagePage.js.map +1 -1
  34. package/package.json +1 -1
@@ -4,135 +4,139 @@ import { cn as r } from "../utils/cn.js";
4
4
  import { PageLayout as i } from "../components/PageLayout.js";
5
5
  import { StatCard as a } from "../components/StatCard.js";
6
6
  import { MediaCover as o, topicIcon as s } from "../components/MediaCover.js";
7
- import { formatDate as c, formatDuration as l, humanizeEnum as u } from "../utils/format.js";
8
- import { PremiumBadge as d, UpgradeGate as f } from "../components/UpgradeGate.js";
9
- import { EmptyView as ee, ErrorView as te } from "../components/StateViews.js";
10
- import { TagStrip as ne } from "../components/TagStrip.js";
11
- import { notify as p } from "../lib/toast.js";
12
- import { useCourseQuery as re, useEnroll as ie, useIssueCertificate as ae, useMyCertificatesQuery as oe } from "../api/technospamApi.js";
7
+ import { formatDate as c, formatDuration as ee, humanizeEnum as l } from "../utils/format.js";
8
+ import { PremiumBadge as u, UpgradeGate as d } from "../components/UpgradeGate.js";
9
+ import { EmptyView as te, ErrorView as ne } from "../components/StateViews.js";
10
+ import { TagStrip as re } from "../components/TagStrip.js";
11
+ import { notify as f } from "../lib/toast.js";
12
+ import { useCourseQuery as ie, useEnroll as ae, useIssueCertificate as oe, useMyCertificatesQuery as se } from "../api/technospamApi.js";
13
13
  import "../components/index.js";
14
- import { FOCUS_PARAMS as se } from "../utils/pageContext.js";
15
- import { lessonPlayerPath as ce } from "../utils/lessonPath.js";
16
- import { useFocusedRecordParam as m } from "../hooks/useFocusedRecordParam.js";
17
- import { useEffect as le } from "react";
18
- import { ArrowRight as h, Award as g, BookOpen as _, CheckCircle2 as v, ChevronDown as y, Clock as b, Eye as x, FileText as S, Layers as C, Lock as w, PlayCircle as T, ShieldCheck as E, Sparkles as D, TrendingUp as O, Trophy as k, Users as A } from "lucide-react";
19
- import { useSearchParams as ue } from "react-router";
20
- import { jsx as j, jsxs as M } from "react/jsx-runtime";
21
- import { Button as N, GlassCard as P, Skeleton as F } from "@burdenoff/fe-libs/ui";
14
+ import { offlineScope as ce, readSavedCourseOutline as le } from "../lib/offlineLessons.js";
15
+ import { useOnlineStatus as ue, usePurgeOtherUsersLessons as de } from "../hooks/useOfflineLessons.js";
16
+ import { FOCUS_PARAMS as fe } from "../utils/pageContext.js";
17
+ import { lessonPlayerPath as p } from "../utils/lessonPath.js";
18
+ import { useFocusedRecordParam as pe } from "../hooks/useFocusedRecordParam.js";
19
+ import { SaveCourseOffline as me } from "../components/lesson/SaveCourseOffline.js";
20
+ import { SavedCourseOutline as he } from "../components/lesson/SavedCourseOutline.js";
21
+ import { useEffect as m, useMemo as ge, useRef as _e } from "react";
22
+ import { ArrowRight as ve, Award as h, BookOpen as g, CheckCircle2 as _, ChevronDown as v, Clock as y, Eye as b, FileText as x, Layers as S, Lock as C, PlayCircle as w, ShieldCheck as T, Sparkles as E, TrendingUp as D, Trophy as O, Users as ye } from "lucide-react";
23
+ import { useSearchParams as be } from "react-router";
24
+ import { jsx as k, jsxs as A } from "react/jsx-runtime";
25
+ import { Button as j, GlassCard as M, Skeleton as N } from "@burdenoff/fe-libs/ui";
22
26
  //#region src/technospam/pages/CoursesCourseDetailsPagePage.tsx
23
- var I = {
27
+ var P = {
24
28
  VIDEO: {
25
- icon: T,
29
+ icon: w,
26
30
  chip: "bg-accent-primary/15 text-accent-primary",
27
31
  badge: "border-accent-primary/25 bg-accent-primary/6 text-accent-primary"
28
32
  },
29
33
  ARTICLE: {
30
- icon: S,
34
+ icon: x,
31
35
  chip: "bg-accent-indigo/15 text-accent-indigo",
32
36
  badge: "border-accent-indigo/25 bg-accent-indigo/10 text-accent-indigo"
33
37
  },
34
38
  INTERACTIVE: {
35
- icon: D,
39
+ icon: E,
36
40
  chip: "bg-accent-teal/15 text-accent-teal",
37
41
  badge: "border-accent-teal/25 bg-accent-teal/10 text-accent-teal"
38
42
  },
39
43
  QUIZ: {
40
- icon: v,
44
+ icon: _,
41
45
  chip: "bg-accent-purple/15 text-accent-purple",
42
46
  badge: "border-accent-purple/25 bg-accent-purple/10 text-accent-purple"
43
47
  },
44
48
  PROJECT: {
45
- icon: C,
49
+ icon: S,
46
50
  chip: "bg-status-warning-bg-subtle text-status-warning-text",
47
51
  badge: "border-status-warning-border bg-status-warning-bg-subtle text-status-warning-text"
48
52
  }
49
53
  };
50
- function L({ icon: e, children: t }) {
51
- return /* @__PURE__ */ M("span", {
54
+ function F({ icon: e, children: t }) {
55
+ return /* @__PURE__ */ A("span", {
52
56
  className: "inline-flex items-center gap-1 rounded-full bg-white/15 px-2.5 py-1 text-xs font-medium text-white ring-1 ring-white/25 backdrop-blur-sm",
53
- children: [e ? /* @__PURE__ */ j(e, { size: 12 }) : null, t]
57
+ children: [e ? /* @__PURE__ */ k(e, { size: 12 }) : null, t]
54
58
  });
55
59
  }
56
- function de({ lesson: e, index: t, done: n, open: i, onToggle: a, onStart: o }) {
57
- let s = I[e.kind] ?? I.ARTICLE, c = s.icon, d = `tec-lesson-body-${e.id}`;
58
- return /* @__PURE__ */ M("div", {
60
+ function xe({ lesson: e, index: t, done: n, open: i, onToggle: a, onStart: o }) {
61
+ let s = P[e.kind] ?? P.ARTICLE, c = s.icon, u = `tec-lesson-body-${e.id}`;
62
+ return /* @__PURE__ */ A("div", {
59
63
  className: "border-b border-border-seam last:border-b-0",
60
- children: [/* @__PURE__ */ M("button", {
64
+ children: [/* @__PURE__ */ A("button", {
61
65
  type: "button",
62
66
  onClick: a,
63
67
  "aria-expanded": i,
64
- "aria-controls": d,
68
+ "aria-controls": u,
65
69
  className: "group flex w-full items-center gap-3 rounded-xl px-2 py-3 text-left transition-colors hover:bg-bg-sunken/60",
66
70
  children: [
67
- /* @__PURE__ */ j("span", {
71
+ /* @__PURE__ */ k("span", {
68
72
  className: "hidden w-6 shrink-0 text-center text-sm font-medium tabular-nums text-text-muted sm:block",
69
73
  children: t + 1
70
74
  }),
71
- /* @__PURE__ */ j("span", {
75
+ /* @__PURE__ */ k("span", {
72
76
  className: r("flex h-9 w-9 shrink-0 items-center justify-center rounded-lg", n ? "bg-status-success-bg-subtle text-status-success-text" : s.chip),
73
- children: j(n ? v : c, { size: 17 })
77
+ children: k(n ? _ : c, { size: 17 })
74
78
  }),
75
- /* @__PURE__ */ M("div", {
79
+ /* @__PURE__ */ A("div", {
76
80
  className: "min-w-0 flex-1",
77
- children: [/* @__PURE__ */ j("span", {
81
+ children: [/* @__PURE__ */ k("span", {
78
82
  className: "block truncate text-sm font-medium text-text-primary",
79
83
  children: e.title
80
- }), /* @__PURE__ */ M("div", {
84
+ }), /* @__PURE__ */ A("div", {
81
85
  className: "mt-1 flex flex-wrap items-center gap-2",
82
- children: [/* @__PURE__ */ j("span", {
86
+ children: [/* @__PURE__ */ k("span", {
83
87
  className: r("inline-flex items-center rounded-full border px-2 py-0.5 text-[11px] font-medium", s.badge),
84
- children: u(e.kind)
85
- }), /* @__PURE__ */ M("span", {
88
+ children: l(e.kind)
89
+ }), /* @__PURE__ */ A("span", {
86
90
  className: "inline-flex items-center gap-1 text-xs text-text-muted",
87
91
  children: [
88
- /* @__PURE__ */ j(b, { size: 12 }),
92
+ /* @__PURE__ */ k(y, { size: 12 }),
89
93
  " ",
90
- l(e.estimatedMinutes)
94
+ ee(e.estimatedMinutes)
91
95
  ]
92
96
  })]
93
97
  })]
94
98
  }),
95
- /* @__PURE__ */ M("div", {
99
+ /* @__PURE__ */ A("div", {
96
100
  className: "flex shrink-0 items-center gap-2",
97
- children: [n ? /* @__PURE__ */ j(v, {
101
+ children: [n ? /* @__PURE__ */ k(_, {
98
102
  size: 18,
99
103
  className: "text-status-success-text"
100
- }) : e.isPreview ? /* @__PURE__ */ M("span", {
104
+ }) : e.isPreview ? /* @__PURE__ */ A("span", {
101
105
  className: "inline-flex items-center gap-1 rounded-full border border-accent-primary/30 bg-accent-primary/6 px-2 py-0.5 text-[11px] font-medium text-accent-primary",
102
- children: [/* @__PURE__ */ j(x, { size: 12 }), " Preview"]
103
- }) : e.isLocked ? /* @__PURE__ */ M("span", {
106
+ children: [/* @__PURE__ */ k(b, { size: 12 }), " Preview"]
107
+ }) : e.isLocked ? /* @__PURE__ */ A("span", {
104
108
  className: "inline-flex items-center gap-1 rounded-full border border-status-warning-border/60 bg-status-warning-bg-subtle px-2 py-0.5 text-[11px] font-medium text-status-warning-text",
105
- children: [/* @__PURE__ */ j(w, { size: 12 }), " Upgrade to unlock"]
106
- }) : /* @__PURE__ */ j(w, {
109
+ children: [/* @__PURE__ */ k(C, { size: 12 }), " Upgrade to unlock"]
110
+ }) : /* @__PURE__ */ k(C, {
107
111
  size: 15,
108
112
  className: "text-text-muted"
109
- }), /* @__PURE__ */ j(y, {
113
+ }), /* @__PURE__ */ k(v, {
110
114
  size: 16,
111
115
  "aria-hidden": !0,
112
116
  className: r("text-text-muted transition-transform duration-200", i ? "rotate-180" : "")
113
117
  })]
114
118
  })
115
119
  ]
116
- }), i ? /* @__PURE__ */ j("div", {
117
- id: d,
120
+ }), i ? /* @__PURE__ */ k("div", {
121
+ id: u,
118
122
  className: "px-2 pb-4 sm:pl-11",
119
- children: e.isLocked ? /* @__PURE__ */ j(f, {
123
+ children: e.isLocked ? /* @__PURE__ */ k(d, {
120
124
  compact: !0,
121
125
  description: "This lesson is part of a paid TechnoSpam plan — its content unlocks once your workspace upgrades."
122
- }) : /* @__PURE__ */ M("div", {
126
+ }) : /* @__PURE__ */ A("div", {
123
127
  className: "space-y-3",
124
- children: [e.content ? /* @__PURE__ */ j("div", {
128
+ children: [e.content ? /* @__PURE__ */ k("div", {
125
129
  className: "rounded-xl border border-border-seam bg-bg-sunken p-4",
126
- children: /* @__PURE__ */ j("p", {
130
+ children: /* @__PURE__ */ k("p", {
127
131
  className: "line-clamp-6 whitespace-pre-wrap text-sm leading-relaxed text-text-secondary",
128
132
  children: e.content
129
133
  })
130
- }) : null, /* @__PURE__ */ M(N, {
134
+ }) : null, /* @__PURE__ */ A(j, {
131
135
  size: "sm",
132
136
  onClick: o,
133
137
  "data-testid": `open-lesson-${e.id}`,
134
138
  children: [
135
- /* @__PURE__ */ j(T, { size: 15 }),
139
+ /* @__PURE__ */ k(w, { size: 15 }),
136
140
  " ",
137
141
  n ? "Review lesson" : "Start lesson"
138
142
  ]
@@ -141,184 +145,207 @@ function de({ lesson: e, index: t, done: n, open: i, onToggle: a, onStart: o })
141
145
  }) : null]
142
146
  });
143
147
  }
144
- function fe({ certificate: e, learnerName: t, courseTitle: n }) {
148
+ function Se({ certificate: e, learnerName: t, courseTitle: n }) {
145
149
  let r = e.status === "REVOKED";
146
- return /* @__PURE__ */ M(P, {
150
+ return /* @__PURE__ */ A(M, {
147
151
  className: "overflow-hidden p-0",
148
- children: [/* @__PURE__ */ j("div", {
152
+ children: [/* @__PURE__ */ k("div", {
149
153
  className: "border-b border-border-seam px-5 py-3",
150
- children: /* @__PURE__ */ j("span", {
154
+ children: /* @__PURE__ */ k("span", {
151
155
  className: "text-xs font-semibold uppercase tracking-wide text-text-muted",
152
156
  children: "Certificate preview"
153
157
  })
154
- }), /* @__PURE__ */ M("div", {
158
+ }), /* @__PURE__ */ A("div", {
155
159
  className: "space-y-4 bg-bg-sunken/50 px-5 py-6 text-center",
156
160
  children: [
157
- /* @__PURE__ */ M("div", {
161
+ /* @__PURE__ */ A("div", {
158
162
  className: "flex items-center justify-center gap-2 text-xs font-semibold uppercase tracking-[0.2em] text-text-muted",
159
- children: [/* @__PURE__ */ j(g, {
163
+ children: [/* @__PURE__ */ k(h, {
160
164
  size: 14,
161
165
  className: "text-status-warning-text"
162
166
  }), " Certificate of completion"]
163
167
  }),
164
- /* @__PURE__ */ j("h3", {
168
+ /* @__PURE__ */ k("h3", {
165
169
  className: "text-lg font-bold text-text-primary",
166
170
  children: n
167
171
  }),
168
- t ? /* @__PURE__ */ M("p", {
172
+ t ? /* @__PURE__ */ A("p", {
169
173
  className: "text-sm text-text-secondary",
170
- children: ["Awarded to ", /* @__PURE__ */ j("span", {
174
+ children: ["Awarded to ", /* @__PURE__ */ k("span", {
171
175
  className: "font-semibold text-text-primary",
172
176
  children: t
173
177
  })]
174
178
  }) : null,
175
- /* @__PURE__ */ M("div", {
179
+ /* @__PURE__ */ A("div", {
176
180
  className: "grid grid-cols-1 gap-3 border-t border-border-seam pt-4 text-left sm:grid-cols-3",
177
181
  children: [
178
- /* @__PURE__ */ M("div", { children: [/* @__PURE__ */ j("div", {
182
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("div", {
179
183
  className: "text-[11px] font-medium uppercase tracking-wide text-text-muted",
180
184
  children: "Serial number"
181
- }), /* @__PURE__ */ j("div", {
185
+ }), /* @__PURE__ */ k("div", {
182
186
  className: "truncate font-mono text-sm text-text-primary",
183
187
  children: e.serial
184
188
  })] }),
185
- /* @__PURE__ */ M("div", { children: [/* @__PURE__ */ j("div", {
189
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("div", {
186
190
  className: "text-[11px] font-medium uppercase tracking-wide text-text-muted",
187
191
  children: "Score"
188
- }), /* @__PURE__ */ j("div", {
192
+ }), /* @__PURE__ */ k("div", {
189
193
  className: "text-sm font-semibold text-text-primary",
190
194
  children: e.score
191
195
  })] }),
192
- /* @__PURE__ */ M("div", { children: [/* @__PURE__ */ j("div", {
196
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("div", {
193
197
  className: "text-[11px] font-medium uppercase tracking-wide text-text-muted",
194
198
  children: "Issued on"
195
- }), /* @__PURE__ */ j("div", {
199
+ }), /* @__PURE__ */ k("div", {
196
200
  className: "text-sm text-text-primary",
197
201
  children: c(e.issuedAt)
198
202
  })] })
199
203
  ]
200
204
  }),
201
- r ? /* @__PURE__ */ M("div", {
205
+ r ? /* @__PURE__ */ A("div", {
202
206
  className: "rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-left text-xs text-status-error-text",
203
207
  children: [
204
208
  "This certificate was revoked",
205
209
  e.revokedAt ? ` on ${c(e.revokedAt)}` : "",
206
210
  e.revokeReason ? ` — ${e.revokeReason}` : "."
207
211
  ]
208
- }) : /* @__PURE__ */ M("span", {
212
+ }) : /* @__PURE__ */ A("span", {
209
213
  className: "inline-flex items-center gap-1 rounded-full border border-status-success-border bg-status-success-bg-subtle px-2.5 py-1 text-xs font-medium text-status-success-text",
210
- children: [/* @__PURE__ */ j(E, { size: 13 }), " Verified"]
214
+ children: [/* @__PURE__ */ k(T, { size: 13 }), " Verified"]
211
215
  })
212
216
  ]
213
217
  })]
214
218
  });
215
219
  }
216
- function R() {
217
- let [c] = ue(), y = c.get("id") ?? "", [x, T] = m(se.lesson), { currentUser: E, workspaceId: D } = e(), I = t(), { emit: R } = n(), { data: z, loading: B, error: V, refetch: pe } = re(y);
218
- le(() => {
219
- y && R("technospam.course.viewed", {
220
- workspaceId: D,
221
- entityId: y,
220
+ function I() {
221
+ let [c] = be(), v = c.get("id") ?? "", [b, w] = pe(fe.lesson), { currentUser: T, workspaceId: E } = e(), P = t();
222
+ de(T?.id);
223
+ let { emit: I } = n(), { data: Ce, loading: L, error: R, refetch: z } = ie(v), B = ue(), V = ce(E, T?.id);
224
+ m(() => {
225
+ v && I("technospam.course.viewed", {
226
+ workspaceId: E,
227
+ entityId: v,
222
228
  entityType: "TEC_COURSE"
223
229
  });
224
230
  }, [
225
- y,
226
- D,
227
- R
231
+ v,
232
+ E,
233
+ I
228
234
  ]);
229
- let [me, { loading: H }] = ie(), U = z?.tecCourse ?? null, { certificates: W, refetch: he } = oe({
235
+ let [we, { loading: H }] = ae(), U = Ce?.tecCourse ?? null, { certificates: W, refetch: Te } = se({
230
236
  buiCourseId: U?.buiCourseId,
231
- technospamCourseId: y,
232
- skip: !y
233
- }), [ge, { loading: G }] = ae(), K = [...U?.lessons ?? []].sort((e, t) => e.position - t.position), q = (U?.enrollments ?? []).find((e) => e.learnerId === E?.id), J = W.find((e) => e.status === "ISSUED") ?? W[0], _e = !!q && q.progressPct >= 100, ve = async () => {
234
- !y || !E?.id || (R("technospam.course.certificate_claimed", {
235
- workspaceId: D,
236
- entityId: y,
237
+ technospamCourseId: v,
238
+ skip: !v
239
+ }), [Ee, { loading: G }] = oe(), K = [...U?.lessons ?? []].sort((e, t) => e.position - t.position), q = (U?.enrollments ?? []).find((e) => e.learnerId === T?.id), J = W.find((e) => e.status === "ISSUED") ?? W[0], De = !!q && q.progressPct >= 100, Oe = async () => {
240
+ !v || !T?.id || (I("technospam.course.certificate_claimed", {
241
+ workspaceId: E,
242
+ entityId: v,
237
243
  entityType: "TEC_COURSE"
238
- }), (await ge({ variables: {
239
- courseId: y,
240
- learnerId: E.id,
244
+ }), (await Ee({ variables: {
245
+ courseId: v,
246
+ learnerId: T.id,
241
247
  score: 100
242
- } })).data?.tecIssueCertificate && (p.success("Certificate issued", "Your verifiable certificate is ready in My Learning."), await he()));
243
- }, ye = async () => {
244
- y && (R("technospam.course.enroll_clicked", {
245
- workspaceId: D,
246
- entityId: y,
248
+ } })).data?.tecIssueCertificate && (f.success("Certificate issued", "Your verifiable certificate is ready in My Learning."), await Te()));
249
+ }, ke = async () => {
250
+ v && (I("technospam.course.enroll_clicked", {
251
+ workspaceId: E,
252
+ entityId: v,
247
253
  entityType: "TEC_COURSE"
248
- }), (await me({ variables: { input: { courseId: y } } })).data?.tecEnroll && (R("technospam.course.enrolled", {
249
- workspaceId: D,
250
- entityId: y,
254
+ }), (await we({ variables: { input: { courseId: v } } })).data?.tecEnroll && (I("technospam.course.enrolled", {
255
+ workspaceId: E,
256
+ entityId: v,
251
257
  entityType: "TEC_COURSE"
252
- }), p.success("Enrolled", `You're enrolled in "${U?.title}".`), await pe()));
253
- };
254
- if (B && !U) return /* @__PURE__ */ M(i, {
258
+ }), f.success("Enrolled", `You're enrolled in "${U?.title}".`), await z()));
259
+ }, Y = ge(() => U || L ? null : le(V, v), [
260
+ U,
261
+ L,
262
+ V,
263
+ v
264
+ ]), X = _e(B);
265
+ if (m(() => {
266
+ let e = B && !X.current;
267
+ X.current = B, e && !U && z();
268
+ }, [
269
+ B,
270
+ U,
271
+ z
272
+ ]), L && !U) return /* @__PURE__ */ A(i, {
255
273
  title: "Course",
256
274
  backPath: "/courses/courses-page",
257
- children: [/* @__PURE__ */ j(F, { className: "mb-4 h-40 w-full rounded-2xl" }), /* @__PURE__ */ j(F, { className: "h-64 w-full rounded-xl" })]
275
+ children: [/* @__PURE__ */ k(N, { className: "mb-4 h-40 w-full rounded-2xl" }), /* @__PURE__ */ k(N, { className: "h-64 w-full rounded-xl" })]
276
+ });
277
+ if (!U && Y) return /* @__PURE__ */ k(i, {
278
+ title: Y.course.title,
279
+ backPath: "/courses/courses-page",
280
+ children: /* @__PURE__ */ k(he, {
281
+ outline: Y,
282
+ online: B,
283
+ onOpenLesson: (e) => P(p(v, e))
284
+ })
258
285
  });
259
- if (V || !U) return /* @__PURE__ */ j(i, {
286
+ if (R || !U) return /* @__PURE__ */ k(i, {
260
287
  title: "Course",
261
288
  backPath: "/courses/courses-page",
262
- children: V ? /* @__PURE__ */ j(te, {
289
+ children: R ? /* @__PURE__ */ k(ne, {
263
290
  title: "Couldn't load course",
264
- error: V
265
- }) : /* @__PURE__ */ j(ee, {
291
+ error: R
292
+ }) : /* @__PURE__ */ k(te, {
266
293
  title: "Course not found",
267
294
  description: "This course may have been unpublished."
268
295
  })
269
296
  });
270
- let Y = q?.lessonsCompleted ?? 0, X = K.find((e) => !e.completedByMe) ?? K[0], Z = K.length > 0 && K.every((e) => e.completedByMe), Q = (e) => I(ce(y, e)), $ = Math.max(0, K.length - Y), be = q && q.progressPct >= 100 ? "Course complete — claim your certificate below." : $ === 1 ? "1 lesson to go — almost there!" : `${$} lessons to go — keep it up!`, xe = `${U.topic ?? ""} ${U.title}`;
271
- return /* @__PURE__ */ M(i, {
297
+ let Z = q?.lessonsCompleted ?? 0, Q = K.find((e) => !e.completedByMe) ?? K[0], $ = K.length > 0 && K.every((e) => e.completedByMe), Ae = (e) => P(p(v, e)), je = Math.max(0, K.length - Z), Me = q && q.progressPct >= 100 ? "Course complete — claim your certificate below." : je === 1 ? "1 lesson to go — almost there!" : `${je} lessons to go — keep it up!`, Ne = `${U.topic ?? ""} ${U.title}`;
298
+ return /* @__PURE__ */ A(i, {
272
299
  backPath: "/courses/courses-page",
273
300
  title: U.title,
274
301
  description: U.summary ?? void 0,
275
- actions: q ? X ? /* @__PURE__ */ M(N, {
276
- onClick: () => Q(X.id),
302
+ actions: q ? Q ? /* @__PURE__ */ A(j, {
303
+ onClick: () => Ae(Q.id),
277
304
  "data-testid": "continue-learning",
278
- children: [j(Z ? v : h, { size: 16 }), Z ? "Review course" : Y > 0 ? "Continue learning" : "Start course"]
279
- }) : null : /* @__PURE__ */ M(N, {
280
- onClick: ye,
305
+ children: [k($ ? _ : ve, { size: 16 }), $ ? "Review course" : Z > 0 ? "Continue learning" : "Start course"]
306
+ }) : null : /* @__PURE__ */ A(j, {
307
+ onClick: ke,
281
308
  disabled: H,
282
309
  children: [
283
- /* @__PURE__ */ j(_, { size: 16 }),
310
+ /* @__PURE__ */ k(g, { size: 16 }),
284
311
  " ",
285
312
  H ? "Enrolling…" : "Enroll"
286
313
  ]
287
314
  }),
288
315
  children: [
289
- /* @__PURE__ */ j(o, {
316
+ /* @__PURE__ */ k(o, {
290
317
  height: "h-40",
291
- seed: xe,
318
+ seed: Ne,
292
319
  icon: s(U.topic ?? U.title),
293
320
  className: "mb-5 rounded-2xl",
294
- children: /* @__PURE__ */ M("div", {
321
+ children: /* @__PURE__ */ A("div", {
295
322
  className: "flex w-full flex-col gap-2",
296
323
  children: [
297
- /* @__PURE__ */ j("span", {
324
+ /* @__PURE__ */ k("span", {
298
325
  className: "text-xs font-medium uppercase tracking-wide text-white/80",
299
326
  children: U.topic ?? "Course"
300
327
  }),
301
- /* @__PURE__ */ j("h2", {
328
+ /* @__PURE__ */ k("h2", {
302
329
  className: "text-2xl font-bold leading-tight text-white drop-shadow-sm sm:text-3xl",
303
330
  children: U.title
304
331
  }),
305
- /* @__PURE__ */ M("div", {
332
+ /* @__PURE__ */ A("div", {
306
333
  className: "flex flex-wrap items-center gap-2",
307
334
  children: [
308
- /* @__PURE__ */ j(L, {
309
- icon: O,
310
- children: u(U.level)
335
+ /* @__PURE__ */ k(F, {
336
+ icon: D,
337
+ children: l(U.level)
311
338
  }),
312
- /* @__PURE__ */ j(L, {
313
- icon: v,
314
- children: u(U.status)
339
+ /* @__PURE__ */ k(F, {
340
+ icon: _,
341
+ children: l(U.status)
315
342
  }),
316
- U.topic ? /* @__PURE__ */ j(L, {
317
- icon: C,
343
+ U.topic ? /* @__PURE__ */ k(F, {
344
+ icon: S,
318
345
  children: U.topic
319
346
  }) : null,
320
- U.isPremiumOnly ? /* @__PURE__ */ j(L, {
321
- icon: w,
347
+ U.isPremiumOnly ? /* @__PURE__ */ k(F, {
348
+ icon: C,
322
349
  children: "Premium"
323
350
  }) : null
324
351
  ]
@@ -326,57 +353,57 @@ function R() {
326
353
  ]
327
354
  })
328
355
  }),
329
- /* @__PURE__ */ j(ne, {
356
+ /* @__PURE__ */ k(re, {
330
357
  tags: U.tags,
331
358
  className: "mb-5"
332
359
  }),
333
- /* @__PURE__ */ M("div", {
360
+ /* @__PURE__ */ A("div", {
334
361
  className: "mb-6 grid grid-cols-2 gap-3 sm:grid-cols-4",
335
362
  children: [
336
- /* @__PURE__ */ j(a, {
363
+ /* @__PURE__ */ k(a, {
337
364
  label: "Lessons",
338
365
  value: K.length,
339
- icon: S,
366
+ icon: x,
340
367
  tone: "blue"
341
368
  }),
342
- /* @__PURE__ */ j(a, {
369
+ /* @__PURE__ */ k(a, {
343
370
  label: "Duration",
344
- value: l(U.estimatedMinutes),
345
- icon: b,
371
+ value: ee(U.estimatedMinutes),
372
+ icon: y,
346
373
  tone: "teal"
347
374
  }),
348
- /* @__PURE__ */ j(a, {
375
+ /* @__PURE__ */ k(a, {
349
376
  label: "Enrolled",
350
377
  value: U.enrollments?.length ?? 0,
351
- icon: A,
378
+ icon: ye,
352
379
  tone: "indigo"
353
380
  }),
354
- /* @__PURE__ */ j(a, {
381
+ /* @__PURE__ */ k(a, {
355
382
  label: "Your progress",
356
383
  value: q ? `${q.progressPct}%` : "Not started",
357
- icon: O,
384
+ icon: D,
358
385
  tone: "purple"
359
386
  })
360
387
  ]
361
388
  }),
362
- q ? /* @__PURE__ */ M(P, {
389
+ q ? /* @__PURE__ */ A(M, {
363
390
  className: "mb-6 p-5",
364
391
  children: [
365
- /* @__PURE__ */ M("div", {
392
+ /* @__PURE__ */ A("div", {
366
393
  className: "mb-3 flex items-center gap-2",
367
394
  children: [
368
- /* @__PURE__ */ j("span", {
395
+ /* @__PURE__ */ k("span", {
369
396
  className: "flex h-8 w-8 items-center justify-center rounded-lg bg-accent-primary/15 text-accent-primary",
370
- children: /* @__PURE__ */ j(O, { size: 16 })
397
+ children: /* @__PURE__ */ k(D, { size: 16 })
371
398
  }),
372
- /* @__PURE__ */ j("span", {
399
+ /* @__PURE__ */ k("span", {
373
400
  className: "text-sm font-semibold text-text-primary",
374
401
  children: "Your progress"
375
402
  }),
376
- /* @__PURE__ */ M("span", {
403
+ /* @__PURE__ */ A("span", {
377
404
  className: "ml-auto text-sm text-text-secondary",
378
405
  children: [
379
- Y,
406
+ Z,
380
407
  "/",
381
408
  K.length,
382
409
  " lessons · ",
@@ -386,109 +413,120 @@ function R() {
386
413
  })
387
414
  ]
388
415
  }),
389
- /* @__PURE__ */ j("div", {
416
+ /* @__PURE__ */ k("div", {
390
417
  className: "h-2.5 w-full overflow-hidden rounded-full bg-bg-sunken",
391
- children: /* @__PURE__ */ j("div", {
418
+ children: /* @__PURE__ */ k("div", {
392
419
  className: "h-full rounded-full bg-gradient-to-r from-accent-primary via-accent-indigo to-accent-purple transition-all duration-500",
393
420
  style: { width: `${q.progressPct}%` }
394
421
  })
395
422
  }),
396
- /* @__PURE__ */ j("p", {
423
+ /* @__PURE__ */ k("p", {
397
424
  className: "mt-2 text-xs text-text-muted",
398
- children: be
425
+ children: Me
399
426
  })
400
427
  ]
401
428
  }) : null,
402
- J ? /* @__PURE__ */ M("div", {
429
+ J ? /* @__PURE__ */ A("div", {
403
430
  className: "mb-6 grid grid-cols-1 gap-4 lg:grid-cols-2",
404
- children: [/* @__PURE__ */ M(P, {
431
+ children: [/* @__PURE__ */ A(M, {
405
432
  className: r("flex items-center gap-4 border p-5", J.status === "REVOKED" ? "border-status-error-border/60 bg-status-error-bg-subtle/20" : "border-status-success-border/60 bg-status-success-bg-subtle/30"),
406
- children: [/* @__PURE__ */ j("span", {
433
+ children: [/* @__PURE__ */ k("span", {
407
434
  className: "flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl bg-status-warning-bg-subtle text-status-warning-text ring-1 ring-status-warning-border/40",
408
- children: /* @__PURE__ */ j(k, { size: 26 })
409
- }), /* @__PURE__ */ M("div", {
435
+ children: /* @__PURE__ */ k(O, { size: 26 })
436
+ }), /* @__PURE__ */ A("div", {
410
437
  className: "min-w-0",
411
- children: [/* @__PURE__ */ j("div", {
438
+ children: [/* @__PURE__ */ k("div", {
412
439
  className: "text-base font-semibold text-text-primary",
413
440
  children: J.status === "REVOKED" ? "Your certificate was revoked" : "You finished this course"
414
- }), /* @__PURE__ */ j("div", {
441
+ }), /* @__PURE__ */ k("div", {
415
442
  className: "text-sm text-text-muted",
416
443
  children: J.status === "REVOKED" ? "Contact a workspace admin if you believe this was a mistake." : "Your verifiable certificate of completion is issued — it also appears in My Learning."
417
444
  })]
418
445
  })]
419
- }), /* @__PURE__ */ j(fe, {
446
+ }), /* @__PURE__ */ k(Se, {
420
447
  certificate: J,
421
- learnerName: E?.name ?? void 0,
448
+ learnerName: T?.name ?? void 0,
422
449
  courseTitle: J.course?.title ?? U.title
423
450
  })]
424
- }) : _e ? /* @__PURE__ */ M(P, {
451
+ }) : De ? /* @__PURE__ */ A(M, {
425
452
  className: "mb-6 flex flex-col items-start gap-4 border border-status-success-border/60 bg-status-success-bg-subtle/40 p-5 sm:flex-row sm:items-center sm:justify-between",
426
- children: [/* @__PURE__ */ M("div", {
453
+ children: [/* @__PURE__ */ A("div", {
427
454
  className: "flex items-center gap-4",
428
- children: [/* @__PURE__ */ j("span", {
455
+ children: [/* @__PURE__ */ k("span", {
429
456
  className: "flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl bg-status-warning-bg-subtle text-status-warning-text ring-1 ring-status-warning-border/40",
430
- children: /* @__PURE__ */ j(k, { size: 26 })
431
- }), /* @__PURE__ */ M("div", { children: [/* @__PURE__ */ j("div", {
457
+ children: /* @__PURE__ */ k(O, { size: 26 })
458
+ }), /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("div", {
432
459
  className: "text-base font-semibold text-text-primary",
433
460
  children: "You finished this course"
434
- }), /* @__PURE__ */ j("div", {
461
+ }), /* @__PURE__ */ k("div", {
435
462
  className: "text-sm text-text-muted",
436
463
  children: "Claim your verifiable certificate of completion."
437
464
  })] })]
438
- }), /* @__PURE__ */ M(N, {
439
- onClick: ve,
465
+ }), /* @__PURE__ */ A(j, {
466
+ onClick: Oe,
440
467
  disabled: G,
441
468
  children: [
442
- /* @__PURE__ */ j(g, { size: 16 }),
469
+ /* @__PURE__ */ k(h, { size: 16 }),
443
470
  " ",
444
471
  G ? "Issuing…" : "Claim certificate"
445
472
  ]
446
473
  })]
447
474
  }) : null,
448
- /* @__PURE__ */ M(P, {
475
+ /* @__PURE__ */ A(M, {
449
476
  className: "p-5",
450
477
  children: [
451
- /* @__PURE__ */ M("div", {
478
+ /* @__PURE__ */ A("div", {
452
479
  className: "mb-3 flex items-center justify-between gap-2",
453
- children: [/* @__PURE__ */ M("h2", {
480
+ children: [/* @__PURE__ */ A("h2", {
454
481
  className: "flex items-center gap-2 text-base font-semibold text-text-primary",
455
482
  children: [
456
- /* @__PURE__ */ j(_, {
483
+ /* @__PURE__ */ k(g, {
457
484
  size: 18,
458
485
  className: "text-accent-primary"
459
486
  }),
460
487
  " Curriculum",
461
- U.isPremiumOnly ? /* @__PURE__ */ j(d, { locked: U.isLocked }) : null
488
+ U.isPremiumOnly ? /* @__PURE__ */ k(u, { locked: U.isLocked }) : null
462
489
  ]
463
- }), K.length ? /* @__PURE__ */ M("span", {
464
- className: "rounded-full bg-status-success-bg-subtle px-2.5 py-1 text-xs font-medium text-status-success-text",
465
- children: [
466
- Y,
467
- "/",
468
- K.length,
469
- " completed"
470
- ]
471
- }) : null]
490
+ }), /* @__PURE__ */ A("div", {
491
+ className: "flex flex-wrap items-center justify-end gap-2",
492
+ children: [q ? /* @__PURE__ */ k(me, {
493
+ scope: V,
494
+ courseId: U.id,
495
+ lessons: K,
496
+ enrollment: {
497
+ id: q.id,
498
+ progressPct: q.progressPct
499
+ }
500
+ }) : null, K.length ? /* @__PURE__ */ A("span", {
501
+ className: "rounded-full bg-status-success-bg-subtle px-2.5 py-1 text-xs font-medium text-status-success-text",
502
+ children: [
503
+ Z,
504
+ "/",
505
+ K.length,
506
+ " completed"
507
+ ]
508
+ }) : null]
509
+ })]
472
510
  }),
473
- U.isLocked ? /* @__PURE__ */ j("div", {
511
+ U.isLocked ? /* @__PURE__ */ k("div", {
474
512
  className: "mb-4",
475
- children: /* @__PURE__ */ j(f, {
513
+ children: /* @__PURE__ */ k(d, {
476
514
  compact: !0,
477
515
  description: "This course is on a paid TechnoSpam plan. Preview lessons below stay free — the rest unlock once your workspace upgrades."
478
516
  })
479
517
  }) : null,
480
- K.length === 0 ? /* @__PURE__ */ j("p", {
518
+ K.length === 0 ? /* @__PURE__ */ k("p", {
481
519
  className: "py-6 text-center text-sm text-text-muted",
482
520
  children: "Lessons for this course are being prepared."
483
- }) : /* @__PURE__ */ j("div", {
521
+ }) : /* @__PURE__ */ k("div", {
484
522
  className: "flex flex-col",
485
- children: K.map((e, t) => /* @__PURE__ */ j(de, {
523
+ children: K.map((e, t) => /* @__PURE__ */ k(xe, {
486
524
  lesson: e,
487
525
  index: t,
488
526
  done: !!e.completedByMe,
489
- open: x === e.id,
490
- onToggle: () => T(x === e.id ? null : e.id),
491
- onStart: () => Q(e.id)
527
+ open: b === e.id,
528
+ onToggle: () => w(b === e.id ? null : e.id),
529
+ onStart: () => Ae(e.id)
492
530
  }, e.id))
493
531
  })
494
532
  ]
@@ -497,6 +535,6 @@ function R() {
497
535
  });
498
536
  }
499
537
  //#endregion
500
- export { R as CoursesCourseDetailsPagePage };
538
+ export { I as CoursesCourseDetailsPagePage };
501
539
 
502
540
  //# sourceMappingURL=CoursesCourseDetailsPagePage.js.map