@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,21 +1,22 @@
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 ee, LoadingView as te } from "../../components/StateViews.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 } from "../../utils/formatters.js";
5
+ import { StatusBadge as a } from "../../components/StatusBadge.js";
6
+ import { EmptyState as o } from "../../components/EmptyState.js";
7
+ import { ErrorView as ee, LoadingView as te, Section as ne } from "../../components/StateViews.js";
7
8
  import "../../context/index.js";
8
- import { useBuiAssessment as ne, useBuiCreateQuestion as re, useBuiPublishAssessment as ie } from "../../hooks/useBuildmyiqApi.js";
9
+ import { useBuiAssessment as re, useBuiCreateQuestion as s, useBuiPublishAssessment as c } from "../../hooks/useBuildmyiqApi.js";
9
10
  import "../../hooks/index.js";
10
11
  import "../../components/index.js";
11
- import { QUESTION_TYPES as o } from "../../types/index.js";
12
- import { useMemo as s, useState as c } from "react";
13
- import { ArrowLeft as ae, CheckCircle2 as l, Circle as u, ClipboardCheck as d, Clock as f, Plus as p, Repeat as m, Send as h, Target as g, Trash2 as _ } from "lucide-react";
14
- import { useParams as v } from "react-router-dom";
15
- import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
16
- import { Button as S, Checkbox as oe, GlassCard as C, Input as w, Label as T, ResponsiveDialog as se, ResponsiveDialogContent as ce, ResponsiveDialogDescription as le, ResponsiveDialogFooter as ue, ResponsiveDialogHeader as de, ResponsiveDialogTitle as E, Select as D, SelectContent as O, SelectItem as k, SelectTrigger as A, SelectValue as j, Textarea as M } from "@burdenoff/fe-libs/ui";
12
+ import { QUESTION_TYPES as l } from "../../types/index.js";
13
+ import { useMemo as u, useState as d } from "react";
14
+ import { ArrowLeft as ie, Circle as f, ClipboardCheck as p, ClipboardEdit as ae, Clock as m, Lightbulb as h, Plus as g, Repeat as _, Send as v, Square as y, Trash2 as oe, Trophy as se } from "lucide-react";
15
+ import { useParams as ce } from "react-router-dom";
16
+ import { Fragment as le, jsx as b, jsxs as x } from "react/jsx-runtime";
17
+ import { Button as S, Checkbox as ue, GlassCard as C, Input as w, Label as T, ResponsiveDialog as de, ResponsiveDialogContent as fe, ResponsiveDialogDescription as pe, ResponsiveDialogFooter as me, ResponsiveDialogHeader as he, ResponsiveDialogTitle as ge, Select as _e, SelectContent as E, SelectItem as D, SelectTrigger as O, SelectValue as k, Textarea as A } from "@burdenoff/fe-libs/ui";
17
18
  //#region src/buildmyiq/pages/assessments/AssessmentDetailPage.tsx
18
- var N = (e) => {
19
+ var j = (e) => {
19
20
  if (!Array.isArray(e)) return [];
20
21
  let t = [];
21
22
  for (let n of e) if (n && typeof n == "object" && "label" in n) {
@@ -29,260 +30,240 @@ var N = (e) => {
29
30
  }
30
31
  }
31
32
  return t;
32
- }, P = new Set(["SINGLE_CHOICE", "MULTIPLE_CHOICE"]), F = (e) => e === "SINGLE_CHOICE" || e === "TRUE_FALSE", I = () => [{
33
+ }, M = 1e3, N = new Set(["SINGLE_CHOICE", "MULTIPLE_CHOICE"]), P = (e) => e === "SINGLE_CHOICE" || e === "TRUE_FALSE", F = () => [{
33
34
  label: "",
34
35
  correct: !1
35
36
  }, {
36
37
  label: "",
37
38
  correct: !1
38
- }], L = () => [{
39
+ }], I = () => [{
39
40
  label: "True",
40
41
  correct: !1
41
42
  }, {
42
43
  label: "False",
43
44
  correct: !1
44
- }], R = () => ({
45
+ }], L = () => ({
45
46
  prompt: "",
46
47
  type: "SINGLE_CHOICE",
47
48
  points: "1",
48
49
  explanation: "",
49
- options: I(),
50
+ options: F(),
50
51
  shortAnswer: ""
51
- }), z = () => {
52
- let { assessmentId: l } = v(), { navigateTo: u } = e(), N = ne(l), z = ie(), V = re(), [fe, H] = c(!1), [U, W] = c(R), [G, K] = c(null), q = N.data ?? null, J = s(() => [...q?.questions ?? []].sort((e, t) => e.position - t.position), [q]), Y = s(() => J.length ? Math.max(...J.map((e) => e.position)) + 1 : 1, [J]), X = U.type === "TRUE_FALSE" || P.has(U.type), Z = () => {
53
- W(R()), K(null), H(!0);
52
+ }), R = () => {
53
+ let { assessmentId: f } = ce(), { navigateTo: h } = e(), y = re(f), j = c(), R = s(), [B, V] = d(!1), [H, U] = d(L), [W, G] = d(null), K = y.data ?? null, q = u(() => [...K?.questions ?? []].sort((e, t) => e.position - t.position), [K]), J = u(() => q.length ? Math.max(...q.map((e) => e.position)) + 1 : 1, [q]), Y = u(() => q.reduce((e, t) => e + t.points, 0), [q]), X = H.type === "TRUE_FALSE" || N.has(H.type), Z = () => {
54
+ U(L()), G(null), V(!0);
54
55
  }, Q = () => {
55
- H(!1), W(R()), K(null);
56
- }, pe = (e) => {
57
- W((t) => {
56
+ V(!1), U(L()), G(null);
57
+ }, ye = (e) => {
58
+ U((t) => {
58
59
  let n = t.options;
59
- return e === "TRUE_FALSE" ? n = L() : P.has(e) && (n = t.options.some((e) => e.label === "True" || e.label === "False") ? I() : t.options), {
60
+ return e === "TRUE_FALSE" ? n = I() : N.has(e) && (n = t.options.some((e) => e.label === "True" || e.label === "False") ? F() : t.options), {
60
61
  ...t,
61
62
  type: e,
62
63
  options: n
63
64
  };
64
65
  });
65
- }, me = (e, t) => {
66
- W((n) => ({
66
+ }, be = (e, t) => {
67
+ U((n) => ({
67
68
  ...n,
68
69
  options: n.options.map((n, r) => r === e ? {
69
70
  ...n,
70
71
  label: t
71
72
  } : n)
72
73
  }));
73
- }, he = (e, t) => {
74
- W((n) => ({
74
+ }, xe = (e, t) => {
75
+ U((n) => ({
75
76
  ...n,
76
77
  options: n.options.map((r, i) => i === e ? {
77
78
  ...r,
78
79
  correct: t
79
- } : F(n.type) ? {
80
+ } : P(n.type) ? {
80
81
  ...r,
81
82
  correct: !1
82
83
  } : r)
83
84
  }));
84
- }, ge = () => {
85
- W((e) => ({
85
+ }, Se = () => {
86
+ U((e) => ({
86
87
  ...e,
87
88
  options: [...e.options, {
88
89
  label: "",
89
90
  correct: !1
90
91
  }]
91
92
  }));
92
- }, $ = (e) => {
93
- W((t) => ({
93
+ }, Ce = (e) => {
94
+ U((t) => ({
94
95
  ...t,
95
96
  options: t.options.filter((t, n) => n !== e)
96
97
  }));
97
- }, _e = async () => {
98
- if (q) try {
99
- await z.mutateAsync(q.id);
98
+ }, $ = async () => {
99
+ if (K) try {
100
+ await j.mutateAsync(K.id);
100
101
  } catch {}
101
- }, ve = async () => {
102
- if (!l) return;
103
- if (!U.prompt.trim()) {
104
- K("Question prompt is required.");
102
+ }, we = async () => {
103
+ if (!f) return;
104
+ if (!H.prompt.trim()) {
105
+ G("Question prompt is required.");
105
106
  return;
106
107
  }
107
108
  let e, t;
108
109
  if (X) {
109
- let n = U.options.map((e) => ({
110
+ let n = H.options.map((e) => ({
110
111
  label: e.label.trim(),
111
112
  correct: e.correct
112
113
  })).filter((e) => e.label.length > 0);
113
- if (P.has(U.type) && n.length < 2) {
114
- K("Add at least two options.");
114
+ if (N.has(H.type) && n.length < 2) {
115
+ G("Add at least two options.");
115
116
  return;
116
117
  }
117
118
  e = n.map((e) => ({ label: e.label }));
118
119
  let r = n.filter((e) => e.correct).map((e) => e.label);
119
120
  r.length && (t = r);
120
- } else U.type === "SHORT_ANSWER" && (t = U.shortAnswer.trim() || void 0);
121
+ } else H.type === "SHORT_ANSWER" && (t = H.shortAnswer.trim() || void 0);
121
122
  try {
122
- await V.mutateAsync({
123
- assessmentId: l,
124
- prompt: U.prompt.trim(),
125
- type: U.type,
126
- points: U.points ? Number(U.points) : void 0,
127
- position: Y,
128
- explanation: U.explanation.trim() || void 0,
123
+ await R.mutateAsync({
124
+ assessmentId: f,
125
+ prompt: H.prompt.trim(),
126
+ type: H.type,
127
+ points: H.points ? Number(H.points) : void 0,
128
+ position: J,
129
+ explanation: H.explanation.trim() || void 0,
129
130
  options: e,
130
131
  answerKey: t
131
132
  }), Q();
132
133
  } catch (e) {
133
- K(e instanceof Error ? e.message : "Failed to add question.");
134
+ G(e instanceof Error ? e.message : "Failed to add question.");
134
135
  }
135
136
  };
136
- if (N.isLoading) return /* @__PURE__ */ b(t, {
137
+ if (y.isLoading) return /* @__PURE__ */ b(n, {
137
138
  title: "Assessment",
138
139
  children: /* @__PURE__ */ b(te, { label: "Loading assessment…" })
139
140
  });
140
- if (N.isError) return /* @__PURE__ */ b(t, {
141
+ if (y.isError) return /* @__PURE__ */ b(n, {
141
142
  title: "Assessment",
142
143
  children: /* @__PURE__ */ b(ee, {
143
144
  message: "Couldn't load this assessment.",
144
- onRetry: () => N.refetch()
145
+ onRetry: () => y.refetch()
145
146
  })
146
147
  });
147
- if (!q) return /* @__PURE__ */ b(t, {
148
+ if (!K) return /* @__PURE__ */ b(n, {
148
149
  title: "Assessment",
149
- children: /* @__PURE__ */ b(a, {
150
+ children: /* @__PURE__ */ b(o, {
150
151
  illustration: "empty-search",
151
152
  title: "Assessment not found",
152
153
  description: "This assessment may have been removed or you don't have access to it.",
153
154
  action: /* @__PURE__ */ b(S, {
154
- onClick: () => u("assessments"),
155
+ onClick: () => h("assessments"),
155
156
  children: "Back to assessments"
156
157
  })
157
158
  })
158
159
  });
159
- let ye = q.status === "DRAFT";
160
- return /* @__PURE__ */ x(t, {
161
- title: q.title,
162
- description: q.description ?? void 0,
163
- actions: /* @__PURE__ */ x(y, { children: [
164
- /* @__PURE__ */ x(S, {
165
- variant: "ghost",
166
- onClick: () => u("submissions"),
167
- children: [/* @__PURE__ */ b(d, { className: "mr-1.5 h-4 w-4" }), " Submissions"]
168
- }),
169
- ye && /* @__PURE__ */ x(S, {
170
- variant: "outline",
171
- onClick: _e,
172
- disabled: z.isPending,
173
- children: [/* @__PURE__ */ b(h, { className: "mr-1.5 h-4 w-4" }), z.isPending ? "Publishing…" : "Publish"]
174
- }),
175
- /* @__PURE__ */ x(S, {
176
- onClick: Z,
177
- children: [/* @__PURE__ */ b(p, { className: "mr-1.5 h-4 w-4" }), " Add question"]
178
- })
179
- ] }),
160
+ let Te = K.status === "DRAFT";
161
+ return /* @__PURE__ */ x(n, {
162
+ title: /* @__PURE__ */ x("span", {
163
+ className: "flex min-w-0 items-center gap-3",
164
+ children: [/* @__PURE__ */ b("span", {
165
+ className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)] text-[var(--color-accent-teal)]",
166
+ children: /* @__PURE__ */ b(ae, { className: "h-5 w-5" })
167
+ }), /* @__PURE__ */ b("span", {
168
+ className: "truncate",
169
+ children: K.title
170
+ })]
171
+ }),
172
+ description: K.description ?? void 0,
173
+ actions: /* @__PURE__ */ x(le, { children: [/* @__PURE__ */ x(S, {
174
+ variant: "ghost",
175
+ onClick: () => h("submissions"),
176
+ children: [/* @__PURE__ */ b(p, { className: "mr-1.5 h-4 w-4" }), " Submissions"]
177
+ }), Te ? /* @__PURE__ */ x(S, {
178
+ onClick: $,
179
+ disabled: j.isPending,
180
+ children: [/* @__PURE__ */ b(v, { className: "mr-1.5 h-4 w-4" }), j.isPending ? "Publishing…" : "Publish"]
181
+ }) : /* @__PURE__ */ b(a, {
182
+ status: K.status,
183
+ className: "px-3 py-1.5"
184
+ })] }),
180
185
  children: [
181
186
  /* @__PURE__ */ x("button", {
182
187
  type: "button",
183
- onClick: () => u("assessments"),
188
+ onClick: () => h("assessments"),
184
189
  className: "mb-4 inline-flex items-center gap-1.5 text-sm text-text-secondary transition-colors hover:text-text-primary",
185
- children: [/* @__PURE__ */ b(ae, { className: "h-4 w-4" }), " All assessments"]
190
+ children: [/* @__PURE__ */ b(ie, { className: "h-4 w-4" }), " All assessments"]
186
191
  }),
187
192
  /* @__PURE__ */ x(C, {
188
- treatment: "plain",
189
- className: "mb-6 p-5",
193
+ treatment: "glass",
194
+ className: "mb-6 p-5 sm:p-6",
190
195
  children: [/* @__PURE__ */ x("div", {
191
- className: "flex flex-wrap items-center gap-2",
196
+ className: "mb-5 flex flex-wrap items-center gap-2",
192
197
  children: [
193
- /* @__PURE__ */ b(i, { status: q.type }),
194
- /* @__PURE__ */ b(i, { status: q.status }),
195
- q.isGraded ? /* @__PURE__ */ b(i, { status: "GRADED" }) : /* @__PURE__ */ b("span", {
198
+ /* @__PURE__ */ b(a, { status: K.type }),
199
+ /* @__PURE__ */ b(a, { status: K.status }),
200
+ K.isGraded ? /* @__PURE__ */ b(a, { status: "GRADED" }) : /* @__PURE__ */ b("span", {
196
201
  className: "inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
197
202
  children: "Not graded"
198
203
  })
199
204
  ]
200
205
  }), /* @__PURE__ */ x("div", {
201
- className: "mt-4 grid grid-cols-2 gap-4 sm:grid-cols-4",
206
+ className: "grid grid-cols-2 gap-y-6 sm:grid-cols-4",
202
207
  children: [
203
- /* @__PURE__ */ x("div", {
204
- className: "flex items-center gap-2.5",
205
- children: [/* @__PURE__ */ b(g, { className: "h-4 w-4 shrink-0 text-text-secondary" }), /* @__PURE__ */ x("div", {
206
- className: "min-w-0",
207
- children: [/* @__PURE__ */ b("p", {
208
- className: "text-xs text-text-secondary",
209
- children: "Passing score"
210
- }), /* @__PURE__ */ x("p", {
211
- className: "font-semibold tabular-nums text-text-primary",
212
- children: [q.passingScore, "%"]
213
- })]
214
- })]
208
+ /* @__PURE__ */ b(z, {
209
+ icon: /* @__PURE__ */ b(se, { className: "h-5 w-5" }),
210
+ label: "Passing score",
211
+ value: `${K.passingScore}%`
215
212
  }),
216
- /* @__PURE__ */ x("div", {
217
- className: "flex items-center gap-2.5",
218
- children: [/* @__PURE__ */ b(f, { className: "h-4 w-4 shrink-0 text-text-secondary" }), /* @__PURE__ */ x("div", {
219
- className: "min-w-0",
220
- children: [/* @__PURE__ */ b("p", {
221
- className: "text-xs text-text-secondary",
222
- children: "Time limit"
223
- }), /* @__PURE__ */ b("p", {
224
- className: "font-semibold text-text-primary",
225
- children: n(q.timeLimitMin)
226
- })]
227
- })]
213
+ /* @__PURE__ */ b(z, {
214
+ icon: /* @__PURE__ */ b(m, { className: "h-5 w-5" }),
215
+ label: "Time limit",
216
+ value: r(K.timeLimitMin),
217
+ divider: !0
228
218
  }),
229
- /* @__PURE__ */ x("div", {
230
- className: "flex items-center gap-2.5",
231
- children: [/* @__PURE__ */ b(m, { className: "h-4 w-4 shrink-0 text-text-secondary" }), /* @__PURE__ */ x("div", {
232
- className: "min-w-0",
233
- children: [/* @__PURE__ */ b("p", {
234
- className: "text-xs text-text-secondary",
235
- children: "Max attempts"
236
- }), /* @__PURE__ */ b("p", {
237
- className: "font-semibold tabular-nums text-text-primary",
238
- children: q.maxAttempts
239
- })]
240
- })]
219
+ /* @__PURE__ */ b(z, {
220
+ icon: /* @__PURE__ */ b(_, { className: "h-5 w-5" }),
221
+ label: "Max attempts",
222
+ value: K.maxAttempts,
223
+ divider: !0
241
224
  }),
242
- /* @__PURE__ */ x("div", {
243
- className: "flex items-center gap-2.5",
244
- children: [/* @__PURE__ */ b(d, { className: "h-4 w-4 shrink-0 text-text-secondary" }), /* @__PURE__ */ x("div", {
245
- className: "min-w-0",
246
- children: [/* @__PURE__ */ b("p", {
247
- className: "text-xs text-text-secondary",
248
- children: "Questions"
249
- }), /* @__PURE__ */ b("p", {
250
- className: "font-semibold tabular-nums text-text-primary",
251
- children: J.length
252
- })]
253
- })]
225
+ /* @__PURE__ */ b(z, {
226
+ icon: /* @__PURE__ */ b(p, { className: "h-5 w-5" }),
227
+ label: "Graded",
228
+ value: K.isGraded ? "Yes" : "No",
229
+ divider: !0
254
230
  })
255
231
  ]
256
232
  })]
257
233
  }),
258
- /* @__PURE__ */ b("h2", {
259
- className: "mb-3 text-base font-semibold text-text-primary",
260
- children: "Questions"
261
- }),
262
- J.length === 0 ? /* @__PURE__ */ b(a, {
263
- illustration: "empty-data",
264
- title: "No questions yet",
265
- description: "Build this assessment by adding its first question.",
234
+ /* @__PURE__ */ b(ne, {
235
+ title: `Questions (${q.length})`,
236
+ description: q.length > 0 ? `${Y} point${Y === 1 ? "" : "s"} across ${q.length} question${q.length === 1 ? "" : "s"}` : void 0,
266
237
  action: /* @__PURE__ */ x(S, {
238
+ variant: "outline",
267
239
  onClick: Z,
268
- children: [/* @__PURE__ */ b(p, { className: "mr-1.5 h-4 w-4" }), " Add question"]
240
+ children: [/* @__PURE__ */ b(g, { className: "mr-1.5 h-4 w-4" }), " Add question"]
241
+ }),
242
+ children: q.length === 0 ? /* @__PURE__ */ b(o, {
243
+ illustration: "empty-data",
244
+ title: "No questions yet",
245
+ description: "Build this assessment by adding its first question.",
246
+ action: /* @__PURE__ */ x(S, {
247
+ onClick: Z,
248
+ children: [/* @__PURE__ */ b(g, { className: "mr-1.5 h-4 w-4" }), " Add question"]
249
+ })
250
+ }) : /* @__PURE__ */ b("ol", {
251
+ className: "flex flex-col gap-3",
252
+ children: q.map((e, t) => /* @__PURE__ */ b(ve, {
253
+ index: t + 1,
254
+ question: e
255
+ }, e.id))
269
256
  })
270
- }) : /* @__PURE__ */ b("ol", {
271
- className: "flex flex-col gap-3",
272
- children: J.map((e, t) => /* @__PURE__ */ b(B, {
273
- index: t + 1,
274
- question: e
275
- }, e.id))
276
257
  }),
277
- /* @__PURE__ */ b(se, {
278
- open: fe,
258
+ /* @__PURE__ */ b(de, {
259
+ open: B,
279
260
  onOpenChange: (e) => {
280
- e ? H(!0) : Q();
261
+ e ? V(!0) : Q();
281
262
  },
282
- children: /* @__PURE__ */ x(ce, { children: [
283
- /* @__PURE__ */ x(de, { children: [/* @__PURE__ */ b(E, { children: "Add question" }), /* @__PURE__ */ x(le, { children: [
263
+ children: /* @__PURE__ */ x(fe, { children: [
264
+ /* @__PURE__ */ x(he, { children: [/* @__PURE__ */ b(ge, { children: "Add question" }), /* @__PURE__ */ x(pe, { children: [
284
265
  "Question ",
285
- Y,
266
+ J,
286
267
  " · pick a type, write the prompt and mark the correct answer(s)."
287
268
  ] })] }),
288
269
  /* @__PURE__ */ x("div", {
@@ -290,19 +271,31 @@ var N = (e) => {
290
271
  children: [
291
272
  /* @__PURE__ */ x("div", {
292
273
  className: "grid gap-1.5",
293
- children: [/* @__PURE__ */ b(T, {
294
- htmlFor: "prompt",
295
- children: "Prompt *"
296
- }), /* @__PURE__ */ b(M, {
297
- id: "prompt",
298
- value: U.prompt,
299
- onChange: (e) => W({
300
- ...U,
301
- prompt: e.target.value
274
+ children: [
275
+ /* @__PURE__ */ b(T, {
276
+ htmlFor: "prompt",
277
+ children: "Prompt *"
302
278
  }),
303
- placeholder: "What do you want to ask?",
304
- rows: 2
305
- })]
279
+ /* @__PURE__ */ b(A, {
280
+ id: "prompt",
281
+ value: H.prompt,
282
+ onChange: (e) => U({
283
+ ...H,
284
+ prompt: e.target.value.slice(0, M)
285
+ }),
286
+ placeholder: "Enter your question prompt…",
287
+ rows: 3,
288
+ maxLength: M
289
+ }),
290
+ /* @__PURE__ */ x("p", {
291
+ className: "text-right text-xs tabular-nums text-text-secondary",
292
+ children: [
293
+ H.prompt.length,
294
+ " / ",
295
+ M
296
+ ]
297
+ })
298
+ ]
306
299
  }),
307
300
  /* @__PURE__ */ x("div", {
308
301
  className: "grid gap-2 sm:grid-cols-2",
@@ -311,15 +304,15 @@ var N = (e) => {
311
304
  children: [/* @__PURE__ */ b(T, {
312
305
  htmlFor: "questionType",
313
306
  children: "Type"
314
- }), /* @__PURE__ */ x(D, {
315
- value: U.type,
316
- onValueChange: (e) => pe(e),
317
- children: [/* @__PURE__ */ b(A, {
307
+ }), /* @__PURE__ */ x(_e, {
308
+ value: H.type,
309
+ onValueChange: (e) => ye(e),
310
+ children: [/* @__PURE__ */ b(O, {
318
311
  id: "questionType",
319
- children: /* @__PURE__ */ b(j, {})
320
- }), /* @__PURE__ */ b(O, { children: o.map((e) => /* @__PURE__ */ b(k, {
312
+ children: /* @__PURE__ */ b(k, {})
313
+ }), /* @__PURE__ */ b(E, { children: l.map((e) => /* @__PURE__ */ b(D, {
321
314
  value: e,
322
- children: r(e)
315
+ children: i(e)
323
316
  }, e)) })]
324
317
  })]
325
318
  }), /* @__PURE__ */ x("div", {
@@ -332,9 +325,9 @@ var N = (e) => {
332
325
  type: "number",
333
326
  min: "0",
334
327
  step: "1",
335
- value: U.points,
336
- onChange: (e) => W({
337
- ...U,
328
+ value: H.points,
329
+ onChange: (e) => U({
330
+ ...H,
338
331
  points: e.target.value
339
332
  }),
340
333
  placeholder: "1"
@@ -344,149 +337,177 @@ var N = (e) => {
344
337
  X && /* @__PURE__ */ x("div", {
345
338
  className: "grid gap-2",
346
339
  children: [
347
- /* @__PURE__ */ x(T, { children: ["Options", U.type !== "TRUE_FALSE" && " *"] }),
340
+ /* @__PURE__ */ x(T, { children: ["Options", H.type !== "TRUE_FALSE" && " *"] }),
348
341
  /* @__PURE__ */ x("p", {
349
342
  className: "-mt-1 text-xs text-text-secondary",
350
343
  children: [
351
344
  "Tick the ",
352
- F(U.type) ? "single correct answer" : "correct answers",
345
+ P(H.type) ? "single correct answer" : "correct answers",
353
346
  "."
354
347
  ]
355
348
  }),
356
349
  /* @__PURE__ */ b("div", {
357
350
  className: "flex flex-col gap-2",
358
- children: U.options.map((e, t) => /* @__PURE__ */ x("div", {
359
- className: "flex items-center gap-2",
351
+ children: H.options.map((e, n) => /* @__PURE__ */ x("div", {
352
+ className: t("flex items-center gap-2.5 rounded-lg border px-2.5 py-1.5 transition-colors", e.correct ? "border-status-success-text bg-status-success-bg-subtle" : "border-border-seam bg-bg-surface"),
360
353
  children: [
361
- /* @__PURE__ */ b("label", {
362
- className: "flex items-center gap-2",
363
- children: /* @__PURE__ */ b(oe, {
364
- checked: e.correct,
365
- onCheckedChange: (e) => he(t, e === !0),
366
- "aria-label": "Mark option correct"
367
- })
354
+ /* @__PURE__ */ b(ue, {
355
+ checked: e.correct,
356
+ onCheckedChange: (e) => xe(n, e === !0),
357
+ "aria-label": "Mark option correct"
368
358
  }),
369
359
  /* @__PURE__ */ b(w, {
370
360
  value: e.label,
371
- readOnly: U.type === "TRUE_FALSE",
372
- onChange: (e) => me(t, e.target.value),
373
- placeholder: `Option ${t + 1}`,
374
- className: "flex-1"
361
+ readOnly: H.type === "TRUE_FALSE",
362
+ onChange: (e) => be(n, e.target.value),
363
+ placeholder: `Option ${n + 1}`,
364
+ className: "flex-1 border-0 bg-transparent px-1 shadow-none focus-visible:ring-0"
375
365
  }),
376
- U.type !== "TRUE_FALSE" && U.options.length > 2 && /* @__PURE__ */ b(S, {
366
+ e.correct && /* @__PURE__ */ b("span", {
367
+ className: "shrink-0 text-xs font-medium text-status-success-text",
368
+ children: "Correct"
369
+ }),
370
+ H.type !== "TRUE_FALSE" && H.options.length > 2 && /* @__PURE__ */ b(S, {
377
371
  type: "button",
378
372
  variant: "ghost",
379
373
  size: "icon",
380
- onClick: () => $(t),
374
+ onClick: () => Ce(n),
381
375
  "aria-label": "Remove option",
382
- children: /* @__PURE__ */ b(_, { className: "h-4 w-4" })
376
+ children: /* @__PURE__ */ b(oe, { className: "h-4 w-4" })
383
377
  })
384
378
  ]
385
- }, t))
379
+ }, n))
386
380
  }),
387
- U.type !== "TRUE_FALSE" && /* @__PURE__ */ x(S, {
381
+ H.type !== "TRUE_FALSE" && /* @__PURE__ */ x(S, {
388
382
  type: "button",
389
383
  variant: "ghost",
390
384
  size: "sm",
391
- onClick: ge,
392
- children: [/* @__PURE__ */ b(p, { className: "mr-1.5 h-4 w-4" }), " Add option"]
385
+ onClick: Se,
386
+ children: [/* @__PURE__ */ b(g, { className: "mr-1.5 h-4 w-4" }), " Add option"]
393
387
  })
394
388
  ]
395
389
  }),
396
- U.type === "SHORT_ANSWER" && /* @__PURE__ */ x("div", {
390
+ H.type === "SHORT_ANSWER" && /* @__PURE__ */ x("div", {
397
391
  className: "grid gap-1.5",
398
392
  children: [/* @__PURE__ */ b(T, {
399
393
  htmlFor: "shortAnswer",
400
394
  children: "Expected answer"
401
395
  }), /* @__PURE__ */ b(w, {
402
396
  id: "shortAnswer",
403
- value: U.shortAnswer,
404
- onChange: (e) => W({
405
- ...U,
397
+ value: H.shortAnswer,
398
+ onChange: (e) => U({
399
+ ...H,
406
400
  shortAnswer: e.target.value
407
401
  }),
408
402
  placeholder: "The accepted answer (used as the grading key)."
409
403
  })]
410
404
  }),
411
- (U.type === "ESSAY" || U.type === "CODE") && /* @__PURE__ */ x("p", {
405
+ (H.type === "ESSAY" || H.type === "CODE") && /* @__PURE__ */ x("p", {
412
406
  className: "rounded-lg bg-bg-sunken px-3 py-2 text-xs text-text-secondary",
413
- children: [r(U.type), " responses are graded manually from the Submissions view."]
407
+ children: [i(H.type), " responses are graded manually from the Submissions view."]
414
408
  }),
415
409
  /* @__PURE__ */ x("div", {
416
410
  className: "grid gap-1.5",
417
411
  children: [/* @__PURE__ */ b(T, {
418
412
  htmlFor: "explanation",
419
413
  children: "Explanation"
420
- }), /* @__PURE__ */ b(M, {
414
+ }), /* @__PURE__ */ b(A, {
421
415
  id: "explanation",
422
- value: U.explanation,
423
- onChange: (e) => W({
424
- ...U,
416
+ value: H.explanation,
417
+ onChange: (e) => U({
418
+ ...H,
425
419
  explanation: e.target.value
426
420
  }),
427
421
  placeholder: "Shown to learners after grading (optional).",
428
422
  rows: 2
429
423
  })]
430
424
  }),
431
- G && /* @__PURE__ */ b("p", {
425
+ W && /* @__PURE__ */ b("p", {
432
426
  className: "text-sm text-status-error-text",
433
- children: G
427
+ children: W
434
428
  })
435
429
  ]
436
430
  }),
437
- /* @__PURE__ */ x(ue, { children: [/* @__PURE__ */ b(S, {
431
+ /* @__PURE__ */ x(me, { children: [/* @__PURE__ */ b(S, {
438
432
  variant: "outline",
439
433
  onClick: Q,
440
434
  children: "Cancel"
441
435
  }), /* @__PURE__ */ b(S, {
442
- onClick: ve,
443
- disabled: V.isPending,
444
- children: V.isPending ? "Adding…" : "Add question"
436
+ onClick: we,
437
+ disabled: R.isPending,
438
+ children: R.isPending ? "Adding…" : "Add question"
445
439
  })] })
446
440
  ] })
447
441
  })
448
442
  ]
449
443
  });
450
- }, B = ({ index: e, question: t }) => {
451
- let n = N(t.options), r = P.has(t.type) || t.type === "TRUE_FALSE";
444
+ }, z = ({ icon: e, label: n, value: r, divider: i }) => /* @__PURE__ */ x("div", {
445
+ className: t("flex items-center gap-3", i && "sm:border-l sm:border-border-seam sm:pl-5"),
446
+ children: [/* @__PURE__ */ b("span", {
447
+ className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)] text-[var(--color-accent-teal)]",
448
+ children: e
449
+ }), /* @__PURE__ */ x("div", {
450
+ className: "min-w-0",
451
+ children: [/* @__PURE__ */ b("p", {
452
+ className: "text-xs font-medium uppercase tracking-wide text-text-secondary",
453
+ children: n
454
+ }), /* @__PURE__ */ b("p", {
455
+ className: "mt-0.5 text-lg font-semibold tabular-nums text-text-primary",
456
+ children: r
457
+ })]
458
+ })]
459
+ }), B = (e) => {
460
+ switch (e) {
461
+ case "SHORT_ANSWER": return "Learners type a short answer — auto-graded against the answer key.";
462
+ case "ESSAY": return "Open long-form response — graded manually from Submissions.";
463
+ case "CODE": return "Code response — graded manually from Submissions.";
464
+ default: return "Free-text response.";
465
+ }
466
+ }, ve = ({ index: e, question: t }) => {
467
+ let n = j(t.options), r = N.has(t.type) || t.type === "TRUE_FALSE", i = t.type === "MULTIPLE_CHOICE";
452
468
  return /* @__PURE__ */ b("li", { children: /* @__PURE__ */ b(C, {
453
469
  treatment: "plain",
454
- className: "p-4",
470
+ className: "p-4 sm:p-5",
455
471
  children: /* @__PURE__ */ x("div", {
456
- className: "flex items-start gap-3",
472
+ className: "flex items-start gap-3.5",
457
473
  children: [/* @__PURE__ */ b("span", {
458
- className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-xs font-semibold tabular-nums text-text-secondary",
474
+ className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-sm font-bold tabular-nums text-[var(--color-accent-teal)]",
459
475
  children: e
460
476
  }), /* @__PURE__ */ x("div", {
461
477
  className: "min-w-0 flex-1",
462
478
  children: [
463
479
  /* @__PURE__ */ x("div", {
464
- className: "flex flex-wrap items-start justify-between gap-2",
465
- children: [/* @__PURE__ */ b("p", {
466
- className: "font-medium text-text-primary",
467
- children: t.prompt
468
- }), /* @__PURE__ */ x("div", {
469
- className: "flex shrink-0 items-center gap-2",
470
- children: [/* @__PURE__ */ b(i, { status: t.type }), /* @__PURE__ */ x("span", {
471
- className: "rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium tabular-nums text-text-secondary",
472
- children: [
473
- t.points,
474
- " pt",
475
- t.points === 1 ? "" : "s"
476
- ]
477
- })]
480
+ className: "flex flex-wrap items-center gap-2",
481
+ children: [/* @__PURE__ */ b(a, { status: t.type }), /* @__PURE__ */ x("span", {
482
+ className: "rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium tabular-nums text-text-secondary",
483
+ children: [
484
+ t.points,
485
+ " pt",
486
+ t.points === 1 ? "" : "s"
487
+ ]
478
488
  })]
479
489
  }),
490
+ /* @__PURE__ */ b("p", {
491
+ className: "mt-2.5 font-medium text-text-primary",
492
+ children: t.prompt
493
+ }),
480
494
  r && n.length > 0 && /* @__PURE__ */ b("ul", {
481
- className: "mt-3 flex flex-col gap-1.5",
495
+ className: "mt-3 flex flex-col gap-2",
482
496
  children: n.map((e, t) => /* @__PURE__ */ x("li", {
483
- className: "flex items-center gap-2 text-sm text-text-secondary",
484
- children: [/* @__PURE__ */ b(u, { className: "h-3.5 w-3.5 shrink-0 opacity-50" }), /* @__PURE__ */ b("span", { children: e.label })]
497
+ className: "flex items-center gap-2.5 rounded-lg border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary",
498
+ children: [b(i ? y : f, { className: "h-4 w-4 shrink-0 text-text-secondary opacity-60" }), /* @__PURE__ */ b("span", {
499
+ className: "min-w-0",
500
+ children: e.label
501
+ })]
485
502
  }, e.id ?? `${t}-${e.label}`))
486
503
  }),
504
+ !r && /* @__PURE__ */ b("p", {
505
+ className: "mt-3 rounded-lg border border-dashed border-border-seam bg-bg-sunken px-3 py-2 text-xs text-text-secondary",
506
+ children: B(t.type)
507
+ }),
487
508
  t.explanation && /* @__PURE__ */ x("p", {
488
509
  className: "mt-3 flex items-start gap-1.5 rounded-lg bg-bg-sunken px-3 py-2 text-xs text-text-secondary",
489
- children: [/* @__PURE__ */ b(l, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-status-success-text" }), /* @__PURE__ */ b("span", { children: t.explanation })]
510
+ children: [/* @__PURE__ */ b(h, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-status-warning-text" }), /* @__PURE__ */ b("span", { children: t.explanation })]
490
511
  })
491
512
  ]
492
513
  })]
@@ -494,6 +515,6 @@ var N = (e) => {
494
515
  }) });
495
516
  };
496
517
  //#endregion
497
- export { z as AssessmentDetailPage };
518
+ export { R as AssessmentDetailPage };
498
519
 
499
520
  //# sourceMappingURL=AssessmentDetailPage.js.map