@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,280 +1,199 @@
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 } from "../../utils/formatters.js";
4
- import { StatusBadge as i } from "../../components/StatusBadge.js";
5
- import { EmptyState as a } from "../../components/EmptyState.js";
6
- import { ErrorView as o, LoadingView as s, Section as c } from "../../components/StateViews.js";
7
- import { Tabs as l } from "../../components/Tabs.js";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { PageLayout as n } from "../../components/PageLayout.js";
4
+ import { formatDate as r, formatDuration as i, formatEnumLabel 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 { Tabs as d } from "../../components/Tabs.js";
8
9
  import "../../context/index.js";
9
- import { useBuiArchiveCourse as u, useBuiAssessments as d, useBuiCourse as f, useBuiCreateLesson as p, useBuiCreateModule as m, useBuiModules as h, useBuiPublishCourse as g, useBuiSkills as _, useBuiUpdateCourse as v } from "../../hooks/useBuildmyiqApi.js";
10
+ import { useBuiArchiveCourse as f, useBuiAssessments as p, useBuiCourse as m, useBuiCreateLesson as h, useBuiCreateModule as g, useBuiModules as _, useBuiPublishCourse as v, useBuiSkills as y, useBuiUpdateCourse as b } from "../../hooks/useBuildmyiqApi.js";
10
11
  import "../../hooks/index.js";
11
- import { EvidenceUpload as y } from "../../components/EvidenceUpload.js";
12
- import { BuiDiscussion as b } from "../../components/BuiDiscussion.js";
12
+ import { EvidenceUpload as x } from "../../components/EvidenceUpload.js";
13
+ import { BuiDiscussion as S } from "../../components/BuiDiscussion.js";
13
14
  import "../../components/index.js";
14
- import { COURSE_LEVELS as x, LESSON_TYPES as S } from "../../types/index.js";
15
- import { Field as C, Modal as w, NO_SKILL as T, SelectField as E } from "./_forms.js";
16
- import { useState as D } from "react";
17
- import { Archive as ee, ArrowLeft as O, BookOpen as k, Clock as A, FileText as j, ListChecks as M, MessageSquare as N, PlayCircle as P, Plus as F, Send as I } from "lucide-react";
18
- import { useParams as L } from "react-router-dom";
19
- import { Fragment as R, jsx as z, jsxs as B } from "react/jsx-runtime";
20
- import { Button as V, GlassCard as H, Input as U, Switch as W, Textarea as G } from "@burdenoff/fe-libs/ui";
15
+ import { COURSE_LEVELS as C, LESSON_TYPES as w } from "../../types/index.js";
16
+ import { Field as T, Modal as E, NO_SKILL as D, SelectField as O } from "./_forms.js";
17
+ import { useState as k } from "react";
18
+ import { Archive as A, ArrowLeft as j, BarChart3 as M, BookOpen as ee, Calendar as N, ClipboardList as P, Clock as F, Eye as I, FileText as L, Globe as te, Image as ne, Link2 as re, ListChecks as R, MessageSquare as ie, MousePointerClick as ae, PlayCircle as z, Plus as B, Radio as V, Send as H } from "lucide-react";
19
+ import { useParams as U } from "react-router-dom";
20
+ import { Fragment as W, jsx as G, jsxs as K } from "react/jsx-runtime";
21
+ import { Button as q, GlassCard as J, Input as Y, Switch as X, Textarea as Z } from "@burdenoff/fe-libs/ui";
21
22
  //#region src/buildmyiq/pages/authoring/CourseBuilderPage.tsx
22
- var K = ({ course: e }) => {
23
- let t = v(), n = g(), a = u(), o = _(), s = o.data ?? [], [l, d] = D(e.title), [f, p] = D(e.summary ?? ""), [m, h] = D(e.description ?? ""), [b, S] = D(e.level), [O, k] = D(e.language), [A, j] = D(String(e.estimatedHours ?? 0)), [M, N] = D(e.skillId ?? "__none__"), [P, F] = D(e.isPublic), [L, H] = D(null), [K, q] = D(null), [J, Y] = D(null), [X, Z] = D(null), [Q, $] = D(!1), te = e.status === "DRAFT" || e.status === "IN_REVIEW", ne = e.status !== "ARCHIVED", re = async () => {
24
- q(null);
25
- let n = {
26
- title: l.trim() || e.title,
27
- summary: f.trim() || void 0,
28
- description: m.trim() || void 0,
29
- level: b,
30
- language: O.trim() || "en",
31
- estimatedHours: A.trim() ? Number(A) : 0,
32
- skillId: M === "__none__" ? void 0 : M,
33
- isPublic: P
34
- };
35
- try {
36
- await t.mutateAsync({
37
- id: e.id,
38
- input: n
39
- });
40
- } catch (e) {
41
- q(e instanceof Error ? e.message : "Failed to save changes.");
42
- }
43
- }, ie = async (n) => {
44
- if (H(n), n) {
45
- Y(null);
46
- try {
47
- await t.mutateAsync({
48
- id: e.id,
49
- input: { coverFileId: n.fileId }
50
- });
51
- } catch (e) {
52
- Y(e instanceof Error ? e.message : "Failed to update the cover.");
53
- }
54
- }
55
- }, ae = async () => {
56
- Z(null);
57
- try {
58
- await n.mutateAsync(e.id);
59
- } catch (e) {
60
- Z(e instanceof Error ? e.message : "Failed to publish the course.");
61
- }
62
- }, oe = async () => {
63
- Z(null);
64
- try {
65
- await a.mutateAsync(e.id), $(!1);
66
- } catch (e) {
67
- Z(e instanceof Error ? e.message : "Failed to archive the course.");
68
- }
69
- };
70
- return /* @__PURE__ */ B("div", {
71
- className: "grid gap-6 lg:grid-cols-3",
72
- children: [
73
- /* @__PURE__ */ z("div", {
74
- className: "lg:col-span-2",
75
- children: /* @__PURE__ */ z(c, {
76
- title: "Course details",
77
- description: "Metadata learners see in the catalog.",
78
- action: /* @__PURE__ */ z(V, {
79
- onClick: re,
80
- disabled: t.isPending,
81
- children: t.isPending ? "Saving…" : "Save changes"
82
- }),
83
- children: /* @__PURE__ */ B("div", {
84
- className: "grid gap-4",
85
- children: [
86
- /* @__PURE__ */ z(C, {
87
- label: "Title",
88
- htmlFor: "detail-title",
89
- required: !0,
90
- children: /* @__PURE__ */ z(U, {
91
- id: "detail-title",
92
- value: l,
93
- onChange: (e) => d(e.target.value)
94
- })
95
- }),
96
- /* @__PURE__ */ z(C, {
97
- label: "Summary",
98
- htmlFor: "detail-summary",
99
- children: /* @__PURE__ */ z(G, {
100
- id: "detail-summary",
101
- rows: 2,
102
- value: f,
103
- onChange: (e) => p(e.target.value),
104
- placeholder: "A short description shown on the catalog card."
105
- })
106
- }),
107
- /* @__PURE__ */ z(C, {
108
- label: "Description",
109
- htmlFor: "detail-description",
110
- children: /* @__PURE__ */ z(G, {
111
- id: "detail-description",
112
- rows: 5,
113
- value: m,
114
- onChange: (e) => h(e.target.value),
115
- placeholder: "The full course overview."
116
- })
117
- }),
118
- /* @__PURE__ */ B("div", {
119
- className: "grid gap-4 sm:grid-cols-2",
120
- children: [
121
- /* @__PURE__ */ z(C, {
122
- label: "Level",
123
- children: /* @__PURE__ */ z(E, {
124
- value: b,
125
- onChange: (e) => S(e),
126
- options: x.map((e) => ({
127
- value: e,
128
- label: r(e)
129
- }))
130
- })
131
- }),
132
- /* @__PURE__ */ z(C, {
133
- label: "Language",
134
- htmlFor: "detail-language",
135
- children: /* @__PURE__ */ z(U, {
136
- id: "detail-language",
137
- value: O,
138
- onChange: (e) => k(e.target.value),
139
- placeholder: "en"
140
- })
141
- }),
142
- /* @__PURE__ */ z(C, {
143
- label: "Estimated hours",
144
- htmlFor: "detail-hours",
145
- children: /* @__PURE__ */ z(U, {
146
- id: "detail-hours",
147
- type: "number",
148
- min: 0,
149
- value: A,
150
- onChange: (e) => j(e.target.value)
151
- })
152
- }),
153
- /* @__PURE__ */ z(C, {
154
- label: "Skill",
155
- children: /* @__PURE__ */ z(E, {
156
- value: M,
157
- onChange: N,
158
- options: [{
159
- value: T,
160
- label: o.isLoading ? "Loading…" : "No skill"
161
- }, ...s.map((e) => ({
162
- value: e.id,
163
- label: e.name
164
- }))]
165
- })
166
- })
167
- ]
168
- }),
169
- /* @__PURE__ */ B("label", {
170
- className: "inline-flex cursor-pointer items-center gap-2 text-sm text-text-secondary",
171
- children: [/* @__PURE__ */ z(W, {
172
- checked: P,
173
- onCheckedChange: F
174
- }), "Publicly visible in the catalog"]
175
- }),
176
- K && /* @__PURE__ */ z("p", {
177
- className: "text-sm text-status-error-text",
178
- children: K
179
- })
180
- ]
181
- })
182
- })
23
+ var oe = {
24
+ ARTICLE: {
25
+ icon: L,
26
+ tint: "bg-bg-sunken text-text-secondary"
27
+ },
28
+ VIDEO: {
29
+ icon: z,
30
+ tint: "bg-[var(--color-accent-soft)] text-text-primary"
31
+ },
32
+ QUIZ: {
33
+ icon: R,
34
+ tint: "bg-status-warning-bg-subtle text-status-warning-text"
35
+ },
36
+ ASSIGNMENT: {
37
+ icon: P,
38
+ tint: "bg-status-success-bg-subtle text-status-success-text"
39
+ },
40
+ INTERACTIVE: {
41
+ icon: ae,
42
+ tint: "bg-[color-mix(in_srgb,var(--color-accent-teal)_18%,transparent)] text-[var(--color-accent-teal)]"
43
+ },
44
+ LIVE_SESSION: {
45
+ icon: V,
46
+ tint: "bg-[color-mix(in_srgb,var(--color-accent-primary)_16%,transparent)] text-[var(--color-accent-primary)]"
47
+ }
48
+ }, se = ({ course: e }) => {
49
+ let t = b(), n = y(), r = n.data ?? [], [i, o] = k(e.title), [s, c] = k(e.summary ?? ""), [l, d] = k(e.description ?? ""), [f, p] = k(e.level), [m, h] = k(e.language), [g, _] = k(String(e.estimatedHours ?? 0)), [v, x] = k(e.skillId ?? "__none__"), [S, w] = k(e.isPublic), [E, A] = k(null);
50
+ return /* @__PURE__ */ G("div", {
51
+ className: "mx-auto max-w-3xl",
52
+ children: /* @__PURE__ */ G(u, {
53
+ title: "Course details",
54
+ description: "Metadata learners see in the catalog.",
55
+ action: /* @__PURE__ */ G(q, {
56
+ onClick: async () => {
57
+ A(null);
58
+ let n = {
59
+ title: i.trim() || e.title,
60
+ summary: s.trim() || void 0,
61
+ description: l.trim() || void 0,
62
+ level: f,
63
+ language: m.trim() || "en",
64
+ estimatedHours: g.trim() ? Number(g) : 0,
65
+ skillId: v === "__none__" ? void 0 : v,
66
+ isPublic: S
67
+ };
68
+ try {
69
+ await t.mutateAsync({
70
+ id: e.id,
71
+ input: n
72
+ });
73
+ } catch (e) {
74
+ A(e instanceof Error ? e.message : "Failed to save changes.");
75
+ }
76
+ },
77
+ disabled: t.isPending,
78
+ children: t.isPending ? "Saving…" : "Save changes"
183
79
  }),
184
- /* @__PURE__ */ B("div", {
185
- className: "flex flex-col gap-6",
186
- children: [/* @__PURE__ */ z(c, {
187
- title: "Cover image",
188
- children: /* @__PURE__ */ B("div", {
189
- className: "grid gap-3",
190
- children: [
191
- /* @__PURE__ */ z("div", {
192
- className: "h-36 w-full overflow-hidden rounded-xl border border-border-seam bg-bg-sunken",
193
- children: e.cover?.downloadUrl ? /* @__PURE__ */ z("img", {
194
- src: e.cover.downloadUrl,
195
- alt: "",
196
- className: "h-full w-full object-cover"
197
- }) : /* @__PURE__ */ z("div", {
198
- className: "flex h-full items-center justify-center text-sm text-text-secondary",
199
- children: "No cover yet"
200
- })
201
- }),
202
- /* @__PURE__ */ z(y, {
203
- id: "course-cover",
204
- label: "Upload cover",
205
- value: L,
206
- onChange: ie,
207
- accept: "image/*",
208
- hint: "PNG or JPG, shown on catalog cards."
209
- }),
210
- J && /* @__PURE__ */ z("p", {
211
- className: "text-xs text-status-error-text",
212
- children: J
80
+ children: /* @__PURE__ */ G(J, {
81
+ treatment: "plain",
82
+ className: "p-5",
83
+ children: /* @__PURE__ */ K("div", {
84
+ className: "grid gap-4",
85
+ children: [
86
+ /* @__PURE__ */ G(T, {
87
+ label: "Title",
88
+ htmlFor: "detail-title",
89
+ required: !0,
90
+ children: /* @__PURE__ */ G(Y, {
91
+ id: "detail-title",
92
+ value: i,
93
+ onChange: (e) => o(e.target.value)
213
94
  })
214
- ]
215
- })
216
- }), /* @__PURE__ */ z(c, {
217
- title: "Publishing",
218
- children: /* @__PURE__ */ B("div", {
219
- className: "grid gap-3",
220
- children: [
221
- /* @__PURE__ */ B("div", {
222
- className: "flex items-center gap-2 text-sm text-text-secondary",
223
- children: ["Status ", /* @__PURE__ */ z(i, { status: e.status })]
224
- }),
225
- te && /* @__PURE__ */ B(V, {
226
- onClick: ae,
227
- disabled: n.isPending,
228
- children: [/* @__PURE__ */ z(I, { className: "mr-1.5 h-4 w-4" }), n.isPending ? "Publishing…" : "Publish course"]
229
- }),
230
- ne && /* @__PURE__ */ B(V, {
231
- variant: "outline",
232
- onClick: () => $(!0),
233
- children: [/* @__PURE__ */ z(ee, { className: "mr-1.5 h-4 w-4" }), " Archive"]
234
- }),
235
- X && /* @__PURE__ */ z("p", {
236
- className: "text-sm text-status-error-text",
237
- children: X
95
+ }),
96
+ /* @__PURE__ */ G(T, {
97
+ label: "Summary",
98
+ htmlFor: "detail-summary",
99
+ children: /* @__PURE__ */ G(Z, {
100
+ id: "detail-summary",
101
+ rows: 2,
102
+ value: s,
103
+ onChange: (e) => c(e.target.value),
104
+ placeholder: "A short description shown on the catalog card."
238
105
  })
239
- ]
240
- })
241
- })]
242
- }),
243
- Q && /* @__PURE__ */ z(w, {
244
- open: !0,
245
- onClose: () => $(!1),
246
- title: "Archive this course?",
247
- description: "Archived courses are hidden from the catalog and cannot be enrolled in.",
248
- footer: /* @__PURE__ */ B(R, { children: [/* @__PURE__ */ z(V, {
249
- variant: "ghost",
250
- onClick: () => $(!1),
251
- disabled: a.isPending,
252
- children: "Cancel"
253
- }), /* @__PURE__ */ z(V, {
254
- variant: "destructive",
255
- onClick: oe,
256
- disabled: a.isPending,
257
- children: a.isPending ? "Archiving…" : "Archive course"
258
- })] }),
259
- children: /* @__PURE__ */ z("p", {
260
- className: "text-sm text-text-secondary",
261
- children: "You can still find it in Authoring under the Archived filter."
106
+ }),
107
+ /* @__PURE__ */ G(T, {
108
+ label: "Description",
109
+ htmlFor: "detail-description",
110
+ children: /* @__PURE__ */ G(Z, {
111
+ id: "detail-description",
112
+ rows: 5,
113
+ value: l,
114
+ onChange: (e) => d(e.target.value),
115
+ placeholder: "The full course overview."
116
+ })
117
+ }),
118
+ /* @__PURE__ */ K("div", {
119
+ className: "grid gap-4 sm:grid-cols-2",
120
+ children: [
121
+ /* @__PURE__ */ G(T, {
122
+ label: "Level",
123
+ children: /* @__PURE__ */ G(O, {
124
+ value: f,
125
+ onChange: (e) => p(e),
126
+ options: C.map((e) => ({
127
+ value: e,
128
+ label: a(e)
129
+ }))
130
+ })
131
+ }),
132
+ /* @__PURE__ */ G(T, {
133
+ label: "Language",
134
+ htmlFor: "detail-language",
135
+ children: /* @__PURE__ */ G(Y, {
136
+ id: "detail-language",
137
+ value: m,
138
+ onChange: (e) => h(e.target.value),
139
+ placeholder: "en"
140
+ })
141
+ }),
142
+ /* @__PURE__ */ G(T, {
143
+ label: "Estimated hours",
144
+ htmlFor: "detail-hours",
145
+ children: /* @__PURE__ */ G(Y, {
146
+ id: "detail-hours",
147
+ type: "number",
148
+ min: 0,
149
+ value: g,
150
+ onChange: (e) => _(e.target.value)
151
+ })
152
+ }),
153
+ /* @__PURE__ */ G(T, {
154
+ label: "Skill",
155
+ children: /* @__PURE__ */ G(O, {
156
+ value: v,
157
+ onChange: x,
158
+ options: [{
159
+ value: D,
160
+ label: n.isLoading ? "Loading…" : "No skill"
161
+ }, ...r.map((e) => ({
162
+ value: e.id,
163
+ label: e.name
164
+ }))]
165
+ })
166
+ })
167
+ ]
168
+ }),
169
+ /* @__PURE__ */ K("label", {
170
+ className: "inline-flex cursor-pointer items-center gap-2 text-sm text-text-secondary",
171
+ children: [/* @__PURE__ */ G(X, {
172
+ checked: S,
173
+ onCheckedChange: w
174
+ }), "Publicly visible in the catalog"]
175
+ }),
176
+ E && /* @__PURE__ */ G("p", {
177
+ className: "text-sm text-status-error-text",
178
+ children: E
179
+ })
180
+ ]
262
181
  })
263
182
  })
264
- ]
183
+ })
265
184
  });
266
- }, q = ({ courseId: e, position: t, onClose: n }) => {
267
- let r = m(), [i, a] = D(""), [o, s] = D(""), [c, l] = D(null), u = i.trim().length > 0 && !r.isPending;
268
- return /* @__PURE__ */ z(w, {
185
+ }, ce = ({ courseId: e, position: t, onClose: n }) => {
186
+ let r = g(), [i, a] = k(""), [o, s] = k(""), [c, l] = k(null), u = i.trim().length > 0 && !r.isPending;
187
+ return /* @__PURE__ */ G(E, {
269
188
  open: !0,
270
189
  onClose: n,
271
190
  title: "Add module",
272
- footer: /* @__PURE__ */ B(R, { children: [/* @__PURE__ */ z(V, {
191
+ footer: /* @__PURE__ */ K(W, { children: [/* @__PURE__ */ G(q, {
273
192
  variant: "ghost",
274
193
  onClick: n,
275
194
  disabled: r.isPending,
276
195
  children: "Cancel"
277
- }), /* @__PURE__ */ z(V, {
196
+ }), /* @__PURE__ */ G(q, {
278
197
  onClick: async () => {
279
198
  if (!u) return;
280
199
  l(null);
@@ -293,54 +212,54 @@ var K = ({ course: e }) => {
293
212
  disabled: !u,
294
213
  children: r.isPending ? "Adding…" : "Add module"
295
214
  })] }),
296
- children: /* @__PURE__ */ B("div", {
215
+ children: /* @__PURE__ */ K("div", {
297
216
  className: "grid gap-4",
298
217
  children: [
299
- /* @__PURE__ */ z(C, {
218
+ /* @__PURE__ */ G(T, {
300
219
  label: "Module title",
301
220
  htmlFor: "module-title",
302
221
  required: !0,
303
- children: /* @__PURE__ */ z(U, {
222
+ children: /* @__PURE__ */ G(Y, {
304
223
  id: "module-title",
305
224
  value: i,
306
225
  onChange: (e) => a(e.target.value),
307
226
  placeholder: "e.g. Getting started"
308
227
  })
309
228
  }),
310
- /* @__PURE__ */ z(C, {
229
+ /* @__PURE__ */ G(T, {
311
230
  label: "Description",
312
231
  htmlFor: "module-description",
313
- children: /* @__PURE__ */ z(G, {
232
+ children: /* @__PURE__ */ G(Z, {
314
233
  id: "module-description",
315
234
  rows: 3,
316
235
  value: o,
317
236
  onChange: (e) => s(e.target.value)
318
237
  })
319
238
  }),
320
- c && /* @__PURE__ */ z("p", {
239
+ c && /* @__PURE__ */ G("p", {
321
240
  className: "text-sm text-status-error-text",
322
241
  children: c
323
242
  })
324
243
  ]
325
244
  })
326
245
  });
327
- }, J = ({ courseId: e, moduleId: t, position: n, onClose: i }) => {
328
- let a = p(), [o, s] = D(""), [c, l] = D("ARTICLE"), [u, d] = D(""), [f, m] = D(""), [h, g] = D(!1), [_, v] = D(null), [b, x] = D(null), T = o.trim().length > 0 && !a.isPending;
329
- return /* @__PURE__ */ z(w, {
246
+ }, le = ({ courseId: e, moduleId: t, position: n, onClose: r }) => {
247
+ let i = h(), [o, s] = k(""), [c, l] = k("ARTICLE"), [u, d] = k(""), [f, p] = k(""), [m, g] = k(!1), [_, v] = k(null), [y, b] = k(null), S = o.trim().length > 0 && !i.isPending;
248
+ return /* @__PURE__ */ G(E, {
330
249
  open: !0,
331
- onClose: i,
250
+ onClose: r,
332
251
  title: "Add lesson",
333
252
  className: "sm:max-w-xl",
334
- footer: /* @__PURE__ */ B(R, { children: [/* @__PURE__ */ z(V, {
253
+ footer: /* @__PURE__ */ K(W, { children: [/* @__PURE__ */ G(q, {
335
254
  variant: "ghost",
336
- onClick: i,
337
- disabled: a.isPending,
255
+ onClick: r,
256
+ disabled: i.isPending,
338
257
  children: "Cancel"
339
- }), /* @__PURE__ */ z(V, {
258
+ }), /* @__PURE__ */ G(q, {
340
259
  onClick: async () => {
341
- if (!T) return;
342
- x(null);
343
- let r = {
260
+ if (!S) return;
261
+ b(null);
262
+ let a = {
344
263
  courseId: e,
345
264
  moduleId: t,
346
265
  title: o.trim(),
@@ -348,245 +267,399 @@ var K = ({ course: e }) => {
348
267
  content: u.trim() || void 0,
349
268
  durationMin: f.trim() ? Number(f) : void 0,
350
269
  position: n,
351
- isPreview: h,
270
+ isPreview: m,
352
271
  mediaFileId: _?.fileId
353
272
  };
354
273
  try {
355
- await a.mutateAsync(r), i();
274
+ await i.mutateAsync(a), r();
356
275
  } catch (e) {
357
- x(e instanceof Error ? e.message : "Failed to add the lesson.");
276
+ b(e instanceof Error ? e.message : "Failed to add the lesson.");
358
277
  }
359
278
  },
360
- disabled: !T,
361
- children: a.isPending ? "Adding…" : "Add lesson"
279
+ disabled: !S,
280
+ children: i.isPending ? "Adding…" : "Add lesson"
362
281
  })] }),
363
- children: /* @__PURE__ */ B("div", {
282
+ children: /* @__PURE__ */ K("div", {
364
283
  className: "grid gap-4",
365
284
  children: [
366
- /* @__PURE__ */ z(C, {
285
+ /* @__PURE__ */ G(T, {
367
286
  label: "Lesson title",
368
287
  htmlFor: "lesson-title",
369
288
  required: !0,
370
- children: /* @__PURE__ */ z(U, {
289
+ children: /* @__PURE__ */ G(Y, {
371
290
  id: "lesson-title",
372
291
  value: o,
373
292
  onChange: (e) => s(e.target.value),
374
293
  placeholder: "e.g. What is data literacy?"
375
294
  })
376
295
  }),
377
- /* @__PURE__ */ B("div", {
296
+ /* @__PURE__ */ K("div", {
378
297
  className: "grid gap-4 sm:grid-cols-2",
379
- children: [/* @__PURE__ */ z(C, {
298
+ children: [/* @__PURE__ */ G(T, {
380
299
  label: "Type",
381
- children: /* @__PURE__ */ z(E, {
300
+ children: /* @__PURE__ */ G(O, {
382
301
  value: c,
383
302
  onChange: (e) => l(e),
384
- options: S.map((e) => ({
303
+ options: w.map((e) => ({
385
304
  value: e,
386
- label: r(e)
305
+ label: a(e)
387
306
  }))
388
307
  })
389
- }), /* @__PURE__ */ z(C, {
308
+ }), /* @__PURE__ */ G(T, {
390
309
  label: "Duration (minutes)",
391
310
  htmlFor: "lesson-duration",
392
- children: /* @__PURE__ */ z(U, {
311
+ children: /* @__PURE__ */ G(Y, {
393
312
  id: "lesson-duration",
394
313
  type: "number",
395
314
  min: 0,
396
315
  value: f,
397
- onChange: (e) => m(e.target.value),
316
+ onChange: (e) => p(e.target.value),
398
317
  placeholder: "0"
399
318
  })
400
319
  })]
401
320
  }),
402
- /* @__PURE__ */ z(C, {
321
+ /* @__PURE__ */ G(T, {
403
322
  label: "Content",
404
323
  htmlFor: "lesson-content",
405
324
  hint: "Lesson body — markdown or plain text.",
406
- children: /* @__PURE__ */ z(G, {
325
+ children: /* @__PURE__ */ G(Z, {
407
326
  id: "lesson-content",
408
327
  rows: 5,
409
328
  value: u,
410
329
  onChange: (e) => d(e.target.value)
411
330
  })
412
331
  }),
413
- /* @__PURE__ */ z(y, {
332
+ /* @__PURE__ */ G(x, {
414
333
  id: "lesson-media",
415
334
  label: "Media (optional)",
416
335
  value: _,
417
336
  onChange: v,
418
337
  hint: "Attach a video, audio file or PDF for this lesson."
419
338
  }),
420
- /* @__PURE__ */ B("label", {
339
+ /* @__PURE__ */ K("label", {
421
340
  className: "inline-flex cursor-pointer items-center gap-2 text-sm text-text-secondary",
422
- children: [/* @__PURE__ */ z(W, {
423
- checked: h,
341
+ children: [/* @__PURE__ */ G(X, {
342
+ checked: m,
424
343
  onCheckedChange: g
425
344
  }), "Free preview lesson"]
426
345
  }),
427
- b && /* @__PURE__ */ z("p", {
346
+ y && /* @__PURE__ */ G("p", {
428
347
  className: "text-sm text-status-error-text",
429
- children: b
348
+ children: y
430
349
  })
431
350
  ]
432
351
  })
433
352
  });
434
- }, Y = ({ module: e, index: t, onAddLesson: i }) => {
435
- let a = [...e.lessons ?? []].sort((e, t) => e.position - t.position);
436
- return /* @__PURE__ */ B(H, {
437
- treatment: "plain",
438
- className: "p-4",
439
- children: [/* @__PURE__ */ B("div", {
440
- className: "flex flex-wrap items-start justify-between gap-3",
441
- children: [/* @__PURE__ */ B("div", {
442
- className: "min-w-0",
443
- children: [/* @__PURE__ */ B("h3", {
444
- className: "font-semibold text-text-primary",
445
- children: [/* @__PURE__ */ B("span", {
446
- className: "mr-2 text-text-tertiary",
447
- children: ["Module ", t + 1]
448
- }), e.title]
449
- }), e.description && /* @__PURE__ */ z("p", {
450
- className: "mt-0.5 text-sm text-text-secondary",
451
- children: e.description
353
+ }, ue = ({ lesson: e }) => {
354
+ let n = oe[e.type], r = n.icon;
355
+ return /* @__PURE__ */ K("li", {
356
+ className: "flex items-center gap-3 rounded-lg border border-border-seam bg-bg-surface px-3 py-2.5",
357
+ children: [
358
+ /* @__PURE__ */ G("span", {
359
+ className: t("flex h-8 w-8 shrink-0 items-center justify-center rounded-lg", n.tint),
360
+ "aria-hidden": "true",
361
+ children: /* @__PURE__ */ G(r, { className: "h-4 w-4" })
362
+ }),
363
+ /* @__PURE__ */ K("div", {
364
+ className: "min-w-0 flex-1",
365
+ children: [/* @__PURE__ */ G("p", {
366
+ className: "truncate text-sm font-medium text-text-primary",
367
+ children: e.title
368
+ }), /* @__PURE__ */ G("p", {
369
+ className: "text-xs text-text-tertiary",
370
+ children: a(e.type)
452
371
  })]
453
- }), /* @__PURE__ */ B(V, {
454
- variant: "outline",
455
- size: "sm",
456
- onClick: i,
457
- children: [/* @__PURE__ */ z(F, { className: "mr-1.5 h-4 w-4" }), " Add lesson"]
458
- })]
459
- }), /* @__PURE__ */ z("div", {
460
- className: "mt-3",
461
- children: a.length === 0 ? /* @__PURE__ */ z("p", {
462
- className: "rounded-lg border border-dashed border-border-seam px-3 py-3 text-sm text-text-secondary",
463
- children: "No lessons yet."
464
- }) : /* @__PURE__ */ z("ul", {
465
- className: "flex flex-col gap-1.5",
466
- children: a.map((e) => /* @__PURE__ */ B("li", {
467
- className: "flex flex-wrap items-center gap-3 rounded-lg border border-border-seam bg-bg-surface px-3 py-2",
468
- children: [
469
- /* @__PURE__ */ z(P, { className: "h-4 w-4 shrink-0 text-text-tertiary" }),
470
- /* @__PURE__ */ z("span", {
471
- className: "min-w-0 flex-1 truncate text-sm text-text-primary",
472
- children: e.title
473
- }),
474
- /* @__PURE__ */ z("span", {
475
- className: "rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary",
476
- children: r(e.type)
477
- }),
478
- e.isPreview && /* @__PURE__ */ z("span", {
479
- className: "rounded-full bg-[var(--color-accent-soft)] px-2 py-0.5 text-xs text-text-primary",
480
- children: "Preview"
481
- }),
482
- e.durationMin > 0 && /* @__PURE__ */ B("span", {
483
- className: "inline-flex items-center gap-1 text-xs text-text-secondary",
372
+ }),
373
+ e.durationMin > 0 && /* @__PURE__ */ K("span", {
374
+ className: "inline-flex shrink-0 items-center gap-1 text-xs text-text-secondary",
375
+ children: [
376
+ /* @__PURE__ */ G(F, { className: "h-3.5 w-3.5" }),
377
+ " ",
378
+ i(e.durationMin)
379
+ ]
380
+ }),
381
+ e.isPreview && /* @__PURE__ */ G("span", {
382
+ className: "shrink-0 rounded-full bg-[var(--color-accent-soft)] px-2 py-0.5 text-xs font-medium text-text-primary",
383
+ children: "Preview"
384
+ })
385
+ ]
386
+ });
387
+ }, Q = ({ module: e, index: t, onAddLesson: n }) => {
388
+ let r = [...e.lessons ?? []].sort((e, t) => e.position - t.position), a = r.reduce((e, t) => e + (t.durationMin || 0), 0);
389
+ return /* @__PURE__ */ K(J, {
390
+ treatment: "plain",
391
+ className: "overflow-hidden",
392
+ children: [
393
+ /* @__PURE__ */ K("div", {
394
+ className: "flex flex-wrap items-center gap-3 border-b border-border-seam bg-bg-sunken/40 px-4 py-3",
395
+ children: [
396
+ /* @__PURE__ */ G("span", {
397
+ className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-action-primary-bg text-sm font-semibold tabular-nums text-action-primary-text",
398
+ "aria-hidden": "true",
399
+ children: t + 1
400
+ }),
401
+ /* @__PURE__ */ K("div", {
402
+ className: "min-w-0 flex-1",
403
+ children: [/* @__PURE__ */ K("h3", {
404
+ className: "truncate font-semibold text-text-primary",
405
+ children: [/* @__PURE__ */ K("span", {
406
+ className: "text-text-tertiary",
407
+ children: [
408
+ "Module ",
409
+ t + 1,
410
+ " · "
411
+ ]
412
+ }), e.title]
413
+ }), /* @__PURE__ */ K("p", {
414
+ className: "text-xs text-text-secondary",
484
415
  children: [
485
- /* @__PURE__ */ z(A, { className: "h-3.5 w-3.5" }),
416
+ r.length,
486
417
  " ",
487
- n(e.durationMin)
418
+ r.length === 1 ? "lesson" : "lessons",
419
+ a > 0 && ` · ${i(a)}`
488
420
  ]
489
- })
490
- ]
491
- }, e.id))
421
+ })]
422
+ }),
423
+ /* @__PURE__ */ K(q, {
424
+ variant: "outline",
425
+ size: "sm",
426
+ onClick: n,
427
+ className: "shrink-0",
428
+ children: [/* @__PURE__ */ G(B, { className: "mr-1.5 h-4 w-4" }), " Add lesson"]
429
+ })
430
+ ]
431
+ }),
432
+ e.description && /* @__PURE__ */ G("p", {
433
+ className: "border-b border-border-seam px-4 py-2.5 text-sm text-text-secondary",
434
+ children: e.description
435
+ }),
436
+ /* @__PURE__ */ G("div", {
437
+ className: "p-3",
438
+ children: r.length === 0 ? /* @__PURE__ */ K("button", {
439
+ type: "button",
440
+ onClick: n,
441
+ className: "flex w-full items-center justify-center gap-2 rounded-lg border border-dashed border-border-seam px-3 py-3 text-sm text-text-secondary transition-colors hover:border-[var(--color-action-primary-bg)] hover:text-text-primary",
442
+ children: [/* @__PURE__ */ G(B, { className: "h-4 w-4" }), " Add the first lesson"]
443
+ }) : /* @__PURE__ */ G("ul", {
444
+ className: "flex flex-col gap-2",
445
+ children: r.map((e) => /* @__PURE__ */ G(ue, { lesson: e }, e.id))
446
+ })
492
447
  })
493
- })]
448
+ ]
494
449
  });
495
- }, X = ({ courseId: e }) => {
496
- let t = h(e), [n, r] = D(!1), [i, l] = D(null), u = t.data ?? [], d = u.find((e) => e.id === i) ?? null;
497
- return /* @__PURE__ */ B(c, {
498
- title: "Curriculum",
499
- description: "Organise the course into modules and lessons.",
500
- action: /* @__PURE__ */ B(V, {
501
- onClick: () => r(!0),
502
- children: [/* @__PURE__ */ z(F, { className: "mr-1.5 h-4 w-4" }), " Add module"]
450
+ }, $ = ({ icon: e, label: t, value: n }) => /* @__PURE__ */ K("div", {
451
+ className: "flex items-center gap-3 py-2.5",
452
+ children: [
453
+ /* @__PURE__ */ G("span", {
454
+ className: "shrink-0 text-text-tertiary",
455
+ "aria-hidden": "true",
456
+ children: e
503
457
  }),
458
+ /* @__PURE__ */ G("span", {
459
+ className: "text-sm text-text-secondary",
460
+ children: t
461
+ }),
462
+ /* @__PURE__ */ G("span", {
463
+ className: "ml-auto min-w-0 truncate text-right text-sm font-medium text-text-primary",
464
+ children: n
465
+ })
466
+ ]
467
+ }), de = ({ course: e }) => {
468
+ let t = e.id, n = _(t), i = b(), [o, d] = k(!1), [f, p] = k(null), [m, h] = k(null), [g, v] = k(null), y = [...n.data ?? []].sort((e, t) => e.position - t.position), S = y.find((e) => e.id === f) ?? null;
469
+ return /* @__PURE__ */ K("div", {
470
+ className: "grid gap-6 lg:grid-cols-3",
504
471
  children: [
505
- t.isLoading ? /* @__PURE__ */ z(s, { label: "Loading curriculum…" }) : t.isError ? /* @__PURE__ */ z(o, {
506
- message: "We couldn't load the curriculum.",
507
- onRetry: () => t.refetch()
508
- }) : u.length === 0 ? /* @__PURE__ */ z(a, {
509
- illustration: "onboarding",
510
- title: "No modules yet",
511
- description: "Add your first module, then fill it with lessons.",
512
- action: /* @__PURE__ */ B(V, {
513
- onClick: () => r(!0),
514
- children: [/* @__PURE__ */ z(F, { className: "mr-1.5 h-4 w-4" }), " Add module"]
472
+ /* @__PURE__ */ G("div", {
473
+ className: "lg:col-span-2",
474
+ children: /* @__PURE__ */ G(u, {
475
+ title: "Curriculum",
476
+ description: "Organise the course into modules and lessons.",
477
+ action: /* @__PURE__ */ K(q, {
478
+ onClick: () => d(!0),
479
+ children: [/* @__PURE__ */ G(B, { className: "mr-1.5 h-4 w-4" }), " Add module"]
480
+ }),
481
+ children: n.isLoading ? /* @__PURE__ */ G(l, { label: "Loading curriculum…" }) : n.isError ? /* @__PURE__ */ G(c, {
482
+ message: "We couldn't load the curriculum.",
483
+ onRetry: () => n.refetch()
484
+ }) : y.length === 0 ? /* @__PURE__ */ G(s, {
485
+ illustration: "onboarding",
486
+ title: "No modules yet",
487
+ description: "Add your first module, then fill it with lessons.",
488
+ action: /* @__PURE__ */ K(q, {
489
+ onClick: () => d(!0),
490
+ children: [/* @__PURE__ */ G(B, { className: "mr-1.5 h-4 w-4" }), " Add module"]
491
+ })
492
+ }) : /* @__PURE__ */ K("div", {
493
+ className: "flex flex-col gap-4",
494
+ children: [y.map((e, t) => /* @__PURE__ */ G(Q, {
495
+ module: e,
496
+ index: t,
497
+ onAddLesson: () => p(e.id)
498
+ }, e.id)), /* @__PURE__ */ K("button", {
499
+ type: "button",
500
+ onClick: () => d(!0),
501
+ className: "flex w-full items-center justify-center gap-2 rounded-xl border-2 border-dashed border-border-seam px-4 py-4 text-sm font-medium text-text-secondary transition-colors hover:border-[var(--color-action-primary-bg)] hover:bg-bg-sunken/40 hover:text-text-primary",
502
+ children: [/* @__PURE__ */ G(B, { className: "h-4 w-4" }), " Add module"]
503
+ })]
504
+ })
515
505
  })
516
- }) : /* @__PURE__ */ z("div", {
517
- className: "flex flex-col gap-4",
518
- children: [...u].sort((e, t) => e.position - t.position).map((e, t) => /* @__PURE__ */ z(Y, {
519
- module: e,
520
- index: t,
521
- onAddLesson: () => l(e.id)
522
- }, e.id))
523
506
  }),
524
- n && /* @__PURE__ */ z(q, {
525
- courseId: e,
526
- position: u.length,
527
- onClose: () => r(!1)
507
+ /* @__PURE__ */ K("div", {
508
+ className: "flex flex-col gap-6",
509
+ children: [/* @__PURE__ */ K(J, {
510
+ treatment: "plain",
511
+ className: "p-5",
512
+ children: [
513
+ /* @__PURE__ */ G("h3", {
514
+ className: "text-base font-semibold text-text-primary",
515
+ children: "Course cover"
516
+ }),
517
+ /* @__PURE__ */ G("p", {
518
+ className: "mt-0.5 text-sm text-text-secondary",
519
+ children: "Upload an image to represent your course."
520
+ }),
521
+ /* @__PURE__ */ G("div", {
522
+ className: "mt-3 aspect-video w-full overflow-hidden rounded-xl border border-border-seam bg-bg-sunken",
523
+ children: e.cover?.downloadUrl ? /* @__PURE__ */ G("img", {
524
+ src: e.cover.downloadUrl,
525
+ alt: "",
526
+ className: "h-full w-full object-cover"
527
+ }) : /* @__PURE__ */ K("div", {
528
+ className: "flex h-full items-center justify-center gap-2 text-sm text-text-tertiary",
529
+ children: [/* @__PURE__ */ G(ne, { className: "h-5 w-5" }), " No cover yet"]
530
+ })
531
+ }),
532
+ /* @__PURE__ */ K("div", {
533
+ className: "mt-3",
534
+ children: [/* @__PURE__ */ G(x, {
535
+ id: "course-cover",
536
+ label: e.cover?.downloadUrl ? "Replace cover" : "Upload cover",
537
+ value: m,
538
+ onChange: async (e) => {
539
+ if (h(e), e) {
540
+ v(null);
541
+ try {
542
+ await i.mutateAsync({
543
+ id: t,
544
+ input: { coverFileId: e.fileId }
545
+ });
546
+ } catch (e) {
547
+ v(e instanceof Error ? e.message : "Failed to update the cover.");
548
+ }
549
+ }
550
+ },
551
+ accept: "image/*",
552
+ hint: "PNG or JPG · 16:9 ratio recommended."
553
+ }), g && /* @__PURE__ */ G("p", {
554
+ className: "mt-1 text-xs text-status-error-text",
555
+ children: g
556
+ })]
557
+ })
558
+ ]
559
+ }), /* @__PURE__ */ K(J, {
560
+ treatment: "plain",
561
+ className: "p-5",
562
+ children: [/* @__PURE__ */ G("h3", {
563
+ className: "text-base font-semibold text-text-primary",
564
+ children: "Course details"
565
+ }), /* @__PURE__ */ K("dl", {
566
+ className: "mt-2 flex flex-col divide-y divide-border-seam",
567
+ children: [
568
+ /* @__PURE__ */ G($, {
569
+ icon: /* @__PURE__ */ G(re, { className: "h-4 w-4" }),
570
+ label: "Slug",
571
+ value: e.slug
572
+ }),
573
+ /* @__PURE__ */ G($, {
574
+ icon: /* @__PURE__ */ G(te, { className: "h-4 w-4" }),
575
+ label: "Language",
576
+ value: e.language ? e.language.toUpperCase() : "—"
577
+ }),
578
+ /* @__PURE__ */ G($, {
579
+ icon: /* @__PURE__ */ G(M, { className: "h-4 w-4" }),
580
+ label: "Level",
581
+ value: a(e.level)
582
+ }),
583
+ /* @__PURE__ */ G($, {
584
+ icon: /* @__PURE__ */ G(I, { className: "h-4 w-4" }),
585
+ label: "Visibility",
586
+ value: e.isPublic ? "Public" : "Private"
587
+ }),
588
+ /* @__PURE__ */ G($, {
589
+ icon: /* @__PURE__ */ G(N, { className: "h-4 w-4" }),
590
+ label: "Created",
591
+ value: r(e.createdAt)
592
+ })
593
+ ]
594
+ })]
595
+ })]
596
+ }),
597
+ o && /* @__PURE__ */ G(ce, {
598
+ courseId: t,
599
+ position: y.length,
600
+ onClose: () => d(!1)
528
601
  }),
529
- i && /* @__PURE__ */ z(J, {
530
- courseId: e,
531
- moduleId: i,
532
- position: d?.lessons?.length ?? 0,
533
- onClose: () => l(null)
602
+ f && /* @__PURE__ */ G(le, {
603
+ courseId: t,
604
+ moduleId: f,
605
+ position: S?.lessons?.length ?? 0,
606
+ onClose: () => p(null)
534
607
  })
535
608
  ]
536
609
  });
537
- }, Z = ({ courseId: t }) => {
538
- let { navigateTo: l } = e(), u = d(t), f = u.data ?? [];
539
- return /* @__PURE__ */ z(c, {
610
+ }, fe = ({ courseId: t }) => {
611
+ let { navigateTo: n } = e(), r = p(t), d = r.data ?? [];
612
+ return /* @__PURE__ */ G(u, {
540
613
  title: "Assessments",
541
614
  description: "Quizzes, exams and assignments attached to this course.",
542
- children: u.isLoading ? /* @__PURE__ */ z(s, { label: "Loading assessments…" }) : u.isError ? /* @__PURE__ */ z(o, {
615
+ children: r.isLoading ? /* @__PURE__ */ G(l, { label: "Loading assessments…" }) : r.isError ? /* @__PURE__ */ G(c, {
543
616
  message: "We couldn't load the assessments.",
544
- onRetry: () => u.refetch()
545
- }) : f.length === 0 ? /* @__PURE__ */ z(a, {
617
+ onRetry: () => r.refetch()
618
+ }) : d.length === 0 ? /* @__PURE__ */ G(s, {
546
619
  illustration: "empty-data",
547
620
  title: "No assessments yet",
548
621
  description: "Create an assessment in the Assessments workspace to test learners on this course.",
549
- action: /* @__PURE__ */ z(V, {
622
+ action: /* @__PURE__ */ G(q, {
550
623
  variant: "outline",
551
- onClick: () => l("assessments"),
624
+ onClick: () => n("assessments"),
552
625
  children: "Open assessments"
553
626
  })
554
- }) : /* @__PURE__ */ z("div", {
627
+ }) : /* @__PURE__ */ G("div", {
555
628
  className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
556
- children: f.map((e) => /* @__PURE__ */ B(H, {
629
+ children: d.map((e) => /* @__PURE__ */ K(J, {
557
630
  treatment: "plain",
558
631
  className: "flex cursor-pointer flex-col gap-2 p-4 transition-shadow hover:shadow-lg",
559
- onClick: () => l(`assessments/${e.id}`),
632
+ onClick: () => n(`assessments/${e.id}`),
560
633
  children: [
561
- /* @__PURE__ */ B("div", {
634
+ /* @__PURE__ */ K("div", {
562
635
  className: "flex items-start justify-between gap-2",
563
- children: [/* @__PURE__ */ z("h3", {
636
+ children: [/* @__PURE__ */ G("h3", {
564
637
  className: "min-w-0 font-semibold text-text-primary",
565
638
  children: e.title
566
- }), /* @__PURE__ */ z(i, { status: e.status })]
639
+ }), /* @__PURE__ */ G(o, { status: e.status })]
567
640
  }),
568
- e.description && /* @__PURE__ */ z("p", {
641
+ e.description && /* @__PURE__ */ G("p", {
569
642
  className: "line-clamp-2 text-sm text-text-secondary",
570
643
  children: e.description
571
644
  }),
572
- /* @__PURE__ */ B("div", {
645
+ /* @__PURE__ */ K("div", {
573
646
  className: "mt-auto flex flex-wrap items-center gap-3 pt-1 text-xs text-text-secondary",
574
647
  children: [
575
- /* @__PURE__ */ z("span", {
648
+ /* @__PURE__ */ G("span", {
576
649
  className: "rounded-full bg-bg-sunken px-2 py-0.5",
577
- children: r(e.type)
650
+ children: a(e.type)
578
651
  }),
579
- /* @__PURE__ */ B("span", { children: [
652
+ /* @__PURE__ */ K("span", { children: [
580
653
  "Pass ≥ ",
581
654
  e.passingScore ?? 0,
582
655
  "%"
583
656
  ] }),
584
- e.timeLimitMin > 0 && /* @__PURE__ */ B("span", {
657
+ e.timeLimitMin > 0 && /* @__PURE__ */ K("span", {
585
658
  className: "inline-flex items-center gap-1",
586
659
  children: [
587
- /* @__PURE__ */ z(A, { className: "h-3.5 w-3.5" }),
660
+ /* @__PURE__ */ G(F, { className: "h-3.5 w-3.5" }),
588
661
  " ",
589
- n(e.timeLimitMin)
662
+ i(e.timeLimitMin)
590
663
  ]
591
664
  })
592
665
  ]
@@ -595,86 +668,146 @@ var K = ({ course: e }) => {
595
668
  }, e.id))
596
669
  })
597
670
  });
598
- }, Q = () => {
599
- let { courseId: n } = L(), { navigateTo: r } = e(), [c, u] = D("details"), d = f(n), p = d.data ?? null;
600
- if (d.isLoading) return /* @__PURE__ */ z(t, {
671
+ }, pe = () => {
672
+ let { courseId: t } = U(), { navigateTo: r } = e(), [i, a] = k("details"), u = m(t), p = u.data ?? null, h = v(), g = f(), [_, y] = k(null), [b, x] = k(!1), C = async () => {
673
+ if (p) {
674
+ y(null);
675
+ try {
676
+ await h.mutateAsync(p.id);
677
+ } catch (e) {
678
+ y(e instanceof Error ? e.message : "Failed to publish the course.");
679
+ }
680
+ }
681
+ }, w = async () => {
682
+ if (p) {
683
+ y(null);
684
+ try {
685
+ await g.mutateAsync(p.id), x(!1);
686
+ } catch (e) {
687
+ y(e instanceof Error ? e.message : "Failed to archive the course.");
688
+ }
689
+ }
690
+ };
691
+ if (u.isLoading) return /* @__PURE__ */ G(n, {
601
692
  title: "Course builder",
602
- children: /* @__PURE__ */ z(s, { label: "Loading course…" })
693
+ children: /* @__PURE__ */ G(l, { label: "Loading course…" })
603
694
  });
604
- if (d.isError) return /* @__PURE__ */ z(t, {
695
+ if (u.isError) return /* @__PURE__ */ G(n, {
605
696
  title: "Course builder",
606
- children: /* @__PURE__ */ z(o, {
697
+ children: /* @__PURE__ */ G(c, {
607
698
  message: "We couldn't load this course.",
608
- onRetry: () => d.refetch()
699
+ onRetry: () => u.refetch()
609
700
  })
610
701
  });
611
- if (!n || !p) return /* @__PURE__ */ z(t, {
702
+ if (!t || !p) return /* @__PURE__ */ G(n, {
612
703
  title: "Course builder",
613
- children: /* @__PURE__ */ z(a, {
704
+ children: /* @__PURE__ */ G(s, {
614
705
  illustration: "empty-search",
615
706
  title: "Course not found",
616
707
  description: "This course may have been archived or removed.",
617
- action: /* @__PURE__ */ z(V, {
708
+ action: /* @__PURE__ */ G(q, {
618
709
  onClick: () => r("authoring"),
619
710
  children: "Back to authoring"
620
711
  })
621
712
  })
622
713
  });
623
- let m = [
714
+ let T = p.status === "DRAFT" || p.status === "IN_REVIEW", D = p.status !== "ARCHIVED", O = [
624
715
  {
625
716
  value: "details",
626
717
  label: "Details",
627
- icon: /* @__PURE__ */ z(j, { className: "h-4 w-4" })
718
+ icon: /* @__PURE__ */ G(L, { className: "h-4 w-4" })
628
719
  },
629
720
  {
630
721
  value: "curriculum",
631
722
  label: "Curriculum",
632
- icon: /* @__PURE__ */ z(k, { className: "h-4 w-4" }),
723
+ icon: /* @__PURE__ */ G(ee, { className: "h-4 w-4" }),
633
724
  count: p.modules?.length ?? 0
634
725
  },
635
726
  {
636
727
  value: "assessments",
637
728
  label: "Assessments",
638
- icon: /* @__PURE__ */ z(M, { className: "h-4 w-4" })
729
+ icon: /* @__PURE__ */ G(R, { className: "h-4 w-4" })
639
730
  },
640
731
  {
641
732
  value: "discussion",
642
733
  label: "Discussion",
643
- icon: /* @__PURE__ */ z(N, { className: "h-4 w-4" })
734
+ icon: /* @__PURE__ */ G(ie, { className: "h-4 w-4" })
644
735
  }
645
736
  ];
646
- return /* @__PURE__ */ z(t, {
647
- title: p.title,
648
- description: p.summary ?? void 0,
649
- actions: /* @__PURE__ */ B(V, {
650
- variant: "ghost",
651
- onClick: () => r("authoring"),
652
- children: [/* @__PURE__ */ z(O, { className: "mr-1.5 h-4 w-4" }), " Back"]
737
+ return /* @__PURE__ */ K(n, {
738
+ title: /* @__PURE__ */ K("span", {
739
+ className: "flex flex-wrap items-center gap-3",
740
+ children: [
741
+ /* @__PURE__ */ G("span", {
742
+ className: "min-w-0",
743
+ children: p.title
744
+ }),
745
+ /* @__PURE__ */ G(o, { status: p.status }),
746
+ /* @__PURE__ */ G(o, { status: p.level })
747
+ ]
653
748
  }),
654
- children: /* @__PURE__ */ B("div", {
749
+ description: p.summary ?? void 0,
750
+ actions: /* @__PURE__ */ K(W, { children: [
751
+ /* @__PURE__ */ K(q, {
752
+ variant: "ghost",
753
+ onClick: () => r("authoring"),
754
+ children: [/* @__PURE__ */ G(j, { className: "mr-1.5 h-4 w-4" }), " Back"]
755
+ }),
756
+ D && /* @__PURE__ */ K(q, {
757
+ variant: "outline",
758
+ onClick: () => x(!0),
759
+ children: [/* @__PURE__ */ G(A, { className: "mr-1.5 h-4 w-4" }), " Archive"]
760
+ }),
761
+ T && /* @__PURE__ */ K(q, {
762
+ onClick: C,
763
+ disabled: h.isPending,
764
+ children: [/* @__PURE__ */ G(H, { className: "mr-1.5 h-4 w-4" }), h.isPending ? "Publishing…" : "Publish"]
765
+ })
766
+ ] }),
767
+ children: [/* @__PURE__ */ K("div", {
655
768
  className: "flex flex-col gap-5",
656
769
  children: [
657
- /* @__PURE__ */ B("div", {
658
- className: "flex flex-wrap items-center gap-2",
659
- children: [/* @__PURE__ */ z(i, { status: p.status }), /* @__PURE__ */ z(i, { status: p.level })]
770
+ _ && /* @__PURE__ */ G("p", {
771
+ className: "rounded-lg border border-status-error-bg-subtle bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
772
+ children: _
660
773
  }),
661
- /* @__PURE__ */ z(l, {
662
- items: m,
663
- value: c,
664
- onChange: u
774
+ /* @__PURE__ */ G(d, {
775
+ items: O,
776
+ value: i,
777
+ onChange: a
665
778
  }),
666
- c === "details" && /* @__PURE__ */ z(K, { course: p }, p.id),
667
- c === "curriculum" && /* @__PURE__ */ z(X, { courseId: n }),
668
- c === "assessments" && /* @__PURE__ */ z(Z, { courseId: n }),
669
- c === "discussion" && /* @__PURE__ */ z(b, {
779
+ i === "details" && /* @__PURE__ */ G(se, { course: p }, p.id),
780
+ i === "curriculum" && /* @__PURE__ */ G(de, { course: p }),
781
+ i === "assessments" && /* @__PURE__ */ G(fe, { courseId: t }),
782
+ i === "discussion" && /* @__PURE__ */ G(S, {
670
783
  entityType: "buildmyiq-course",
671
- entityId: n
784
+ entityId: t
672
785
  })
673
786
  ]
674
- })
787
+ }), b && /* @__PURE__ */ G(E, {
788
+ open: !0,
789
+ onClose: () => x(!1),
790
+ title: "Archive this course?",
791
+ description: "Archived courses are hidden from the catalog and cannot be enrolled in.",
792
+ footer: /* @__PURE__ */ K(W, { children: [/* @__PURE__ */ G(q, {
793
+ variant: "ghost",
794
+ onClick: () => x(!1),
795
+ disabled: g.isPending,
796
+ children: "Cancel"
797
+ }), /* @__PURE__ */ G(q, {
798
+ variant: "destructive",
799
+ onClick: w,
800
+ disabled: g.isPending,
801
+ children: g.isPending ? "Archiving…" : "Archive course"
802
+ })] }),
803
+ children: /* @__PURE__ */ G("p", {
804
+ className: "text-sm text-text-secondary",
805
+ children: "You can still find it in Authoring under the Archived filter."
806
+ })
807
+ })]
675
808
  });
676
809
  };
677
810
  //#endregion
678
- export { Q as CourseBuilderPage };
811
+ export { pe as CourseBuilderPage };
679
812
 
680
813
  //# sourceMappingURL=CourseBuilderPage.js.map