@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,38 +1,61 @@
1
1
  import { useBuildmyiq as e } from "../../context/BuildmyiqContext.js";
2
2
  import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { formatDate as n } from "../../utils/formatters.js";
4
- import { StatusBadge as ee } from "../../components/StatusBadge.js";
5
- import { EmptyState as te } from "../../components/EmptyState.js";
6
- import { ErrorView as ne, LoadingView as re } from "../../components/StateViews.js";
7
- import { DataTable as r } from "../../components/DataTable.js";
8
- import { FilterTabs as i } from "../../components/FilterTabs.js";
3
+ import { MetricsCard as n } from "../../components/MetricsCard.js";
4
+ import { formatDate as r, formatPercent as ee } from "../../utils/formatters.js";
5
+ import { StatusBadge as te } from "../../components/StatusBadge.js";
6
+ import { EmptyState as ne } from "../../components/EmptyState.js";
7
+ import { ErrorView as re, LoadingView as i } from "../../components/StateViews.js";
8
+ import { DataTable as ie } from "../../components/DataTable.js";
9
+ import { FilterTabs as ae } from "../../components/FilterTabs.js";
10
+ import { Pagination as oe } from "../../components/Pagination.js";
11
+ import { Avatar as se } from "../../components/Avatar.js";
9
12
  import "../../context/index.js";
10
- import { useBuiCertificates as a, useBuiCourses as o, useBuiIssueCertificate as s, useBuiRevokeCertificate as ie } from "../../hooks/useBuildmyiqApi.js";
13
+ import { useBuiCertificates as ce, useBuiCourses as le, useBuiIssueCertificate as ue, useBuiRevokeCertificate as de } from "../../hooks/useBuildmyiqApi.js";
11
14
  import "../../hooks/index.js";
12
- import { FileLink as ae } from "../../components/FileLink.js";
15
+ import { FileLink as fe } from "../../components/FileLink.js";
13
16
  import "../../components/index.js";
14
- import { useMemo as c, useState as l } from "react";
15
- import { Award as u, Ban as oe, Download as se, Plus as d } from "lucide-react";
16
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
17
- import { Button as m, Input as h, Label as g, ResponsiveDialog as _, ResponsiveDialogContent as v, ResponsiveDialogDescription as y, ResponsiveDialogFooter as b, ResponsiveDialogHeader as x, ResponsiveDialogTitle as ce, Select as S, SelectContent as C, SelectItem as w, SelectTrigger as T, SelectValue as E } from "@burdenoff/fe-libs/ui";
17
+ import { useMemo as a, useState as o } from "react";
18
+ import { Award as s, Ban as c, CalendarClock as pe, Download as me, Plus as l, Search as he, ShieldCheck as ge } from "lucide-react";
19
+ import { Fragment as _e, jsx as u, jsxs as d } from "react/jsx-runtime";
20
+ import { Button as f, Input as p, Label as m, ResponsiveDialog as ve, ResponsiveDialogContent as ye, ResponsiveDialogDescription as be, ResponsiveDialogFooter as xe, ResponsiveDialogHeader as Se, ResponsiveDialogTitle as Ce, Select as h, SelectContent as g, SelectItem as _, SelectTrigger as v, SelectValue as y } from "@burdenoff/fe-libs/ui";
18
21
  //#region src/buildmyiq/pages/certificates/CertificatesPage.tsx
19
- var le = (e) => {
22
+ var b = 8, we = (e) => {
20
23
  let t = e.trim();
21
24
  if (!t) return;
22
25
  let n = new Date(t);
23
26
  return Number.isNaN(n.getTime()) ? void 0 : n.toISOString();
24
- }, ue = () => `BMIQ-${Date.now().toString(36).toUpperCase()}`, D = () => {
25
- let { currentUser: D } = e(), O = D?.id, [k, de] = l(O ? "MINE" : "ALL"), [A, j] = l("ALL"), [M, N] = l(!1), [P, F] = l(null), [I, L] = l(null), [R, z] = l(null), B = () => ({
27
+ }, Te = () => `BMIQ-${Date.now().toString(36).toUpperCase()}`, x = () => {
28
+ let { currentUser: x } = e(), S = x?.id, [C, Ee] = o(S ? "MINE" : "ALL"), [w, T] = o("ALL"), [E, D] = o(""), [De, O] = o(0), [Oe, k] = o(!1), [A, j] = o(null), [M, N] = o(null), [P, F] = o(null), I = () => ({
26
29
  courseId: "",
27
- learnerId: O ?? "",
28
- serial: ue(),
30
+ learnerId: S ?? "",
31
+ serial: Te(),
29
32
  finalScore: "",
30
33
  expiresAt: ""
31
- }), [V, H] = l(B), U = o({ limit: 100 }), W = c(() => U.data?.items ?? [], [U.data]), G = c(() => {
34
+ }), [L, R] = o(I), z = le({ limit: 100 }), B = a(() => z.data?.items ?? [], [z.data]), V = a(() => {
32
35
  let e = /* @__PURE__ */ new Map();
33
- for (let t of W) e.set(t.id, t.title);
36
+ for (let t of B) e.set(t.id, t.title);
34
37
  return e;
35
- }, [W]), K = a(A === "ALL" ? void 0 : A, k === "MINE" ? O : void 0), q = s(), fe = ie(), J = c(() => K.data ?? [], [K.data]), pe = [{
38
+ }, [B]), H = ce(w === "ALL" ? void 0 : w, C === "MINE" ? S : void 0), U = ue(), ke = de(), W = a(() => H.data ?? [], [H.data]), G = a(() => {
39
+ let e = E.trim().toLowerCase();
40
+ return e ? W.filter((t) => {
41
+ let n = (V.get(t.courseId) ?? "").toLowerCase(), r = t.learnerId === S ? "you me mine" : t.learnerId.toLowerCase();
42
+ return t.serial.toLowerCase().includes(e) || n.includes(e) || r.includes(e);
43
+ }) : W;
44
+ }, [
45
+ W,
46
+ E,
47
+ V,
48
+ S
49
+ ]), K = a(() => {
50
+ let e = 0, t = 0, n = 0;
51
+ for (let r of W) r.status === "ISSUED" ? e += 1 : r.status === "EXPIRED" ? t += 1 : r.status === "REVOKED" && (n += 1);
52
+ return {
53
+ total: W.length,
54
+ issued: e,
55
+ expired: t,
56
+ revoked: n
57
+ };
58
+ }, [W]), Ae = Math.max(1, Math.ceil(G.length / b)), q = Math.min(De, Ae - 1), J = a(() => G.slice(q * b, q * b + b), [G, q]), je = [{
36
59
  value: "MINE",
37
60
  label: "Mine"
38
61
  }, {
@@ -40,26 +63,26 @@ var le = (e) => {
40
63
  label: "All"
41
64
  }], Y = async (e) => {
42
65
  if (!(typeof window < "u" && !window.confirm(`Revoke certificate ${e.serial}? This cannot be undone.`))) {
43
- L(null), z(e.id);
66
+ N(null), F(e.id);
44
67
  try {
45
- await fe.mutateAsync(e.id);
68
+ await ke.mutateAsync(e.id);
46
69
  } catch (e) {
47
- L(e instanceof Error ? e.message : "Failed to revoke certificate.");
70
+ N(e instanceof Error ? e.message : "Failed to revoke certificate.");
48
71
  } finally {
49
- z(null);
72
+ F(null);
50
73
  }
51
74
  }
52
- }, me = [
75
+ }, Me = [
53
76
  {
54
77
  key: "serial",
55
78
  header: "Serial",
56
79
  sortValue: (e) => e.serial.toLowerCase(),
57
- render: (e) => /* @__PURE__ */ p("div", {
80
+ render: (e) => /* @__PURE__ */ d("div", {
58
81
  className: "flex items-center gap-3",
59
- children: [/* @__PURE__ */ f("div", {
82
+ children: [/* @__PURE__ */ u("div", {
60
83
  className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-[var(--color-accent-primary)]",
61
- children: /* @__PURE__ */ f(u, { className: "h-4 w-4" })
62
- }), /* @__PURE__ */ f("span", {
84
+ children: /* @__PURE__ */ u(s, { className: "h-4 w-4" })
85
+ }), /* @__PURE__ */ u("span", {
63
86
  className: "min-w-0 truncate font-mono text-xs font-semibold text-text-primary",
64
87
  children: e.serial
65
88
  })]
@@ -68,39 +91,49 @@ var le = (e) => {
68
91
  {
69
92
  key: "course",
70
93
  header: "Course",
71
- sortValue: (e) => (G.get(e.courseId) ?? "").toLowerCase(),
72
- render: (e) => /* @__PURE__ */ f("span", {
94
+ hideOnMobile: !0,
95
+ sortValue: (e) => (V.get(e.courseId) ?? "").toLowerCase(),
96
+ render: (e) => /* @__PURE__ */ u("span", {
73
97
  className: "text-text-secondary",
74
- children: G.get(e.courseId) ?? "—"
98
+ children: V.get(e.courseId) ?? "—"
75
99
  })
76
100
  },
77
101
  {
78
102
  key: "learner",
79
103
  header: "Learner",
80
- hideOnMobile: !0,
81
- sortValue: (e) => e.learnerId === O ? "" : e.learnerId,
82
- render: (e) => e.learnerId === O ? /* @__PURE__ */ f("span", {
83
- className: "font-medium text-text-primary",
84
- children: "You"
85
- }) : /* @__PURE__ */ p("span", {
86
- className: "font-mono text-xs text-text-tertiary",
87
- title: e.learnerId,
88
- children: [e.learnerId.slice(0, 8), "…"]
89
- })
104
+ sortValue: (e) => e.learnerId === S ? "" : e.learnerId,
105
+ render: (e) => {
106
+ let t = e.learnerId === S, n = t ? x?.name ?? x?.username ?? x?.email ?? null : null;
107
+ return /* @__PURE__ */ d("div", {
108
+ className: "flex items-center gap-2.5",
109
+ children: [/* @__PURE__ */ u(se, {
110
+ size: "sm",
111
+ seed: e.learnerId,
112
+ name: n
113
+ }), t ? /* @__PURE__ */ u("span", {
114
+ className: "font-medium text-text-primary",
115
+ children: "You"
116
+ }) : /* @__PURE__ */ d("span", {
117
+ className: "font-mono text-xs text-text-tertiary",
118
+ title: e.learnerId,
119
+ children: [e.learnerId.slice(0, 8), "…"]
120
+ })]
121
+ });
122
+ }
90
123
  },
91
124
  {
92
125
  key: "status",
93
126
  header: "Status",
94
- render: (e) => /* @__PURE__ */ f(ee, { status: e.status })
127
+ render: (e) => /* @__PURE__ */ u(te, { status: e.status })
95
128
  },
96
129
  {
97
130
  key: "issuedAt",
98
131
  header: "Issued",
99
132
  hideOnMobile: !0,
100
133
  sortValue: (e) => e.issuedAt,
101
- render: (e) => /* @__PURE__ */ f("span", {
134
+ render: (e) => /* @__PURE__ */ u("span", {
102
135
  className: "text-text-secondary",
103
- children: n(e.issuedAt)
136
+ children: r(e.issuedAt)
104
137
  })
105
138
  },
106
139
  {
@@ -108,9 +141,9 @@ var le = (e) => {
108
141
  header: "Expires",
109
142
  hideOnMobile: !0,
110
143
  sortValue: (e) => e.expiresAt ?? "",
111
- render: (e) => /* @__PURE__ */ f("span", {
144
+ render: (e) => /* @__PURE__ */ u("span", {
112
145
  className: "text-text-tertiary",
113
- children: n(e.expiresAt)
146
+ children: r(e.expiresAt)
114
147
  })
115
148
  },
116
149
  {
@@ -119,16 +152,16 @@ var le = (e) => {
119
152
  align: "right",
120
153
  hideOnMobile: !0,
121
154
  sortValue: (e) => e.finalScore ?? -1,
122
- render: (e) => /* @__PURE__ */ f("span", {
123
- className: "tabular-nums text-text-secondary",
124
- children: e.finalScore ?? "—"
155
+ render: (e) => /* @__PURE__ */ u("span", {
156
+ className: "font-medium tabular-nums text-text-primary",
157
+ children: e.finalScore == null ? "—" : ee(e.finalScore)
125
158
  })
126
159
  },
127
160
  {
128
161
  key: "file",
129
- header: "File",
162
+ header: "PDF",
130
163
  hideOnMobile: !0,
131
- render: (e) => e.file ? /* @__PURE__ */ f(ae, { fileId: e.file.id }) : /* @__PURE__ */ f("span", {
164
+ render: (e) => e.file ? /* @__PURE__ */ u(fe, { fileId: e.file.id }) : /* @__PURE__ */ u("span", {
132
165
  className: "text-text-tertiary",
133
166
  children: "—"
134
167
  })
@@ -137,220 +170,273 @@ var le = (e) => {
137
170
  key: "actions",
138
171
  header: "",
139
172
  align: "right",
140
- render: (e) => e.status === "ISSUED" ? /* @__PURE__ */ p(m, {
173
+ render: (e) => e.status === "ISSUED" ? /* @__PURE__ */ d(f, {
141
174
  variant: "ghost",
142
175
  size: "sm",
143
176
  className: "text-status-error-text hover:text-status-error-text",
144
- disabled: R === e.id,
177
+ disabled: P === e.id,
145
178
  onClick: () => void Y(e),
146
- children: [/* @__PURE__ */ f(oe, { className: "mr-1.5 h-4 w-4" }), R === e.id ? "Revoking…" : "Revoke"]
179
+ children: [/* @__PURE__ */ u(c, { className: "mr-1.5 h-4 w-4" }), P === e.id ? "Revoking…" : "Revoke"]
147
180
  }) : null
148
181
  }
149
182
  ], X = () => {
150
- H(B()), F(null), N(!0);
183
+ R(I()), j(null), k(!0);
151
184
  }, Z = () => {
152
- N(!1), H(B()), F(null);
153
- }, he = async () => {
154
- if (!V.courseId) {
155
- F("Please choose a course for this certificate.");
185
+ k(!1), R(I()), j(null);
186
+ }, Ne = async () => {
187
+ if (!L.courseId) {
188
+ j("Please choose a course for this certificate.");
156
189
  return;
157
190
  }
158
- if (!V.learnerId.trim()) {
159
- F("A learner (user ID) is required.");
191
+ if (!L.learnerId.trim()) {
192
+ j("A learner (user ID) is required.");
160
193
  return;
161
194
  }
162
- if (!V.serial.trim()) {
163
- F("A certificate serial is required.");
195
+ if (!L.serial.trim()) {
196
+ j("A certificate serial is required.");
164
197
  return;
165
198
  }
166
- let e = V.finalScore.trim() ? Number(V.finalScore) : void 0;
199
+ let e = L.finalScore.trim() ? Number(L.finalScore) : void 0;
167
200
  if (e !== void 0 && (!Number.isFinite(e) || e < 0)) {
168
- F("Final score must be a non-negative number.");
201
+ j("Final score must be a non-negative number.");
169
202
  return;
170
203
  }
171
- let t = le(V.expiresAt);
172
- F(null);
204
+ let t = we(L.expiresAt);
205
+ j(null);
173
206
  try {
174
- await q.mutateAsync({
175
- courseId: V.courseId,
176
- learnerId: V.learnerId.trim(),
177
- serial: V.serial.trim(),
207
+ await U.mutateAsync({
208
+ courseId: L.courseId,
209
+ learnerId: L.learnerId.trim(),
210
+ serial: L.serial.trim(),
178
211
  finalScore: e,
179
212
  expiresAt: t
180
213
  }), Z();
181
214
  } catch (e) {
182
- F(e instanceof Error ? e.message : "Failed to issue certificate.");
215
+ j(e instanceof Error ? e.message : "Failed to issue certificate.");
183
216
  }
184
- }, Q = W.length > 0, $ = k === "MINE" || A !== "ALL";
185
- return /* @__PURE__ */ p(t, {
217
+ }, Q = B.length > 0, $ = C === "MINE" || w !== "ALL" || E.trim().length > 0, Pe = !H.isLoading && !H.isError && K.total > 0;
218
+ return /* @__PURE__ */ d(t, {
186
219
  title: "Certificates",
187
220
  description: "Verifiable credentials issued to learners on course completion.",
188
221
  titleGradient: !0,
189
222
  aurora: !0,
190
- actions: /* @__PURE__ */ p(m, {
223
+ actions: /* @__PURE__ */ d(f, {
191
224
  onClick: X,
192
225
  disabled: !Q,
193
- children: [/* @__PURE__ */ f(d, { className: "mr-1.5 h-4 w-4" }), " Issue certificate"]
226
+ children: [/* @__PURE__ */ u(l, { className: "mr-1.5 h-4 w-4" }), " Issue certificate"]
194
227
  }),
195
228
  children: [
196
- /* @__PURE__ */ p("div", {
229
+ Pe && /* @__PURE__ */ d("div", {
230
+ className: "mb-5 grid grid-cols-2 gap-4 sm:grid-cols-4",
231
+ children: [
232
+ /* @__PURE__ */ u(n, {
233
+ icon: /* @__PURE__ */ u(s, { className: "h-5 w-5" }),
234
+ value: K.total,
235
+ label: "Certificates",
236
+ featured: !0
237
+ }),
238
+ /* @__PURE__ */ u(n, {
239
+ icon: /* @__PURE__ */ u(ge, { className: "h-5 w-5" }),
240
+ value: K.issued,
241
+ label: "Issued",
242
+ accent: "success"
243
+ }),
244
+ /* @__PURE__ */ u(n, {
245
+ icon: /* @__PURE__ */ u(pe, { className: "h-5 w-5" }),
246
+ value: K.expired,
247
+ label: "Expired"
248
+ }),
249
+ /* @__PURE__ */ u(n, {
250
+ icon: /* @__PURE__ */ u(c, { className: "h-5 w-5" }),
251
+ value: K.revoked,
252
+ label: "Revoked",
253
+ accent: "error"
254
+ })
255
+ ]
256
+ }),
257
+ /* @__PURE__ */ d("div", {
197
258
  className: "mb-5 flex flex-wrap items-center gap-3",
198
- children: [/* @__PURE__ */ f(i, {
199
- options: pe,
200
- value: k,
201
- onChange: de
202
- }), /* @__PURE__ */ p(S, {
203
- value: A,
204
- onValueChange: (e) => j(e),
205
- children: [/* @__PURE__ */ f(T, {
206
- className: "w-56",
207
- "aria-label": "Filter by course",
208
- children: /* @__PURE__ */ f(E, { placeholder: "All courses" })
209
- }), /* @__PURE__ */ p(C, { children: [/* @__PURE__ */ f(w, {
210
- value: "ALL",
211
- children: "All courses"
212
- }), W.map((e) => /* @__PURE__ */ f(w, {
213
- value: e.id,
214
- children: e.title
215
- }, e.id))] })]
216
- })]
259
+ children: [
260
+ /* @__PURE__ */ u(ae, {
261
+ options: je,
262
+ value: C,
263
+ onChange: (e) => {
264
+ Ee(e), O(0);
265
+ }
266
+ }),
267
+ /* @__PURE__ */ d(h, {
268
+ value: w,
269
+ onValueChange: (e) => {
270
+ T(e), O(0);
271
+ },
272
+ children: [/* @__PURE__ */ u(v, {
273
+ className: "w-56",
274
+ "aria-label": "Filter by course",
275
+ children: /* @__PURE__ */ u(y, { placeholder: "All courses" })
276
+ }), /* @__PURE__ */ d(g, { children: [/* @__PURE__ */ u(_, {
277
+ value: "ALL",
278
+ children: "All courses"
279
+ }), B.map((e) => /* @__PURE__ */ u(_, {
280
+ value: e.id,
281
+ children: e.title
282
+ }, e.id))] })]
283
+ }),
284
+ /* @__PURE__ */ d("div", {
285
+ className: "relative w-full sm:ml-auto sm:w-64",
286
+ children: [/* @__PURE__ */ u(he, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary" }), /* @__PURE__ */ u(p, {
287
+ value: E,
288
+ onChange: (e) => {
289
+ D(e.target.value), O(0);
290
+ },
291
+ placeholder: "Search certificates…",
292
+ "aria-label": "Search certificates",
293
+ className: "pl-9"
294
+ })]
295
+ })
296
+ ]
217
297
  }),
218
- I && /* @__PURE__ */ f("p", {
298
+ M && /* @__PURE__ */ u("p", {
219
299
  className: "mb-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
220
- children: I
300
+ children: M
221
301
  }),
222
- K.isLoading ? /* @__PURE__ */ f(re, { label: "Loading certificates…" }) : K.isError ? /* @__PURE__ */ f(ne, {
302
+ H.isLoading ? /* @__PURE__ */ u(i, { label: "Loading certificates…" }) : H.isError ? /* @__PURE__ */ u(re, {
223
303
  message: "Couldn't load certificates.",
224
- onRetry: () => K.refetch()
225
- }) : J.length === 0 ? /* @__PURE__ */ f(te, {
304
+ onRetry: () => H.refetch()
305
+ }) : G.length === 0 ? /* @__PURE__ */ u(ne, {
226
306
  illustration: $ ? "empty-search" : "onboarding",
227
- icon: /* @__PURE__ */ f(u, { className: "h-10 w-10" }),
307
+ icon: /* @__PURE__ */ u(s, { className: "h-10 w-10" }),
228
308
  title: $ ? "No certificates match these filters" : "No certificates issued yet",
229
- description: $ ? k === "MINE" ? "You haven't earned a certificate for this selection yet." : "No certificates have been issued for this course yet." : Q ? "Issue a certificate to credential a learner who has completed a course." : "Publish a course first, then issue certificates to learners who complete it.",
230
- action: !$ && Q ? /* @__PURE__ */ p(m, {
309
+ description: $ ? E.trim().length > 0 ? "No credentials match your search. Try a different serial, course, or learner." : C === "MINE" ? "You haven't earned a certificate for this selection yet." : "No certificates have been issued for this course yet." : Q ? "Issue a certificate to credential a learner who has completed a course." : "Publish a course first, then issue certificates to learners who complete it.",
310
+ action: !$ && Q ? /* @__PURE__ */ d(f, {
231
311
  onClick: X,
232
- children: [/* @__PURE__ */ f(d, { className: "mr-1.5 h-4 w-4" }), " Issue certificate"]
312
+ children: [/* @__PURE__ */ u(l, { className: "mr-1.5 h-4 w-4" }), " Issue certificate"]
233
313
  }) : void 0
234
- }) : /* @__PURE__ */ f(r, {
235
- columns: me,
314
+ }) : /* @__PURE__ */ d(_e, { children: [/* @__PURE__ */ u(ie, {
315
+ columns: Me,
236
316
  rows: J,
237
317
  rowKey: (e) => e.id,
238
318
  defaultSort: {
239
319
  key: "issuedAt",
240
320
  dir: "desc"
241
321
  }
242
- }),
243
- /* @__PURE__ */ f(_, {
244
- open: M,
322
+ }), /* @__PURE__ */ u(oe, {
323
+ page: q,
324
+ pageSize: b,
325
+ itemCount: J.length,
326
+ hasMore: (q + 1) * b < G.length,
327
+ onPageChange: O
328
+ })] }),
329
+ /* @__PURE__ */ u(ve, {
330
+ open: Oe,
245
331
  onOpenChange: (e) => {
246
- e ? N(!0) : Z();
332
+ e ? k(!0) : Z();
247
333
  },
248
- children: /* @__PURE__ */ p(v, { children: [/* @__PURE__ */ p(x, { children: [/* @__PURE__ */ f(ce, { children: "Issue certificate" }), /* @__PURE__ */ f(y, { children: "Credential a learner for completing a course. The serial is auto-generated but editable." })] }), /* @__PURE__ */ p("form", {
334
+ children: /* @__PURE__ */ d(ye, { children: [/* @__PURE__ */ d(Se, { children: [/* @__PURE__ */ u(Ce, { children: "Issue certificate" }), /* @__PURE__ */ u(be, { children: "Credential a learner for completing a course. The serial is auto-generated but editable." })] }), /* @__PURE__ */ d("form", {
249
335
  onSubmit: (e) => {
250
- e.preventDefault(), he();
336
+ e.preventDefault(), Ne();
251
337
  },
252
- children: [/* @__PURE__ */ p("div", {
338
+ children: [/* @__PURE__ */ d("div", {
253
339
  className: "grid gap-4 py-2",
254
340
  children: [
255
- /* @__PURE__ */ p("div", {
341
+ /* @__PURE__ */ d("div", {
256
342
  className: "grid gap-1.5",
257
- children: [/* @__PURE__ */ f(g, {
343
+ children: [/* @__PURE__ */ u(m, {
258
344
  htmlFor: "cert-course",
259
345
  children: "Course *"
260
- }), /* @__PURE__ */ p(S, {
261
- value: V.courseId,
262
- onValueChange: (e) => H((t) => ({
346
+ }), /* @__PURE__ */ d(h, {
347
+ value: L.courseId,
348
+ onValueChange: (e) => R((t) => ({
263
349
  ...t,
264
350
  courseId: e
265
351
  })),
266
- children: [/* @__PURE__ */ f(T, {
352
+ children: [/* @__PURE__ */ u(v, {
267
353
  id: "cert-course",
268
- children: /* @__PURE__ */ f(E, { placeholder: "Select a course" })
269
- }), /* @__PURE__ */ f(C, { children: W.map((e) => /* @__PURE__ */ f(w, {
354
+ children: /* @__PURE__ */ u(y, { placeholder: "Select a course" })
355
+ }), /* @__PURE__ */ u(g, { children: B.map((e) => /* @__PURE__ */ u(_, {
270
356
  value: e.id,
271
357
  children: e.title
272
358
  }, e.id)) })]
273
359
  })]
274
360
  }),
275
- /* @__PURE__ */ p("div", {
361
+ /* @__PURE__ */ d("div", {
276
362
  className: "grid gap-1.5",
277
- children: [/* @__PURE__ */ f(g, {
363
+ children: [/* @__PURE__ */ u(m, {
278
364
  htmlFor: "cert-learner",
279
365
  children: "Learner (user ID) *"
280
- }), /* @__PURE__ */ f(h, {
366
+ }), /* @__PURE__ */ u(p, {
281
367
  id: "cert-learner",
282
- value: V.learnerId,
283
- onChange: (e) => H((t) => ({
368
+ value: L.learnerId,
369
+ onChange: (e) => R((t) => ({
284
370
  ...t,
285
371
  learnerId: e.target.value
286
372
  })),
287
373
  placeholder: "Defaults to you"
288
374
  })]
289
375
  }),
290
- /* @__PURE__ */ p("div", {
376
+ /* @__PURE__ */ d("div", {
291
377
  className: "grid gap-1.5",
292
- children: [/* @__PURE__ */ f(g, {
378
+ children: [/* @__PURE__ */ u(m, {
293
379
  htmlFor: "cert-serial",
294
380
  children: "Serial *"
295
- }), /* @__PURE__ */ f(h, {
381
+ }), /* @__PURE__ */ u(p, {
296
382
  id: "cert-serial",
297
- value: V.serial,
298
- onChange: (e) => H((t) => ({
383
+ value: L.serial,
384
+ onChange: (e) => R((t) => ({
299
385
  ...t,
300
386
  serial: e.target.value
301
387
  })),
302
388
  placeholder: "BMIQ-XXXXXX"
303
389
  })]
304
390
  }),
305
- /* @__PURE__ */ p("div", {
391
+ /* @__PURE__ */ d("div", {
306
392
  className: "grid gap-2 sm:grid-cols-2",
307
- children: [/* @__PURE__ */ p("div", {
393
+ children: [/* @__PURE__ */ d("div", {
308
394
  className: "grid gap-1.5",
309
- children: [/* @__PURE__ */ f(g, {
395
+ children: [/* @__PURE__ */ u(m, {
310
396
  htmlFor: "cert-score",
311
397
  children: "Final score"
312
- }), /* @__PURE__ */ f(h, {
398
+ }), /* @__PURE__ */ u(p, {
313
399
  id: "cert-score",
314
400
  type: "number",
315
401
  min: "0",
316
402
  step: "0.1",
317
- value: V.finalScore,
318
- onChange: (e) => H((t) => ({
403
+ value: L.finalScore,
404
+ onChange: (e) => R((t) => ({
319
405
  ...t,
320
406
  finalScore: e.target.value
321
407
  })),
322
408
  placeholder: "e.g. 92"
323
409
  })]
324
- }), /* @__PURE__ */ p("div", {
410
+ }), /* @__PURE__ */ d("div", {
325
411
  className: "grid gap-1.5",
326
- children: [/* @__PURE__ */ f(g, {
412
+ children: [/* @__PURE__ */ u(m, {
327
413
  htmlFor: "cert-expires",
328
414
  children: "Expires"
329
- }), /* @__PURE__ */ f(h, {
415
+ }), /* @__PURE__ */ u(p, {
330
416
  id: "cert-expires",
331
417
  type: "date",
332
- value: V.expiresAt,
333
- onChange: (e) => H((t) => ({
418
+ value: L.expiresAt,
419
+ onChange: (e) => R((t) => ({
334
420
  ...t,
335
421
  expiresAt: e.target.value
336
422
  }))
337
423
  })]
338
424
  })]
339
425
  }),
340
- P && /* @__PURE__ */ f("p", {
426
+ A && /* @__PURE__ */ u("p", {
341
427
  className: "text-sm text-status-error-text",
342
- children: P
428
+ children: A
343
429
  })
344
430
  ]
345
- }), /* @__PURE__ */ p(b, { children: [/* @__PURE__ */ f(m, {
431
+ }), /* @__PURE__ */ d(xe, { children: [/* @__PURE__ */ u(f, {
346
432
  type: "button",
347
433
  variant: "outline",
348
434
  onClick: Z,
349
435
  children: "Cancel"
350
- }), /* @__PURE__ */ p(m, {
436
+ }), /* @__PURE__ */ d(f, {
351
437
  type: "submit",
352
- disabled: q.isPending,
353
- children: [/* @__PURE__ */ f(se, { className: "mr-1.5 h-4 w-4" }), q.isPending ? "Issuing…" : "Issue certificate"]
438
+ disabled: U.isPending,
439
+ children: [/* @__PURE__ */ u(me, { className: "mr-1.5 h-4 w-4" }), U.isPending ? "Issuing…" : "Issue certificate"]
354
440
  })] })]
355
441
  })] })
356
442
  })
@@ -358,6 +444,6 @@ var le = (e) => {
358
444
  });
359
445
  };
360
446
  //#endregion
361
- export { D as CertificatesPage };
447
+ export { x as CertificatesPage };
362
448
 
363
449
  //# sourceMappingURL=CertificatesPage.js.map