@burdenoff/microfe-technospam 2026.704.1 → 2026.705.1

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 (23) hide show
  1. package/dist/technospam/api/technospamApi.js +232 -150
  2. package/dist/technospam/api/technospamApi.js.map +1 -1
  3. package/dist/technospam/components/LoadMore.js +18 -2
  4. package/dist/technospam/components/LoadMore.js.map +1 -0
  5. package/dist/technospam/pages/AdminAdminDashboardPagePage.js +664 -334
  6. package/dist/technospam/pages/AdminAdminDashboardPagePage.js.map +1 -1
  7. package/dist/technospam/pages/ApplicationsProblemsPagePage.js +79 -72
  8. package/dist/technospam/pages/ApplicationsProblemsPagePage.js.map +1 -1
  9. package/dist/technospam/pages/CoursesCourseDetailsPagePage.js +140 -87
  10. package/dist/technospam/pages/CoursesCourseDetailsPagePage.js.map +1 -1
  11. package/dist/technospam/pages/CoursesCoursesPagePage.js +75 -68
  12. package/dist/technospam/pages/CoursesCoursesPagePage.js.map +1 -1
  13. package/dist/technospam/pages/CoursesMyLearningPagePage.js +3 -0
  14. package/dist/technospam/pages/CoursesMyLearningPagePage.js.map +1 -1
  15. package/dist/technospam/pages/HackathonsHackathonsPagePage.js +76 -53
  16. package/dist/technospam/pages/HackathonsHackathonsPagePage.js.map +1 -1
  17. package/dist/technospam/pages/MentorshipMentorProfilePagePage.js +36 -35
  18. package/dist/technospam/pages/MentorshipMentorProfilePagePage.js.map +1 -1
  19. package/dist/technospam/pages/MentorshipMentorsPagePage.js +112 -103
  20. package/dist/technospam/pages/MentorshipMentorsPagePage.js.map +1 -1
  21. package/dist/technospam/pages/MentorshipSessionsPagePage.js +219 -110
  22. package/dist/technospam/pages/MentorshipSessionsPagePage.js.map +1 -1
  23. package/package.json +1 -1
@@ -6,41 +6,41 @@ import { StatusBadge as a } from "../components/StatusBadge.js";
6
6
  import { EmptyView as o, ErrorView as s } from "../components/StateViews.js";
7
7
  import "../components/index.js";
8
8
  import { notify as c } from "../lib/toast.js";
9
- import { useCourseQuery as l, useEnroll as u, useUpdateProgress as d } from "../api/technospamApi.js";
10
- import { BookOpen as f, CheckCircle2 as p, Clock as m, FileText as h, Layers as g, Lock as _, PlayCircle as v, Sparkles as y } from "lucide-react";
11
- import { useSearchParams as b } from "react-router-dom";
12
- import { jsx as x, jsxs as S } from "react/jsx-runtime";
13
- import { Badge as C, Button as w, GlassCard as T, Skeleton as E } from "@burdenoff/fe-libs/ui";
9
+ import { useCertificatesQuery as l, useCourseQuery as u, useEnroll as d, useIssueCertificate as f, useUpdateProgress as p } from "../api/technospamApi.js";
10
+ import { Award as m, BookOpen as h, CheckCircle2 as g, Clock as _, FileText as v, Layers as y, Lock as b, PlayCircle as x, Sparkles as S } from "lucide-react";
11
+ import { useSearchParams as C } from "react-router-dom";
12
+ import { jsx as w, jsxs as T } from "react/jsx-runtime";
13
+ import { Badge as E, Button as D, GlassCard as O, Skeleton as k } from "@burdenoff/fe-libs/ui";
14
14
  //#region src/technospam/pages/CoursesCourseDetailsPagePage.tsx
15
- var D = {
16
- VIDEO: v,
17
- ARTICLE: h,
18
- INTERACTIVE: y,
19
- QUIZ: p,
20
- PROJECT: g
15
+ var A = {
16
+ VIDEO: x,
17
+ ARTICLE: v,
18
+ INTERACTIVE: S,
19
+ QUIZ: g,
20
+ PROJECT: y
21
21
  };
22
- function O({ lesson: e, done: t }) {
23
- let n = D[e.kind] ?? h;
24
- return /* @__PURE__ */ S("div", {
22
+ function j({ lesson: e, done: t }) {
23
+ let n = A[e.kind] ?? v;
24
+ return /* @__PURE__ */ T("div", {
25
25
  className: "flex items-center gap-3 border-b border-border-seam py-3 last:border-0",
26
26
  children: [
27
- /* @__PURE__ */ x("span", {
27
+ /* @__PURE__ */ w("span", {
28
28
  className: `flex h-8 w-8 shrink-0 items-center justify-center rounded-lg ${t ? "bg-status-success-bg-subtle text-status-success-text" : "bg-bg-sunken text-text-secondary"}`,
29
- children: x(t ? p : n, { size: 16 })
29
+ children: w(t ? g : n, { size: 16 })
30
30
  }),
31
- /* @__PURE__ */ S("div", {
31
+ /* @__PURE__ */ T("div", {
32
32
  className: "min-w-0 flex-1",
33
- children: [/* @__PURE__ */ S("div", {
33
+ children: [/* @__PURE__ */ T("div", {
34
34
  className: "flex items-center gap-2",
35
- children: [/* @__PURE__ */ x("span", {
35
+ children: [/* @__PURE__ */ w("span", {
36
36
  className: "truncate text-sm font-medium text-text-primary",
37
37
  children: e.title
38
- }), e.isPreview ? /* @__PURE__ */ x(C, {
38
+ }), e.isPreview ? /* @__PURE__ */ w(E, {
39
39
  variant: "secondary",
40
40
  className: "text-[11px]",
41
41
  children: "Preview"
42
42
  }) : null]
43
- }), /* @__PURE__ */ S("div", {
43
+ }), /* @__PURE__ */ T("div", {
44
44
  className: "text-xs text-text-muted",
45
45
  children: [
46
46
  i(e.kind),
@@ -49,152 +49,205 @@ function O({ lesson: e, done: t }) {
49
49
  ]
50
50
  })]
51
51
  }),
52
- !e.isPreview && !t ? /* @__PURE__ */ x(_, {
52
+ !e.isPreview && !t ? /* @__PURE__ */ w(b, {
53
53
  size: 14,
54
54
  className: "text-text-muted"
55
55
  }) : null
56
56
  ]
57
57
  });
58
58
  }
59
- function k() {
60
- let [i] = b(), _ = i.get("id") ?? "", { currentUser: v } = e(), { data: y, loading: D, error: k, refetch: A } = l(_), [j, { loading: M }] = u(), [N, { loading: P }] = d(), F = y?.tecCourse ?? null, I = [...F?.lessons ?? []].sort((e, t) => e.position - t.position), L = (F?.enrollments ?? []).find((e) => e.learnerId === v?.id), R = async () => {
61
- _ && (await j({ variables: { input: { courseId: _ } } })).data?.tecEnroll && (c.success("Enrolled", `You're enrolled in "${F?.title}".`), await A());
62
- }, z = async () => {
63
- if (!L) return;
64
- let e = Math.min(I.length, L.lessonsCompleted + 1), t = I.length ? Math.round(e / I.length * 100) : 100;
65
- (await N({ variables: { input: {
66
- enrollmentId: L.id,
59
+ function M() {
60
+ let [i] = C(), b = i.get("id") ?? "", { currentUser: x } = e(), { data: S, loading: A, error: M, refetch: N } = u(b), [P, { loading: F }] = d(), [I, { loading: L }] = p(), { data: R, refetch: z } = l(x?.id && b ? {
61
+ learnerId: x.id,
62
+ courseId: b
63
+ } : {}), [B, { loading: V }] = f(), H = S?.tecCourse ?? null, U = [...H?.lessons ?? []].sort((e, t) => e.position - t.position), W = (H?.enrollments ?? []).find((e) => e.learnerId === x?.id), G = (R?.tecListCertificates ?? []).find((e) => e.status === "ISSUED"), K = !!W && W.progressPct >= 100, q = async () => {
64
+ !b || !x?.id || (await B({ variables: {
65
+ courseId: b,
66
+ learnerId: x.id,
67
+ score: 100
68
+ } })).data?.tecIssueCertificate && (c.success("Certificate issued", "Your verifiable certificate is ready in My Learning."), await z());
69
+ }, J = async () => {
70
+ b && (await P({ variables: { input: { courseId: b } } })).data?.tecEnroll && (c.success("Enrolled", `You're enrolled in "${H?.title}".`), await N());
71
+ }, Y = async () => {
72
+ if (!W) return;
73
+ let e = Math.min(U.length, W.lessonsCompleted + 1), t = U.length ? Math.round(e / U.length * 100) : 100;
74
+ (await I({ variables: { input: {
75
+ enrollmentId: W.id,
67
76
  lessonsCompleted: e,
68
77
  progressPct: t
69
- } } })).data?.tecUpdateProgress && (c.success("Progress saved", `${t}% complete`), await A());
78
+ } } })).data?.tecUpdateProgress && (c.success("Progress saved", `${t}% complete`), await N());
70
79
  };
71
- if (D && !F) return /* @__PURE__ */ S(t, {
80
+ if (A && !H) return /* @__PURE__ */ T(t, {
72
81
  title: "Course",
73
82
  backPath: "/courses/courses-page",
74
- children: [/* @__PURE__ */ x(E, { className: "mb-4 h-40 w-full rounded-xl" }), /* @__PURE__ */ x(E, { className: "h-64 w-full rounded-xl" })]
83
+ children: [/* @__PURE__ */ w(k, { className: "mb-4 h-40 w-full rounded-xl" }), /* @__PURE__ */ w(k, { className: "h-64 w-full rounded-xl" })]
75
84
  });
76
- if (k || !F) return /* @__PURE__ */ x(t, {
85
+ if (M || !H) return /* @__PURE__ */ w(t, {
77
86
  title: "Course",
78
87
  backPath: "/courses/courses-page",
79
- children: k ? /* @__PURE__ */ x(s, {
88
+ children: M ? /* @__PURE__ */ w(s, {
80
89
  title: "Couldn't load course",
81
- error: k
82
- }) : /* @__PURE__ */ x(o, {
90
+ error: M
91
+ }) : /* @__PURE__ */ w(o, {
83
92
  title: "Course not found",
84
93
  description: "This course may have been unpublished."
85
94
  })
86
95
  });
87
- let B = L?.lessonsCompleted ?? 0;
88
- return /* @__PURE__ */ S(t, {
96
+ let X = W?.lessonsCompleted ?? 0;
97
+ return /* @__PURE__ */ T(t, {
89
98
  hero: !0,
90
99
  backPath: "/courses/courses-page",
91
- title: F.title,
92
- description: F.summary ?? void 0,
93
- actions: L ? /* @__PURE__ */ S(w, {
94
- onClick: z,
95
- disabled: P || B >= I.length,
96
- children: [/* @__PURE__ */ x(p, { size: 16 }), B >= I.length ? "Completed" : "Complete next lesson"]
97
- }) : /* @__PURE__ */ S(w, {
98
- onClick: R,
99
- disabled: M,
100
+ title: H.title,
101
+ description: H.summary ?? void 0,
102
+ actions: W ? /* @__PURE__ */ T(D, {
103
+ onClick: Y,
104
+ disabled: L || X >= U.length,
105
+ children: [/* @__PURE__ */ w(g, { size: 16 }), X >= U.length ? "Completed" : "Complete next lesson"]
106
+ }) : /* @__PURE__ */ T(D, {
107
+ onClick: J,
108
+ disabled: F,
100
109
  children: [
101
- /* @__PURE__ */ x(f, { size: 16 }),
110
+ /* @__PURE__ */ w(h, { size: 16 }),
102
111
  " ",
103
- M ? "Enrolling…" : "Enroll"
112
+ F ? "Enrolling…" : "Enroll"
104
113
  ]
105
114
  }),
106
115
  children: [
107
- /* @__PURE__ */ S("div", {
116
+ /* @__PURE__ */ T("div", {
108
117
  className: "mb-5 flex flex-wrap items-center gap-2",
109
118
  children: [
110
- /* @__PURE__ */ x(a, {
111
- status: F.level,
119
+ /* @__PURE__ */ w(a, {
120
+ status: H.level,
112
121
  kind: "level"
113
122
  }),
114
- /* @__PURE__ */ x(a, { status: F.status }),
115
- F.topic ? /* @__PURE__ */ S(C, {
123
+ /* @__PURE__ */ w(a, { status: H.status }),
124
+ H.topic ? /* @__PURE__ */ T(E, {
116
125
  variant: "outline",
117
126
  className: "gap-1",
118
127
  children: [
119
- /* @__PURE__ */ x(g, { size: 12 }),
128
+ /* @__PURE__ */ w(y, { size: 12 }),
120
129
  " ",
121
- F.topic
130
+ H.topic
122
131
  ]
123
132
  }) : null,
124
- F.tags.map((e) => /* @__PURE__ */ x(C, {
133
+ H.tags.map((e) => /* @__PURE__ */ w(E, {
125
134
  variant: "secondary",
126
135
  children: e
127
136
  }, e))
128
137
  ]
129
138
  }),
130
- /* @__PURE__ */ S("div", {
139
+ /* @__PURE__ */ T("div", {
131
140
  className: "mb-6 grid grid-cols-2 gap-3 sm:grid-cols-4",
132
141
  children: [
133
- /* @__PURE__ */ x(n, {
142
+ /* @__PURE__ */ w(n, {
134
143
  label: "Lessons",
135
- value: I.length,
136
- icon: h
144
+ value: U.length,
145
+ icon: v
137
146
  }),
138
- /* @__PURE__ */ x(n, {
147
+ /* @__PURE__ */ w(n, {
139
148
  label: "Duration",
140
- value: r(F.estimatedMinutes),
141
- icon: m
149
+ value: r(H.estimatedMinutes),
150
+ icon: _
142
151
  }),
143
- /* @__PURE__ */ x(n, {
152
+ /* @__PURE__ */ w(n, {
144
153
  label: "Enrolled",
145
- value: F.enrollments?.length ?? 0,
146
- icon: f
154
+ value: H.enrollments?.length ?? 0,
155
+ icon: h
147
156
  }),
148
- /* @__PURE__ */ x(n, {
157
+ /* @__PURE__ */ w(n, {
149
158
  label: "Your progress",
150
- value: L ? `${L.progressPct}%` : "Not started",
151
- icon: p
159
+ value: W ? `${W.progressPct}%` : "Not started",
160
+ icon: g
152
161
  })
153
162
  ]
154
163
  }),
155
- L ? /* @__PURE__ */ S(T, {
164
+ W ? /* @__PURE__ */ T(O, {
156
165
  className: "mb-6 p-4",
157
- children: [/* @__PURE__ */ S("div", {
166
+ children: [/* @__PURE__ */ T("div", {
158
167
  className: "mb-2 flex items-center justify-between text-sm",
159
- children: [/* @__PURE__ */ x("span", {
168
+ children: [/* @__PURE__ */ w("span", {
160
169
  className: "font-medium text-text-primary",
161
170
  children: "Your progress"
162
- }), /* @__PURE__ */ S("span", {
171
+ }), /* @__PURE__ */ T("span", {
163
172
  className: "text-text-secondary",
164
173
  children: [
165
- B,
174
+ X,
166
175
  "/",
167
- I.length,
176
+ U.length,
168
177
  " lessons · ",
169
- L.progressPct,
178
+ W.progressPct,
170
179
  "%"
171
180
  ]
172
181
  })]
173
- }), /* @__PURE__ */ x("div", {
182
+ }), /* @__PURE__ */ w("div", {
174
183
  className: "h-2 w-full overflow-hidden rounded-full bg-bg-sunken",
175
- children: /* @__PURE__ */ x("div", {
184
+ children: /* @__PURE__ */ w("div", {
176
185
  className: "h-full rounded-full bg-accent-primary transition-all",
177
- style: { width: `${L.progressPct}%` }
186
+ style: { width: `${W.progressPct}%` }
178
187
  })
179
188
  })]
180
189
  }) : null,
181
- /* @__PURE__ */ S(T, {
190
+ G ? /* @__PURE__ */ T(O, {
191
+ className: "mb-6 flex flex-wrap items-center gap-3 border-status-success-border p-4",
192
+ children: [/* @__PURE__ */ w(m, {
193
+ className: "text-accent-teal",
194
+ size: 22
195
+ }), /* @__PURE__ */ T("div", {
196
+ className: "min-w-0",
197
+ children: [/* @__PURE__ */ w("div", {
198
+ className: "text-sm font-semibold text-text-primary",
199
+ children: "Certificate earned"
200
+ }), /* @__PURE__ */ T("div", {
201
+ className: "text-xs text-text-muted",
202
+ children: [
203
+ "Serial ",
204
+ G.serial,
205
+ " · Score ",
206
+ G.score
207
+ ]
208
+ })]
209
+ })]
210
+ }) : K ? /* @__PURE__ */ T(O, {
211
+ className: "mb-6 flex flex-wrap items-center justify-between gap-3 p-4",
212
+ children: [/* @__PURE__ */ T("div", {
213
+ className: "flex items-center gap-3",
214
+ children: [/* @__PURE__ */ w(m, {
215
+ className: "text-accent-teal",
216
+ size: 22
217
+ }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("div", {
218
+ className: "text-sm font-semibold text-text-primary",
219
+ children: "You finished this course"
220
+ }), /* @__PURE__ */ w("div", {
221
+ className: "text-xs text-text-muted",
222
+ children: "Claim your verifiable certificate of completion."
223
+ })] })]
224
+ }), /* @__PURE__ */ T(D, {
225
+ onClick: q,
226
+ disabled: V,
227
+ children: [
228
+ /* @__PURE__ */ w(m, { size: 16 }),
229
+ " ",
230
+ V ? "Issuing…" : "Claim certificate"
231
+ ]
232
+ })]
233
+ }) : null,
234
+ /* @__PURE__ */ T(O, {
182
235
  className: "p-5",
183
- children: [/* @__PURE__ */ x("h2", {
236
+ children: [/* @__PURE__ */ w("h2", {
184
237
  className: "mb-2 text-base font-semibold text-text-primary",
185
238
  children: "Curriculum"
186
- }), I.length === 0 ? /* @__PURE__ */ x("p", {
239
+ }), U.length === 0 ? /* @__PURE__ */ w("p", {
187
240
  className: "py-6 text-center text-sm text-text-muted",
188
241
  children: "Lessons for this course are being prepared."
189
- }) : /* @__PURE__ */ x("div", { children: I.map((e, t) => /* @__PURE__ */ x(O, {
242
+ }) : /* @__PURE__ */ w("div", { children: U.map((e, t) => /* @__PURE__ */ w(j, {
190
243
  lesson: e,
191
- done: t < B
244
+ done: t < X
192
245
  }, e.id)) })]
193
246
  })
194
247
  ]
195
248
  });
196
249
  }
197
250
  //#endregion
198
- export { k as CoursesCourseDetailsPagePage };
251
+ export { M as CoursesCourseDetailsPagePage };
199
252
 
200
253
  //# sourceMappingURL=CoursesCourseDetailsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CoursesCourseDetailsPagePage.js","names":[],"sources":["../../../src/technospam/pages/CoursesCourseDetailsPagePage.tsx"],"sourcesContent":["import { useSearchParams } from 'react-router-dom';\nimport {\n BookOpen,\n CheckCircle2,\n Clock,\n FileText,\n Lock,\n PlayCircle,\n Layers,\n Sparkles,\n} from 'lucide-react';\nimport { Badge, Button, GlassCard, Skeleton } from '@burdenoff/fe-libs/ui';\nimport { EmptyView, ErrorView, PageLayout, StatCard, StatusBadge } from '../components';\nimport { useTechnoSpam } from '../providers/TechnoSpamProvider';\nimport {\n useCourseQuery,\n useEnroll,\n useUpdateProgress,\n type TecLesson,\n type TecEnrollment,\n} from '../api/technospamApi';\nimport { formatDuration, humanizeEnum } from '../utils/format';\nimport { notify } from '../lib/toast';\n\nconst LESSON_ICON: Record<string, typeof PlayCircle> = {\n VIDEO: PlayCircle,\n ARTICLE: FileText,\n INTERACTIVE: Sparkles,\n QUIZ: CheckCircle2,\n PROJECT: Layers,\n};\n\nfunction LessonRow({ lesson, done }: { lesson: TecLesson; done: boolean }) {\n const Icon = LESSON_ICON[lesson.kind] ?? FileText;\n return (\n <div className=\"flex items-center gap-3 border-b border-border-seam py-3 last:border-0\">\n <span\n className={`flex h-8 w-8 shrink-0 items-center justify-center rounded-lg ${\n done\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-bg-sunken text-text-secondary'\n }`}\n >\n {done ? <CheckCircle2 size={16} /> : <Icon size={16} />}\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate text-sm font-medium text-text-primary\">{lesson.title}</span>\n {lesson.isPreview ? (\n <Badge variant=\"secondary\" className=\"text-[11px]\">\n Preview\n </Badge>\n ) : null}\n </div>\n <div className=\"text-xs text-text-muted\">\n {humanizeEnum(lesson.kind)} · {formatDuration(lesson.estimatedMinutes)}\n </div>\n </div>\n {!lesson.isPreview && !done ? <Lock size={14} className=\"text-text-muted\" /> : null}\n </div>\n );\n}\n\nexport function CoursesCourseDetailsPagePage() {\n const [params] = useSearchParams();\n const id = params.get('id') ?? '';\n const { currentUser } = useTechnoSpam();\n const { data, loading, error, refetch } = useCourseQuery(id);\n const [enroll, { loading: enrolling }] = useEnroll();\n const [updateProgress, { loading: savingProgress }] = useUpdateProgress();\n\n const course = data?.tecCourse ?? null;\n const lessons = [...(course?.lessons ?? [])].sort((a, b) => a.position - b.position);\n const myEnrollment: TecEnrollment | undefined = (course?.enrollments ?? []).find(\n (e) => e.learnerId === currentUser?.id\n );\n\n const handleEnroll = async () => {\n if (!id) return;\n const res = await enroll({ variables: { input: { courseId: id } } });\n if (res.data?.tecEnroll) {\n notify.success('Enrolled', `You're enrolled in \"${course?.title}\".`);\n await refetch();\n }\n };\n\n const handleProgress = async () => {\n if (!myEnrollment) return;\n const nextCompleted = Math.min(lessons.length, myEnrollment.lessonsCompleted + 1);\n const pct = lessons.length ? Math.round((nextCompleted / lessons.length) * 100) : 100;\n const res = await updateProgress({\n variables: {\n input: { enrollmentId: myEnrollment.id, lessonsCompleted: nextCompleted, progressPct: pct },\n },\n });\n if (res.data?.tecUpdateProgress) {\n notify.success('Progress saved', `${pct}% complete`);\n await refetch();\n }\n };\n\n if (loading && !course) {\n return (\n <PageLayout title=\"Course\" backPath=\"/courses/courses-page\">\n <Skeleton className=\"mb-4 h-40 w-full rounded-xl\" />\n <Skeleton className=\"h-64 w-full rounded-xl\" />\n </PageLayout>\n );\n }\n\n if (error || !course) {\n return (\n <PageLayout title=\"Course\" backPath=\"/courses/courses-page\">\n {error ? (\n <ErrorView title=\"Couldn't load course\" error={error} />\n ) : (\n <EmptyView\n title=\"Course not found\"\n description=\"This course may have been unpublished.\"\n />\n )}\n </PageLayout>\n );\n }\n\n const completedLessons = myEnrollment?.lessonsCompleted ?? 0;\n\n return (\n <PageLayout\n hero\n backPath=\"/courses/courses-page\"\n title={course.title}\n description={course.summary ?? undefined}\n actions={\n myEnrollment ? (\n <Button\n onClick={handleProgress}\n disabled={savingProgress || completedLessons >= lessons.length}\n >\n <CheckCircle2 size={16} />\n {completedLessons >= lessons.length ? 'Completed' : 'Complete next lesson'}\n </Button>\n ) : (\n <Button onClick={handleEnroll} disabled={enrolling}>\n <BookOpen size={16} /> {enrolling ? 'Enrolling…' : 'Enroll'}\n </Button>\n )\n }\n >\n <div className=\"mb-5 flex flex-wrap items-center gap-2\">\n <StatusBadge status={course.level} kind=\"level\" />\n <StatusBadge status={course.status} />\n {course.topic ? (\n <Badge variant=\"outline\" className=\"gap-1\">\n <Layers size={12} /> {course.topic}\n </Badge>\n ) : null}\n {course.tags.map((t) => (\n <Badge key={t} variant=\"secondary\">\n {t}\n </Badge>\n ))}\n </div>\n\n <div className=\"mb-6 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard label=\"Lessons\" value={lessons.length} icon={FileText} />\n <StatCard label=\"Duration\" value={formatDuration(course.estimatedMinutes)} icon={Clock} />\n <StatCard label=\"Enrolled\" value={course.enrollments?.length ?? 0} icon={BookOpen} />\n <StatCard\n label=\"Your progress\"\n value={myEnrollment ? `${myEnrollment.progressPct}%` : 'Not started'}\n icon={CheckCircle2}\n />\n </div>\n\n {myEnrollment ? (\n <GlassCard className=\"mb-6 p-4\">\n <div className=\"mb-2 flex items-center justify-between text-sm\">\n <span className=\"font-medium text-text-primary\">Your progress</span>\n <span className=\"text-text-secondary\">\n {completedLessons}/{lessons.length} lessons · {myEnrollment.progressPct}%\n </span>\n </div>\n <div className=\"h-2 w-full overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-full rounded-full bg-accent-primary transition-all\"\n style={{ width: `${myEnrollment.progressPct}%` }}\n />\n </div>\n </GlassCard>\n ) : null}\n\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-2 text-base font-semibold text-text-primary\">Curriculum</h2>\n {lessons.length === 0 ? (\n <p className=\"py-6 text-center text-sm text-text-muted\">\n Lessons for this course are being prepared.\n </p>\n ) : (\n <div>\n {lessons.map((lesson, i) => (\n <LessonRow key={lesson.id} lesson={lesson} done={i < completedLessons} />\n ))}\n </div>\n )}\n </GlassCard>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CoursesCourseDetailsPagePage.js","names":[],"sources":["../../../src/technospam/pages/CoursesCourseDetailsPagePage.tsx"],"sourcesContent":["import { useSearchParams } from 'react-router-dom';\nimport {\n Award,\n BookOpen,\n CheckCircle2,\n Clock,\n FileText,\n Lock,\n PlayCircle,\n Layers,\n Sparkles,\n} from 'lucide-react';\nimport { Badge, Button, GlassCard, Skeleton } from '@burdenoff/fe-libs/ui';\nimport { EmptyView, ErrorView, PageLayout, StatCard, StatusBadge } from '../components';\nimport { useTechnoSpam } from '../providers/TechnoSpamProvider';\nimport {\n useCertificatesQuery,\n useCourseQuery,\n useEnroll,\n useIssueCertificate,\n useUpdateProgress,\n type TecLesson,\n type TecEnrollment,\n} from '../api/technospamApi';\nimport { formatDuration, humanizeEnum } from '../utils/format';\nimport { notify } from '../lib/toast';\n\nconst LESSON_ICON: Record<string, typeof PlayCircle> = {\n VIDEO: PlayCircle,\n ARTICLE: FileText,\n INTERACTIVE: Sparkles,\n QUIZ: CheckCircle2,\n PROJECT: Layers,\n};\n\nfunction LessonRow({ lesson, done }: { lesson: TecLesson; done: boolean }) {\n const Icon = LESSON_ICON[lesson.kind] ?? FileText;\n return (\n <div className=\"flex items-center gap-3 border-b border-border-seam py-3 last:border-0\">\n <span\n className={`flex h-8 w-8 shrink-0 items-center justify-center rounded-lg ${\n done\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-bg-sunken text-text-secondary'\n }`}\n >\n {done ? <CheckCircle2 size={16} /> : <Icon size={16} />}\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate text-sm font-medium text-text-primary\">{lesson.title}</span>\n {lesson.isPreview ? (\n <Badge variant=\"secondary\" className=\"text-[11px]\">\n Preview\n </Badge>\n ) : null}\n </div>\n <div className=\"text-xs text-text-muted\">\n {humanizeEnum(lesson.kind)} · {formatDuration(lesson.estimatedMinutes)}\n </div>\n </div>\n {!lesson.isPreview && !done ? <Lock size={14} className=\"text-text-muted\" /> : null}\n </div>\n );\n}\n\nexport function CoursesCourseDetailsPagePage() {\n const [params] = useSearchParams();\n const id = params.get('id') ?? '';\n const { currentUser } = useTechnoSpam();\n const { data, loading, error, refetch } = useCourseQuery(id);\n const [enroll, { loading: enrolling }] = useEnroll();\n const [updateProgress, { loading: savingProgress }] = useUpdateProgress();\n const { data: certData, refetch: refetchCerts } = useCertificatesQuery(\n currentUser?.id && id ? { learnerId: currentUser.id, courseId: id } : {}\n );\n const [issueCertificate, { loading: claiming }] = useIssueCertificate();\n\n const course = data?.tecCourse ?? null;\n const lessons = [...(course?.lessons ?? [])].sort((a, b) => a.position - b.position);\n const myEnrollment: TecEnrollment | undefined = (course?.enrollments ?? []).find(\n (e) => e.learnerId === currentUser?.id\n );\n const myCertificate = (certData?.tecListCertificates ?? []).find((c) => c.status === 'ISSUED');\n const isComplete = !!myEnrollment && myEnrollment.progressPct >= 100;\n\n const handleClaimCertificate = async () => {\n if (!id || !currentUser?.id) return;\n const res = await issueCertificate({\n variables: { courseId: id, learnerId: currentUser.id, score: 100 },\n });\n if (res.data?.tecIssueCertificate) {\n notify.success('Certificate issued', 'Your verifiable certificate is ready in My Learning.');\n await refetchCerts();\n }\n };\n\n const handleEnroll = async () => {\n if (!id) return;\n const res = await enroll({ variables: { input: { courseId: id } } });\n if (res.data?.tecEnroll) {\n notify.success('Enrolled', `You're enrolled in \"${course?.title}\".`);\n await refetch();\n }\n };\n\n const handleProgress = async () => {\n if (!myEnrollment) return;\n const nextCompleted = Math.min(lessons.length, myEnrollment.lessonsCompleted + 1);\n const pct = lessons.length ? Math.round((nextCompleted / lessons.length) * 100) : 100;\n const res = await updateProgress({\n variables: {\n input: { enrollmentId: myEnrollment.id, lessonsCompleted: nextCompleted, progressPct: pct },\n },\n });\n if (res.data?.tecUpdateProgress) {\n notify.success('Progress saved', `${pct}% complete`);\n await refetch();\n }\n };\n\n if (loading && !course) {\n return (\n <PageLayout title=\"Course\" backPath=\"/courses/courses-page\">\n <Skeleton className=\"mb-4 h-40 w-full rounded-xl\" />\n <Skeleton className=\"h-64 w-full rounded-xl\" />\n </PageLayout>\n );\n }\n\n if (error || !course) {\n return (\n <PageLayout title=\"Course\" backPath=\"/courses/courses-page\">\n {error ? (\n <ErrorView title=\"Couldn't load course\" error={error} />\n ) : (\n <EmptyView\n title=\"Course not found\"\n description=\"This course may have been unpublished.\"\n />\n )}\n </PageLayout>\n );\n }\n\n const completedLessons = myEnrollment?.lessonsCompleted ?? 0;\n\n return (\n <PageLayout\n hero\n backPath=\"/courses/courses-page\"\n title={course.title}\n description={course.summary ?? undefined}\n actions={\n myEnrollment ? (\n <Button\n onClick={handleProgress}\n disabled={savingProgress || completedLessons >= lessons.length}\n >\n <CheckCircle2 size={16} />\n {completedLessons >= lessons.length ? 'Completed' : 'Complete next lesson'}\n </Button>\n ) : (\n <Button onClick={handleEnroll} disabled={enrolling}>\n <BookOpen size={16} /> {enrolling ? 'Enrolling…' : 'Enroll'}\n </Button>\n )\n }\n >\n <div className=\"mb-5 flex flex-wrap items-center gap-2\">\n <StatusBadge status={course.level} kind=\"level\" />\n <StatusBadge status={course.status} />\n {course.topic ? (\n <Badge variant=\"outline\" className=\"gap-1\">\n <Layers size={12} /> {course.topic}\n </Badge>\n ) : null}\n {course.tags.map((t) => (\n <Badge key={t} variant=\"secondary\">\n {t}\n </Badge>\n ))}\n </div>\n\n <div className=\"mb-6 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard label=\"Lessons\" value={lessons.length} icon={FileText} />\n <StatCard label=\"Duration\" value={formatDuration(course.estimatedMinutes)} icon={Clock} />\n <StatCard label=\"Enrolled\" value={course.enrollments?.length ?? 0} icon={BookOpen} />\n <StatCard\n label=\"Your progress\"\n value={myEnrollment ? `${myEnrollment.progressPct}%` : 'Not started'}\n icon={CheckCircle2}\n />\n </div>\n\n {myEnrollment ? (\n <GlassCard className=\"mb-6 p-4\">\n <div className=\"mb-2 flex items-center justify-between text-sm\">\n <span className=\"font-medium text-text-primary\">Your progress</span>\n <span className=\"text-text-secondary\">\n {completedLessons}/{lessons.length} lessons · {myEnrollment.progressPct}%\n </span>\n </div>\n <div className=\"h-2 w-full overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-full rounded-full bg-accent-primary transition-all\"\n style={{ width: `${myEnrollment.progressPct}%` }}\n />\n </div>\n </GlassCard>\n ) : null}\n\n {myCertificate ? (\n <GlassCard className=\"mb-6 flex flex-wrap items-center gap-3 border-status-success-border p-4\">\n <Award className=\"text-accent-teal\" size={22} />\n <div className=\"min-w-0\">\n <div className=\"text-sm font-semibold text-text-primary\">Certificate earned</div>\n <div className=\"text-xs text-text-muted\">\n Serial {myCertificate.serial} · Score {myCertificate.score}\n </div>\n </div>\n </GlassCard>\n ) : isComplete ? (\n <GlassCard className=\"mb-6 flex flex-wrap items-center justify-between gap-3 p-4\">\n <div className=\"flex items-center gap-3\">\n <Award className=\"text-accent-teal\" size={22} />\n <div>\n <div className=\"text-sm font-semibold text-text-primary\">\n You finished this course\n </div>\n <div className=\"text-xs text-text-muted\">\n Claim your verifiable certificate of completion.\n </div>\n </div>\n </div>\n <Button onClick={handleClaimCertificate} disabled={claiming}>\n <Award size={16} /> {claiming ? 'Issuing…' : 'Claim certificate'}\n </Button>\n </GlassCard>\n ) : null}\n\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-2 text-base font-semibold text-text-primary\">Curriculum</h2>\n {lessons.length === 0 ? (\n <p className=\"py-6 text-center text-sm text-text-muted\">\n Lessons for this course are being prepared.\n </p>\n ) : (\n <div>\n {lessons.map((lesson, i) => (\n <LessonRow key={lesson.id} lesson={lesson} done={i < completedLessons} />\n ))}\n </div>\n )}\n </GlassCard>\n </PageLayout>\n );\n}\n"],"mappings":"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"}