@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,214 +1,259 @@
1
1
  import { useBuildmyiq as e } from "../../context/BuildmyiqContext.js";
2
2
  import { cn as t } from "../../utils/cn.js";
3
3
  import { PageLayout as n } from "../../components/PageLayout.js";
4
- import { formatDuration as r } from "../../utils/formatters.js";
5
- import { StatusBadge as i } from "../../components/StatusBadge.js";
6
- import { EmptyState as a } from "../../components/EmptyState.js";
7
- import { ErrorView as o, LoadingView as s } from "../../components/StateViews.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 s, LoadingView as c } from "../../components/StateViews.js";
8
+ import { ProgressRing as l } from "../../components/Viz.js";
8
9
  import "../../context/index.js";
9
- import { useBuiAssessment as c, useBuiEnrollments as l, useBuiSubmitAssessment as u } from "../../hooks/useBuildmyiqApi.js";
10
+ import { useBuiAssessment as u, useBuiEnrollments as d, useBuiSubmitAssessment as f } from "../../hooks/useBuildmyiqApi.js";
10
11
  import "../../hooks/index.js";
11
12
  import "../../components/index.js";
12
- import { useMemo as d, useState as f } from "react";
13
- import { ArrowLeft as p, CheckCircle2 as m, ClipboardCheck as h, Send as g } from "lucide-react";
14
- import { useParams as _ } from "react-router-dom";
15
- import { jsx as v, jsxs as y } from "react/jsx-runtime";
16
- import { Button as b, GlassCard as x, Input as S, Textarea as C } from "@burdenoff/fe-libs/ui";
13
+ import { useMemo as p, useState as m } from "react";
14
+ import { ArrowLeft as h, CheckCircle2 as g, ClipboardCheck as _, Clock as v, FileText as y, RefreshCw as b, Send as x, Target as S } from "lucide-react";
15
+ import { useParams as C } from "react-router-dom";
16
+ import { jsx as w, jsxs as T } from "react/jsx-runtime";
17
+ import { Button as E, GlassCard as D, Input as O, Textarea as k } from "@burdenoff/fe-libs/ui";
17
18
  //#region src/buildmyiq/pages/assessments/TakeAssessmentPage.tsx
18
- function w(e) {
19
+ function A(e) {
19
20
  return Array.isArray(e) ? e.map((e) => e && typeof e == "object" && "label" in e ? { label: String(e.label) } : null).filter((e) => e !== null && e.label.length > 0) : [];
20
21
  }
21
- var T = [{ label: "True" }, { label: "False" }], E = () => {
22
- let { assessmentId: E } = _(), { currentUser: D, navigateTo: O } = e(), k = c(E), A = k.data ?? null, j = l({
23
- learnerId: D?.id,
24
- courseId: A?.courseId,
25
- enabled: !!(D?.id && A?.courseId)
26
- }).data?.items?.[0]?.id, M = u(), [N, P] = f({}), [F, I] = f(null), L = d(() => [...A?.questions ?? []].sort((e, t) => e.position - t.position), [A]), R = (e, t) => {
27
- P((n) => ({
22
+ var j = [{ label: "True" }, { label: "False" }], M = ({ icon: e, label: t, value: n }) => /* @__PURE__ */ T("div", {
23
+ className: "flex items-center gap-3 py-3 first:pt-0 last:pb-0 sm:px-5 sm:py-0 sm:first:pl-0 sm:last:pr-0",
24
+ children: [/* @__PURE__ */ w("span", {
25
+ className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-[var(--color-accent-teal)]",
26
+ children: e
27
+ }), /* @__PURE__ */ T("div", {
28
+ className: "min-w-0",
29
+ children: [/* @__PURE__ */ w("p", {
30
+ className: "text-xs text-text-secondary",
31
+ children: t
32
+ }), /* @__PURE__ */ w("p", {
33
+ className: "text-sm font-semibold text-text-primary",
34
+ children: n
35
+ })]
36
+ })]
37
+ }), N = () => {
38
+ let { assessmentId: N } = C(), { currentUser: P, navigateTo: F } = e(), I = u(N), L = I.data ?? null, R = d({
39
+ learnerId: P?.id,
40
+ courseId: L?.courseId,
41
+ enabled: !!(P?.id && L?.courseId)
42
+ }).data?.items?.[0]?.id, z = f(), [B, V] = m({}), [H, U] = m(null), W = p(() => [...L?.questions ?? []].sort((e, t) => e.position - t.position), [L]), G = (e, t) => {
43
+ V((n) => ({
28
44
  ...n,
29
45
  [e]: t
30
46
  }));
31
- }, z = (e, t) => {
32
- P((n) => {
47
+ }, K = (e, t) => {
48
+ V((n) => {
33
49
  let r = Array.isArray(n[e]) ? n[e] : [];
34
50
  return {
35
51
  ...n,
36
52
  [e]: r.includes(t) ? r.filter((e) => e !== t) : [...r, t]
37
53
  };
38
54
  });
39
- }, B = L.filter((e) => {
40
- let t = N[e.id];
55
+ }, q = (e) => {
56
+ let t = B[e.id];
41
57
  return Array.isArray(t) ? t.length > 0 : !!(t && String(t).trim());
42
- }).length, V = async () => {
43
- E && I((await M.mutateAsync({
44
- assessmentId: E,
45
- enrollmentId: j,
58
+ }, J = W.filter(q).length, Y = W.length > 0 ? J / W.length * 100 : 0, X = W.length - J, Z = J === 0 ? "Answer a question to get started." : X === 0 ? "All questions answered — ready to submit." : `${X} question${X === 1 ? "" : "s"} left to answer.`, Q = async () => {
59
+ N && U((await z.mutateAsync({
60
+ assessmentId: N,
61
+ enrollmentId: R,
46
62
  attempt: 1,
47
- answers: N
63
+ answers: B
48
64
  })).id);
49
- }, H = A ? /* @__PURE__ */ y(b, {
65
+ }, $ = L ? /* @__PURE__ */ T(E, {
50
66
  variant: "ghost",
51
67
  size: "sm",
52
- onClick: () => O(`catalog/${A.courseId}`),
53
- children: [/* @__PURE__ */ v(p, { className: "mr-1 h-4 w-4" }), " Back to course"]
68
+ onClick: () => F(`catalog/${L.courseId}`),
69
+ children: [/* @__PURE__ */ w(h, { className: "mr-1 h-4 w-4" }), " Back to course"]
54
70
  }) : void 0;
55
- return E ? k.isLoading ? /* @__PURE__ */ v(n, {
71
+ return N ? I.isLoading ? /* @__PURE__ */ w(n, {
56
72
  title: "Assessment",
57
- children: /* @__PURE__ */ v(s, { label: "Loading the assessment…" })
58
- }) : k.isError || !A ? /* @__PURE__ */ v(n, {
73
+ children: /* @__PURE__ */ w(c, { label: "Loading the assessment…" })
74
+ }) : I.isError || !L ? /* @__PURE__ */ w(n, {
59
75
  title: "Assessment",
60
- actions: H,
61
- children: /* @__PURE__ */ v(o, {
76
+ actions: $,
77
+ children: /* @__PURE__ */ w(s, {
62
78
  title: "Couldn't load this assessment",
63
- message: k.error instanceof Error ? k.error.message : void 0,
64
- onRetry: () => k.refetch()
79
+ message: I.error instanceof Error ? I.error.message : void 0,
80
+ onRetry: () => I.refetch()
65
81
  })
66
- }) : A.status === "PUBLISHED" ? F ? /* @__PURE__ */ v(n, {
67
- title: A.title,
68
- actions: H,
69
- children: /* @__PURE__ */ v("div", {
82
+ }) : L.status === "PUBLISHED" ? H ? /* @__PURE__ */ w(n, {
83
+ title: L.title,
84
+ actions: $,
85
+ children: /* @__PURE__ */ w("div", {
70
86
  className: "mx-auto max-w-lg",
71
- children: /* @__PURE__ */ y(x, {
87
+ children: /* @__PURE__ */ T(D, {
72
88
  treatment: "glass",
73
89
  glow: !0,
74
90
  className: "flex flex-col items-center gap-4 p-8 text-center",
75
91
  children: [
76
- /* @__PURE__ */ v("div", {
92
+ /* @__PURE__ */ w("div", {
77
93
  className: "flex h-14 w-14 items-center justify-center rounded-full bg-status-success-bg-subtle",
78
- children: /* @__PURE__ */ v(m, { className: "h-7 w-7 text-status-success-text" })
94
+ children: /* @__PURE__ */ w(g, { className: "h-7 w-7 text-status-success-text" })
79
95
  }),
80
- /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("h2", {
96
+ /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("h2", {
81
97
  className: "text-lg font-semibold text-text-primary",
82
98
  children: "Submitted"
83
- }), /* @__PURE__ */ y("p", {
99
+ }), /* @__PURE__ */ T("p", {
84
100
  className: "mt-1 text-sm text-text-secondary",
85
101
  children: [
86
102
  "Your answers for “",
87
- A.title,
103
+ L.title,
88
104
  "” were submitted.",
89
- A.isGraded ? " An educator will grade them — you’ll see your score and feedback in My Learning." : " Thanks for completing it."
105
+ L.isGraded ? " An educator will grade them — you’ll see your score and feedback in My Learning." : " Thanks for completing it."
90
106
  ]
91
107
  })] }),
92
- /* @__PURE__ */ y("div", {
108
+ /* @__PURE__ */ T("div", {
93
109
  className: "flex flex-wrap justify-center gap-2",
94
- children: [/* @__PURE__ */ v(b, {
110
+ children: [/* @__PURE__ */ w(E, {
95
111
  variant: "secondary",
96
- onClick: () => O("learning"),
112
+ onClick: () => F("learning"),
97
113
  children: "Go to My Learning"
98
- }), /* @__PURE__ */ v(b, {
114
+ }), /* @__PURE__ */ w(E, {
99
115
  variant: "ghost",
100
- onClick: () => O(`catalog/${A.courseId}`),
116
+ onClick: () => F(`catalog/${L.courseId}`),
101
117
  children: "Back to course"
102
118
  })]
103
119
  })
104
120
  ]
105
121
  })
106
122
  })
107
- }) : /* @__PURE__ */ v(n, {
108
- title: A.title,
109
- description: A.description ?? void 0,
110
- actions: H,
111
- children: /* @__PURE__ */ y("div", {
112
- className: "mx-auto max-w-3xl",
113
- children: [/* @__PURE__ */ y("div", {
114
- className: "mb-6 flex flex-wrap items-center gap-3",
115
- children: [
116
- /* @__PURE__ */ v(i, { status: A.type }),
117
- /* @__PURE__ */ y("span", {
118
- className: "text-sm text-text-secondary",
119
- children: [
120
- "Passing score ",
121
- A.passingScore,
122
- "%"
123
- ]
124
- }),
125
- A.timeLimitMin > 0 && /* @__PURE__ */ y("span", {
126
- className: "text-sm text-text-secondary",
127
- children: ["· ", r(A.timeLimitMin)]
128
- }),
129
- /* @__PURE__ */ y("span", {
130
- className: "text-sm text-text-secondary",
131
- children: [
132
- "· ",
133
- B,
134
- "/",
135
- L.length,
136
- " answered"
137
- ]
138
- })
139
- ]
140
- }), L.length === 0 ? /* @__PURE__ */ v(a, {
141
- icon: /* @__PURE__ */ v(h, { className: "h-8 w-8" }),
123
+ }) : /* @__PURE__ */ w(n, {
124
+ title: L.title,
125
+ description: L.description ?? void 0,
126
+ actions: $,
127
+ children: /* @__PURE__ */ T("div", {
128
+ className: "mx-auto max-w-3xl pb-4",
129
+ children: [/* @__PURE__ */ w(D, {
130
+ treatment: "glass",
131
+ className: "mb-6 p-4 sm:px-5",
132
+ children: /* @__PURE__ */ T("div", {
133
+ className: "flex flex-col divide-y divide-border-seam sm:flex-row sm:flex-wrap sm:items-center sm:divide-x sm:divide-y-0",
134
+ children: [
135
+ /* @__PURE__ */ w(M, {
136
+ icon: /* @__PURE__ */ w(y, { className: "h-4 w-4" }),
137
+ label: "Type",
138
+ value: /* @__PURE__ */ w(a, { status: L.type })
139
+ }),
140
+ /* @__PURE__ */ w(M, {
141
+ icon: /* @__PURE__ */ w(S, { className: "h-4 w-4" }),
142
+ label: "Passing score",
143
+ value: `${L.passingScore}%`
144
+ }),
145
+ L.timeLimitMin > 0 && /* @__PURE__ */ w(M, {
146
+ icon: /* @__PURE__ */ w(v, { className: "h-4 w-4" }),
147
+ label: "Time limit",
148
+ value: r(L.timeLimitMin)
149
+ }),
150
+ L.maxAttempts > 0 && /* @__PURE__ */ w(M, {
151
+ icon: /* @__PURE__ */ w(b, { className: "h-4 w-4" }),
152
+ label: "Attempts",
153
+ value: L.maxAttempts
154
+ }),
155
+ /* @__PURE__ */ T("div", {
156
+ className: "flex items-center gap-3 py-3 sm:ml-auto sm:py-0 sm:pl-5",
157
+ children: [/* @__PURE__ */ w(l, {
158
+ value: Y,
159
+ size: 44,
160
+ stroke: 5,
161
+ label: `${J}/${W.length}`
162
+ }), /* @__PURE__ */ T("div", {
163
+ className: "min-w-0",
164
+ children: [/* @__PURE__ */ T("p", {
165
+ className: "text-sm font-semibold text-text-primary tabular-nums",
166
+ children: [
167
+ J,
168
+ " of ",
169
+ W.length
170
+ ]
171
+ }), /* @__PURE__ */ w("p", {
172
+ className: "text-xs text-text-secondary",
173
+ children: "answered"
174
+ })]
175
+ })]
176
+ })
177
+ ]
178
+ })
179
+ }), W.length === 0 ? /* @__PURE__ */ w(o, {
180
+ icon: /* @__PURE__ */ w(_, { className: "h-8 w-8" }),
142
181
  title: "No questions yet",
143
182
  description: "This assessment doesn't have any questions to answer."
144
- }) : /* @__PURE__ */ y("div", {
183
+ }) : /* @__PURE__ */ T("div", {
145
184
  className: "flex flex-col gap-4",
146
185
  children: [
147
- L.map((e, n) => {
148
- let r = e.type === "TRUE_FALSE" ? T : w(e.options), i = N[e.id];
149
- return /* @__PURE__ */ v(x, {
150
- treatment: "plain",
151
- className: "p-5",
152
- children: /* @__PURE__ */ y("div", {
153
- className: "flex items-start gap-3",
154
- children: [/* @__PURE__ */ v("span", {
155
- className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-xs font-semibold text-text-secondary tabular-nums",
156
- children: n + 1
157
- }), /* @__PURE__ */ y("div", {
186
+ W.map((e, n) => {
187
+ let r = e.type === "TRUE_FALSE" ? j : A(e.options), a = B[e.id], o = q(e);
188
+ return /* @__PURE__ */ w(D, {
189
+ treatment: o ? "insight" : "plain",
190
+ className: t("p-5 transition-shadow", o && "ring-1 ring-[var(--color-accent-soft)]"),
191
+ children: /* @__PURE__ */ T("div", {
192
+ className: "flex items-start gap-3 sm:gap-4",
193
+ children: [/* @__PURE__ */ w("span", {
194
+ className: t("mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-sm font-semibold tabular-nums transition-colors", o ? "bg-status-success-bg-subtle text-status-success-text" : "bg-[var(--color-accent-soft)] text-text-primary"),
195
+ children: o ? /* @__PURE__ */ w(g, { className: "h-4 w-4" }) : n + 1
196
+ }), /* @__PURE__ */ T("div", {
158
197
  className: "min-w-0 flex-1",
159
198
  children: [
160
- /* @__PURE__ */ v("p", {
161
- className: "font-medium text-text-primary",
162
- children: e.prompt
199
+ /* @__PURE__ */ T("div", {
200
+ className: "flex flex-wrap items-center gap-2",
201
+ children: [/* @__PURE__ */ w("span", {
202
+ className: "rounded-md bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary",
203
+ children: i(e.type)
204
+ }), /* @__PURE__ */ T("span", {
205
+ className: "ml-auto text-xs text-text-secondary tabular-nums",
206
+ children: [
207
+ e.points,
208
+ " ",
209
+ e.points === 1 ? "point" : "points"
210
+ ]
211
+ })]
163
212
  }),
164
- /* @__PURE__ */ y("p", {
165
- className: "mt-0.5 text-xs text-text-secondary",
166
- children: [
167
- e.points,
168
- " ",
169
- e.points === 1 ? "point" : "points"
170
- ]
213
+ /* @__PURE__ */ w("p", {
214
+ className: "mt-2.5 font-medium text-text-primary",
215
+ children: e.prompt
171
216
  }),
172
- /* @__PURE__ */ y("div", {
217
+ /* @__PURE__ */ T("div", {
173
218
  className: "mt-4",
174
219
  children: [
175
- (e.type === "SINGLE_CHOICE" || e.type === "TRUE_FALSE") && /* @__PURE__ */ v("div", {
220
+ (e.type === "SINGLE_CHOICE" || e.type === "TRUE_FALSE") && /* @__PURE__ */ w("div", {
176
221
  className: "flex flex-col gap-2",
177
- children: r.map((n) => /* @__PURE__ */ y("label", {
178
- className: t("flex cursor-pointer items-center gap-3 rounded-lg border px-3 py-2 text-sm transition-colors", i === n.label ? "border-accent bg-[var(--color-accent-soft)] text-text-primary" : "border-border-seam text-text-secondary hover:bg-bg-sunken"),
179
- children: [/* @__PURE__ */ v("input", {
222
+ children: r.map((n) => /* @__PURE__ */ T("label", {
223
+ className: t("flex min-h-[44px] cursor-pointer items-center gap-3 rounded-xl border px-3.5 py-2.5 text-sm transition-colors", a === n.label ? "border-[var(--color-accent-teal)] bg-[var(--color-accent-soft)] text-text-primary" : "border-border-seam text-text-secondary hover:border-border-strong hover:bg-bg-sunken"),
224
+ children: [/* @__PURE__ */ w("input", {
180
225
  type: "radio",
181
226
  name: e.id,
182
- className: "accent-[var(--color-accent-primary)]",
183
- checked: i === n.label,
184
- onChange: () => R(e.id, n.label)
227
+ className: "h-4 w-4 accent-[var(--color-accent-teal)]",
228
+ checked: a === n.label,
229
+ onChange: () => G(e.id, n.label)
185
230
  }), n.label]
186
231
  }, n.label))
187
232
  }),
188
- e.type === "MULTIPLE_CHOICE" && /* @__PURE__ */ v("div", {
233
+ e.type === "MULTIPLE_CHOICE" && /* @__PURE__ */ w("div", {
189
234
  className: "flex flex-col gap-2",
190
235
  children: r.map((n) => {
191
- let r = Array.isArray(i) && i.includes(n.label);
192
- return /* @__PURE__ */ y("label", {
193
- className: t("flex cursor-pointer items-center gap-3 rounded-lg border px-3 py-2 text-sm transition-colors", r ? "border-accent bg-[var(--color-accent-soft)] text-text-primary" : "border-border-seam text-text-secondary hover:bg-bg-sunken"),
194
- children: [/* @__PURE__ */ v("input", {
236
+ let r = Array.isArray(a) && a.includes(n.label);
237
+ return /* @__PURE__ */ T("label", {
238
+ className: t("flex min-h-[44px] cursor-pointer items-center gap-3 rounded-xl border px-3.5 py-2.5 text-sm transition-colors", r ? "border-[var(--color-accent-teal)] bg-[var(--color-accent-soft)] text-text-primary" : "border-border-seam text-text-secondary hover:border-border-strong hover:bg-bg-sunken"),
239
+ children: [/* @__PURE__ */ w("input", {
195
240
  type: "checkbox",
196
- className: "accent-[var(--color-accent-primary)]",
241
+ className: "h-4 w-4 rounded accent-[var(--color-accent-teal)]",
197
242
  checked: r,
198
- onChange: () => z(e.id, n.label)
243
+ onChange: () => K(e.id, n.label)
199
244
  }), n.label]
200
245
  }, n.label);
201
246
  })
202
247
  }),
203
- e.type === "SHORT_ANSWER" && /* @__PURE__ */ v(S, {
204
- value: typeof i == "string" ? i : "",
205
- onChange: (t) => R(e.id, t.target.value),
206
- placeholder: "Your answer"
248
+ e.type === "SHORT_ANSWER" && /* @__PURE__ */ w(O, {
249
+ value: typeof a == "string" ? a : "",
250
+ onChange: (t) => G(e.id, t.target.value),
251
+ placeholder: "Type your answer here…"
207
252
  }),
208
- (e.type === "ESSAY" || e.type === "CODE") && /* @__PURE__ */ v(C, {
253
+ (e.type === "ESSAY" || e.type === "CODE") && /* @__PURE__ */ w(k, {
209
254
  rows: e.type === "CODE" ? 6 : 4,
210
- value: typeof i == "string" ? i : "",
211
- onChange: (t) => R(e.id, t.target.value),
255
+ value: typeof a == "string" ? a : "",
256
+ onChange: (t) => G(e.id, t.target.value),
212
257
  placeholder: e.type === "CODE" ? "Write your code…" : "Write your answer…",
213
258
  className: e.type === "CODE" ? "font-mono text-sm" : void 0
214
259
  })
@@ -219,46 +264,65 @@ var T = [{ label: "True" }, { label: "False" }], E = () => {
219
264
  })
220
265
  }, e.id);
221
266
  }),
222
- M.isError && /* @__PURE__ */ v("p", {
267
+ z.isError && /* @__PURE__ */ w("p", {
223
268
  className: "text-sm text-status-error-text",
224
- children: M.error instanceof Error ? M.error.message : "Could not submit your answers."
269
+ children: z.error instanceof Error ? z.error.message : "Could not submit your answers."
225
270
  }),
226
- /* @__PURE__ */ y("div", {
227
- className: "sticky bottom-0 flex items-center justify-between gap-3 border-t border-border-seam bg-bg-surface/90 py-3 backdrop-blur",
228
- children: [/* @__PURE__ */ y("span", {
229
- className: "text-sm text-text-secondary tabular-nums",
230
- children: [
231
- B,
232
- " of ",
233
- L.length,
234
- " answered"
235
- ]
236
- }), /* @__PURE__ */ y(b, {
237
- onClick: V,
238
- disabled: M.isPending || B === 0,
239
- children: [/* @__PURE__ */ v(g, { className: "mr-1 h-4 w-4" }), M.isPending ? "Submitting…" : "Submit assessment"]
240
- })]
271
+ /* @__PURE__ */ w("div", {
272
+ className: "sticky bottom-0 z-10 pt-2",
273
+ children: /* @__PURE__ */ T("div", {
274
+ className: "flex flex-col gap-3 rounded-2xl border border-border-seam bg-bg-surface/90 p-4 shadow-elevation-2 backdrop-blur sm:flex-row sm:items-center sm:justify-between",
275
+ children: [/* @__PURE__ */ T("div", {
276
+ className: "flex items-center gap-3",
277
+ children: [/* @__PURE__ */ w(l, {
278
+ value: Y,
279
+ size: 44,
280
+ stroke: 5,
281
+ label: `${J}/${W.length}`
282
+ }), /* @__PURE__ */ T("div", {
283
+ className: "min-w-0",
284
+ children: [/* @__PURE__ */ T("p", {
285
+ className: "text-sm font-semibold text-text-primary tabular-nums",
286
+ children: [
287
+ J,
288
+ " of ",
289
+ W.length,
290
+ " answered"
291
+ ]
292
+ }), /* @__PURE__ */ w("p", {
293
+ className: "text-xs text-text-secondary",
294
+ children: Z
295
+ })]
296
+ })]
297
+ }), /* @__PURE__ */ T(E, {
298
+ size: "lg",
299
+ className: "max-sm:w-full",
300
+ onClick: Q,
301
+ disabled: z.isPending || J === 0,
302
+ children: [/* @__PURE__ */ w(x, { className: "mr-1.5 h-4 w-4" }), z.isPending ? "Submitting…" : "Submit assessment"]
303
+ })]
304
+ })
241
305
  })
242
306
  ]
243
307
  })]
244
308
  })
245
- }) : /* @__PURE__ */ v(n, {
246
- title: A.title,
247
- actions: H,
248
- children: /* @__PURE__ */ v(a, {
309
+ }) : /* @__PURE__ */ w(n, {
310
+ title: L.title,
311
+ actions: $,
312
+ children: /* @__PURE__ */ w(o, {
249
313
  illustration: "empty-data",
250
314
  title: "This assessment isn't open yet",
251
315
  description: "It has to be published by an educator before you can take it."
252
316
  })
253
- }) : /* @__PURE__ */ v(n, {
317
+ }) : /* @__PURE__ */ w(n, {
254
318
  title: "Assessment",
255
- children: /* @__PURE__ */ v(a, {
319
+ children: /* @__PURE__ */ w(o, {
256
320
  illustration: "empty-data",
257
321
  title: "No assessment selected"
258
322
  })
259
323
  });
260
324
  };
261
325
  //#endregion
262
- export { E as TakeAssessmentPage };
326
+ export { N as TakeAssessmentPage };
263
327
 
264
328
  //# sourceMappingURL=TakeAssessmentPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TakeAssessmentPage.js","names":[],"sources":["../../../../src/buildmyiq/pages/assessments/TakeAssessmentPage.tsx"],"sourcesContent":["/**\n * TakeAssessmentPage — the LEARNER-facing surface to attempt a published\n * assessment and submit answers.\n * @module buildmyiq/pages/assessments\n *\n * Loads the assessment + its questions, collects an answer per question (typed\n * to the question kind), resolves the caller's enrollment for the assessment's\n * course, and submits via `buiSubmitAssessment` ({ assessmentId, enrollmentId?,\n * answers }). Grading is done by an educator in the Grading queue — this page is\n * honest about that (\"submitted, awaiting grading\"). All data is live.\n */\n\nimport type { FC } from 'react';\nimport { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, CheckCircle2, ClipboardCheck, Send } from 'lucide-react';\nimport { Button, GlassCard, Input, Textarea } from '@burdenoff/fe-libs/ui';\nimport {\n PageLayout,\n StatusBadge,\n LoadingView,\n ErrorView,\n EmptyState,\n} from '../../components';\nimport { useBuildmyiq } from '../../context';\nimport { useBuiAssessment, useBuiEnrollments, useBuiSubmitAssessment } from '../../hooks';\nimport { cn } from '../../utils/cn';\nimport { formatDuration } from '../../utils/formatters';\nimport type { BuiQuestion } from '../../types';\n\ninterface Choice {\n label: string;\n}\n\n/** Narrow the untyped `options` JSON blob to a list of `{ label }` choices. */\nfunction parseChoices(options: unknown): Choice[] {\n if (!Array.isArray(options)) return [];\n return options\n .map((o) => (o && typeof o === 'object' && 'label' in o ? { label: String((o as { label: unknown }).label) } : null))\n .filter((c): c is Choice => c !== null && c.label.length > 0);\n}\n\ntype AnswerValue = string | string[];\n\nconst TRUE_FALSE_CHOICES: Choice[] = [{ label: 'True' }, { label: 'False' }];\n\nexport const TakeAssessmentPage: FC = () => {\n const { assessmentId } = useParams<{ assessmentId: string }>();\n const { currentUser, navigateTo } = useBuildmyiq();\n\n const assessmentQuery = useBuiAssessment(assessmentId);\n const assessment = assessmentQuery.data ?? null;\n\n const enrollmentsQuery = useBuiEnrollments({\n learnerId: currentUser?.id,\n courseId: assessment?.courseId,\n enabled: Boolean(currentUser?.id && assessment?.courseId),\n });\n const enrollmentId = enrollmentsQuery.data?.items?.[0]?.id;\n\n const submit = useBuiSubmitAssessment();\n const [answers, setAnswers] = useState<Record<string, AnswerValue>>({});\n const [submittedId, setSubmittedId] = useState<string | null>(null);\n\n const questions = useMemo<BuiQuestion[]>(\n () => [...(assessment?.questions ?? [])].sort((a, b) => a.position - b.position),\n [assessment]\n );\n\n const setAnswer = (qid: string, value: AnswerValue): void => {\n setAnswers((prev) => ({ ...prev, [qid]: value }));\n };\n\n const toggleMulti = (qid: string, label: string): void => {\n setAnswers((prev) => {\n const cur = Array.isArray(prev[qid]) ? (prev[qid] as string[]) : [];\n return { ...prev, [qid]: cur.includes(label) ? cur.filter((l) => l !== label) : [...cur, label] };\n });\n };\n\n const answeredCount = questions.filter((q) => {\n const a = answers[q.id];\n return Array.isArray(a) ? a.length > 0 : Boolean(a && String(a).trim());\n }).length;\n\n const handleSubmit = async (): Promise<void> => {\n if (!assessmentId) return;\n const result = await submit.mutateAsync({\n assessmentId,\n enrollmentId,\n attempt: 1,\n answers,\n });\n setSubmittedId(result.id);\n };\n\n const backToCourse = assessment\n ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo(`catalog/${assessment.courseId}`)}>\n <ArrowLeft className=\"mr-1 h-4 w-4\" /> Back to course\n </Button>\n )\n : undefined;\n\n if (!assessmentId) {\n return (\n <PageLayout title=\"Assessment\">\n <EmptyState illustration=\"empty-data\" title=\"No assessment selected\" />\n </PageLayout>\n );\n }\n\n if (assessmentQuery.isLoading) {\n return (\n <PageLayout title=\"Assessment\">\n <LoadingView label=\"Loading the assessment…\" />\n </PageLayout>\n );\n }\n\n if (assessmentQuery.isError || !assessment) {\n return (\n <PageLayout title=\"Assessment\" actions={backToCourse}>\n <ErrorView\n title=\"Couldn't load this assessment\"\n message={assessmentQuery.error instanceof Error ? assessmentQuery.error.message : undefined}\n onRetry={() => assessmentQuery.refetch()}\n />\n </PageLayout>\n );\n }\n\n if (assessment.status !== 'PUBLISHED') {\n return (\n <PageLayout title={assessment.title} actions={backToCourse}>\n <EmptyState\n illustration=\"empty-data\"\n title=\"This assessment isn't open yet\"\n description=\"It has to be published by an educator before you can take it.\"\n />\n </PageLayout>\n );\n }\n\n // Submitted confirmation\n if (submittedId) {\n return (\n <PageLayout title={assessment.title} actions={backToCourse}>\n <div className=\"mx-auto max-w-lg\">\n <GlassCard treatment=\"glass\" glow className=\"flex flex-col items-center gap-4 p-8 text-center\">\n <div className=\"flex h-14 w-14 items-center justify-center rounded-full bg-status-success-bg-subtle\">\n <CheckCircle2 className=\"h-7 w-7 text-status-success-text\" />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Submitted</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Your answers for “{assessment.title}” were submitted.\n {assessment.isGraded\n ? ' An educator will grade them — you’ll see your score and feedback in My Learning.'\n : ' Thanks for completing it.'}\n </p>\n </div>\n <div className=\"flex flex-wrap justify-center gap-2\">\n <Button variant=\"secondary\" onClick={() => navigateTo('learning')}>\n Go to My Learning\n </Button>\n <Button variant=\"ghost\" onClick={() => navigateTo(`catalog/${assessment.courseId}`)}>\n Back to course\n </Button>\n </div>\n </GlassCard>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={assessment.title}\n description={assessment.description ?? undefined}\n actions={backToCourse}\n >\n <div className=\"mx-auto max-w-3xl\">\n {/* Meta strip */}\n <div className=\"mb-6 flex flex-wrap items-center gap-3\">\n <StatusBadge status={assessment.type} />\n <span className=\"text-sm text-text-secondary\">Passing score {assessment.passingScore}%</span>\n {assessment.timeLimitMin > 0 && (\n <span className=\"text-sm text-text-secondary\">· {formatDuration(assessment.timeLimitMin)}</span>\n )}\n <span className=\"text-sm text-text-secondary\">\n · {answeredCount}/{questions.length} answered\n </span>\n </div>\n\n {questions.length === 0 ? (\n <EmptyState\n icon={<ClipboardCheck className=\"h-8 w-8\" />}\n title=\"No questions yet\"\n description=\"This assessment doesn't have any questions to answer.\"\n />\n ) : (\n <div className=\"flex flex-col gap-4\">\n {questions.map((q, idx) => {\n const choices =\n q.type === 'TRUE_FALSE' ? TRUE_FALSE_CHOICES : parseChoices(q.options);\n const answer = answers[q.id];\n return (\n <GlassCard key={q.id} treatment=\"plain\" className=\"p-5\">\n <div className=\"flex items-start gap-3\">\n <span className=\"mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-xs font-semibold text-text-secondary tabular-nums\">\n {idx + 1}\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"font-medium text-text-primary\">{q.prompt}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {q.points} {q.points === 1 ? 'point' : 'points'}\n </p>\n\n <div className=\"mt-4\">\n {(q.type === 'SINGLE_CHOICE' || q.type === 'TRUE_FALSE') && (\n <div className=\"flex flex-col gap-2\">\n {choices.map((c) => (\n <label\n key={c.label}\n className={cn(\n 'flex cursor-pointer items-center gap-3 rounded-lg border px-3 py-2 text-sm transition-colors',\n answer === c.label\n ? 'border-accent bg-[var(--color-accent-soft)] text-text-primary'\n : 'border-border-seam text-text-secondary hover:bg-bg-sunken'\n )}\n >\n <input\n type=\"radio\"\n name={q.id}\n className=\"accent-[var(--color-accent-primary)]\"\n checked={answer === c.label}\n onChange={() => setAnswer(q.id, c.label)}\n />\n {c.label}\n </label>\n ))}\n </div>\n )}\n\n {q.type === 'MULTIPLE_CHOICE' && (\n <div className=\"flex flex-col gap-2\">\n {choices.map((c) => {\n const checked = Array.isArray(answer) && answer.includes(c.label);\n return (\n <label\n key={c.label}\n className={cn(\n 'flex cursor-pointer items-center gap-3 rounded-lg border px-3 py-2 text-sm transition-colors',\n checked\n ? 'border-accent bg-[var(--color-accent-soft)] text-text-primary'\n : 'border-border-seam text-text-secondary hover:bg-bg-sunken'\n )}\n >\n <input\n type=\"checkbox\"\n className=\"accent-[var(--color-accent-primary)]\"\n checked={checked}\n onChange={() => toggleMulti(q.id, c.label)}\n />\n {c.label}\n </label>\n );\n })}\n </div>\n )}\n\n {q.type === 'SHORT_ANSWER' && (\n <Input\n value={typeof answer === 'string' ? answer : ''}\n onChange={(e) => setAnswer(q.id, e.target.value)}\n placeholder=\"Your answer\"\n />\n )}\n\n {(q.type === 'ESSAY' || q.type === 'CODE') && (\n <Textarea\n rows={q.type === 'CODE' ? 6 : 4}\n value={typeof answer === 'string' ? answer : ''}\n onChange={(e) => setAnswer(q.id, e.target.value)}\n placeholder={q.type === 'CODE' ? 'Write your code…' : 'Write your answer…'}\n className={q.type === 'CODE' ? 'font-mono text-sm' : undefined}\n />\n )}\n </div>\n </div>\n </div>\n </GlassCard>\n );\n })}\n\n {submit.isError && (\n <p className=\"text-sm text-status-error-text\">\n {submit.error instanceof Error ? submit.error.message : 'Could not submit your answers.'}\n </p>\n )}\n\n <div className=\"sticky bottom-0 flex items-center justify-between gap-3 border-t border-border-seam bg-bg-surface/90 py-3 backdrop-blur\">\n <span className=\"text-sm text-text-secondary tabular-nums\">\n {answeredCount} of {questions.length} answered\n </span>\n <Button onClick={handleSubmit} disabled={submit.isPending || answeredCount === 0}>\n <Send className=\"mr-1 h-4 w-4\" />\n {submit.isPending ? 'Submitting…' : 'Submit assessment'}\n </Button>\n </div>\n </div>\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"TakeAssessmentPage.js","names":[],"sources":["../../../../src/buildmyiq/pages/assessments/TakeAssessmentPage.tsx"],"sourcesContent":["/**\n * TakeAssessmentPage — the LEARNER-facing surface to attempt a published\n * assessment and submit answers.\n * @module buildmyiq/pages/assessments\n *\n * Loads the assessment + its questions, collects an answer per question (typed\n * to the question kind), resolves the caller's enrollment for the assessment's\n * course, and submits via `buiSubmitAssessment` ({ assessmentId, enrollmentId?,\n * answers }). Grading is done by an educator in the Grading queue — this page is\n * honest about that (\"submitted, awaiting grading\"). All data is live.\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n CheckCircle2,\n ClipboardCheck,\n Clock,\n FileText,\n RefreshCw,\n Send,\n Target,\n} from 'lucide-react';\nimport { Button, GlassCard, Input, Textarea } from '@burdenoff/fe-libs/ui';\nimport {\n PageLayout,\n StatusBadge,\n ProgressRing,\n LoadingView,\n ErrorView,\n EmptyState,\n} from '../../components';\nimport { useBuildmyiq } from '../../context';\nimport { useBuiAssessment, useBuiEnrollments, useBuiSubmitAssessment } from '../../hooks';\nimport { cn } from '../../utils/cn';\nimport { formatDuration, formatEnumLabel } from '../../utils/formatters';\nimport type { BuiQuestion } from '../../types';\n\ninterface Choice {\n label: string;\n}\n\n/** Narrow the untyped `options` JSON blob to a list of `{ label }` choices. */\nfunction parseChoices(options: unknown): Choice[] {\n if (!Array.isArray(options)) return [];\n return options\n .map((o) => (o && typeof o === 'object' && 'label' in o ? { label: String((o as { label: unknown }).label) } : null))\n .filter((c): c is Choice => c !== null && c.label.length > 0);\n}\n\ntype AnswerValue = string | string[];\n\nconst TRUE_FALSE_CHOICES: Choice[] = [{ label: 'True' }, { label: 'False' }];\n\ninterface MetaCellProps {\n icon: ReactNode;\n label: string;\n value: ReactNode;\n}\n\nconst MetaCell: FC<MetaCellProps> = ({ icon, label, value }) => (\n <div className=\"flex items-center gap-3 py-3 first:pt-0 last:pb-0 sm:px-5 sm:py-0 sm:first:pl-0 sm:last:pr-0\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-[var(--color-accent-teal)]\">\n {icon}\n </span>\n <div className=\"min-w-0\">\n <p className=\"text-xs text-text-secondary\">{label}</p>\n <p className=\"text-sm font-semibold text-text-primary\">{value}</p>\n </div>\n </div>\n);\n\nexport const TakeAssessmentPage: FC = () => {\n const { assessmentId } = useParams<{ assessmentId: string }>();\n const { currentUser, navigateTo } = useBuildmyiq();\n\n const assessmentQuery = useBuiAssessment(assessmentId);\n const assessment = assessmentQuery.data ?? null;\n\n const enrollmentsQuery = useBuiEnrollments({\n learnerId: currentUser?.id,\n courseId: assessment?.courseId,\n enabled: Boolean(currentUser?.id && assessment?.courseId),\n });\n const enrollmentId = enrollmentsQuery.data?.items?.[0]?.id;\n\n const submit = useBuiSubmitAssessment();\n const [answers, setAnswers] = useState<Record<string, AnswerValue>>({});\n const [submittedId, setSubmittedId] = useState<string | null>(null);\n\n const questions = useMemo<BuiQuestion[]>(\n () => [...(assessment?.questions ?? [])].sort((a, b) => a.position - b.position),\n [assessment]\n );\n\n const setAnswer = (qid: string, value: AnswerValue): void => {\n setAnswers((prev) => ({ ...prev, [qid]: value }));\n };\n\n const toggleMulti = (qid: string, label: string): void => {\n setAnswers((prev) => {\n const cur = Array.isArray(prev[qid]) ? (prev[qid] as string[]) : [];\n return { ...prev, [qid]: cur.includes(label) ? cur.filter((l) => l !== label) : [...cur, label] };\n });\n };\n\n const isAnswered = (q: BuiQuestion): boolean => {\n const a = answers[q.id];\n return Array.isArray(a) ? a.length > 0 : Boolean(a && String(a).trim());\n };\n\n const answeredCount = questions.filter(isAnswered).length;\n const answeredPct = questions.length > 0 ? (answeredCount / questions.length) * 100 : 0;\n const remaining = questions.length - answeredCount;\n const encouragement =\n answeredCount === 0\n ? 'Answer a question to get started.'\n : remaining === 0\n ? 'All questions answered — ready to submit.'\n : `${remaining} question${remaining === 1 ? '' : 's'} left to answer.`;\n\n const handleSubmit = async (): Promise<void> => {\n if (!assessmentId) return;\n const result = await submit.mutateAsync({\n assessmentId,\n enrollmentId,\n attempt: 1,\n answers,\n });\n setSubmittedId(result.id);\n };\n\n const backToCourse = assessment\n ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo(`catalog/${assessment.courseId}`)}>\n <ArrowLeft className=\"mr-1 h-4 w-4\" /> Back to course\n </Button>\n )\n : undefined;\n\n if (!assessmentId) {\n return (\n <PageLayout title=\"Assessment\">\n <EmptyState illustration=\"empty-data\" title=\"No assessment selected\" />\n </PageLayout>\n );\n }\n\n if (assessmentQuery.isLoading) {\n return (\n <PageLayout title=\"Assessment\">\n <LoadingView label=\"Loading the assessment…\" />\n </PageLayout>\n );\n }\n\n if (assessmentQuery.isError || !assessment) {\n return (\n <PageLayout title=\"Assessment\" actions={backToCourse}>\n <ErrorView\n title=\"Couldn't load this assessment\"\n message={assessmentQuery.error instanceof Error ? assessmentQuery.error.message : undefined}\n onRetry={() => assessmentQuery.refetch()}\n />\n </PageLayout>\n );\n }\n\n if (assessment.status !== 'PUBLISHED') {\n return (\n <PageLayout title={assessment.title} actions={backToCourse}>\n <EmptyState\n illustration=\"empty-data\"\n title=\"This assessment isn't open yet\"\n description=\"It has to be published by an educator before you can take it.\"\n />\n </PageLayout>\n );\n }\n\n // Submitted confirmation\n if (submittedId) {\n return (\n <PageLayout title={assessment.title} actions={backToCourse}>\n <div className=\"mx-auto max-w-lg\">\n <GlassCard treatment=\"glass\" glow className=\"flex flex-col items-center gap-4 p-8 text-center\">\n <div className=\"flex h-14 w-14 items-center justify-center rounded-full bg-status-success-bg-subtle\">\n <CheckCircle2 className=\"h-7 w-7 text-status-success-text\" />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Submitted</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Your answers for “{assessment.title}” were submitted.\n {assessment.isGraded\n ? ' An educator will grade them — you’ll see your score and feedback in My Learning.'\n : ' Thanks for completing it.'}\n </p>\n </div>\n <div className=\"flex flex-wrap justify-center gap-2\">\n <Button variant=\"secondary\" onClick={() => navigateTo('learning')}>\n Go to My Learning\n </Button>\n <Button variant=\"ghost\" onClick={() => navigateTo(`catalog/${assessment.courseId}`)}>\n Back to course\n </Button>\n </div>\n </GlassCard>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={assessment.title}\n description={assessment.description ?? undefined}\n actions={backToCourse}\n >\n <div className=\"mx-auto max-w-3xl pb-4\">\n {/* Meta strip — type · passing score · time limit · attempts · answered */}\n <GlassCard treatment=\"glass\" className=\"mb-6 p-4 sm:px-5\">\n <div className=\"flex flex-col divide-y divide-border-seam sm:flex-row sm:flex-wrap sm:items-center sm:divide-x sm:divide-y-0\">\n <MetaCell\n icon={<FileText className=\"h-4 w-4\" />}\n label=\"Type\"\n value={<StatusBadge status={assessment.type} />}\n />\n <MetaCell\n icon={<Target className=\"h-4 w-4\" />}\n label=\"Passing score\"\n value={`${assessment.passingScore}%`}\n />\n {assessment.timeLimitMin > 0 && (\n <MetaCell\n icon={<Clock className=\"h-4 w-4\" />}\n label=\"Time limit\"\n value={formatDuration(assessment.timeLimitMin)}\n />\n )}\n {assessment.maxAttempts > 0 && (\n <MetaCell\n icon={<RefreshCw className=\"h-4 w-4\" />}\n label=\"Attempts\"\n value={assessment.maxAttempts}\n />\n )}\n <div className=\"flex items-center gap-3 py-3 sm:ml-auto sm:py-0 sm:pl-5\">\n <ProgressRing\n value={answeredPct}\n size={44}\n stroke={5}\n label={`${answeredCount}/${questions.length}`}\n />\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary tabular-nums\">\n {answeredCount} of {questions.length}\n </p>\n <p className=\"text-xs text-text-secondary\">answered</p>\n </div>\n </div>\n </div>\n </GlassCard>\n\n {questions.length === 0 ? (\n <EmptyState\n icon={<ClipboardCheck className=\"h-8 w-8\" />}\n title=\"No questions yet\"\n description=\"This assessment doesn't have any questions to answer.\"\n />\n ) : (\n <div className=\"flex flex-col gap-4\">\n {questions.map((q, idx) => {\n const choices =\n q.type === 'TRUE_FALSE' ? TRUE_FALSE_CHOICES : parseChoices(q.options);\n const answer = answers[q.id];\n const answered = isAnswered(q);\n return (\n <GlassCard\n key={q.id}\n treatment={answered ? 'insight' : 'plain'}\n className={cn(\n 'p-5 transition-shadow',\n answered && 'ring-1 ring-[var(--color-accent-soft)]'\n )}\n >\n <div className=\"flex items-start gap-3 sm:gap-4\">\n <span\n className={cn(\n 'mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-sm font-semibold tabular-nums transition-colors',\n answered\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-[var(--color-accent-soft)] text-text-primary'\n )}\n >\n {answered ? <CheckCircle2 className=\"h-4 w-4\" /> : idx + 1}\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded-md bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {formatEnumLabel(q.type)}\n </span>\n <span className=\"ml-auto text-xs text-text-secondary tabular-nums\">\n {q.points} {q.points === 1 ? 'point' : 'points'}\n </span>\n </div>\n <p className=\"mt-2.5 font-medium text-text-primary\">{q.prompt}</p>\n\n <div className=\"mt-4\">\n {(q.type === 'SINGLE_CHOICE' || q.type === 'TRUE_FALSE') && (\n <div className=\"flex flex-col gap-2\">\n {choices.map((c) => (\n <label\n key={c.label}\n className={cn(\n 'flex min-h-[44px] cursor-pointer items-center gap-3 rounded-xl border px-3.5 py-2.5 text-sm transition-colors',\n answer === c.label\n ? 'border-[var(--color-accent-teal)] bg-[var(--color-accent-soft)] text-text-primary'\n : 'border-border-seam text-text-secondary hover:border-border-strong hover:bg-bg-sunken'\n )}\n >\n <input\n type=\"radio\"\n name={q.id}\n className=\"h-4 w-4 accent-[var(--color-accent-teal)]\"\n checked={answer === c.label}\n onChange={() => setAnswer(q.id, c.label)}\n />\n {c.label}\n </label>\n ))}\n </div>\n )}\n\n {q.type === 'MULTIPLE_CHOICE' && (\n <div className=\"flex flex-col gap-2\">\n {choices.map((c) => {\n const checked = Array.isArray(answer) && answer.includes(c.label);\n return (\n <label\n key={c.label}\n className={cn(\n 'flex min-h-[44px] cursor-pointer items-center gap-3 rounded-xl border px-3.5 py-2.5 text-sm transition-colors',\n checked\n ? 'border-[var(--color-accent-teal)] bg-[var(--color-accent-soft)] text-text-primary'\n : 'border-border-seam text-text-secondary hover:border-border-strong hover:bg-bg-sunken'\n )}\n >\n <input\n type=\"checkbox\"\n className=\"h-4 w-4 rounded accent-[var(--color-accent-teal)]\"\n checked={checked}\n onChange={() => toggleMulti(q.id, c.label)}\n />\n {c.label}\n </label>\n );\n })}\n </div>\n )}\n\n {q.type === 'SHORT_ANSWER' && (\n <Input\n value={typeof answer === 'string' ? answer : ''}\n onChange={(e) => setAnswer(q.id, e.target.value)}\n placeholder=\"Type your answer here…\"\n />\n )}\n\n {(q.type === 'ESSAY' || q.type === 'CODE') && (\n <Textarea\n rows={q.type === 'CODE' ? 6 : 4}\n value={typeof answer === 'string' ? answer : ''}\n onChange={(e) => setAnswer(q.id, e.target.value)}\n placeholder={q.type === 'CODE' ? 'Write your code…' : 'Write your answer…'}\n className={q.type === 'CODE' ? 'font-mono text-sm' : undefined}\n />\n )}\n </div>\n </div>\n </div>\n </GlassCard>\n );\n })}\n\n {submit.isError && (\n <p className=\"text-sm text-status-error-text\">\n {submit.error instanceof Error ? submit.error.message : 'Could not submit your answers.'}\n </p>\n )}\n\n {/* Sticky submit bar */}\n <div className=\"sticky bottom-0 z-10 pt-2\">\n <div className=\"flex flex-col gap-3 rounded-2xl border border-border-seam bg-bg-surface/90 p-4 shadow-elevation-2 backdrop-blur sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-center gap-3\">\n <ProgressRing\n value={answeredPct}\n size={44}\n stroke={5}\n label={`${answeredCount}/${questions.length}`}\n />\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary tabular-nums\">\n {answeredCount} of {questions.length} answered\n </p>\n <p className=\"text-xs text-text-secondary\">{encouragement}</p>\n </div>\n </div>\n <Button\n size=\"lg\"\n className=\"max-sm:w-full\"\n onClick={handleSubmit}\n disabled={submit.isPending || answeredCount === 0}\n >\n <Send className=\"mr-1.5 h-4 w-4\" />\n {submit.isPending ? 'Submitting…' : 'Submit assessment'}\n </Button>\n </div>\n </div>\n </div>\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AuthoringPage.d.ts","sourceRoot":"","sources":["../../../../src/buildmyiq/pages/authoring/AuthoringPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAmLhC,eAAO,MAAM,aAAa,EAAE,EAgH3B,CAAC"}
1
+ {"version":3,"file":"AuthoringPage.d.ts","sourceRoot":"","sources":["../../../../src/buildmyiq/pages/authoring/AuthoringPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAmLhC,eAAO,MAAM,aAAa,EAAE,EA0H3B,CAAC"}