@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,24 +1,26 @@
1
1
  import { useBuildmyiq as e } from "../../context/BuildmyiqContext.js";
2
2
  import { PageLayout as t } from "../../components/PageLayout.js";
3
3
  import { MetricsCard as n } from "../../components/MetricsCard.js";
4
- import { formatDateTime 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 ee } from "../../components/StateViews.js";
8
- import { DataTable as te } from "../../components/DataTable.js";
9
- import { FilterTabs as s } from "../../components/FilterTabs.js";
4
+ import { formatDate as r, formatDateTime as i } from "../../utils/formatters.js";
5
+ import { StatusBadge as a } from "../../components/StatusBadge.js";
6
+ import { EmptyState as ee } from "../../components/EmptyState.js";
7
+ import { ErrorView as o, LoadingView as te } from "../../components/StateViews.js";
8
+ import { DataTable as ne } from "../../components/DataTable.js";
9
+ import { Tabs as s } from "../../components/Tabs.js";
10
10
  import { Pagination as c } from "../../components/Pagination.js";
11
+ import { Avatar as l } from "../../components/Avatar.js";
11
12
  import "../../context/index.js";
12
- import { useBuiGradeSubmission as l, useBuiSubmissions as ne } from "../../hooks/useBuildmyiqApi.js";
13
- import { useCursorPager as re } from "../../hooks/useCursorPager.js";
13
+ import { useBuiGradeSubmission as u, useBuiSubmissions as re } from "../../hooks/useBuildmyiqApi.js";
14
+ import { useCursorPager as ie } from "../../hooks/useCursorPager.js";
14
15
  import "../../hooks/index.js";
15
16
  import "../../components/index.js";
16
- import { useMemo as u, useState as d } from "react";
17
- import { CheckCircle2 as f, ClipboardList as p, Clock as m, GraduationCap as h, Undo2 as ie } from "lucide-react";
18
- import { Fragment as ae, jsx as g, jsxs as _ } from "react/jsx-runtime";
19
- import { Button as v, Input as y, Label as b, ResponsiveDialog as x, ResponsiveDialogContent as S, ResponsiveDialogDescription as C, ResponsiveDialogFooter as w, ResponsiveDialogHeader as T, ResponsiveDialogTitle as oe, Switch as se, Textarea as ce } from "@burdenoff/fe-libs/ui";
17
+ import { useMemo as d, useState as f } from "react";
18
+ import { BookOpen as ae, CheckCircle2 as oe, ClipboardList as p, Clock as se, GraduationCap as m, Undo2 as h } from "lucide-react";
19
+ import { Fragment as ce, jsx as g, jsxs as _ } from "react/jsx-runtime";
20
+ import { Button as v, Input as y, Label as b, Sheet as x, SheetContent as le, SheetDescription as ue, SheetFooter as de, SheetHeader as fe, SheetTitle as pe, Switch as me, Textarea as he } from "@burdenoff/fe-libs/ui";
21
+ import { useMediaQuery as ge } from "@burdenoff/fe-libs/shared/hooks";
20
22
  //#region src/buildmyiq/pages/submissions/SubmissionsPage.tsx
21
- var E = 24, le = [
23
+ var S = 24, _e = [
22
24
  {
23
25
  value: "ALL",
24
26
  label: "All"
@@ -39,35 +41,53 @@ var E = 24, le = [
39
41
  value: "RETURNED",
40
42
  label: "Returned"
41
43
  }
42
- ], D = (e) => e.length > 10 ? `${e.slice(0, 8)}…` : e, O = (e) => typeof e == "object" && !!e && !Array.isArray(e), k = (e) => e == null ? "—" : typeof e == "string" ? e : typeof e == "number" || typeof e == "boolean" ? String(e) : JSON.stringify(e, null, 2), A = ({ answers: e }) => {
44
+ ], ve = [{
45
+ value: "submission",
46
+ label: "Submission"
47
+ }, {
48
+ value: "details",
49
+ label: "Details"
50
+ }], C = (e) => e.length > 10 ? `${e.slice(0, 8)}…` : e, ye = (e) => r(e, {
51
+ day: void 0,
52
+ month: void 0,
53
+ year: void 0,
54
+ hour: "numeric",
55
+ minute: "2-digit"
56
+ }), w = (e) => typeof e == "object" && !!e && !Array.isArray(e), T = (e) => e == null ? "—" : typeof e == "string" ? e : typeof e == "number" || typeof e == "boolean" ? String(e) : JSON.stringify(e, null, 2), E = ({ answers: e }) => {
43
57
  if (e == null) return /* @__PURE__ */ g("p", {
44
58
  className: "text-sm text-text-secondary",
45
59
  children: "No answers were submitted."
46
60
  });
47
- if (O(e)) {
61
+ if (w(e)) {
48
62
  let t = Object.entries(e);
49
63
  return t.length === 0 ? /* @__PURE__ */ g("p", {
50
64
  className: "text-sm text-text-secondary",
51
65
  children: "No answers were submitted."
52
- }) : /* @__PURE__ */ g("dl", {
53
- className: "divide-y divide-border-seam/60",
54
- children: t.map(([e, t]) => /* @__PURE__ */ _("div", {
55
- className: "grid gap-1 py-2 sm:grid-cols-3 sm:gap-3",
56
- children: [/* @__PURE__ */ g("dt", {
57
- className: "break-words font-mono text-xs text-text-secondary sm:col-span-1",
58
- children: e
59
- }), /* @__PURE__ */ g("dd", {
60
- className: "whitespace-pre-wrap break-words text-sm text-text-primary sm:col-span-2",
61
- children: k(t)
66
+ }) : /* @__PURE__ */ g("ol", {
67
+ className: "grid gap-2.5",
68
+ children: t.map(([e, t], n) => /* @__PURE__ */ _("li", {
69
+ className: "grid gap-1 rounded-lg border border-border-seam/70 bg-bg-surface/60 p-3 sm:grid-cols-[minmax(0,7rem)_1fr] sm:gap-3",
70
+ children: [/* @__PURE__ */ _("div", {
71
+ className: "flex items-baseline gap-2 sm:col-span-1",
72
+ children: [/* @__PURE__ */ _("span", {
73
+ className: "shrink-0 text-xs font-semibold text-[var(--color-accent-teal)] tabular-nums",
74
+ children: ["Q", n + 1]
75
+ }), /* @__PURE__ */ g("span", {
76
+ className: "break-words font-mono text-xs text-text-secondary",
77
+ children: e
78
+ })]
79
+ }), /* @__PURE__ */ g("span", {
80
+ className: "whitespace-pre-wrap break-words text-sm text-text-primary sm:col-span-1",
81
+ children: T(t)
62
82
  })]
63
83
  }, e))
64
84
  });
65
85
  }
66
86
  return /* @__PURE__ */ g("pre", {
67
- className: "overflow-x-auto whitespace-pre-wrap break-words text-xs text-text-primary",
87
+ className: "overflow-x-auto whitespace-pre-wrap break-words rounded-lg border border-border-seam/70 bg-bg-surface/60 p-3 text-xs text-text-primary",
68
88
  children: JSON.stringify(e, null, 2)
69
89
  });
70
- }, j = ({ label: e, children: t }) => /* @__PURE__ */ _("div", {
90
+ }, D = ({ label: e, children: t }) => /* @__PURE__ */ _("div", {
71
91
  className: "min-w-0",
72
92
  children: [/* @__PURE__ */ g("p", {
73
93
  className: "text-xs font-medium uppercase tracking-wide text-text-secondary",
@@ -76,50 +96,54 @@ var E = 24, le = [
76
96
  className: "mt-0.5 text-sm text-text-primary",
77
97
  children: t
78
98
  })]
79
- }), M = () => {
80
- let { currentUser: O } = e(), [k, M] = d("ALL"), N = re(), [P, F] = d(null), [I, L] = d(!1), [R, z] = d(""), [B, V] = d(!1), [H, U] = d(""), [W, G] = d(null), { data: K, isLoading: ue, isError: de, refetch: fe } = ne({
81
- status: k === "ALL" ? void 0 : k,
82
- cursor: N.cursor,
83
- limit: E
84
- }), q = l(), J = u(() => K?.items ?? [], [K]), Y = u(() => {
99
+ }), O = () => {
100
+ let { currentUser: w } = e(), T = ge("(min-width: 768px)"), [O, k] = f("ALL"), A = ie(), [j, M] = f(null), [N, P] = f("submission"), [F, I] = f(!1), [L, R] = f(""), [z, B] = f(!1), [V, H] = f(""), [U, W] = f(null), { data: G, isLoading: be, isError: xe, refetch: Se } = re({
101
+ status: O === "ALL" ? void 0 : O,
102
+ cursor: A.cursor,
103
+ limit: S
104
+ }), K = u(), q = d(() => G?.items ?? [], [G]), J = d(() => {
105
+ if (!w) return;
106
+ let e = [w.firstName, w.lastName].filter(Boolean).join(" ").trim();
107
+ return w.name?.trim() || e || w.username || w.email;
108
+ }, [w]), Y = d(() => {
85
109
  let e = {
86
- total: J.length,
110
+ total: q.length,
87
111
  awaiting: 0,
88
112
  graded: 0,
89
113
  returned: 0
90
114
  };
91
- for (let t of J) t.status === "SUBMITTED" || t.status === "GRADING" ? e.awaiting += 1 : t.status === "GRADED" ? e.graded += 1 : t.status === "RETURNED" && (e.returned += 1);
115
+ for (let t of q) t.status === "SUBMITTED" || t.status === "GRADING" ? e.awaiting += 1 : t.status === "GRADED" ? e.graded += 1 : t.status === "RETURNED" && (e.returned += 1);
92
116
  return e;
93
- }, [J]), pe = (e) => {
94
- F(e), z(e.score == null ? "" : String(e.score)), V(e.passed ?? !1), U(e.feedback ?? ""), L(!1), G(null);
95
- }, X = () => {
96
- F(null), L(!1), G(null);
97
- }, me = (e) => {
98
- M(e), N.reset();
99
- }, he = async () => {
100
- if (!P) return;
101
- let e = R.trim(), t = Number(e);
117
+ }, [q]), X = (e) => e === w?.id, Ce = (e) => X(e) ? "You" : `Learner ${C(e)}`, we = (e) => {
118
+ M(e), P("submission"), R(e.score == null ? "" : String(e.score)), B(e.passed ?? !1), H(e.feedback ?? ""), I(!1), W(null);
119
+ }, Z = () => {
120
+ M(null), I(!1), W(null);
121
+ }, Te = (e) => {
122
+ k(e), A.reset();
123
+ }, Ee = async () => {
124
+ if (!j) return;
125
+ let e = L.trim(), t = Number(e);
102
126
  if (e === "" || Number.isNaN(t)) {
103
- G("Enter a numeric score.");
127
+ W("Enter a numeric score.");
104
128
  return;
105
129
  }
106
130
  if (t < 0) {
107
- G("Score cannot be negative.");
131
+ W("Score cannot be negative.");
108
132
  return;
109
133
  }
110
134
  try {
111
- await q.mutateAsync({
112
- id: P.id,
135
+ await K.mutateAsync({
136
+ id: j.id,
113
137
  input: {
114
138
  score: t,
115
- passed: B,
116
- feedback: H.trim() || void 0
139
+ passed: z,
140
+ feedback: V.trim() || void 0
117
141
  }
118
- }), X();
142
+ }), Z();
119
143
  } catch (e) {
120
- G(e instanceof Error ? e.message : "Failed to save grade.");
144
+ W(e instanceof Error ? e.message : "Failed to save grade.");
121
145
  }
122
- }, Z = P != null && (P.status === "SUBMITTED" || P.status === "GRADING"), Q = P != null && (P.status === "GRADED" || P.status === "RETURNED"), ge = P != null && P.status === "IN_PROGRESS", $ = P != null && (Z || I);
146
+ }, De = j != null && (j.status === "SUBMITTED" || j.status === "GRADING"), Q = j != null && (j.status === "GRADED" || j.status === "RETURNED"), Oe = j != null && j.status === "IN_PROGRESS", $ = j != null && (De || F);
123
147
  return /* @__PURE__ */ _(t, {
124
148
  title: "Grading",
125
149
  description: "Review and grade assessment submissions across every course in your workspace.",
@@ -138,296 +162,376 @@ var E = 24, le = [
138
162
  featured: !0
139
163
  }),
140
164
  /* @__PURE__ */ g(n, {
141
- icon: /* @__PURE__ */ g(m, { className: "h-5 w-5" }),
165
+ icon: /* @__PURE__ */ g(se, { className: "h-5 w-5" }),
142
166
  value: Y.awaiting,
143
167
  label: "Awaiting grade (this page)",
144
168
  accent: "warning"
145
169
  }),
146
170
  /* @__PURE__ */ g(n, {
147
- icon: /* @__PURE__ */ g(f, { className: "h-5 w-5" }),
171
+ icon: /* @__PURE__ */ g(oe, { className: "h-5 w-5" }),
148
172
  value: Y.graded,
149
173
  label: "Graded (this page)",
150
174
  accent: "success"
151
175
  }),
152
176
  /* @__PURE__ */ g(n, {
153
- icon: /* @__PURE__ */ g(ie, { className: "h-5 w-5" }),
177
+ icon: /* @__PURE__ */ g(h, { className: "h-5 w-5" }),
154
178
  value: Y.returned,
155
179
  label: "Returned (this page)"
156
180
  })
157
181
  ]
158
182
  }),
159
183
  /* @__PURE__ */ g(s, {
160
- options: le,
161
- value: k,
162
- onChange: me
184
+ items: _e,
185
+ value: O,
186
+ onChange: Te
163
187
  }),
164
- ue ? /* @__PURE__ */ g(ee, { label: "Loading submissions…" }) : de ? /* @__PURE__ */ g(o, {
188
+ be ? /* @__PURE__ */ g(te, { label: "Loading submissions…" }) : xe ? /* @__PURE__ */ g(o, {
165
189
  title: "Couldn't load submissions",
166
190
  message: "The grading queue failed to load.",
167
- onRetry: () => fe()
168
- }) : J.length === 0 ? /* @__PURE__ */ g(a, {
191
+ onRetry: () => Se()
192
+ }) : q.length === 0 ? /* @__PURE__ */ g(ee, {
169
193
  illustration: "empty-data",
170
- icon: /* @__PURE__ */ g(h, { className: "h-10 w-10" }),
171
- title: k === "ALL" ? "No submissions yet" : "Nothing in this status",
172
- description: k === "ALL" ? "When learners submit assessments, their attempts will appear here for grading." : "No submissions currently match this status filter."
173
- }) : /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g(te, {
174
- columns: [
175
- {
176
- key: "learner",
177
- header: "Learner",
178
- sortValue: (e) => e.learnerId,
179
- render: (e) => e.learnerId === O?.id ? /* @__PURE__ */ g("span", {
180
- className: "font-medium text-text-primary",
181
- children: "You"
182
- }) : /* @__PURE__ */ g("span", {
183
- className: "font-mono text-xs text-text-secondary",
184
- title: e.learnerId,
185
- children: D(e.learnerId)
186
- })
187
- },
188
- {
189
- key: "assessment",
190
- header: "Assessment",
191
- hideOnMobile: !0,
192
- render: (e) => /* @__PURE__ */ g("span", {
193
- className: "font-mono text-xs text-text-secondary",
194
- title: e.assessmentId,
195
- children: D(e.assessmentId)
196
- })
197
- },
198
- {
199
- key: "attempt",
200
- header: "Attempt",
201
- align: "right",
202
- hideOnMobile: !0,
203
- sortValue: (e) => e.attempt,
204
- render: (e) => /* @__PURE__ */ _("span", {
205
- className: "tabular-nums text-text-secondary",
206
- children: ["#", e.attempt]
207
- })
208
- },
209
- {
210
- key: "status",
211
- header: "Status",
212
- sortValue: (e) => e.status,
213
- render: (e) => /* @__PURE__ */ g(i, { status: e.status })
214
- },
215
- {
216
- key: "score",
217
- header: "Score",
218
- align: "right",
219
- sortValue: (e) => e.score ?? -1,
220
- render: (e) => /* @__PURE__ */ g("span", {
221
- className: "tabular-nums font-medium text-text-primary",
222
- children: e.score ?? "—"
223
- })
224
- },
225
- {
194
+ icon: /* @__PURE__ */ g(m, { className: "h-10 w-10" }),
195
+ title: O === "ALL" ? "No submissions yet" : "Nothing in this status",
196
+ description: O === "ALL" ? "When learners submit assessments, their attempts will appear here for grading." : "No submissions currently match this status filter."
197
+ }) : /* @__PURE__ */ _("div", {
198
+ className: "flex flex-col gap-4",
199
+ children: [/* @__PURE__ */ g(ne, {
200
+ columns: [
201
+ {
202
+ key: "learner",
203
+ header: "Learner",
204
+ sortValue: (e) => X(e.learnerId) ? "" : e.learnerId,
205
+ render: (e) => /* @__PURE__ */ _("div", {
206
+ className: "flex items-center gap-3",
207
+ children: [/* @__PURE__ */ g(l, {
208
+ size: "sm",
209
+ name: X(e.learnerId) ? J : void 0,
210
+ seed: e.learnerId,
211
+ src: X(e.learnerId) ? w?.avatar : void 0
212
+ }), /* @__PURE__ */ _("div", {
213
+ className: "min-w-0",
214
+ children: [/* @__PURE__ */ g("span", {
215
+ className: "block truncate font-medium text-text-primary",
216
+ title: e.learnerId,
217
+ children: X(e.learnerId) ? "You" : C(e.learnerId)
218
+ }), X(e.learnerId) && J && /* @__PURE__ */ g("span", {
219
+ className: "block truncate text-xs text-text-secondary",
220
+ children: J
221
+ })]
222
+ })]
223
+ })
224
+ },
225
+ {
226
+ key: "assessment",
227
+ header: "Assessment",
228
+ hideOnMobile: !0,
229
+ render: (e) => /* @__PURE__ */ _("span", {
230
+ className: "inline-flex items-center gap-2 text-text-secondary",
231
+ children: [/* @__PURE__ */ g(ae, { className: "h-4 w-4 shrink-0 opacity-70" }), /* @__PURE__ */ g("span", {
232
+ className: "font-mono text-xs",
233
+ title: e.assessmentId,
234
+ children: C(e.assessmentId)
235
+ })]
236
+ })
237
+ },
238
+ {
239
+ key: "attempt",
240
+ header: "Attempt",
241
+ align: "right",
242
+ hideOnMobile: !0,
243
+ sortValue: (e) => e.attempt,
244
+ render: (e) => /* @__PURE__ */ _("span", {
245
+ className: "tabular-nums text-text-secondary",
246
+ children: ["#", e.attempt]
247
+ })
248
+ },
249
+ {
250
+ key: "status",
251
+ header: "Status",
252
+ sortValue: (e) => e.status,
253
+ render: (e) => /* @__PURE__ */ g(a, { status: e.status })
254
+ },
255
+ {
256
+ key: "score",
257
+ header: "Score",
258
+ align: "right",
259
+ sortValue: (e) => e.score ?? -1,
260
+ render: (e) => e.score == null ? /* @__PURE__ */ g("span", {
261
+ className: "text-text-secondary",
262
+ children: "—"
263
+ }) : /* @__PURE__ */ g("span", {
264
+ className: "tabular-nums font-semibold text-text-primary",
265
+ children: e.score
266
+ })
267
+ },
268
+ {
269
+ key: "submittedAt",
270
+ header: "Submitted",
271
+ align: "right",
272
+ hideOnMobile: !0,
273
+ sortValue: (e) => e.submittedAt ?? e.createdAt,
274
+ render: (e) => /* @__PURE__ */ _("div", {
275
+ className: "whitespace-nowrap text-right",
276
+ children: [/* @__PURE__ */ g("div", {
277
+ className: "text-text-primary",
278
+ children: r(e.submittedAt)
279
+ }), e.submittedAt && /* @__PURE__ */ g("div", {
280
+ className: "text-xs text-text-secondary",
281
+ children: ye(e.submittedAt)
282
+ })]
283
+ })
284
+ }
285
+ ],
286
+ rows: q,
287
+ rowKey: (e) => e.id,
288
+ onRowClick: we,
289
+ defaultSort: {
226
290
  key: "submittedAt",
227
- header: "Submitted",
228
- hideOnMobile: !0,
229
- sortValue: (e) => e.submittedAt ?? e.createdAt,
230
- render: (e) => /* @__PURE__ */ g("span", {
231
- className: "whitespace-nowrap text-text-secondary",
232
- children: r(e.submittedAt)
233
- })
291
+ dir: "desc"
234
292
  }
235
- ],
236
- rows: J,
237
- rowKey: (e) => e.id,
238
- onRowClick: pe,
239
- defaultSort: {
240
- key: "submittedAt",
241
- dir: "desc"
242
- }
243
- }), /* @__PURE__ */ g(c, {
244
- page: N.page,
245
- pageSize: E,
246
- itemCount: J.length,
247
- hasMore: K?.pageInfo?.hasMore ?? !1,
248
- onPageChange: (e) => N.onPageChange(e, K?.pageInfo?.cursor)
249
- })] })
293
+ }), /* @__PURE__ */ g(c, {
294
+ page: A.page,
295
+ pageSize: S,
296
+ itemCount: q.length,
297
+ hasMore: G?.pageInfo?.hasMore ?? !1,
298
+ onPageChange: (e) => A.onPageChange(e, G?.pageInfo?.cursor)
299
+ })]
300
+ })
250
301
  ]
251
302
  }), /* @__PURE__ */ g(x, {
252
- open: P != null,
303
+ open: j != null,
253
304
  onOpenChange: (e) => {
254
- e || X();
305
+ e || Z();
255
306
  },
256
- children: /* @__PURE__ */ g(S, {
257
- className: "max-h-[88vh] overflow-y-auto sm:max-w-[640px]",
258
- children: P && /* @__PURE__ */ _(ae, { children: [
259
- /* @__PURE__ */ _(T, { children: [/* @__PURE__ */ g(oe, { children: Z || I ? "Grade submission" : "Submission details" }), /* @__PURE__ */ _(C, { children: [
260
- P.learnerId === O?.id ? "Your attempt" : `Learner ${D(P.learnerId)}`,
261
- " ",
262
- "· attempt #",
263
- P.attempt
264
- ] })] }),
265
- /* @__PURE__ */ _("div", {
266
- className: "grid gap-5 py-2",
307
+ children: /* @__PURE__ */ g(le, {
308
+ side: T ? "right" : "bottom",
309
+ className: T ? "flex w-full max-w-none flex-col gap-0 p-0 sm:max-w-xl" : "flex max-h-[92vh] w-full flex-col gap-0 rounded-t-2xl p-0",
310
+ children: j && /* @__PURE__ */ _(ce, { children: [
311
+ /* @__PURE__ */ _(fe, {
312
+ className: "border-b border-border-seam p-5 pr-12",
267
313
  children: [
268
314
  /* @__PURE__ */ _("div", {
269
- className: "grid grid-cols-2 gap-4 rounded-xl bg-bg-sunken/60 p-4 sm:grid-cols-3",
315
+ className: "flex items-center gap-3",
316
+ children: [/* @__PURE__ */ g(l, {
317
+ size: "md",
318
+ name: X(j.learnerId) ? J : void 0,
319
+ seed: j.learnerId,
320
+ src: X(j.learnerId) ? w?.avatar : void 0
321
+ }), /* @__PURE__ */ _("div", {
322
+ className: "min-w-0",
323
+ children: [/* @__PURE__ */ g(pe, {
324
+ className: "truncate text-lg",
325
+ children: Ce(j.learnerId)
326
+ }), /* @__PURE__ */ _(ue, {
327
+ className: "truncate font-mono text-xs",
328
+ title: j.assessmentId,
329
+ children: ["Assessment ", C(j.assessmentId)]
330
+ })]
331
+ })]
332
+ }),
333
+ /* @__PURE__ */ _("p", {
334
+ className: "text-xs text-text-secondary",
335
+ children: [
336
+ "Attempt #",
337
+ j.attempt,
338
+ " · Submitted ",
339
+ i(j.submittedAt)
340
+ ]
341
+ }),
342
+ /* @__PURE__ */ g("div", {
343
+ className: "pt-1",
344
+ children: /* @__PURE__ */ g(a, { status: j.status })
345
+ })
346
+ ]
347
+ }),
348
+ /* @__PURE__ */ _("div", {
349
+ className: "flex-1 overflow-y-auto px-5 py-4",
350
+ children: [
351
+ /* @__PURE__ */ g(s, {
352
+ items: ve,
353
+ value: N,
354
+ onChange: P,
355
+ className: "mb-4"
356
+ }),
357
+ N === "submission" ? /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ _("p", {
358
+ className: "mb-2 text-sm font-semibold text-text-primary",
270
359
  children: [
271
- /* @__PURE__ */ g(j, {
360
+ "Answers",
361
+ " ",
362
+ /* @__PURE__ */ g("span", {
363
+ className: "font-normal text-text-secondary",
364
+ children: "(read-only)"
365
+ })
366
+ ]
367
+ }), /* @__PURE__ */ g(E, { answers: j.answers })] }) : /* @__PURE__ */ _("div", {
368
+ className: "grid grid-cols-2 gap-4 rounded-xl bg-bg-sunken/60 p-4",
369
+ children: [
370
+ /* @__PURE__ */ g(D, {
272
371
  label: "Status",
273
- children: /* @__PURE__ */ g(i, { status: P.status })
372
+ children: /* @__PURE__ */ g(a, { status: j.status })
274
373
  }),
275
- /* @__PURE__ */ g(j, {
374
+ /* @__PURE__ */ g(D, {
276
375
  label: "Attempt",
277
376
  children: /* @__PURE__ */ _("span", {
278
377
  className: "tabular-nums",
279
- children: ["#", P.attempt]
378
+ children: ["#", j.attempt]
280
379
  })
281
380
  }),
282
- /* @__PURE__ */ g(j, {
381
+ /* @__PURE__ */ g(D, {
283
382
  label: "Submitted",
284
- children: r(P.submittedAt)
383
+ children: i(j.submittedAt)
285
384
  }),
286
- /* @__PURE__ */ g(j, {
385
+ /* @__PURE__ */ g(D, {
287
386
  label: "Assessment",
288
387
  children: /* @__PURE__ */ g("span", {
289
388
  className: "font-mono text-xs",
290
- title: P.assessmentId,
291
- children: D(P.assessmentId)
389
+ title: j.assessmentId,
390
+ children: C(j.assessmentId)
292
391
  })
293
392
  }),
294
- P.enrollmentId && /* @__PURE__ */ g(j, {
393
+ j.enrollmentId && /* @__PURE__ */ g(D, {
295
394
  label: "Enrollment",
296
395
  children: /* @__PURE__ */ g("span", {
297
396
  className: "font-mono text-xs",
298
- title: P.enrollmentId,
299
- children: D(P.enrollmentId)
397
+ title: j.enrollmentId,
398
+ children: C(j.enrollmentId)
300
399
  })
301
400
  }),
302
- P.gradedAt && /* @__PURE__ */ g(j, {
401
+ j.gradedAt && /* @__PURE__ */ g(D, {
303
402
  label: "Graded",
304
- children: r(P.gradedAt)
403
+ children: i(j.gradedAt)
305
404
  })
306
405
  ]
307
406
  }),
308
- /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("p", {
309
- className: "mb-2 text-sm font-semibold text-text-primary",
310
- children: "Answers"
311
- }), /* @__PURE__ */ g("div", {
312
- className: "max-h-64 overflow-y-auto rounded-xl border border-border-seam p-4",
313
- children: /* @__PURE__ */ g(A, { answers: P.answers })
314
- })] }),
315
- ge && /* @__PURE__ */ g("p", {
316
- className: "rounded-lg bg-bg-sunken/60 px-4 py-3 text-sm text-text-secondary",
317
- children: "This attempt is still in progress — there is nothing to grade until the learner submits."
318
- }),
319
- Q && !I && /* @__PURE__ */ _("div", {
320
- className: "rounded-xl border border-border-seam p-4",
321
- children: [/* @__PURE__ */ _("div", {
322
- className: "flex items-start justify-between gap-3",
323
- children: [/* @__PURE__ */ _("div", {
324
- className: "grid grid-cols-2 gap-4",
325
- children: [/* @__PURE__ */ g(j, {
326
- label: "Score",
327
- children: /* @__PURE__ */ g("span", {
328
- className: "tabular-nums font-semibold",
329
- children: P.score ?? "—"
330
- })
331
- }), /* @__PURE__ */ g(j, {
332
- label: "Result",
333
- children: P.passed == null ? /* @__PURE__ */ g("span", {
334
- className: "text-text-secondary",
335
- children: "—"
336
- }) : /* @__PURE__ */ g(i, { status: P.passed ? "GRADED" : "RETURNED" })
337
- })]
338
- }), /* @__PURE__ */ g(v, {
339
- variant: "outline",
340
- size: "sm",
341
- onClick: () => L(!0),
342
- children: "Re-grade"
343
- })]
344
- }), /* @__PURE__ */ g("div", {
345
- className: "mt-3",
346
- children: /* @__PURE__ */ g(j, {
347
- label: "Feedback",
348
- children: P.feedback ? /* @__PURE__ */ g("span", {
349
- className: "whitespace-pre-wrap",
350
- children: P.feedback
351
- }) : /* @__PURE__ */ g("span", {
352
- className: "text-text-secondary",
353
- children: "No feedback provided."
354
- })
355
- })
356
- })]
357
- }),
358
- $ && /* @__PURE__ */ _("div", {
359
- className: "grid gap-4",
407
+ /* @__PURE__ */ _("div", {
408
+ className: "mt-6 border-t border-border-seam pt-5",
360
409
  children: [
361
- /* @__PURE__ */ _("div", {
362
- className: "grid gap-2 sm:grid-cols-2",
410
+ /* @__PURE__ */ g("p", {
411
+ className: "mb-3 text-sm font-semibold text-text-primary",
412
+ children: "Grade"
413
+ }),
414
+ Oe && /* @__PURE__ */ g("p", {
415
+ className: "rounded-lg bg-bg-sunken/60 px-4 py-3 text-sm text-text-secondary",
416
+ children: "This attempt is still in progress — there is nothing to grade until the learner submits."
417
+ }),
418
+ Q && !F && /* @__PURE__ */ _("div", {
419
+ className: "rounded-xl border border-border-seam p-4",
363
420
  children: [/* @__PURE__ */ _("div", {
364
- className: "grid gap-1.5",
365
- children: [/* @__PURE__ */ g(b, {
366
- htmlFor: "grade-score",
367
- children: "Score"
368
- }), /* @__PURE__ */ g(y, {
369
- id: "grade-score",
370
- type: "number",
371
- min: "0",
372
- step: "1",
373
- value: R,
374
- onChange: (e) => z(e.target.value),
375
- placeholder: "e.g. 85"
376
- })]
377
- }), /* @__PURE__ */ _("div", {
378
- className: "grid gap-1.5",
379
- children: [/* @__PURE__ */ g(b, {
380
- htmlFor: "grade-passed",
381
- children: "Result"
382
- }), /* @__PURE__ */ _("div", {
383
- className: "flex h-9 items-center gap-3",
384
- children: [/* @__PURE__ */ g(se, {
385
- id: "grade-passed",
386
- checked: B,
387
- onCheckedChange: V
388
- }), /* @__PURE__ */ g("span", {
389
- className: "text-sm text-text-secondary",
390
- children: B ? "Passed" : "Not passed"
421
+ className: "flex items-start justify-between gap-3",
422
+ children: [/* @__PURE__ */ _("div", {
423
+ className: "grid grid-cols-2 gap-4",
424
+ children: [/* @__PURE__ */ g(D, {
425
+ label: "Score",
426
+ children: /* @__PURE__ */ g("span", {
427
+ className: "tabular-nums font-semibold",
428
+ children: j.score ?? "—"
429
+ })
430
+ }), /* @__PURE__ */ g(D, {
431
+ label: "Result",
432
+ children: j.passed == null ? /* @__PURE__ */ g("span", {
433
+ className: "text-text-secondary",
434
+ children: "—"
435
+ }) : /* @__PURE__ */ g(a, { status: j.passed ? "GRADED" : "RETURNED" })
391
436
  })]
437
+ }), /* @__PURE__ */ g(v, {
438
+ variant: "outline",
439
+ size: "sm",
440
+ onClick: () => I(!0),
441
+ children: "Re-grade"
392
442
  })]
443
+ }), /* @__PURE__ */ g("div", {
444
+ className: "mt-3",
445
+ children: /* @__PURE__ */ g(D, {
446
+ label: "Feedback",
447
+ children: j.feedback ? /* @__PURE__ */ g("span", {
448
+ className: "whitespace-pre-wrap",
449
+ children: j.feedback
450
+ }) : /* @__PURE__ */ g("span", {
451
+ className: "text-text-secondary",
452
+ children: "No feedback provided."
453
+ })
454
+ })
393
455
  })]
394
456
  }),
395
- /* @__PURE__ */ _("div", {
396
- className: "grid gap-1.5",
397
- children: [/* @__PURE__ */ g(b, {
398
- htmlFor: "grade-feedback",
399
- children: "Feedback"
400
- }), /* @__PURE__ */ g(ce, {
401
- id: "grade-feedback",
402
- value: H,
403
- onChange: (e) => U(e.target.value),
404
- placeholder: "Notes, corrections or encouragement for the learner (optional).",
405
- rows: 3
406
- })]
407
- }),
408
- W && /* @__PURE__ */ g("p", {
409
- className: "text-sm text-status-error-text",
410
- children: W
457
+ $ && /* @__PURE__ */ _("div", {
458
+ className: "grid gap-4",
459
+ children: [
460
+ /* @__PURE__ */ _("div", {
461
+ className: "grid gap-4 sm:grid-cols-2",
462
+ children: [/* @__PURE__ */ _("div", {
463
+ className: "grid gap-1.5",
464
+ children: [/* @__PURE__ */ g(b, {
465
+ htmlFor: "grade-score",
466
+ children: "Score"
467
+ }), /* @__PURE__ */ g(y, {
468
+ id: "grade-score",
469
+ type: "number",
470
+ min: "0",
471
+ step: "1",
472
+ value: L,
473
+ onChange: (e) => R(e.target.value),
474
+ placeholder: "e.g. 85"
475
+ })]
476
+ }), /* @__PURE__ */ _("div", {
477
+ className: "grid gap-1.5",
478
+ children: [/* @__PURE__ */ g(b, {
479
+ htmlFor: "grade-passed",
480
+ children: "Result"
481
+ }), /* @__PURE__ */ _("div", {
482
+ className: "flex h-10 items-center gap-3",
483
+ children: [/* @__PURE__ */ g(me, {
484
+ id: "grade-passed",
485
+ checked: z,
486
+ onCheckedChange: B
487
+ }), /* @__PURE__ */ g("span", {
488
+ className: "text-sm text-text-secondary",
489
+ children: z ? "Passed" : "Not passed"
490
+ })]
491
+ })]
492
+ })]
493
+ }),
494
+ /* @__PURE__ */ _("div", {
495
+ className: "grid gap-1.5",
496
+ children: [/* @__PURE__ */ g(b, {
497
+ htmlFor: "grade-feedback",
498
+ children: "Feedback"
499
+ }), /* @__PURE__ */ g(he, {
500
+ id: "grade-feedback",
501
+ value: V,
502
+ onChange: (e) => H(e.target.value),
503
+ placeholder: "Notes, corrections or encouragement for the learner (optional).",
504
+ rows: 4
505
+ })]
506
+ }),
507
+ U && /* @__PURE__ */ g("p", {
508
+ className: "text-sm text-status-error-text",
509
+ children: U
510
+ })
511
+ ]
411
512
  })
412
513
  ]
413
514
  })
414
515
  ]
415
516
  }),
416
- /* @__PURE__ */ _(w, { children: [/* @__PURE__ */ g(v, {
417
- variant: "outline",
418
- onClick: X,
419
- children: $ ? "Cancel" : "Close"
420
- }), $ && /* @__PURE__ */ g(v, {
421
- onClick: he,
422
- disabled: q.isPending,
423
- children: q.isPending ? "Saving…" : Q ? "Update grade" : "Save grade"
424
- })] })
517
+ /* @__PURE__ */ _(de, {
518
+ className: "flex-row justify-end gap-3 border-t border-border-seam p-4",
519
+ children: [/* @__PURE__ */ g(v, {
520
+ variant: "outline",
521
+ onClick: Z,
522
+ children: $ ? "Cancel" : "Close"
523
+ }), $ && /* @__PURE__ */ g(v, {
524
+ onClick: Ee,
525
+ disabled: K.isPending,
526
+ children: K.isPending ? "Saving…" : Q ? "Update grade" : "Grade submission"
527
+ })]
528
+ })
425
529
  ] })
426
530
  })
427
531
  })]
428
532
  });
429
533
  };
430
534
  //#endregion
431
- export { M as SubmissionsPage };
535
+ export { O as SubmissionsPage };
432
536
 
433
537
  //# sourceMappingURL=SubmissionsPage.js.map