@burdenoff/microfe-buildmyiq 2026.705.13 → 2026.706.10

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 (67) hide show
  1. package/dist/buildmyiq/BuildmyiqRoot.d.ts.map +1 -1
  2. package/dist/buildmyiq/BuildmyiqRoot.js +57 -49
  3. package/dist/buildmyiq/BuildmyiqRoot.js.map +1 -1
  4. package/dist/buildmyiq/BuildmyiqRoutes.d.ts.map +1 -1
  5. package/dist/buildmyiq/BuildmyiqRoutes.js +15 -11
  6. package/dist/buildmyiq/BuildmyiqRoutes.js.map +1 -1
  7. package/dist/buildmyiq/components/Avatar.d.ts +15 -0
  8. package/dist/buildmyiq/components/Avatar.d.ts.map +1 -0
  9. package/dist/buildmyiq/components/Avatar.js +42 -0
  10. package/dist/buildmyiq/components/Avatar.js.map +1 -0
  11. package/dist/buildmyiq/components/Viz.d.ts +25 -0
  12. package/dist/buildmyiq/components/Viz.d.ts.map +1 -0
  13. package/dist/buildmyiq/components/Viz.js +78 -0
  14. package/dist/buildmyiq/components/Viz.js.map +1 -0
  15. package/dist/buildmyiq/components/index.d.ts +2 -0
  16. package/dist/buildmyiq/components/index.d.ts.map +1 -1
  17. package/dist/buildmyiq/components/index.js +2 -0
  18. package/dist/buildmyiq/pages/DashboardPage.d.ts.map +1 -1
  19. package/dist/buildmyiq/pages/DashboardPage.js +200 -98
  20. package/dist/buildmyiq/pages/DashboardPage.js.map +1 -1
  21. package/dist/buildmyiq/pages/assessments/AssessmentDetailPage.d.ts.map +1 -1
  22. package/dist/buildmyiq/pages/assessments/AssessmentDetailPage.js +262 -241
  23. package/dist/buildmyiq/pages/assessments/AssessmentDetailPage.js.map +1 -1
  24. package/dist/buildmyiq/pages/assessments/AssessmentsPage.d.ts.map +1 -1
  25. package/dist/buildmyiq/pages/assessments/AssessmentsPage.js +142 -115
  26. package/dist/buildmyiq/pages/assessments/AssessmentsPage.js.map +1 -1
  27. package/dist/buildmyiq/pages/assessments/TakeAssessmentPage.d.ts.map +1 -1
  28. package/dist/buildmyiq/pages/assessments/TakeAssessmentPage.js +220 -156
  29. package/dist/buildmyiq/pages/assessments/TakeAssessmentPage.js.map +1 -1
  30. package/dist/buildmyiq/pages/authoring/AuthoringPage.d.ts.map +1 -1
  31. package/dist/buildmyiq/pages/authoring/AuthoringPage.js +51 -46
  32. package/dist/buildmyiq/pages/authoring/AuthoringPage.js.map +1 -1
  33. package/dist/buildmyiq/pages/authoring/CourseBuilderPage.d.ts.map +1 -1
  34. package/dist/buildmyiq/pages/authoring/CourseBuilderPage.js +581 -448
  35. package/dist/buildmyiq/pages/authoring/CourseBuilderPage.js.map +1 -1
  36. package/dist/buildmyiq/pages/catalog/CatalogPage.d.ts.map +1 -1
  37. package/dist/buildmyiq/pages/catalog/CatalogPage.js +52 -42
  38. package/dist/buildmyiq/pages/catalog/CatalogPage.js.map +1 -1
  39. package/dist/buildmyiq/pages/catalog/CourseDetailPage.d.ts.map +1 -1
  40. package/dist/buildmyiq/pages/catalog/CourseDetailPage.js +422 -301
  41. package/dist/buildmyiq/pages/catalog/CourseDetailPage.js.map +1 -1
  42. package/dist/buildmyiq/pages/certificates/CertificatesPage.d.ts.map +1 -1
  43. package/dist/buildmyiq/pages/certificates/CertificatesPage.js +237 -151
  44. package/dist/buildmyiq/pages/certificates/CertificatesPage.js.map +1 -1
  45. package/dist/buildmyiq/pages/cohorts/CohortsPage.d.ts.map +1 -1
  46. package/dist/buildmyiq/pages/cohorts/CohortsPage.js +219 -138
  47. package/dist/buildmyiq/pages/cohorts/CohortsPage.js.map +1 -1
  48. package/dist/buildmyiq/pages/insights/InsightsPage.d.ts.map +1 -1
  49. package/dist/buildmyiq/pages/insights/InsightsPage.js +276 -152
  50. package/dist/buildmyiq/pages/insights/InsightsPage.js.map +1 -1
  51. package/dist/buildmyiq/pages/learning/LessonPlayerPage.d.ts.map +1 -1
  52. package/dist/buildmyiq/pages/learning/LessonPlayerPage.js +237 -174
  53. package/dist/buildmyiq/pages/learning/LessonPlayerPage.js.map +1 -1
  54. package/dist/buildmyiq/pages/learning/MyLearningPage.d.ts.map +1 -1
  55. package/dist/buildmyiq/pages/learning/MyLearningPage.js +307 -169
  56. package/dist/buildmyiq/pages/learning/MyLearningPage.js.map +1 -1
  57. package/dist/buildmyiq/pages/paths/PathsPage.d.ts +4 -0
  58. package/dist/buildmyiq/pages/paths/PathsPage.d.ts.map +1 -0
  59. package/dist/buildmyiq/pages/paths/PathsPage.js +187 -0
  60. package/dist/buildmyiq/pages/paths/PathsPage.js.map +1 -0
  61. package/dist/buildmyiq/pages/skills/SkillsPage.d.ts.map +1 -1
  62. package/dist/buildmyiq/pages/skills/SkillsPage.js +233 -140
  63. package/dist/buildmyiq/pages/skills/SkillsPage.js.map +1 -1
  64. package/dist/buildmyiq/pages/submissions/SubmissionsPage.d.ts.map +1 -1
  65. package/dist/buildmyiq/pages/submissions/SubmissionsPage.js +379 -275
  66. package/dist/buildmyiq/pages/submissions/SubmissionsPage.js.map +1 -1
  67. package/package.json +1 -1
@@ -1,362 +1,483 @@
1
1
  import { useBuildmyiq as e } from "../../context/BuildmyiqContext.js";
2
- import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { formatDuration as n, formatEnumLabel as r, formatHours as i } from "../../utils/formatters.js";
4
- import { StatusBadge as a } from "../../components/StatusBadge.js";
5
- import { EmptyState as o } from "../../components/EmptyState.js";
6
- import { ErrorView as s, LoadingView as c, Section as l } from "../../components/StateViews.js";
7
- import { MiniBar as u } from "../../components/MiniBar.js";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { PageLayout as n } from "../../components/PageLayout.js";
4
+ import { formatDuration as r, formatEnumLabel as i, formatHours as a } from "../../utils/formatters.js";
5
+ import { StatusBadge as o } from "../../components/StatusBadge.js";
6
+ import { EmptyState as s } from "../../components/EmptyState.js";
7
+ import { ErrorView as c, LoadingView as l, Section as u } from "../../components/StateViews.js";
8
+ import { MiniBar as d } from "../../components/MiniBar.js";
8
9
  import "../../context/index.js";
9
- import { useBuiAssessments as d, useBuiCourse as f, useBuiEnroll as p, useBuiEnrollments as m, useBuiModules as h } from "../../hooks/useBuildmyiqApi.js";
10
+ import { useBuiAssessments as f, useBuiCourse as ee, useBuiEnroll as p, useBuiEnrollments as m, useBuiModules as h } from "../../hooks/useBuildmyiqApi.js";
10
11
  import "../../hooks/index.js";
11
- import { BuiDiscussion as g } from "../../components/BuiDiscussion.js";
12
- import { BuiTags as _ } from "../../components/BuiTags.js";
12
+ import { BuiDiscussion as te } from "../../components/BuiDiscussion.js";
13
+ import { BuiTags as ne } from "../../components/BuiTags.js";
13
14
  import "../../components/index.js";
14
- import { useMemo as v, useState as y } from "react";
15
- import { ArrowLeft as b, BookOpen as x, ClipboardCheck as S, ClipboardList as C, Clock as w, FileText as T, GraduationCap as E, Layers as D, ListChecks as O, MousePointerClick as k, PlayCircle as A, Radio as j, Sparkles as M, Video as N } from "lucide-react";
16
- import { useParams as P } from "react-router-dom";
17
- import { Fragment as F, jsx as I, jsxs as L } from "react/jsx-runtime";
18
- import { Button as R, GlassCard as z } from "@burdenoff/fe-libs/ui";
15
+ import { useMemo as g, useState as _ } from "react";
16
+ import { ArrowLeft as re, ArrowRight as v, BookOpen as y, ChevronDown as b, ClipboardCheck as x, ClipboardList as S, Clock as C, FileText as w, GraduationCap as ie, Layers as T, ListChecks as E, MousePointerClick as D, PlayCircle as ae, Radio as O, Sparkles as oe, Video as k } from "lucide-react";
17
+ import { useParams as A } from "react-router-dom";
18
+ import { jsx as j, jsxs as M } from "react/jsx-runtime";
19
+ import { Button as N, GlassCard as P } from "@burdenoff/fe-libs/ui";
19
20
  //#region src/buildmyiq/pages/catalog/CourseDetailPage.tsx
20
- var B = "buildmyiq-course", V = {
21
- ARTICLE: T,
22
- VIDEO: N,
23
- QUIZ: O,
24
- ASSIGNMENT: C,
25
- INTERACTIVE: k,
26
- LIVE_SESSION: j
27
- }, H = ({ lesson: e }) => /* @__PURE__ */ L("li", {
28
- className: "flex items-center gap-3 px-4 py-3",
21
+ var F = "buildmyiq-course", se = "__ungrouped__", I = {
22
+ ARTICLE: w,
23
+ VIDEO: k,
24
+ QUIZ: E,
25
+ ASSIGNMENT: S,
26
+ INTERACTIVE: D,
27
+ LIVE_SESSION: O
28
+ }, L = ({ lesson: e, index: t }) => /* @__PURE__ */ M("li", {
29
+ className: "flex items-center gap-3 px-4 py-3 transition-colors hover:bg-bg-sunken/60",
29
30
  children: [
30
- /* @__PURE__ */ I("span", {
31
- className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary",
32
- children: /* @__PURE__ */ I(V[e.type] ?? T, { className: "h-4 w-4" })
31
+ /* @__PURE__ */ j("span", {
32
+ className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
33
+ children: /* @__PURE__ */ j(I[e.type] ?? w, { className: "h-4 w-4" })
33
34
  }),
34
- /* @__PURE__ */ L("div", {
35
+ /* @__PURE__ */ M("div", {
35
36
  className: "min-w-0 flex-1",
36
- children: [/* @__PURE__ */ I("p", {
37
+ children: [/* @__PURE__ */ M("p", {
37
38
  className: "truncate text-sm font-medium text-text-primary",
38
- children: e.title
39
- }), /* @__PURE__ */ I("p", {
39
+ children: [/* @__PURE__ */ M("span", {
40
+ className: "mr-1.5 tabular-nums text-text-tertiary",
41
+ children: [t + 1, "."]
42
+ }), e.title]
43
+ }), /* @__PURE__ */ j("p", {
40
44
  className: "text-xs text-text-tertiary",
41
- children: r(e.type)
45
+ children: i(e.type)
42
46
  })]
43
47
  }),
44
- e.isPreview && /* @__PURE__ */ I("span", {
45
- className: "shrink-0 rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs font-medium text-status-success-text",
46
- children: "Preview"
47
- }),
48
- e.durationMin > 0 && /* @__PURE__ */ L("span", {
48
+ e.durationMin > 0 && /* @__PURE__ */ M("span", {
49
49
  className: "hidden shrink-0 items-center gap-1 text-xs tabular-nums text-text-secondary sm:inline-flex",
50
50
  children: [
51
- /* @__PURE__ */ I(w, { className: "h-3.5 w-3.5" }),
51
+ /* @__PURE__ */ j(C, { className: "h-3.5 w-3.5" }),
52
52
  " ",
53
- n(e.durationMin)
53
+ r(e.durationMin)
54
54
  ]
55
+ }),
56
+ e.isPreview && /* @__PURE__ */ j("span", {
57
+ className: "shrink-0 rounded-full border border-[var(--color-accent-teal)] px-2 py-0.5 text-xs font-medium text-[var(--color-accent-teal)]",
58
+ children: "Preview"
55
59
  })
56
60
  ]
57
- }), U = () => {
58
- let { courseId: r } = P(), { currentUser: C, navigateTo: T } = e(), O = C?.id, k = f(r), j = h(r), N = d(r), V = m({
59
- courseId: r,
60
- learnerId: O,
61
- enabled: !!(r && O)
62
- }), U = p(), [W, G] = y(null), K = k.data ?? null, q = j.data ?? [], J = N.data ?? [], Y = V.data?.items ?? [], X = v(() => Y.find((e) => e.status !== "DROPPED" && e.status !== "EXPIRED"), [Y]), Z = v(() => (K?.lessons ?? []).filter((e) => !e.moduleId), [K]), Q = K?.lessons?.length ?? 0;
63
- return r ? k.isLoading ? /* @__PURE__ */ I(t, {
61
+ }), R = ({ icon: e, children: t }) => /* @__PURE__ */ M("span", {
62
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam bg-bg-surface px-3 py-1.5 text-xs font-medium text-text-secondary",
63
+ children: [/* @__PURE__ */ j(e, {
64
+ className: "h-3.5 w-3.5 text-text-tertiary",
65
+ "aria-hidden": !0
66
+ }), t]
67
+ }), z = () => {
68
+ let { courseId: i } = A(), { currentUser: S, navigateTo: w } = e(), E = S?.id, D = ee(i), O = h(i), k = f(i), I = m({
69
+ courseId: i,
70
+ learnerId: E,
71
+ enabled: !!(i && E)
72
+ }), z = p(), [B, V] = _(null), [H, U] = _(null), W = D.data ?? null, G = O.data ?? [], K = k.data ?? [], q = I.data?.items ?? [], J = g(() => q.find((e) => e.status !== "DROPPED" && e.status !== "EXPIRED"), [q]), Y = g(() => (W?.lessons ?? []).filter((e) => !e.moduleId), [W]), X = g(() => {
73
+ let e = G.map((e) => ({
74
+ id: e.id,
75
+ title: e.title,
76
+ description: e.description,
77
+ lessons: e.lessons ?? []
78
+ }));
79
+ return Y.length > 0 && e.push({
80
+ id: se,
81
+ title: "Additional lessons",
82
+ lessons: Y
83
+ }), e;
84
+ }, [G, Y]), Z = W?.lessons?.length ?? 0, ce = K.filter((e) => e.status === "PUBLISHED").length, Q = H ?? new Set(X.slice(0, 1).map((e) => e.id)), $ = X.length > 0 && X.every((e) => Q.has(e.id)), le = (e) => {
85
+ let t = new Set(Q);
86
+ t.has(e) ? t.delete(e) : t.add(e), U(t);
87
+ };
88
+ return i ? D.isLoading ? /* @__PURE__ */ j(n, {
64
89
  title: "Course",
65
- children: /* @__PURE__ */ I(c, { label: "Loading course…" })
66
- }) : k.isError ? /* @__PURE__ */ I(t, {
90
+ children: /* @__PURE__ */ j(l, { label: "Loading course…" })
91
+ }) : D.isError ? /* @__PURE__ */ j(n, {
67
92
  title: "Course",
68
- children: /* @__PURE__ */ I(s, {
93
+ children: /* @__PURE__ */ j(c, {
69
94
  title: "Couldn't load this course",
70
- message: k.error instanceof Error ? k.error.message : void 0,
71
- onRetry: () => k.refetch()
95
+ message: D.error instanceof Error ? D.error.message : void 0,
96
+ onRetry: () => D.refetch()
72
97
  })
73
- }) : K ? /* @__PURE__ */ I(t, {
74
- title: K.title,
75
- children: /* @__PURE__ */ L("div", {
76
- className: "mx-auto flex w-full max-w-5xl flex-col gap-8",
98
+ }) : W ? /* @__PURE__ */ j(n, {
99
+ title: W.title,
100
+ children: /* @__PURE__ */ M("div", {
101
+ className: "mx-auto flex w-full max-w-6xl flex-col gap-6",
77
102
  children: [
78
- /* @__PURE__ */ L("button", {
79
- type: "button",
80
- onClick: () => T("catalog"),
81
- className: "inline-flex w-fit items-center gap-1.5 text-sm text-text-secondary transition-colors hover:text-text-primary",
82
- children: [/* @__PURE__ */ I(b, { className: "h-4 w-4" }), " Back to catalog"]
83
- }),
84
- /* @__PURE__ */ I(z, {
85
- treatment: "plain",
86
- className: "overflow-hidden",
87
- children: /* @__PURE__ */ L("div", {
88
- className: "grid grid-cols-1 lg:grid-cols-[minmax(0,2fr)_minmax(0,3fr)]",
89
- children: [/* @__PURE__ */ I("div", {
90
- className: "relative h-48 w-full overflow-hidden bg-bg-sunken lg:h-full",
91
- children: K.cover?.downloadUrl ? /* @__PURE__ */ I("img", {
92
- src: K.cover.downloadUrl,
93
- alt: "",
94
- className: "h-full w-full object-cover"
95
- }) : /* @__PURE__ */ I("div", {
96
- className: "flex h-full min-h-[12rem] w-full items-center justify-center bg-[var(--color-accent-soft)]",
97
- children: /* @__PURE__ */ I(x, { className: "h-10 w-10 text-text-secondary opacity-60" })
103
+ /* @__PURE__ */ M("div", {
104
+ className: "flex flex-wrap items-center justify-between gap-3",
105
+ children: [/* @__PURE__ */ M("nav", {
106
+ className: "flex min-w-0 items-center gap-1.5 text-sm",
107
+ "aria-label": "Breadcrumb",
108
+ children: [
109
+ /* @__PURE__ */ j("button", {
110
+ type: "button",
111
+ onClick: () => w("catalog"),
112
+ className: "shrink-0 font-medium text-[var(--color-accent-teal)] transition-colors hover:opacity-80",
113
+ children: "Catalog"
114
+ }),
115
+ /* @__PURE__ */ j("span", {
116
+ className: "shrink-0 text-text-tertiary",
117
+ children: "/"
118
+ }),
119
+ /* @__PURE__ */ j("span", {
120
+ className: "truncate text-text-secondary",
121
+ children: W.title
98
122
  })
99
- }), /* @__PURE__ */ L("div", {
100
- className: "flex flex-col gap-4 p-6",
101
- children: [
102
- /* @__PURE__ */ L("div", {
103
- className: "flex flex-wrap items-center gap-2",
104
- children: [/* @__PURE__ */ I(a, { status: K.level }), K.skill?.name && /* @__PURE__ */ L("span", {
105
- className: "inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
123
+ ]
124
+ }), /* @__PURE__ */ M("button", {
125
+ type: "button",
126
+ onClick: () => w("catalog"),
127
+ className: "inline-flex shrink-0 items-center gap-1.5 text-sm text-text-secondary transition-colors hover:text-text-primary",
128
+ children: [/* @__PURE__ */ j(re, { className: "h-4 w-4" }), " Back to catalog"]
129
+ })]
130
+ }),
131
+ /* @__PURE__ */ M("div", {
132
+ className: "grid grid-cols-1 gap-6 lg:grid-cols-[minmax(0,1fr)_20rem]",
133
+ children: [/* @__PURE__ */ j(P, {
134
+ treatment: "plain",
135
+ className: "overflow-hidden",
136
+ children: /* @__PURE__ */ M("div", {
137
+ className: "grid grid-cols-1 sm:grid-cols-[minmax(0,15rem)_minmax(0,1fr)]",
138
+ children: [/* @__PURE__ */ j("div", {
139
+ className: "relative h-44 w-full overflow-hidden bg-bg-sunken sm:h-full",
140
+ children: W.cover?.downloadUrl ? /* @__PURE__ */ j("img", {
141
+ src: W.cover.downloadUrl,
142
+ alt: "",
143
+ className: "h-full w-full object-cover"
144
+ }) : /* @__PURE__ */ j("div", {
145
+ className: "flex h-full min-h-[11rem] w-full items-center justify-center bg-[var(--color-accent-soft)]",
146
+ children: /* @__PURE__ */ j(y, { className: "h-10 w-10 text-text-secondary opacity-60" })
147
+ })
148
+ }), /* @__PURE__ */ M("div", {
149
+ className: "flex flex-col gap-4 p-6",
150
+ children: [
151
+ /* @__PURE__ */ M("div", {
152
+ className: "flex flex-wrap items-center gap-2",
153
+ children: [/* @__PURE__ */ j(o, { status: W.level }), /* @__PURE__ */ j(o, { status: W.status })]
154
+ }),
155
+ /* @__PURE__ */ M("div", { children: [/* @__PURE__ */ j("h1", {
156
+ className: "text-2xl font-semibold tracking-tight text-text-primary",
157
+ children: W.title
158
+ }), W.summary && /* @__PURE__ */ j("p", {
159
+ className: "mt-2 text-sm text-text-secondary",
160
+ children: W.summary
161
+ })] }),
162
+ /* @__PURE__ */ M("div", {
163
+ className: "flex flex-wrap gap-2",
106
164
  children: [
107
- /* @__PURE__ */ I(M, { className: "h-3.5 w-3.5" }),
108
- " ",
109
- K.skill.name
165
+ W.skill?.name && /* @__PURE__ */ j(R, {
166
+ icon: oe,
167
+ children: W.skill.name
168
+ }),
169
+ /* @__PURE__ */ M(R, {
170
+ icon: T,
171
+ children: [
172
+ G.length,
173
+ " module",
174
+ G.length === 1 ? "" : "s",
175
+ " · ",
176
+ Z,
177
+ " lesson",
178
+ Z === 1 ? "" : "s"
179
+ ]
180
+ }),
181
+ W.estimatedHours > 0 && /* @__PURE__ */ j(R, {
182
+ icon: C,
183
+ children: a(W.estimatedHours)
184
+ })
110
185
  ]
111
- })]
186
+ }),
187
+ W.tags.length > 0 && /* @__PURE__ */ j("div", {
188
+ className: "flex flex-wrap gap-1.5",
189
+ children: W.tags.map((e) => /* @__PURE__ */ j("span", {
190
+ className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
191
+ children: e
192
+ }, e))
193
+ }),
194
+ W.description && /* @__PURE__ */ j("p", {
195
+ className: "whitespace-pre-wrap text-sm leading-relaxed text-text-secondary",
196
+ children: W.description
197
+ })
198
+ ]
199
+ })]
200
+ })
201
+ }), /* @__PURE__ */ j(P, {
202
+ treatment: "glass",
203
+ glow: !0,
204
+ className: "h-fit p-5 lg:sticky lg:top-4",
205
+ children: J ? /* @__PURE__ */ M("div", {
206
+ className: "flex flex-col gap-4",
207
+ children: [
208
+ /* @__PURE__ */ M(N, {
209
+ size: "lg",
210
+ className: "w-full",
211
+ onClick: () => w(`learning/${J.id}`),
212
+ children: [/* @__PURE__ */ j(ae, { className: "mr-2 h-4 w-4" }), " Continue learning"]
112
213
  }),
113
- /* @__PURE__ */ L("div", { children: [/* @__PURE__ */ I("h1", {
114
- className: "text-2xl font-semibold text-text-primary",
115
- children: K.title
116
- }), K.summary && /* @__PURE__ */ I("p", {
117
- className: "mt-2 text-sm text-text-secondary",
118
- children: K.summary
119
- })] }),
120
- /* @__PURE__ */ L("div", {
121
- className: "flex flex-wrap items-center gap-x-4 gap-y-2 text-xs text-text-secondary",
122
- children: [/* @__PURE__ */ L("span", {
123
- className: "inline-flex items-center gap-1",
124
- children: [
125
- /* @__PURE__ */ I(D, { className: "h-3.5 w-3.5" }),
126
- " ",
127
- q.length,
128
- " module",
129
- q.length === 1 ? "" : "s",
130
- " · ",
131
- Q,
132
- " lesson",
133
- Q === 1 ? "" : "s"
134
- ]
135
- }), K.estimatedHours > 0 && /* @__PURE__ */ L("span", {
136
- className: "inline-flex items-center gap-1",
137
- children: [
138
- /* @__PURE__ */ I(w, { className: "h-3.5 w-3.5" }),
139
- " ",
140
- i(K.estimatedHours)
141
- ]
142
- })]
214
+ /* @__PURE__ */ M("div", {
215
+ className: "flex flex-col gap-1.5",
216
+ children: [/* @__PURE__ */ M("div", {
217
+ className: "flex items-center justify-between text-sm",
218
+ children: [/* @__PURE__ */ j("span", {
219
+ className: "text-text-secondary",
220
+ children: "Your progress"
221
+ }), /* @__PURE__ */ M("span", {
222
+ className: "font-semibold tabular-nums text-text-primary",
223
+ children: [J.progressPct, "%"]
224
+ })]
225
+ }), /* @__PURE__ */ j(d, { value: J.progressPct })]
226
+ }),
227
+ /* @__PURE__ */ M("div", {
228
+ className: "flex items-center justify-between border-t border-border-seam pt-3 text-xs",
229
+ children: [/* @__PURE__ */ j("span", {
230
+ className: "text-text-secondary",
231
+ children: "Enrollment"
232
+ }), /* @__PURE__ */ j(o, { status: J.status })]
233
+ })
234
+ ]
235
+ }) : /* @__PURE__ */ M("div", {
236
+ className: "flex flex-col gap-4",
237
+ children: [
238
+ /* @__PURE__ */ M(N, {
239
+ size: "lg",
240
+ className: "w-full",
241
+ onClick: async () => {
242
+ if (!(!i || !E)) {
243
+ V(null);
244
+ try {
245
+ w(`learning/${(await z.mutateAsync({
246
+ courseId: i,
247
+ learnerId: E
248
+ })).id}`);
249
+ } catch (e) {
250
+ V(e instanceof Error ? e.message : "Could not enrol in this course.");
251
+ }
252
+ }
253
+ },
254
+ disabled: z.isPending || !E,
255
+ children: [
256
+ /* @__PURE__ */ j(ie, { className: "mr-2 h-4 w-4" }),
257
+ z.isPending ? "Enrolling…" : "Enrol in this course",
258
+ !z.isPending && /* @__PURE__ */ j(v, { className: "ml-2 h-4 w-4" })
259
+ ]
143
260
  }),
144
- K.tags.length > 0 && /* @__PURE__ */ I("div", {
145
- className: "flex flex-wrap gap-1.5",
146
- children: K.tags.map((e) => /* @__PURE__ */ I("span", {
147
- className: "rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary",
148
- children: e
149
- }, e))
261
+ !E && /* @__PURE__ */ j("p", {
262
+ className: "text-xs text-text-tertiary",
263
+ children: "Sign in to your workspace to enrol."
150
264
  }),
151
- K.description && /* @__PURE__ */ I("p", {
152
- className: "whitespace-pre-wrap text-sm leading-relaxed text-text-secondary",
153
- children: K.description
265
+ B && /* @__PURE__ */ j("p", {
266
+ className: "text-xs text-status-error-text",
267
+ children: B
154
268
  }),
155
- /* @__PURE__ */ I("div", {
156
- className: "mt-auto flex flex-col gap-2 pt-2",
157
- children: X ? /* @__PURE__ */ L(F, { children: [/* @__PURE__ */ L(R, {
158
- size: "lg",
159
- className: "w-full sm:w-auto",
160
- onClick: () => T(`learning/${X.id}`),
161
- children: [/* @__PURE__ */ I(A, { className: "mr-2 h-4 w-4" }), " Continue learning"]
162
- }), /* @__PURE__ */ L("div", {
163
- className: "flex items-center gap-2",
164
- children: [/* @__PURE__ */ I(u, {
165
- value: X.progressPct,
166
- className: "flex-1"
167
- }), /* @__PURE__ */ L("span", {
168
- className: "shrink-0 text-xs tabular-nums text-text-secondary",
169
- children: [X.progressPct, "% complete"]
170
- })]
171
- })] }) : /* @__PURE__ */ L(F, { children: [
172
- /* @__PURE__ */ L(R, {
173
- size: "lg",
174
- className: "w-full sm:w-auto",
175
- onClick: async () => {
176
- if (!(!r || !O)) {
177
- G(null);
178
- try {
179
- T(`learning/${(await U.mutateAsync({
180
- courseId: r,
181
- learnerId: O
182
- })).id}`);
183
- } catch (e) {
184
- G(e instanceof Error ? e.message : "Could not enrol in this course.");
185
- }
186
- }
187
- },
188
- disabled: U.isPending || !O,
189
- children: [/* @__PURE__ */ I(E, { className: "mr-2 h-4 w-4" }), U.isPending ? "Enrolling…" : "Enrol in this course"]
269
+ /* @__PURE__ */ M("dl", {
270
+ className: "flex flex-col gap-2.5 border-t border-border-seam pt-3 text-sm",
271
+ children: [
272
+ /* @__PURE__ */ M("div", {
273
+ className: "flex items-center justify-between",
274
+ children: [/* @__PURE__ */ M("dt", {
275
+ className: "inline-flex items-center gap-1.5 text-text-secondary",
276
+ children: [/* @__PURE__ */ j(T, { className: "h-3.5 w-3.5 text-text-tertiary" }), " Lessons"]
277
+ }), /* @__PURE__ */ j("dd", {
278
+ className: "font-medium tabular-nums text-text-primary",
279
+ children: Z
280
+ })]
190
281
  }),
191
- !O && /* @__PURE__ */ I("p", {
192
- className: "text-xs text-text-tertiary",
193
- children: "Sign in to your workspace to enrol."
282
+ W.estimatedHours > 0 && /* @__PURE__ */ M("div", {
283
+ className: "flex items-center justify-between",
284
+ children: [/* @__PURE__ */ M("dt", {
285
+ className: "inline-flex items-center gap-1.5 text-text-secondary",
286
+ children: [/* @__PURE__ */ j(C, { className: "h-3.5 w-3.5 text-text-tertiary" }), " Duration"]
287
+ }), /* @__PURE__ */ j("dd", {
288
+ className: "font-medium text-text-primary",
289
+ children: a(W.estimatedHours)
290
+ })]
194
291
  }),
195
- W && /* @__PURE__ */ I("p", {
196
- className: "text-xs text-status-error-text",
197
- children: W
292
+ /* @__PURE__ */ M("div", {
293
+ className: "flex items-center justify-between",
294
+ children: [/* @__PURE__ */ M("dt", {
295
+ className: "inline-flex items-center gap-1.5 text-text-secondary",
296
+ children: [/* @__PURE__ */ j(x, { className: "h-3.5 w-3.5 text-text-tertiary" }), " Assessments"]
297
+ }), /* @__PURE__ */ j("dd", {
298
+ className: "font-medium tabular-nums text-text-primary",
299
+ children: ce
300
+ })]
198
301
  })
199
- ] })
302
+ ]
200
303
  })
201
304
  ]
202
- })]
203
- })
204
- }),
205
- /* @__PURE__ */ I(l, {
206
- title: "Curriculum",
207
- description: "Modules and lessons in this course.",
208
- children: j.isLoading ? /* @__PURE__ */ I(c, { label: "Loading curriculum…" }) : j.isError ? /* @__PURE__ */ I(s, {
209
- title: "Couldn't load the curriculum",
210
- message: j.error instanceof Error ? j.error.message : void 0,
211
- onRetry: () => j.refetch()
212
- }) : q.length === 0 && Z.length === 0 ? /* @__PURE__ */ I(o, {
213
- illustration: "empty-data",
214
- title: "No lessons yet",
215
- description: "The instructor hasn't added any modules or lessons to this course."
216
- }) : /* @__PURE__ */ L("div", {
217
- className: "flex flex-col gap-4",
218
- children: [q.map((e, t) => {
219
- let n = e.lessons ?? [];
220
- return /* @__PURE__ */ L("div", {
221
- className: "overflow-hidden rounded-xl border border-border-seam bg-bg-surface",
222
- children: [/* @__PURE__ */ L("div", {
223
- className: "border-b border-border-seam px-4 py-3",
224
- children: [/* @__PURE__ */ L("div", {
225
- className: "flex items-baseline justify-between gap-3",
226
- children: [/* @__PURE__ */ L("h3", {
227
- className: "font-semibold text-text-primary",
228
- children: [/* @__PURE__ */ I("span", {
229
- className: "mr-2 text-text-tertiary",
230
- children: String(t + 1).padStart(2, "0")
231
- }), e.title]
232
- }), /* @__PURE__ */ L("span", {
233
- className: "shrink-0 text-xs text-text-tertiary",
234
- children: [
235
- n.length,
236
- " lesson",
237
- n.length === 1 ? "" : "s"
238
- ]
239
- })]
240
- }), e.description && /* @__PURE__ */ I("p", {
241
- className: "mt-1 text-sm text-text-secondary",
242
- children: e.description
243
- })]
244
- }), n.length === 0 ? /* @__PURE__ */ I("p", {
245
- className: "px-4 py-3 text-sm text-text-tertiary",
246
- children: "No lessons in this module yet."
247
- }) : /* @__PURE__ */ I("ul", {
248
- className: "divide-y divide-border-seam",
249
- children: n.map((e) => /* @__PURE__ */ I(H, { lesson: e }, e.id))
250
- })]
251
- }, e.id);
252
- }), Z.length > 0 && /* @__PURE__ */ L("div", {
253
- className: "overflow-hidden rounded-xl border border-border-seam bg-bg-surface",
254
- children: [/* @__PURE__ */ I("div", {
255
- className: "border-b border-border-seam px-4 py-3",
256
- children: /* @__PURE__ */ I("h3", {
257
- className: "font-semibold text-text-primary",
258
- children: "Additional lessons"
259
- })
260
- }), /* @__PURE__ */ I("ul", {
261
- className: "divide-y divide-border-seam",
262
- children: Z.map((e) => /* @__PURE__ */ I(H, { lesson: e }, e.id))
263
- })]
264
- })]
265
- })
305
+ })
306
+ })]
266
307
  }),
267
- /* @__PURE__ */ I(l, {
268
- title: "Assessments",
269
- description: "Quizzes and exams for this course.",
270
- children: N.isLoading ? /* @__PURE__ */ I(c, { label: "Loading assessments…" }) : N.isError ? /* @__PURE__ */ I(s, {
271
- title: "Couldn't load assessments",
272
- message: N.error instanceof Error ? N.error.message : void 0,
273
- onRetry: () => N.refetch()
274
- }) : J.length === 0 ? /* @__PURE__ */ I(o, {
275
- illustration: "empty-data",
276
- icon: /* @__PURE__ */ I(S, { className: "h-9 w-9" }),
277
- title: "No assessments yet",
278
- description: "This course doesn't have any quizzes or exams attached."
279
- }) : /* @__PURE__ */ I("ul", {
280
- className: "flex flex-col gap-3",
281
- children: J.map((e) => /* @__PURE__ */ L("li", {
282
- className: "flex flex-wrap items-center gap-3 rounded-xl border border-border-seam bg-bg-surface p-4",
283
- children: [
284
- /* @__PURE__ */ I("span", {
285
- className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
286
- children: /* @__PURE__ */ I(S, { className: "h-4 w-4" })
287
- }),
288
- /* @__PURE__ */ L("div", {
289
- className: "min-w-0 flex-1",
290
- children: [/* @__PURE__ */ I("p", {
291
- className: "truncate font-medium text-text-primary",
292
- children: e.title
293
- }), /* @__PURE__ */ L("div", {
294
- className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-text-secondary",
308
+ /* @__PURE__ */ M("div", {
309
+ className: "grid grid-cols-1 gap-6 lg:grid-cols-[minmax(0,1.7fr)_minmax(0,1fr)]",
310
+ children: [/* @__PURE__ */ j("div", { children: /* @__PURE__ */ j(u, {
311
+ title: "Curriculum",
312
+ description: "Modules and lessons in this course.",
313
+ action: X.length > 1 ? /* @__PURE__ */ j("button", {
314
+ type: "button",
315
+ onClick: () => {
316
+ U($ ? /* @__PURE__ */ new Set() : new Set(X.map((e) => e.id)));
317
+ },
318
+ className: "text-sm font-medium text-[var(--color-accent-teal)] transition-colors hover:opacity-80",
319
+ children: $ ? "Collapse all" : "Expand all"
320
+ }) : void 0,
321
+ children: O.isLoading ? /* @__PURE__ */ j(l, { label: "Loading curriculum…" }) : O.isError ? /* @__PURE__ */ j(c, {
322
+ title: "Couldn't load the curriculum",
323
+ message: O.error instanceof Error ? O.error.message : void 0,
324
+ onRetry: () => O.refetch()
325
+ }) : X.length === 0 ? /* @__PURE__ */ j(s, {
326
+ illustration: "empty-data",
327
+ title: "No lessons yet",
328
+ description: "The instructor hasn't added any modules or lessons to this course."
329
+ }) : /* @__PURE__ */ j("div", {
330
+ className: "flex flex-col gap-3",
331
+ children: X.map((e, n) => {
332
+ let r = Q.has(e.id), i = `curriculum-panel-${e.id}`;
333
+ return /* @__PURE__ */ M("div", {
334
+ className: t("overflow-hidden rounded-xl border bg-bg-surface transition-colors", r ? "border-[var(--color-accent-soft)]" : "border-border-seam"),
335
+ children: [/* @__PURE__ */ M("button", {
336
+ type: "button",
337
+ onClick: () => le(e.id),
338
+ "aria-expanded": r,
339
+ "aria-controls": i,
340
+ className: "flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-bg-sunken/50",
295
341
  children: [
296
- /* @__PURE__ */ L("span", { children: [
297
- "Pass ≥ ",
298
- e.passingScore,
299
- "%"
300
- ] }),
301
- /* @__PURE__ */ L("span", { children: [
302
- e.maxAttempts,
303
- " attempt",
304
- e.maxAttempts === 1 ? "" : "s"
305
- ] }),
306
- e.timeLimitMin > 0 && /* @__PURE__ */ L("span", {
307
- className: "inline-flex items-center gap-1",
308
- children: [/* @__PURE__ */ I(w, { className: "h-3.5 w-3.5" }), n(e.timeLimitMin)]
342
+ /* @__PURE__ */ j("span", {
343
+ className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-action-primary-bg text-xs font-semibold text-action-primary-text",
344
+ children: n + 1
345
+ }),
346
+ /* @__PURE__ */ M("div", {
347
+ className: "min-w-0 flex-1",
348
+ children: [/* @__PURE__ */ j("h3", {
349
+ className: "truncate font-semibold text-text-primary",
350
+ children: e.title
351
+ }), e.description && r && /* @__PURE__ */ j("p", {
352
+ className: "mt-0.5 line-clamp-2 text-sm text-text-secondary",
353
+ children: e.description
354
+ })]
355
+ }),
356
+ /* @__PURE__ */ M("span", {
357
+ className: "shrink-0 text-xs text-text-tertiary",
358
+ children: [
359
+ e.lessons.length,
360
+ " lesson",
361
+ e.lessons.length === 1 ? "" : "s"
362
+ ]
363
+ }),
364
+ /* @__PURE__ */ j(b, {
365
+ className: t("h-4 w-4 shrink-0 text-text-tertiary transition-transform", r && "rotate-180"),
366
+ "aria-hidden": !0
309
367
  })
310
368
  ]
311
- })]
312
- }),
313
- /* @__PURE__ */ L("div", {
314
- className: "flex shrink-0 items-center gap-2",
315
- children: [
316
- /* @__PURE__ */ I(a, { status: e.type }),
317
- /* @__PURE__ */ I(a, { status: e.status }),
318
- e.status === "PUBLISHED" && X && /* @__PURE__ */ I(R, {
369
+ }), r && (e.lessons.length === 0 ? /* @__PURE__ */ j("p", {
370
+ className: "border-t border-border-seam px-4 py-3 text-sm text-text-tertiary",
371
+ children: "No lessons in this module yet."
372
+ }) : /* @__PURE__ */ j("ul", {
373
+ id: i,
374
+ className: "divide-y divide-border-seam border-t border-border-seam",
375
+ children: e.lessons.map((e, t) => /* @__PURE__ */ j(L, {
376
+ lesson: e,
377
+ index: t
378
+ }, e.id))
379
+ }))]
380
+ }, e.id);
381
+ })
382
+ })
383
+ }) }), /* @__PURE__ */ M("div", {
384
+ className: "flex flex-col gap-6",
385
+ children: [/* @__PURE__ */ j("div", { children: /* @__PURE__ */ j(u, {
386
+ title: "Assessments",
387
+ description: "Quizzes and exams for this course.",
388
+ children: k.isLoading ? /* @__PURE__ */ j(l, { label: "Loading assessments…" }) : k.isError ? /* @__PURE__ */ j(c, {
389
+ title: "Couldn't load assessments",
390
+ message: k.error instanceof Error ? k.error.message : void 0,
391
+ onRetry: () => k.refetch()
392
+ }) : K.length === 0 ? /* @__PURE__ */ j(s, {
393
+ illustration: "empty-data",
394
+ icon: /* @__PURE__ */ j(x, { className: "h-9 w-9" }),
395
+ title: "No assessments yet",
396
+ description: "This course doesn't have any quizzes or exams attached."
397
+ }) : /* @__PURE__ */ j("ul", {
398
+ className: "flex flex-col gap-3",
399
+ children: K.map((e) => /* @__PURE__ */ M("li", {
400
+ className: "rounded-xl border border-border-seam bg-bg-surface p-4",
401
+ children: [/* @__PURE__ */ M("div", {
402
+ className: "flex items-start gap-3",
403
+ children: [/* @__PURE__ */ j("span", {
404
+ className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
405
+ children: /* @__PURE__ */ j(x, { className: "h-4 w-4" })
406
+ }), /* @__PURE__ */ M("div", {
407
+ className: "min-w-0 flex-1",
408
+ children: [
409
+ /* @__PURE__ */ j("p", {
410
+ className: "font-medium text-text-primary",
411
+ children: e.title
412
+ }),
413
+ /* @__PURE__ */ M("div", {
414
+ className: "mt-1.5 flex flex-wrap items-center gap-1.5",
415
+ children: [/* @__PURE__ */ j(o, { status: e.type }), /* @__PURE__ */ j(o, { status: e.status })]
416
+ }),
417
+ /* @__PURE__ */ M("div", {
418
+ className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-text-secondary",
419
+ children: [
420
+ /* @__PURE__ */ M("span", { children: [
421
+ "Pass ≥ ",
422
+ e.passingScore,
423
+ "%"
424
+ ] }),
425
+ /* @__PURE__ */ M("span", { children: [
426
+ e.maxAttempts,
427
+ " attempt",
428
+ e.maxAttempts === 1 ? "" : "s"
429
+ ] }),
430
+ e.timeLimitMin > 0 && /* @__PURE__ */ M("span", {
431
+ className: "inline-flex items-center gap-1",
432
+ children: [/* @__PURE__ */ j(C, { className: "h-3.5 w-3.5" }), r(e.timeLimitMin)]
433
+ })
434
+ ]
435
+ })
436
+ ]
437
+ })]
438
+ }), e.status === "PUBLISHED" && J && /* @__PURE__ */ j("div", {
439
+ className: "mt-3 flex justify-end",
440
+ children: /* @__PURE__ */ j(N, {
319
441
  size: "sm",
320
- onClick: () => T(`assessments/${e.id}/take`),
442
+ onClick: () => w(`assessments/${e.id}/take`),
321
443
  children: "Take"
322
444
  })
323
- ]
324
- })
325
- ]
326
- }, e.id))
327
- })
328
- }),
329
- /* @__PURE__ */ I(_, {
330
- entityType: B,
331
- entityId: r
445
+ })]
446
+ }, e.id))
447
+ })
448
+ }) }), /* @__PURE__ */ j("div", { children: /* @__PURE__ */ j(te, {
449
+ entityType: F,
450
+ entityId: i,
451
+ description: "Ask questions and discuss this course with your workspace."
452
+ }) })]
453
+ })]
332
454
  }),
333
- /* @__PURE__ */ I(g, {
334
- entityType: B,
335
- entityId: r,
336
- description: "Ask questions and discuss this course with your workspace."
337
- })
455
+ /* @__PURE__ */ j("div", { children: /* @__PURE__ */ j(ne, {
456
+ entityType: F,
457
+ entityId: i
458
+ }) })
338
459
  ]
339
460
  })
340
- }) : /* @__PURE__ */ I(t, {
461
+ }) : /* @__PURE__ */ j(n, {
341
462
  title: "Course",
342
- children: /* @__PURE__ */ I(o, {
463
+ children: /* @__PURE__ */ j(s, {
343
464
  illustration: "empty-search",
344
465
  title: "Course not found",
345
466
  description: "This course may have been unpublished or removed.",
346
- action: /* @__PURE__ */ I(R, {
347
- onClick: () => T("catalog"),
467
+ action: /* @__PURE__ */ j(N, {
468
+ onClick: () => w("catalog"),
348
469
  children: "Back to catalog"
349
470
  })
350
471
  })
351
- }) : /* @__PURE__ */ I(t, {
472
+ }) : /* @__PURE__ */ j(n, {
352
473
  title: "Course",
353
- children: /* @__PURE__ */ I(s, {
474
+ children: /* @__PURE__ */ j(c, {
354
475
  title: "Missing course",
355
476
  message: "No course was specified."
356
477
  })
357
478
  });
358
479
  };
359
480
  //#endregion
360
- export { U as CourseDetailPage };
481
+ export { z as CourseDetailPage };
361
482
 
362
483
  //# sourceMappingURL=CourseDetailPage.js.map