@burdenoff/microfe-technospam 2026.1102.3 → 2026.1102.4

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