@burdenoff/microfe-buildmyiq 2026.705.10 → 2026.705.12
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.
- package/dist/buildmyiq/pages/learning/MyLearningPage.js +216 -149
- package/dist/buildmyiq/pages/learning/MyLearningPage.js.map +1 -1
- package/dist/buildmyiq/utils/cn.js +2 -2
- package/dist/node_modules/{.bun/clsx@2.1.1/node_modules/clsx → clsx}/dist/clsx.js +1 -1
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/{.bun/tailwind-merge@3.5.0/node_modules/tailwind-merge → tailwind-merge}/dist/bundle-mjs.js +212 -170
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/package.json +1 -1
- package/dist/buildmyiq/BuildmyiqRoot.d.ts +0 -5
- package/dist/buildmyiq/BuildmyiqRoot.d.ts.map +0 -1
- package/dist/buildmyiq/BuildmyiqRoutes.d.ts +0 -4
- package/dist/buildmyiq/BuildmyiqRoutes.d.ts.map +0 -1
- package/dist/buildmyiq/components/BuiDiscussion.d.ts +0 -18
- package/dist/buildmyiq/components/BuiDiscussion.d.ts.map +0 -1
- package/dist/buildmyiq/components/BuiTags.d.ts +0 -17
- package/dist/buildmyiq/components/BuiTags.d.ts.map +0 -1
- package/dist/buildmyiq/components/DataTable.d.ts +0 -28
- package/dist/buildmyiq/components/DataTable.d.ts.map +0 -1
- package/dist/buildmyiq/components/EmptyState.d.ts +0 -18
- package/dist/buildmyiq/components/EmptyState.d.ts.map +0 -1
- package/dist/buildmyiq/components/EvidenceUpload.d.ts +0 -14
- package/dist/buildmyiq/components/EvidenceUpload.d.ts.map +0 -1
- package/dist/buildmyiq/components/FileLink.d.ts +0 -15
- package/dist/buildmyiq/components/FileLink.d.ts.map +0 -1
- package/dist/buildmyiq/components/FilterTabs.d.ts +0 -18
- package/dist/buildmyiq/components/FilterTabs.d.ts.map +0 -1
- package/dist/buildmyiq/components/MetricsCard.d.ts +0 -23
- package/dist/buildmyiq/components/MetricsCard.d.ts.map +0 -1
- package/dist/buildmyiq/components/MiniBar.d.ts +0 -16
- package/dist/buildmyiq/components/MiniBar.d.ts.map +0 -1
- package/dist/buildmyiq/components/PageLayout.d.ts +0 -16
- package/dist/buildmyiq/components/PageLayout.d.ts.map +0 -1
- package/dist/buildmyiq/components/Pagination.d.ts +0 -22
- package/dist/buildmyiq/components/Pagination.d.ts.map +0 -1
- package/dist/buildmyiq/components/StateViews.d.ts +0 -24
- package/dist/buildmyiq/components/StateViews.d.ts.map +0 -1
- package/dist/buildmyiq/components/StatusBadge.d.ts +0 -9
- package/dist/buildmyiq/components/StatusBadge.d.ts.map +0 -1
- package/dist/buildmyiq/components/Tabs.d.ts +0 -17
- package/dist/buildmyiq/components/Tabs.d.ts.map +0 -1
- package/dist/buildmyiq/components/index.d.ts +0 -19
- package/dist/buildmyiq/components/index.d.ts.map +0 -1
- package/dist/buildmyiq/context/BuildmyiqContext.d.ts +0 -16
- package/dist/buildmyiq/context/BuildmyiqContext.d.ts.map +0 -1
- package/dist/buildmyiq/context/index.d.ts +0 -6
- package/dist/buildmyiq/context/index.d.ts.map +0 -1
- package/dist/buildmyiq/hooks/index.d.ts +0 -10
- package/dist/buildmyiq/hooks/index.d.ts.map +0 -1
- package/dist/buildmyiq/hooks/useBuiComments.d.ts +0 -36
- package/dist/buildmyiq/hooks/useBuiComments.d.ts.map +0 -1
- package/dist/buildmyiq/hooks/useBuiFiles.d.ts +0 -47
- package/dist/buildmyiq/hooks/useBuiFiles.d.ts.map +0 -1
- package/dist/buildmyiq/hooks/useBuiTags.d.ts +0 -44
- package/dist/buildmyiq/hooks/useBuiTags.d.ts.map +0 -1
- package/dist/buildmyiq/hooks/useBuildmyiqApi.d.ts +0 -65
- package/dist/buildmyiq/hooks/useBuildmyiqApi.d.ts.map +0 -1
- package/dist/buildmyiq/hooks/useCursorPager.d.ts +0 -33
- package/dist/buildmyiq/hooks/useCursorPager.d.ts.map +0 -1
- package/dist/buildmyiq/index.d.ts +0 -9
- package/dist/buildmyiq/index.d.ts.map +0 -1
- package/dist/buildmyiq/pages/DashboardPage.d.ts +0 -4
- package/dist/buildmyiq/pages/DashboardPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/_shared/CourseCard.d.ts +0 -13
- package/dist/buildmyiq/pages/_shared/CourseCard.d.ts.map +0 -1
- package/dist/buildmyiq/pages/_shared/index.d.ts +0 -6
- package/dist/buildmyiq/pages/_shared/index.d.ts.map +0 -1
- package/dist/buildmyiq/pages/assessments/AssessmentDetailPage.d.ts +0 -4
- package/dist/buildmyiq/pages/assessments/AssessmentDetailPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/assessments/AssessmentsPage.d.ts +0 -4
- package/dist/buildmyiq/pages/assessments/AssessmentsPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/assessments/TakeAssessmentPage.d.ts +0 -4
- package/dist/buildmyiq/pages/assessments/TakeAssessmentPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/authoring/AuthoringPage.d.ts +0 -4
- package/dist/buildmyiq/pages/authoring/AuthoringPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/authoring/CourseBuilderPage.d.ts +0 -4
- package/dist/buildmyiq/pages/authoring/CourseBuilderPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/authoring/_forms.d.ts +0 -44
- package/dist/buildmyiq/pages/authoring/_forms.d.ts.map +0 -1
- package/dist/buildmyiq/pages/catalog/CatalogPage.d.ts +0 -4
- package/dist/buildmyiq/pages/catalog/CatalogPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/catalog/CourseDetailPage.d.ts +0 -4
- package/dist/buildmyiq/pages/catalog/CourseDetailPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/certificates/CertificatesPage.d.ts +0 -4
- package/dist/buildmyiq/pages/certificates/CertificatesPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/cohorts/CohortsPage.d.ts +0 -4
- package/dist/buildmyiq/pages/cohorts/CohortsPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/insights/InsightsPage.d.ts +0 -4
- package/dist/buildmyiq/pages/insights/InsightsPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/learning/LessonPlayerPage.d.ts +0 -4
- package/dist/buildmyiq/pages/learning/LessonPlayerPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/learning/MyLearningPage.d.ts +0 -4
- package/dist/buildmyiq/pages/learning/MyLearningPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/skills/SkillsPage.d.ts +0 -4
- package/dist/buildmyiq/pages/skills/SkillsPage.d.ts.map +0 -1
- package/dist/buildmyiq/pages/submissions/SubmissionsPage.d.ts +0 -4
- package/dist/buildmyiq/pages/submissions/SubmissionsPage.d.ts.map +0 -1
- package/dist/buildmyiq/types/index.d.ts +0 -382
- package/dist/buildmyiq/types/index.d.ts.map +0 -1
- package/dist/buildmyiq/utils/cn.d.ts +0 -4
- package/dist/buildmyiq/utils/cn.d.ts.map +0 -1
- package/dist/buildmyiq/utils/formatters.d.ts +0 -33
- package/dist/buildmyiq/utils/formatters.d.ts.map +0 -1
- package/dist/buildmyiq/utils/i18n.d.ts +0 -6
- package/dist/buildmyiq/utils/i18n.d.ts.map +0 -1
- package/dist/buildmyiq/utils/index.d.ts +0 -9
- package/dist/buildmyiq/utils/index.d.ts.map +0 -1
- package/dist/buildmyiq/utils/navigation.d.ts +0 -14
- package/dist/buildmyiq/utils/navigation.d.ts.map +0 -1
- package/dist/dev/main.d.ts +0 -2
- package/dist/dev/main.d.ts.map +0 -1
- package/dist/generated/global-operations.d.ts +0 -2
- package/dist/generated/global-operations.d.ts.map +0 -1
- package/dist/generated/global-types.d.ts +0 -18199
- package/dist/generated/global-types.d.ts.map +0 -1
- package/dist/generated/wspace-operations.d.ts +0 -2
- package/dist/generated/wspace-operations.d.ts.map +0 -1
- package/dist/generated/wspace-types.d.ts +0 -43046
- package/dist/generated/wspace-types.d.ts.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js.map +0 -1
- package/dist/node_modules/.bun/tailwind-merge@3.5.0/node_modules/tailwind-merge/dist/bundle-mjs.js.map +0 -1
|
@@ -12,182 +12,249 @@ import "../../hooks/index.js";
|
|
|
12
12
|
import { FileLink as h } from "../../components/FileLink.js";
|
|
13
13
|
import "../../components/index.js";
|
|
14
14
|
import { useMemo as g, useState as _ } from "react";
|
|
15
|
-
import { ArrowRight as v, Award as y,
|
|
16
|
-
import { jsx as
|
|
17
|
-
import { Button as
|
|
15
|
+
import { ArrowRight as v, Award as y, ClipboardCheck as b, GraduationCap as x, PlayCircle as S } from "lucide-react";
|
|
16
|
+
import { jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
17
|
+
import { Button as T, GlassCard as E } from "@burdenoff/fe-libs/ui";
|
|
18
18
|
//#region src/buildmyiq/pages/learning/MyLearningPage.tsx
|
|
19
|
-
var
|
|
20
|
-
let { currentUser:
|
|
21
|
-
learnerId:
|
|
19
|
+
var D = new Set(["ENROLLED", "IN_PROGRESS"]), O = () => {
|
|
20
|
+
let { currentUser: O, navigateTo: k } = e(), A = O?.id, [j, M] = _("in_progress"), N = p({
|
|
21
|
+
learnerId: A,
|
|
22
22
|
limit: 100,
|
|
23
|
-
enabled: !!
|
|
24
|
-
}),
|
|
25
|
-
learnerId:
|
|
23
|
+
enabled: !!A
|
|
24
|
+
}), P = f({ limit: 100 }), F = d(void 0, A), I = m({
|
|
25
|
+
learnerId: A,
|
|
26
26
|
limit: 50,
|
|
27
|
-
enabled: !!
|
|
28
|
-
})
|
|
29
|
-
g(() => [...F.data?.items ?? []].sort((e, t) => (t.submittedAt ?? t.createdAt).localeCompare(e.submittedAt ?? e.createdAt)), [F.data]);
|
|
30
|
-
let I = g(() => M.data?.items ?? [], [M.data]), L = g(() => N.data?.items ?? [], [N.data]), R = g(() => P.data ?? [], [P.data]), z = g(() => {
|
|
27
|
+
enabled: !!A
|
|
28
|
+
}), L = g(() => [...I.data?.items ?? []].sort((e, t) => (t.submittedAt ?? t.createdAt).localeCompare(e.submittedAt ?? e.createdAt)), [I.data]), R = g(() => N.data?.items ?? [], [N.data]), z = g(() => P.data?.items ?? [], [P.data]), B = g(() => F.data ?? [], [F.data]), V = g(() => {
|
|
31
29
|
let e = /* @__PURE__ */ new Map();
|
|
32
|
-
for (let t of
|
|
30
|
+
for (let t of z) e.set(t.id, t.title);
|
|
33
31
|
return e;
|
|
34
|
-
}, [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
]),
|
|
32
|
+
}, [z]), H = (e) => V.get(e) ?? "Course", U = g(() => R.filter((e) => D.has(e.status)), [R]), W = g(() => R.filter((e) => e.status === "COMPLETED"), [R]), G = g(() => [...j === "in_progress" ? U : j === "completed" ? W : R].sort((e, t) => (t.lastActiveAt ?? t.enrolledAt).localeCompare(e.lastActiveAt ?? e.enrolledAt)), [
|
|
33
|
+
j,
|
|
34
|
+
U,
|
|
35
|
+
W,
|
|
36
|
+
R
|
|
37
|
+
]), K = g(() => [...B].sort((e, t) => t.issuedAt.localeCompare(e.issuedAt)), [B]), q = [
|
|
40
38
|
{
|
|
41
39
|
value: "in_progress",
|
|
42
40
|
label: "In progress",
|
|
43
|
-
count:
|
|
41
|
+
count: U.length
|
|
44
42
|
},
|
|
45
43
|
{
|
|
46
44
|
value: "completed",
|
|
47
45
|
label: "Completed",
|
|
48
|
-
count:
|
|
46
|
+
count: W.length
|
|
49
47
|
},
|
|
50
48
|
{
|
|
51
49
|
value: "all",
|
|
52
50
|
label: "All",
|
|
53
|
-
count:
|
|
51
|
+
count: R.length
|
|
54
52
|
}
|
|
55
|
-
],
|
|
56
|
-
return /* @__PURE__ */
|
|
53
|
+
], J = !!A && (N.isLoading || P.isLoading);
|
|
54
|
+
return /* @__PURE__ */ C(t, {
|
|
57
55
|
title: "My Learning",
|
|
58
56
|
description: "Your enrollments, progress and the credentials you've earned.",
|
|
59
57
|
titleGradient: !0,
|
|
60
58
|
aurora: !0,
|
|
61
|
-
children: /* @__PURE__ */
|
|
59
|
+
children: /* @__PURE__ */ w("div", {
|
|
62
60
|
className: "flex flex-col gap-6",
|
|
63
|
-
children: [
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
title: "Certificates",
|
|
141
|
-
description: "Verifiable credentials issued for the courses you've completed.",
|
|
142
|
-
action: /* @__PURE__ */ C(w, {
|
|
143
|
-
variant: "ghost",
|
|
144
|
-
size: "sm",
|
|
145
|
-
onClick: () => O("certificates"),
|
|
146
|
-
children: [/* @__PURE__ */ S(b, { className: "mr-1 h-4 w-4" }), " All certificates"]
|
|
61
|
+
children: [
|
|
62
|
+
/* @__PURE__ */ w(c, {
|
|
63
|
+
title: "Courses",
|
|
64
|
+
description: "Everything you're enrolled in.",
|
|
65
|
+
children: [A && R.length > 0 && /* @__PURE__ */ C("div", {
|
|
66
|
+
className: "mb-4",
|
|
67
|
+
children: /* @__PURE__ */ C(l, {
|
|
68
|
+
items: q,
|
|
69
|
+
value: j,
|
|
70
|
+
onChange: M
|
|
71
|
+
})
|
|
72
|
+
}), A ? J ? /* @__PURE__ */ C(s, { label: "Loading your enrollments…" }) : N.isError ? /* @__PURE__ */ C(o, {
|
|
73
|
+
title: "Couldn't load your learning",
|
|
74
|
+
message: N.error instanceof Error ? N.error.message : void 0,
|
|
75
|
+
onRetry: () => N.refetch()
|
|
76
|
+
}) : R.length === 0 ? /* @__PURE__ */ C(a, {
|
|
77
|
+
illustration: "onboarding",
|
|
78
|
+
title: "You're not enrolled in anything yet",
|
|
79
|
+
description: "Browse the catalog and enrol in a course to start learning.",
|
|
80
|
+
action: /* @__PURE__ */ C(T, {
|
|
81
|
+
onClick: () => k("catalog"),
|
|
82
|
+
children: "Explore the catalog"
|
|
83
|
+
})
|
|
84
|
+
}) : G.length === 0 ? /* @__PURE__ */ C(a, {
|
|
85
|
+
illustration: "empty-data",
|
|
86
|
+
title: j === "in_progress" ? "No courses in progress" : j === "completed" ? "No completed courses yet" : "No courses",
|
|
87
|
+
description: j === "completed" ? "Finish a course to see it here — and earn a certificate." : "Switch tabs or enrol in a new course to keep learning."
|
|
88
|
+
}) : /* @__PURE__ */ C("div", {
|
|
89
|
+
className: "flex flex-col gap-3",
|
|
90
|
+
children: G.map((e) => /* @__PURE__ */ w(E, {
|
|
91
|
+
treatment: "plain",
|
|
92
|
+
className: "flex flex-col gap-3 p-4 sm:flex-row sm:items-center sm:gap-4",
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ C("div", {
|
|
95
|
+
className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)]",
|
|
96
|
+
children: /* @__PURE__ */ C(S, { className: "h-5 w-5 text-text-primary" })
|
|
97
|
+
}),
|
|
98
|
+
/* @__PURE__ */ w("div", {
|
|
99
|
+
className: "min-w-0 flex-1",
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ w("div", {
|
|
102
|
+
className: "flex flex-wrap items-center gap-2",
|
|
103
|
+
children: [/* @__PURE__ */ C("p", {
|
|
104
|
+
className: "truncate font-medium text-text-primary",
|
|
105
|
+
children: H(e.courseId)
|
|
106
|
+
}), /* @__PURE__ */ C(i, { status: e.status })]
|
|
107
|
+
}),
|
|
108
|
+
/* @__PURE__ */ w("div", {
|
|
109
|
+
className: "mt-2 flex items-center gap-2",
|
|
110
|
+
children: [/* @__PURE__ */ C(u, {
|
|
111
|
+
value: e.progressPct,
|
|
112
|
+
className: "max-w-sm flex-1"
|
|
113
|
+
}), /* @__PURE__ */ w("span", {
|
|
114
|
+
className: "shrink-0 text-xs tabular-nums text-text-secondary",
|
|
115
|
+
children: [Math.round(e.progressPct ?? 0), "%"]
|
|
116
|
+
})]
|
|
117
|
+
}),
|
|
118
|
+
/* @__PURE__ */ C("p", {
|
|
119
|
+
className: "mt-1 text-xs text-text-secondary",
|
|
120
|
+
children: e.status === "COMPLETED" && e.completedAt ? `Completed ${r(e.completedAt)}` : `Active ${r(e.lastActiveAt ?? e.enrolledAt)}`
|
|
121
|
+
})
|
|
122
|
+
]
|
|
123
|
+
}),
|
|
124
|
+
/* @__PURE__ */ w(T, {
|
|
125
|
+
variant: "secondary",
|
|
126
|
+
size: "sm",
|
|
127
|
+
className: "shrink-0 max-sm:w-full",
|
|
128
|
+
onClick: () => k(`learning/${e.id}`),
|
|
129
|
+
children: [e.status === "COMPLETED" ? "Review" : "Continue", /* @__PURE__ */ C(v, { className: "ml-1 h-4 w-4" })]
|
|
130
|
+
})
|
|
131
|
+
]
|
|
132
|
+
}, e.id))
|
|
133
|
+
}) : /* @__PURE__ */ C(a, {
|
|
134
|
+
illustration: "empty-people",
|
|
135
|
+
title: "Sign in to see your learning",
|
|
136
|
+
description: "Your enrollments and progress appear here once you are signed in to the workspace."
|
|
137
|
+
})]
|
|
147
138
|
}),
|
|
148
|
-
|
|
149
|
-
title: "
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
className: "flex flex-col gap-3
|
|
161
|
-
children:
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
139
|
+
/* @__PURE__ */ C(c, {
|
|
140
|
+
title: "Assessment results",
|
|
141
|
+
description: "Your submitted assessments, scores and educator feedback.",
|
|
142
|
+
children: A ? I.isLoading ? /* @__PURE__ */ C(s, { label: "Loading your results…" }) : I.isError ? /* @__PURE__ */ C(o, {
|
|
143
|
+
title: "Couldn't load your results",
|
|
144
|
+
message: I.error instanceof Error ? I.error.message : void 0,
|
|
145
|
+
onRetry: () => I.refetch()
|
|
146
|
+
}) : L.length === 0 ? /* @__PURE__ */ C(a, {
|
|
147
|
+
illustration: "empty-data",
|
|
148
|
+
title: "No assessment results yet",
|
|
149
|
+
description: "Take a course assessment and your score and feedback will appear here."
|
|
150
|
+
}) : /* @__PURE__ */ C("div", {
|
|
151
|
+
className: "flex flex-col gap-3",
|
|
152
|
+
children: L.map((e) => /* @__PURE__ */ w(E, {
|
|
153
|
+
treatment: "plain",
|
|
154
|
+
className: "flex flex-wrap items-center gap-3 p-4",
|
|
155
|
+
children: [
|
|
156
|
+
/* @__PURE__ */ C("div", {
|
|
165
157
|
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)]",
|
|
166
|
-
children: /* @__PURE__ */
|
|
167
|
-
}),
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
158
|
+
children: /* @__PURE__ */ C(b, { className: "h-5 w-5 text-text-primary" })
|
|
159
|
+
}),
|
|
160
|
+
/* @__PURE__ */ w("div", {
|
|
161
|
+
className: "min-w-0 flex-1",
|
|
162
|
+
children: [
|
|
163
|
+
/* @__PURE__ */ w("div", {
|
|
164
|
+
className: "flex flex-wrap items-center gap-2",
|
|
165
|
+
children: [
|
|
166
|
+
/* @__PURE__ */ w("p", {
|
|
167
|
+
className: "font-medium text-text-primary",
|
|
168
|
+
children: ["Attempt ", e.attempt]
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ C(i, { status: e.status }),
|
|
171
|
+
e.passed != null && /* @__PURE__ */ C("span", {
|
|
172
|
+
className: `text-xs font-medium ${e.passed ? "text-status-success-text" : "text-status-error-text"}`,
|
|
173
|
+
children: e.passed ? "Passed" : "Not passed"
|
|
174
|
+
})
|
|
175
|
+
]
|
|
176
|
+
}),
|
|
177
|
+
e.feedback && /* @__PURE__ */ C("p", {
|
|
178
|
+
className: "mt-1 text-sm text-text-secondary",
|
|
179
|
+
children: e.feedback
|
|
180
|
+
}),
|
|
181
|
+
/* @__PURE__ */ w("p", {
|
|
182
|
+
className: "mt-1 text-xs text-text-secondary",
|
|
183
|
+
children: [
|
|
184
|
+
"Submitted ",
|
|
185
|
+
n(e.submittedAt ?? e.createdAt),
|
|
186
|
+
e.gradedAt ? ` · graded ${n(e.gradedAt)}` : ""
|
|
187
|
+
]
|
|
188
|
+
})
|
|
189
|
+
]
|
|
190
|
+
}),
|
|
191
|
+
/* @__PURE__ */ w("div", {
|
|
192
|
+
className: "shrink-0 text-right",
|
|
193
|
+
children: [/* @__PURE__ */ C("p", {
|
|
194
|
+
className: "text-lg font-semibold tabular-nums text-text-primary",
|
|
195
|
+
children: e.score == null ? "—" : `${e.score}%`
|
|
196
|
+
}), /* @__PURE__ */ C("p", {
|
|
197
|
+
className: "text-xs text-text-secondary",
|
|
198
|
+
children: "score"
|
|
199
|
+
})]
|
|
200
|
+
})
|
|
201
|
+
]
|
|
202
|
+
}, e.id))
|
|
203
|
+
}) : null
|
|
204
|
+
}),
|
|
205
|
+
/* @__PURE__ */ C(c, {
|
|
206
|
+
title: "Certificates",
|
|
207
|
+
description: "Verifiable credentials issued for the courses you've completed.",
|
|
208
|
+
action: /* @__PURE__ */ w(T, {
|
|
209
|
+
variant: "ghost",
|
|
210
|
+
size: "sm",
|
|
211
|
+
onClick: () => k("certificates"),
|
|
212
|
+
children: [/* @__PURE__ */ C(x, { className: "mr-1 h-4 w-4" }), " All certificates"]
|
|
213
|
+
}),
|
|
214
|
+
children: A ? F.isLoading ? /* @__PURE__ */ C(s, { label: "Loading your certificates…" }) : F.isError ? /* @__PURE__ */ C(o, {
|
|
215
|
+
title: "Couldn't load your certificates",
|
|
216
|
+
message: F.error instanceof Error ? F.error.message : void 0,
|
|
217
|
+
onRetry: () => F.refetch()
|
|
218
|
+
}) : K.length === 0 ? /* @__PURE__ */ C(a, {
|
|
219
|
+
illustration: "empty-data",
|
|
220
|
+
title: "No certificates yet",
|
|
221
|
+
description: "Complete a credentialed course to earn a verifiable certificate."
|
|
222
|
+
}) : /* @__PURE__ */ C("div", {
|
|
223
|
+
className: "grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3",
|
|
224
|
+
children: K.map((e) => /* @__PURE__ */ w(E, {
|
|
225
|
+
treatment: "plain",
|
|
226
|
+
className: "flex flex-col gap-3 p-4",
|
|
227
|
+
children: [
|
|
228
|
+
/* @__PURE__ */ w("div", {
|
|
229
|
+
className: "flex items-start justify-between gap-3",
|
|
230
|
+
children: [/* @__PURE__ */ C("div", {
|
|
231
|
+
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)]",
|
|
232
|
+
children: /* @__PURE__ */ C(y, { className: "h-5 w-5 text-text-primary" })
|
|
233
|
+
}), /* @__PURE__ */ C(i, { status: e.status })]
|
|
234
|
+
}),
|
|
235
|
+
/* @__PURE__ */ w("div", {
|
|
236
|
+
className: "min-w-0",
|
|
237
|
+
children: [/* @__PURE__ */ C("p", {
|
|
238
|
+
className: "truncate font-medium text-text-primary",
|
|
239
|
+
children: H(e.courseId)
|
|
240
|
+
}), /* @__PURE__ */ C("p", {
|
|
241
|
+
className: "mt-0.5 font-mono text-xs text-text-secondary",
|
|
242
|
+
children: e.serial
|
|
243
|
+
})]
|
|
244
|
+
}),
|
|
245
|
+
/* @__PURE__ */ w("div", {
|
|
246
|
+
className: "mt-auto flex flex-wrap items-center justify-between gap-2 pt-1 text-xs text-text-secondary",
|
|
247
|
+
children: [/* @__PURE__ */ w("span", { children: ["Issued ", n(e.issuedAt)] }), e.file ? /* @__PURE__ */ C(h, { fileId: e.file.id }) : null]
|
|
248
|
+
})
|
|
249
|
+
]
|
|
250
|
+
}, e.id))
|
|
251
|
+
}) : null
|
|
252
|
+
})
|
|
253
|
+
]
|
|
187
254
|
})
|
|
188
255
|
});
|
|
189
256
|
};
|
|
190
257
|
//#endregion
|
|
191
|
-
export {
|
|
258
|
+
export { O as MyLearningPage };
|
|
192
259
|
|
|
193
260
|
//# sourceMappingURL=MyLearningPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MyLearningPage.js","names":[],"sources":["../../../../src/buildmyiq/pages/learning/MyLearningPage.tsx"],"sourcesContent":["/**\n * MyLearningPage — the caller's personal learning surface.\n * @module buildmyiq/pages/learning\n *\n * Renders the current learner's real enrollments (`buiListEnrollments` filtered\n * by `learnerId`) grouped by progress, plus the credentials they have earned\n * (`buiListCertificates`). Course titles are resolved from `buiListCourses`\n * (id → title map, falling back to \"Course\"). Every list carries an honest\n * loading / error / empty state — no fabricated rows.\n */\n\nimport type { FC } from 'react';\nimport { useMemo, useState } from 'react';\nimport { GraduationCap, Award, ArrowRight, PlayCircle, ClipboardCheck } from 'lucide-react';\nimport { Button, GlassCard } from '@burdenoff/fe-libs/ui';\nimport {\n PageLayout,\n Tabs,\n StatusBadge,\n MiniBar,\n EmptyState,\n LoadingView,\n ErrorView,\n Section,\n FileLink,\n} from '../../components';\nimport type { TabItem } from '../../components';\nimport { useBuildmyiq } from '../../context';\nimport {\n useBuiEnrollments,\n useBuiCourses,\n useBuiCertificates,\n useBuiSubmissions,\n} from '../../hooks';\nimport { formatRelativeTime, formatDate } from '../../utils/formatters';\nimport type { BuiEnrollment, BuiCourse, BuiCertificate } from '../../types';\n\ntype LearningTab = 'in_progress' | 'completed' | 'all';\n\nconst IN_PROGRESS_STATUSES = new Set(['ENROLLED', 'IN_PROGRESS']);\n\nexport const MyLearningPage: FC = () => {\n const { currentUser, navigateTo } = useBuildmyiq();\n const learnerId = currentUser?.id;\n\n const [tab, setTab] = useState<LearningTab>('in_progress');\n\n const enrollmentsQuery = useBuiEnrollments({\n learnerId,\n limit: 100,\n enabled: Boolean(learnerId),\n });\n const coursesQuery = useBuiCourses({ limit: 100 });\n const certsQuery = useBuiCertificates(undefined, learnerId);\n const submissionsQuery = useBuiSubmissions({\n learnerId,\n limit: 50,\n enabled: Boolean(learnerId),\n });\n const submissions = useMemo(\n () =>\n [...(submissionsQuery.data?.items ?? [])].sort((a, b) =>\n (b.submittedAt ?? b.createdAt).localeCompare(a.submittedAt ?? a.createdAt)\n ),\n [submissionsQuery.data]\n );\n\n const enrollments: BuiEnrollment[] = useMemo(\n () => enrollmentsQuery.data?.items ?? [],\n [enrollmentsQuery.data]\n );\n const courses: BuiCourse[] = useMemo(() => coursesQuery.data?.items ?? [], [coursesQuery.data]);\n const certificates: BuiCertificate[] = useMemo(() => certsQuery.data ?? [], [certsQuery.data]);\n\n const courseTitleById = useMemo(() => {\n const map = new Map<string, string>();\n for (const c of courses) map.set(c.id, c.title);\n return map;\n }, [courses]);\n\n const titleFor = (courseId: string): string => courseTitleById.get(courseId) ?? 'Course';\n\n const inProgress = useMemo(\n () => enrollments.filter((e) => IN_PROGRESS_STATUSES.has(e.status)),\n [enrollments]\n );\n const completed = useMemo(\n () => enrollments.filter((e) => e.status === 'COMPLETED'),\n [enrollments]\n );\n\n const visible = useMemo(() => {\n const rows = tab === 'in_progress' ? inProgress : tab === 'completed' ? completed : enrollments;\n return [...rows].sort((a, b) =>\n (b.lastActiveAt ?? b.enrolledAt).localeCompare(a.lastActiveAt ?? a.enrolledAt)\n );\n }, [tab, inProgress, completed, enrollments]);\n\n const sortedCertificates = useMemo(\n () => [...certificates].sort((a, b) => b.issuedAt.localeCompare(a.issuedAt)),\n [certificates]\n );\n\n const tabs: TabItem<LearningTab>[] = [\n { value: 'in_progress', label: 'In progress', count: inProgress.length },\n { value: 'completed', label: 'Completed', count: completed.length },\n { value: 'all', label: 'All', count: enrollments.length },\n ];\n\n const isLoading = Boolean(learnerId) && (enrollmentsQuery.isLoading || coursesQuery.isLoading);\n\n const renderEnrollments = () => {\n if (!learnerId) {\n return (\n <EmptyState\n illustration=\"empty-people\"\n title=\"Sign in to see your learning\"\n description=\"Your enrollments and progress appear here once you are signed in to the workspace.\"\n />\n );\n }\n if (isLoading) return <LoadingView label=\"Loading your enrollments…\" />;\n if (enrollmentsQuery.isError) {\n return (\n <ErrorView\n title=\"Couldn't load your learning\"\n message={\n enrollmentsQuery.error instanceof Error ? enrollmentsQuery.error.message : undefined\n }\n onRetry={() => enrollmentsQuery.refetch()}\n />\n );\n }\n if (enrollments.length === 0) {\n return (\n <EmptyState\n illustration=\"onboarding\"\n title=\"You're not enrolled in anything yet\"\n description=\"Browse the catalog and enrol in a course to start learning.\"\n action={<Button onClick={() => navigateTo('catalog')}>Explore the catalog</Button>}\n />\n );\n }\n if (visible.length === 0) {\n const label =\n tab === 'in_progress'\n ? 'No courses in progress'\n : tab === 'completed'\n ? 'No completed courses yet'\n : 'No courses';\n return (\n <EmptyState\n illustration=\"empty-data\"\n title={label}\n description={\n tab === 'completed'\n ? 'Finish a course to see it here — and earn a certificate.'\n : 'Switch tabs or enrol in a new course to keep learning.'\n }\n />\n );\n }\n return (\n <div className=\"flex flex-col gap-3\">\n {visible.map((e) => (\n <GlassCard\n key={e.id}\n treatment=\"plain\"\n className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-center sm:gap-4\"\n >\n <div className=\"flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)]\">\n <PlayCircle className=\"h-5 w-5 text-text-primary\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"truncate font-medium text-text-primary\">{titleFor(e.courseId)}</p>\n <StatusBadge status={e.status} />\n </div>\n <div className=\"mt-2 flex items-center gap-2\">\n <MiniBar value={e.progressPct} className=\"max-w-sm flex-1\" />\n <span className=\"shrink-0 text-xs tabular-nums text-text-secondary\">\n {Math.round(e.progressPct ?? 0)}%\n </span>\n </div>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {e.status === 'COMPLETED' && e.completedAt\n ? `Completed ${formatRelativeTime(e.completedAt)}`\n : `Active ${formatRelativeTime(e.lastActiveAt ?? e.enrolledAt)}`}\n </p>\n </div>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n className=\"shrink-0 max-sm:w-full\"\n onClick={() => navigateTo(`learning/${e.id}`)}\n >\n {e.status === 'COMPLETED' ? 'Review' : 'Continue'}\n <ArrowRight className=\"ml-1 h-4 w-4\" />\n </Button>\n </GlassCard>\n ))}\n </div>\n );\n };\n\n const renderCertificates = () => {\n if (!learnerId) return null;\n if (certsQuery.isLoading) return <LoadingView label=\"Loading your certificates…\" />;\n if (certsQuery.isError) {\n return (\n <ErrorView\n title=\"Couldn't load your certificates\"\n message={certsQuery.error instanceof Error ? certsQuery.error.message : undefined}\n onRetry={() => certsQuery.refetch()}\n />\n );\n }\n if (sortedCertificates.length === 0) {\n return (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No certificates yet\"\n description=\"Complete a credentialed course to earn a verifiable certificate.\"\n />\n );\n }\n return (\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {sortedCertificates.map((cert) => (\n <GlassCard key={cert.id} treatment=\"plain\" className=\"flex flex-col gap-3 p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)]\">\n <Award className=\"h-5 w-5 text-text-primary\" />\n </div>\n <StatusBadge status={cert.status} />\n </div>\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{titleFor(cert.courseId)}</p>\n <p className=\"mt-0.5 font-mono text-xs text-text-secondary\">{cert.serial}</p>\n </div>\n <div className=\"mt-auto flex flex-wrap items-center justify-between gap-2 pt-1 text-xs text-text-secondary\">\n <span>Issued {formatDate(cert.issuedAt)}</span>\n {cert.file ? <FileLink fileId={cert.file.id} /> : null}\n </div>\n </GlassCard>\n ))}\n </div>\n );\n };\n\n const renderResults = () => {\n if (!learnerId) return null;\n if (submissionsQuery.isLoading) return <LoadingView label=\"Loading your results…\" />;\n if (submissionsQuery.isError)\n return (\n <ErrorView\n title=\"Couldn't load your results\"\n message={submissionsQuery.error instanceof Error ? submissionsQuery.error.message : undefined}\n onRetry={() => submissionsQuery.refetch()}\n />\n );\n if (submissions.length === 0)\n return (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No assessment results yet\"\n description=\"Take a course assessment and your score and feedback will appear here.\"\n />\n );\n return (\n <div className=\"flex flex-col gap-3\">\n {submissions.map((s) => (\n <GlassCard key={s.id} treatment=\"plain\" className=\"flex flex-wrap items-center gap-3 p-4\">\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)]\">\n <ClipboardCheck className=\"h-5 w-5 text-text-primary\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"font-medium text-text-primary\">Attempt {s.attempt}</p>\n <StatusBadge status={s.status} />\n {s.passed != null && (\n <span\n className={`text-xs font-medium ${s.passed ? 'text-status-success-text' : 'text-status-error-text'}`}\n >\n {s.passed ? 'Passed' : 'Not passed'}\n </span>\n )}\n </div>\n {s.feedback && <p className=\"mt-1 text-sm text-text-secondary\">{s.feedback}</p>}\n <p className=\"mt-1 text-xs text-text-secondary\">\n Submitted {formatDate(s.submittedAt ?? s.createdAt)}\n {s.gradedAt ? ` · graded ${formatDate(s.gradedAt)}` : ''}\n </p>\n </div>\n <div className=\"shrink-0 text-right\">\n <p className=\"text-lg font-semibold tabular-nums text-text-primary\">\n {s.score != null ? `${s.score}%` : '—'}\n </p>\n <p className=\"text-xs text-text-secondary\">score</p>\n </div>\n </GlassCard>\n ))}\n </div>\n );\n };\n\n return (\n <PageLayout\n title=\"My Learning\"\n description=\"Your enrollments, progress and the credentials you've earned.\"\n titleGradient\n aurora\n >\n <div className=\"flex flex-col gap-6\">\n <Section title=\"Courses\" description=\"Everything you're enrolled in.\">\n {learnerId && enrollments.length > 0 && (\n <div className=\"mb-4\">\n <Tabs items={tabs} value={tab} onChange={setTab} />\n </div>\n )}\n {renderEnrollments()}\n </Section>\n\n <Section\n title=\"Certificates\"\n description=\"Verifiable credentials issued for the courses you've completed.\"\n action={\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo('certificates')}>\n <GraduationCap className=\"mr-1 h-4 w-4\" /> All certificates\n </Button>\n }\n >\n {renderCertificates()}\n </Section>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MyLearningPage.js","names":[],"sources":["../../../../src/buildmyiq/pages/learning/MyLearningPage.tsx"],"sourcesContent":["/**\n * MyLearningPage — the caller's personal learning surface.\n * @module buildmyiq/pages/learning\n *\n * Renders the current learner's real enrollments (`buiListEnrollments` filtered\n * by `learnerId`) grouped by progress, plus the credentials they have earned\n * (`buiListCertificates`). Course titles are resolved from `buiListCourses`\n * (id → title map, falling back to \"Course\"). Every list carries an honest\n * loading / error / empty state — no fabricated rows.\n */\n\nimport type { FC } from 'react';\nimport { useMemo, useState } from 'react';\nimport { GraduationCap, Award, ArrowRight, PlayCircle, ClipboardCheck } from 'lucide-react';\nimport { Button, GlassCard } from '@burdenoff/fe-libs/ui';\nimport {\n PageLayout,\n Tabs,\n StatusBadge,\n MiniBar,\n EmptyState,\n LoadingView,\n ErrorView,\n Section,\n FileLink,\n} from '../../components';\nimport type { TabItem } from '../../components';\nimport { useBuildmyiq } from '../../context';\nimport {\n useBuiEnrollments,\n useBuiCourses,\n useBuiCertificates,\n useBuiSubmissions,\n} from '../../hooks';\nimport { formatRelativeTime, formatDate } from '../../utils/formatters';\nimport type { BuiEnrollment, BuiCourse, BuiCertificate } from '../../types';\n\ntype LearningTab = 'in_progress' | 'completed' | 'all';\n\nconst IN_PROGRESS_STATUSES = new Set(['ENROLLED', 'IN_PROGRESS']);\n\nexport const MyLearningPage: FC = () => {\n const { currentUser, navigateTo } = useBuildmyiq();\n const learnerId = currentUser?.id;\n\n const [tab, setTab] = useState<LearningTab>('in_progress');\n\n const enrollmentsQuery = useBuiEnrollments({\n learnerId,\n limit: 100,\n enabled: Boolean(learnerId),\n });\n const coursesQuery = useBuiCourses({ limit: 100 });\n const certsQuery = useBuiCertificates(undefined, learnerId);\n const submissionsQuery = useBuiSubmissions({\n learnerId,\n limit: 50,\n enabled: Boolean(learnerId),\n });\n const submissions = useMemo(\n () =>\n [...(submissionsQuery.data?.items ?? [])].sort((a, b) =>\n (b.submittedAt ?? b.createdAt).localeCompare(a.submittedAt ?? a.createdAt)\n ),\n [submissionsQuery.data]\n );\n\n const enrollments: BuiEnrollment[] = useMemo(\n () => enrollmentsQuery.data?.items ?? [],\n [enrollmentsQuery.data]\n );\n const courses: BuiCourse[] = useMemo(() => coursesQuery.data?.items ?? [], [coursesQuery.data]);\n const certificates: BuiCertificate[] = useMemo(() => certsQuery.data ?? [], [certsQuery.data]);\n\n const courseTitleById = useMemo(() => {\n const map = new Map<string, string>();\n for (const c of courses) map.set(c.id, c.title);\n return map;\n }, [courses]);\n\n const titleFor = (courseId: string): string => courseTitleById.get(courseId) ?? 'Course';\n\n const inProgress = useMemo(\n () => enrollments.filter((e) => IN_PROGRESS_STATUSES.has(e.status)),\n [enrollments]\n );\n const completed = useMemo(\n () => enrollments.filter((e) => e.status === 'COMPLETED'),\n [enrollments]\n );\n\n const visible = useMemo(() => {\n const rows = tab === 'in_progress' ? inProgress : tab === 'completed' ? completed : enrollments;\n return [...rows].sort((a, b) =>\n (b.lastActiveAt ?? b.enrolledAt).localeCompare(a.lastActiveAt ?? a.enrolledAt)\n );\n }, [tab, inProgress, completed, enrollments]);\n\n const sortedCertificates = useMemo(\n () => [...certificates].sort((a, b) => b.issuedAt.localeCompare(a.issuedAt)),\n [certificates]\n );\n\n const tabs: TabItem<LearningTab>[] = [\n { value: 'in_progress', label: 'In progress', count: inProgress.length },\n { value: 'completed', label: 'Completed', count: completed.length },\n { value: 'all', label: 'All', count: enrollments.length },\n ];\n\n const isLoading = Boolean(learnerId) && (enrollmentsQuery.isLoading || coursesQuery.isLoading);\n\n const renderEnrollments = () => {\n if (!learnerId) {\n return (\n <EmptyState\n illustration=\"empty-people\"\n title=\"Sign in to see your learning\"\n description=\"Your enrollments and progress appear here once you are signed in to the workspace.\"\n />\n );\n }\n if (isLoading) return <LoadingView label=\"Loading your enrollments…\" />;\n if (enrollmentsQuery.isError) {\n return (\n <ErrorView\n title=\"Couldn't load your learning\"\n message={\n enrollmentsQuery.error instanceof Error ? enrollmentsQuery.error.message : undefined\n }\n onRetry={() => enrollmentsQuery.refetch()}\n />\n );\n }\n if (enrollments.length === 0) {\n return (\n <EmptyState\n illustration=\"onboarding\"\n title=\"You're not enrolled in anything yet\"\n description=\"Browse the catalog and enrol in a course to start learning.\"\n action={<Button onClick={() => navigateTo('catalog')}>Explore the catalog</Button>}\n />\n );\n }\n if (visible.length === 0) {\n const label =\n tab === 'in_progress'\n ? 'No courses in progress'\n : tab === 'completed'\n ? 'No completed courses yet'\n : 'No courses';\n return (\n <EmptyState\n illustration=\"empty-data\"\n title={label}\n description={\n tab === 'completed'\n ? 'Finish a course to see it here — and earn a certificate.'\n : 'Switch tabs or enrol in a new course to keep learning.'\n }\n />\n );\n }\n return (\n <div className=\"flex flex-col gap-3\">\n {visible.map((e) => (\n <GlassCard\n key={e.id}\n treatment=\"plain\"\n className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-center sm:gap-4\"\n >\n <div className=\"flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)]\">\n <PlayCircle className=\"h-5 w-5 text-text-primary\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"truncate font-medium text-text-primary\">{titleFor(e.courseId)}</p>\n <StatusBadge status={e.status} />\n </div>\n <div className=\"mt-2 flex items-center gap-2\">\n <MiniBar value={e.progressPct} className=\"max-w-sm flex-1\" />\n <span className=\"shrink-0 text-xs tabular-nums text-text-secondary\">\n {Math.round(e.progressPct ?? 0)}%\n </span>\n </div>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {e.status === 'COMPLETED' && e.completedAt\n ? `Completed ${formatRelativeTime(e.completedAt)}`\n : `Active ${formatRelativeTime(e.lastActiveAt ?? e.enrolledAt)}`}\n </p>\n </div>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n className=\"shrink-0 max-sm:w-full\"\n onClick={() => navigateTo(`learning/${e.id}`)}\n >\n {e.status === 'COMPLETED' ? 'Review' : 'Continue'}\n <ArrowRight className=\"ml-1 h-4 w-4\" />\n </Button>\n </GlassCard>\n ))}\n </div>\n );\n };\n\n const renderCertificates = () => {\n if (!learnerId) return null;\n if (certsQuery.isLoading) return <LoadingView label=\"Loading your certificates…\" />;\n if (certsQuery.isError) {\n return (\n <ErrorView\n title=\"Couldn't load your certificates\"\n message={certsQuery.error instanceof Error ? certsQuery.error.message : undefined}\n onRetry={() => certsQuery.refetch()}\n />\n );\n }\n if (sortedCertificates.length === 0) {\n return (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No certificates yet\"\n description=\"Complete a credentialed course to earn a verifiable certificate.\"\n />\n );\n }\n return (\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {sortedCertificates.map((cert) => (\n <GlassCard key={cert.id} treatment=\"plain\" className=\"flex flex-col gap-3 p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)]\">\n <Award className=\"h-5 w-5 text-text-primary\" />\n </div>\n <StatusBadge status={cert.status} />\n </div>\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{titleFor(cert.courseId)}</p>\n <p className=\"mt-0.5 font-mono text-xs text-text-secondary\">{cert.serial}</p>\n </div>\n <div className=\"mt-auto flex flex-wrap items-center justify-between gap-2 pt-1 text-xs text-text-secondary\">\n <span>Issued {formatDate(cert.issuedAt)}</span>\n {cert.file ? <FileLink fileId={cert.file.id} /> : null}\n </div>\n </GlassCard>\n ))}\n </div>\n );\n };\n\n const renderResults = () => {\n if (!learnerId) return null;\n if (submissionsQuery.isLoading) return <LoadingView label=\"Loading your results…\" />;\n if (submissionsQuery.isError)\n return (\n <ErrorView\n title=\"Couldn't load your results\"\n message={submissionsQuery.error instanceof Error ? submissionsQuery.error.message : undefined}\n onRetry={() => submissionsQuery.refetch()}\n />\n );\n if (submissions.length === 0)\n return (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No assessment results yet\"\n description=\"Take a course assessment and your score and feedback will appear here.\"\n />\n );\n return (\n <div className=\"flex flex-col gap-3\">\n {submissions.map((s) => (\n <GlassCard key={s.id} treatment=\"plain\" className=\"flex flex-wrap items-center gap-3 p-4\">\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)]\">\n <ClipboardCheck className=\"h-5 w-5 text-text-primary\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"font-medium text-text-primary\">Attempt {s.attempt}</p>\n <StatusBadge status={s.status} />\n {s.passed != null && (\n <span\n className={`text-xs font-medium ${s.passed ? 'text-status-success-text' : 'text-status-error-text'}`}\n >\n {s.passed ? 'Passed' : 'Not passed'}\n </span>\n )}\n </div>\n {s.feedback && <p className=\"mt-1 text-sm text-text-secondary\">{s.feedback}</p>}\n <p className=\"mt-1 text-xs text-text-secondary\">\n Submitted {formatDate(s.submittedAt ?? s.createdAt)}\n {s.gradedAt ? ` · graded ${formatDate(s.gradedAt)}` : ''}\n </p>\n </div>\n <div className=\"shrink-0 text-right\">\n <p className=\"text-lg font-semibold tabular-nums text-text-primary\">\n {s.score != null ? `${s.score}%` : '—'}\n </p>\n <p className=\"text-xs text-text-secondary\">score</p>\n </div>\n </GlassCard>\n ))}\n </div>\n );\n };\n\n return (\n <PageLayout\n title=\"My Learning\"\n description=\"Your enrollments, progress and the credentials you've earned.\"\n titleGradient\n aurora\n >\n <div className=\"flex flex-col gap-6\">\n <Section title=\"Courses\" description=\"Everything you're enrolled in.\">\n {learnerId && enrollments.length > 0 && (\n <div className=\"mb-4\">\n <Tabs items={tabs} value={tab} onChange={setTab} />\n </div>\n )}\n {renderEnrollments()}\n </Section>\n\n <Section\n title=\"Assessment results\"\n description=\"Your submitted assessments, scores and educator feedback.\"\n >\n {renderResults()}\n </Section>\n\n <Section\n title=\"Certificates\"\n description=\"Verifiable credentials issued for the courses you've completed.\"\n action={\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo('certificates')}>\n <GraduationCap className=\"mr-1 h-4 w-4\" /> All certificates\n </Button>\n }\n >\n {renderCertificates()}\n </Section>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../../node_modules
|
|
2
|
-
import { twMerge as t } from "../../node_modules
|
|
1
|
+
import e from "../../node_modules/clsx/dist/clsx.js";
|
|
2
|
+
import { twMerge as t } from "../../node_modules/tailwind-merge/dist/bundle-mjs.js";
|
|
3
3
|
//#region src/buildmyiq/utils/cn.ts
|
|
4
4
|
function n(...n) {
|
|
5
5
|
return t(e(n));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clsx.js","names":[],"sources":["../../../../node_modules/clsx/dist/clsx.mjs"],"sourcesContent":["function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;"],"x_google_ignoreList":[0],"mappings":";AAAA,SAAS,EAAE,GAAE;CAAC,IAAI,GAAE,GAAE,IAAE;AAAG,KAAa,OAAO,KAAjB,YAA8B,OAAO,KAAjB,SAAmB,MAAG;UAAoB,OAAO,KAAjB,SAAmB,KAAG,MAAM,QAAQ,EAAE,EAAC;EAAC,IAAI,IAAE,EAAE;AAAO,OAAI,IAAE,GAAE,IAAE,GAAE,IAAI,GAAE,OAAK,IAAE,EAAE,EAAE,GAAG,MAAI,MAAI,KAAG,MAAK,KAAG;OAAQ,MAAI,KAAK,EAAE,GAAE,OAAK,MAAI,KAAG,MAAK,KAAG;AAAG,QAAO;;AAAE,SAAgB,IAAM;AAAC,MAAI,IAAI,GAAE,GAAE,IAAE,GAAE,IAAE,IAAG,IAAE,UAAU,QAAO,IAAE,GAAE,IAAI,EAAC,IAAE,UAAU,QAAM,IAAE,EAAE,EAAE,MAAI,MAAI,KAAG,MAAK,KAAG;AAAG,QAAO"}
|