@burdenoff/microfe-technospam 2026.705.2 → 2026.709.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.
- package/dist/generated/wspace-operations.js +67 -0
- package/dist/generated/wspace-operations.js.map +1 -0
- package/dist/index.js +3 -1
- package/dist/technospam/hooks/useTechnoSpamAnalytics.js +13 -0
- package/dist/technospam/hooks/useTechnoSpamAnalytics.js.map +1 -0
- package/dist/technospam/index.js +2 -0
- package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.js +129 -105
- package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.js.map +1 -1
- package/dist/technospam/pages/ApplicationsProblemsPagePage.js +87 -72
- package/dist/technospam/pages/ApplicationsProblemsPagePage.js.map +1 -1
- package/dist/technospam/pages/CoursesCourseDetailsPagePage.js +174 -143
- package/dist/technospam/pages/CoursesCourseDetailsPagePage.js.map +1 -1
- package/dist/technospam/pages/CoursesCoursesPagePage.js +95 -80
- package/dist/technospam/pages/CoursesCoursesPagePage.js.map +1 -1
- package/dist/technospam/pages/HackathonsHackathonsPagePage.js +93 -78
- package/dist/technospam/pages/HackathonsHackathonsPagePage.js.map +1 -1
- package/dist/technospam/pages/MentorshipMentorProfilePagePage.js +135 -121
- package/dist/technospam/pages/MentorshipMentorProfilePagePage.js.map +1 -1
- package/dist/technospam/pages/MentorshipMentorsPagePage.js +156 -142
- package/dist/technospam/pages/MentorshipMentorsPagePage.js.map +1 -1
- package/dist/technospam/pages/MentorshipSessionsPagePage.js +129 -112
- package/dist/technospam/pages/MentorshipSessionsPagePage.js.map +1 -1
- package/dist/technospam/services/assistantApi.js +222 -0
- package/dist/technospam/services/assistantApi.js.map +1 -0
- package/dist/technospam/services/createSandboxAssistantTransport.js +120 -0
- package/dist/technospam/services/createSandboxAssistantTransport.js.map +1 -0
- package/dist/technospam/utils/pageContext.js +46 -0
- package/dist/technospam/utils/pageContext.js.map +1 -0
- package/package.json +5 -1
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PageLayout as
|
|
3
|
-
import { StatCard as
|
|
4
|
-
import { MediaCover as
|
|
5
|
-
import { formatDuration as
|
|
6
|
-
import { StatusBadge as
|
|
7
|
-
import { LoadMore as
|
|
8
|
-
import { EmptyView as
|
|
1
|
+
import { useTechnoSpam as e, useTechnoSpamNavigate as t } from "../providers/TechnoSpamProvider.js";
|
|
2
|
+
import { PageLayout as n } from "../components/PageLayout.js";
|
|
3
|
+
import { StatCard as r } from "../components/StatCard.js";
|
|
4
|
+
import { MediaCover as i, topicIcon as a } from "../components/MediaCover.js";
|
|
5
|
+
import { formatDuration as o } from "../utils/format.js";
|
|
6
|
+
import { StatusBadge as s } from "../components/StatusBadge.js";
|
|
7
|
+
import { LoadMore as c } from "../components/LoadMore.js";
|
|
8
|
+
import { EmptyView as l, ErrorView as u, LoadingGrid as d } from "../components/StateViews.js";
|
|
9
9
|
import "../components/index.js";
|
|
10
|
-
import { pageArg as
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
10
|
+
import { pageArg as f, useCoursesQuery as p, usePageLimit as m } from "../api/technospamApi.js";
|
|
11
|
+
import { useTechnoSpamAnalytics as h } from "../hooks/useTechnoSpamAnalytics.js";
|
|
12
|
+
import { useMemo as g, useState as _ } from "react";
|
|
13
|
+
import { BookOpen as v, Clock as y, GraduationCap as b, Layers as x, Search as S, Sparkles as C } from "lucide-react";
|
|
14
|
+
import { jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
15
|
+
import { Badge as E, Button as D, GlassCard as O, Input as k, Tabs as A, TabsList as j, TabsTrigger as M } from "@burdenoff/fe-libs/ui";
|
|
15
16
|
//#region src/technospam/pages/CoursesCoursesPagePage.tsx
|
|
16
|
-
var
|
|
17
|
+
var N = [
|
|
17
18
|
{
|
|
18
19
|
value: "ALL",
|
|
19
20
|
label: "All levels"
|
|
@@ -35,51 +36,51 @@ var j = [
|
|
|
35
36
|
label: "Expert"
|
|
36
37
|
}
|
|
37
38
|
];
|
|
38
|
-
function
|
|
39
|
-
return /* @__PURE__ */
|
|
39
|
+
function P({ course: e, onOpen: t }) {
|
|
40
|
+
return /* @__PURE__ */ T(O, {
|
|
40
41
|
className: "group flex cursor-pointer flex-col overflow-hidden transition-all duration-200 hover:-translate-y-1 hover:shadow-lg",
|
|
41
42
|
onClick: t,
|
|
42
|
-
children: [/* @__PURE__ */
|
|
43
|
+
children: [/* @__PURE__ */ w(i, {
|
|
43
44
|
seed: `${e.topic ?? ""} ${e.title}`,
|
|
44
|
-
icon:
|
|
45
|
-
children: /* @__PURE__ */
|
|
45
|
+
icon: a(e.topic ?? e.title),
|
|
46
|
+
children: /* @__PURE__ */ w(s, {
|
|
46
47
|
status: e.level,
|
|
47
48
|
kind: "level"
|
|
48
49
|
})
|
|
49
|
-
}), /* @__PURE__ */
|
|
50
|
+
}), /* @__PURE__ */ T("div", {
|
|
50
51
|
className: "flex flex-1 flex-col gap-3 p-4",
|
|
51
52
|
children: [
|
|
52
|
-
/* @__PURE__ */
|
|
53
|
+
/* @__PURE__ */ T("div", {
|
|
53
54
|
className: "min-w-0",
|
|
54
|
-
children: [/* @__PURE__ */
|
|
55
|
+
children: [/* @__PURE__ */ w("h3", {
|
|
55
56
|
className: "truncate text-base font-semibold text-text-primary group-hover:text-accent-primary",
|
|
56
57
|
children: e.title
|
|
57
|
-
}), e.summary ? /* @__PURE__ */
|
|
58
|
+
}), e.summary ? /* @__PURE__ */ w("p", {
|
|
58
59
|
className: "mt-1 line-clamp-2 text-sm text-text-secondary",
|
|
59
60
|
children: e.summary
|
|
60
61
|
}) : null]
|
|
61
62
|
}),
|
|
62
|
-
/* @__PURE__ */
|
|
63
|
+
/* @__PURE__ */ T("div", {
|
|
63
64
|
className: "mt-auto flex flex-wrap items-center gap-3 text-xs text-text-muted",
|
|
64
|
-
children: [e.topic ? /* @__PURE__ */
|
|
65
|
+
children: [e.topic ? /* @__PURE__ */ T("span", {
|
|
65
66
|
className: "inline-flex items-center gap-1",
|
|
66
67
|
children: [
|
|
67
|
-
/* @__PURE__ */
|
|
68
|
+
/* @__PURE__ */ w(x, { size: 13 }),
|
|
68
69
|
" ",
|
|
69
70
|
e.topic
|
|
70
71
|
]
|
|
71
|
-
}) : null, /* @__PURE__ */
|
|
72
|
+
}) : null, /* @__PURE__ */ T("span", {
|
|
72
73
|
className: "inline-flex items-center gap-1",
|
|
73
74
|
children: [
|
|
74
|
-
/* @__PURE__ */
|
|
75
|
+
/* @__PURE__ */ w(y, { size: 13 }),
|
|
75
76
|
" ",
|
|
76
|
-
|
|
77
|
+
o(e.estimatedMinutes)
|
|
77
78
|
]
|
|
78
79
|
})]
|
|
79
80
|
}),
|
|
80
|
-
e.tags.length ? /* @__PURE__ */
|
|
81
|
+
e.tags.length ? /* @__PURE__ */ w("div", {
|
|
81
82
|
className: "flex flex-wrap gap-1.5",
|
|
82
|
-
children: e.tags.slice(0, 3).map((e) => /* @__PURE__ */
|
|
83
|
+
children: e.tags.slice(0, 3).map((e) => /* @__PURE__ */ w(E, {
|
|
83
84
|
variant: "secondary",
|
|
84
85
|
className: "text-[11px]",
|
|
85
86
|
children: e
|
|
@@ -89,99 +90,113 @@ function M({ course: e, onOpen: t }) {
|
|
|
89
90
|
})]
|
|
90
91
|
});
|
|
91
92
|
}
|
|
92
|
-
function
|
|
93
|
-
let
|
|
93
|
+
function F() {
|
|
94
|
+
let i = t(), { workspaceId: a } = e(), { emit: s } = h(), [x, E] = _("ALL"), [O, F] = _(""), { limit: I, more: L } = m(), { data: R, loading: z, error: B } = p({
|
|
94
95
|
status: "PUBLISHED",
|
|
95
|
-
pagination:
|
|
96
|
-
...
|
|
97
|
-
}),
|
|
98
|
-
let e =
|
|
99
|
-
return e ?
|
|
100
|
-
}, [
|
|
101
|
-
return /* @__PURE__ */
|
|
96
|
+
pagination: f(I),
|
|
97
|
+
...x === "ALL" ? {} : { level: x }
|
|
98
|
+
}), V = R?.tecListCourses.items ?? [], H = R?.tecListCourses.pageInfo.hasMore ?? !1, U = g(() => {
|
|
99
|
+
let e = O.trim().toLowerCase();
|
|
100
|
+
return e ? V.filter((t) => t.title.toLowerCase().includes(e) || (t.topic ?? "").toLowerCase().includes(e) || t.tags.some((t) => t.toLowerCase().includes(e))) : V;
|
|
101
|
+
}, [V, O]);
|
|
102
|
+
return /* @__PURE__ */ T(n, {
|
|
102
103
|
hero: !0,
|
|
103
104
|
title: "Course Catalog",
|
|
104
105
|
description: "Learn technology by doing — practical, project-based courses across the stack.",
|
|
105
|
-
actions: /* @__PURE__ */
|
|
106
|
+
actions: /* @__PURE__ */ T(D, {
|
|
106
107
|
variant: "outline",
|
|
107
|
-
onClick: () =>
|
|
108
|
-
children: [/* @__PURE__ */
|
|
108
|
+
onClick: () => i("/courses/my-learning-page"),
|
|
109
|
+
children: [/* @__PURE__ */ w(b, { size: 16 }), " My Learning"]
|
|
109
110
|
}),
|
|
110
111
|
children: [
|
|
111
|
-
/* @__PURE__ */
|
|
112
|
+
/* @__PURE__ */ T("div", {
|
|
112
113
|
className: "mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4",
|
|
113
114
|
children: [
|
|
114
|
-
/* @__PURE__ */
|
|
115
|
+
/* @__PURE__ */ w(r, {
|
|
115
116
|
label: "Courses",
|
|
116
|
-
value:
|
|
117
|
-
icon:
|
|
117
|
+
value: V.length,
|
|
118
|
+
icon: v,
|
|
118
119
|
tone: "blue"
|
|
119
120
|
}),
|
|
120
|
-
/* @__PURE__ */
|
|
121
|
+
/* @__PURE__ */ w(r, {
|
|
121
122
|
label: "Beginner-friendly",
|
|
122
|
-
value:
|
|
123
|
-
icon:
|
|
123
|
+
value: V.filter((e) => e.level === "BEGINNER").length,
|
|
124
|
+
icon: C,
|
|
124
125
|
tone: "green"
|
|
125
126
|
}),
|
|
126
|
-
/* @__PURE__ */
|
|
127
|
+
/* @__PURE__ */ w(r, {
|
|
127
128
|
label: "Advanced+",
|
|
128
|
-
value:
|
|
129
|
-
icon:
|
|
129
|
+
value: V.filter((e) => e.level === "ADVANCED" || e.level === "EXPERT").length,
|
|
130
|
+
icon: b,
|
|
130
131
|
tone: "purple"
|
|
131
132
|
}),
|
|
132
|
-
/* @__PURE__ */
|
|
133
|
+
/* @__PURE__ */ w(r, {
|
|
133
134
|
label: "Total content",
|
|
134
|
-
value:
|
|
135
|
-
icon:
|
|
135
|
+
value: o(V.reduce((e, t) => e + t.estimatedMinutes, 0)),
|
|
136
|
+
icon: y,
|
|
136
137
|
tone: "teal"
|
|
137
138
|
})
|
|
138
139
|
]
|
|
139
140
|
}),
|
|
140
|
-
/* @__PURE__ */
|
|
141
|
+
/* @__PURE__ */ T("div", {
|
|
141
142
|
className: "mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
|
|
142
|
-
children: [/* @__PURE__ */
|
|
143
|
-
value:
|
|
144
|
-
onValueChange: (e) =>
|
|
145
|
-
children: /* @__PURE__ */
|
|
143
|
+
children: [/* @__PURE__ */ w(A, {
|
|
144
|
+
value: x,
|
|
145
|
+
onValueChange: (e) => E(e),
|
|
146
|
+
children: /* @__PURE__ */ w(j, { children: N.map((e) => /* @__PURE__ */ w(M, {
|
|
146
147
|
value: e.value,
|
|
147
148
|
children: e.label
|
|
148
149
|
}, e.value)) })
|
|
149
|
-
}), /* @__PURE__ */
|
|
150
|
+
}), /* @__PURE__ */ T("div", {
|
|
150
151
|
className: "relative w-full sm:w-72",
|
|
151
|
-
children: [/* @__PURE__ */ S
|
|
152
|
+
children: [/* @__PURE__ */ w(S, {
|
|
152
153
|
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-text-muted",
|
|
153
154
|
size: 16
|
|
154
|
-
}), /* @__PURE__ */
|
|
155
|
+
}), /* @__PURE__ */ w(k, {
|
|
155
156
|
className: "pl-9",
|
|
156
157
|
placeholder: "Search courses…",
|
|
157
|
-
value:
|
|
158
|
-
onChange: (e) =>
|
|
158
|
+
value: O,
|
|
159
|
+
onChange: (e) => F(e.target.value),
|
|
160
|
+
onBlur: () => {
|
|
161
|
+
let e = O.trim();
|
|
162
|
+
e && s("technospam.search.performed", {
|
|
163
|
+
workspaceId: a,
|
|
164
|
+
entityType: "course",
|
|
165
|
+
queryLength: e.length
|
|
166
|
+
});
|
|
167
|
+
}
|
|
159
168
|
})]
|
|
160
169
|
})]
|
|
161
170
|
}),
|
|
162
|
-
|
|
171
|
+
z && !V.length ? /* @__PURE__ */ w(d, {}) : B ? /* @__PURE__ */ w(u, {
|
|
163
172
|
title: "Couldn't load courses",
|
|
164
|
-
error:
|
|
165
|
-
}) :
|
|
166
|
-
icon: /* @__PURE__ */
|
|
167
|
-
title:
|
|
168
|
-
description:
|
|
169
|
-
}) : /* @__PURE__ */
|
|
173
|
+
error: B
|
|
174
|
+
}) : U.length === 0 ? /* @__PURE__ */ w(l, {
|
|
175
|
+
icon: /* @__PURE__ */ w(v, { size: 26 }),
|
|
176
|
+
title: O || x !== "ALL" ? "No matching courses" : "No courses published yet",
|
|
177
|
+
description: O || x !== "ALL" ? "Try a different search or level filter." : "Published courses will appear here. Check back soon — TechnoSpam is pre-launch."
|
|
178
|
+
}) : /* @__PURE__ */ w("div", {
|
|
170
179
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
171
|
-
children:
|
|
180
|
+
children: U.map((e) => /* @__PURE__ */ w(P, {
|
|
172
181
|
course: e,
|
|
173
|
-
onOpen: () =>
|
|
182
|
+
onOpen: () => {
|
|
183
|
+
s("technospam.course.viewed", {
|
|
184
|
+
workspaceId: a,
|
|
185
|
+
entityId: e.id,
|
|
186
|
+
entityType: "TEC_COURSE"
|
|
187
|
+
}), i(`/courses/course-details-page?id=${e.id}`);
|
|
188
|
+
}
|
|
174
189
|
}, e.id))
|
|
175
190
|
}),
|
|
176
|
-
/* @__PURE__ */
|
|
177
|
-
hasMore:
|
|
178
|
-
loading:
|
|
179
|
-
onClick:
|
|
191
|
+
/* @__PURE__ */ w(c, {
|
|
192
|
+
hasMore: H,
|
|
193
|
+
loading: z,
|
|
194
|
+
onClick: L
|
|
180
195
|
})
|
|
181
196
|
]
|
|
182
197
|
});
|
|
183
198
|
}
|
|
184
199
|
//#endregion
|
|
185
|
-
export {
|
|
200
|
+
export { F as CoursesCoursesPagePage };
|
|
186
201
|
|
|
187
202
|
//# sourceMappingURL=CoursesCoursesPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoursesCoursesPagePage.js","names":[],"sources":["../../../src/technospam/pages/CoursesCoursesPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { BookOpen, Clock, GraduationCap, Layers, Search, Sparkles } from 'lucide-react';\nimport {\n Badge,\n Button,\n GlassCard,\n Input,\n Tabs,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n EmptyView,\n ErrorView,\n LoadMore,\n LoadingGrid,\n MediaCover,\n PageLayout,\n StatCard,\n StatusBadge,\n topicIcon,\n} from '../components';\nimport { useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport {\n pageArg,\n useCoursesQuery,\n usePageLimit,\n type TecCourse,\n type TecCourseLevel,\n} from '../api/technospamApi';\nimport { formatDuration } from '../utils/format';\n\nconst LEVELS: Array<{ value: 'ALL' | TecCourseLevel; label: string }> = [\n { value: 'ALL', label: 'All levels' },\n { value: 'BEGINNER', label: 'Beginner' },\n { value: 'INTERMEDIATE', label: 'Intermediate' },\n { value: 'ADVANCED', label: 'Advanced' },\n { value: 'EXPERT', label: 'Expert' },\n];\n\nfunction CourseCard({ course, onOpen }: { course: TecCourse; onOpen: () => void }) {\n return (\n <GlassCard\n className=\"group flex cursor-pointer flex-col overflow-hidden transition-all duration-200 hover:-translate-y-1 hover:shadow-lg\"\n onClick={onOpen}\n >\n <MediaCover\n seed={`${course.topic ?? ''} ${course.title}`}\n icon={topicIcon(course.topic ?? course.title)}\n >\n <StatusBadge status={course.level} kind=\"level\" />\n </MediaCover>\n <div className=\"flex flex-1 flex-col gap-3 p-4\">\n <div className=\"min-w-0\">\n <h3 className=\"truncate text-base font-semibold text-text-primary group-hover:text-accent-primary\">\n {course.title}\n </h3>\n {course.summary ? (\n <p className=\"mt-1 line-clamp-2 text-sm text-text-secondary\">{course.summary}</p>\n ) : null}\n </div>\n <div className=\"mt-auto flex flex-wrap items-center gap-3 text-xs text-text-muted\">\n {course.topic ? (\n <span className=\"inline-flex items-center gap-1\">\n <Layers size={13} /> {course.topic}\n </span>\n ) : null}\n <span className=\"inline-flex items-center gap-1\">\n <Clock size={13} /> {formatDuration(course.estimatedMinutes)}\n </span>\n </div>\n {course.tags.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {course.tags.slice(0, 3).map((t) => (\n <Badge key={t} variant=\"secondary\" className=\"text-[11px]\">\n {t}\n </Badge>\n ))}\n </div>\n ) : null}\n </div>\n </GlassCard>\n );\n}\n\nexport function CoursesCoursesPagePage() {\n const navigate = useTechnoSpamNavigate();\n const [level, setLevel] = useState<'ALL' | TecCourseLevel>('ALL');\n const [search, setSearch] = useState('');\n\n const { limit, more } = usePageLimit();\n const { data, loading, error } = useCoursesQuery({\n status: 'PUBLISHED',\n pagination: pageArg(limit),\n ...(level !== 'ALL' ? { level } : {}),\n });\n\n const courses = data?.tecListCourses.items ?? [];\n const hasMore = data?.tecListCourses.pageInfo.hasMore ?? false;\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n if (!q) return courses;\n return courses.filter(\n (c) =>\n c.title.toLowerCase().includes(q) ||\n (c.topic ?? '').toLowerCase().includes(q) ||\n c.tags.some((t) => t.toLowerCase().includes(q))\n );\n }, [courses, search]);\n\n return (\n <PageLayout\n hero\n title=\"Course Catalog\"\n description=\"Learn technology by doing — practical, project-based courses across the stack.\"\n actions={\n <Button variant=\"outline\" onClick={() => navigate('/courses/my-learning-page')}>\n <GraduationCap size={16} /> My Learning\n </Button>\n }\n >\n <div className=\"mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard label=\"Courses\" value={courses.length} icon={BookOpen} tone=\"blue\" />\n <StatCard\n label=\"Beginner-friendly\"\n value={courses.filter((c) => c.level === 'BEGINNER').length}\n icon={Sparkles}\n tone=\"green\"\n />\n <StatCard\n label=\"Advanced+\"\n value={courses.filter((c) => c.level === 'ADVANCED' || c.level === 'EXPERT').length}\n icon={GraduationCap}\n tone=\"purple\"\n />\n <StatCard\n label=\"Total content\"\n value={formatDuration(courses.reduce((s, c) => s + c.estimatedMinutes, 0))}\n icon={Clock}\n tone=\"teal\"\n />\n </div>\n\n <div className=\"mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <Tabs value={level} onValueChange={(v) => setLevel(v as 'ALL' | TecCourseLevel)}>\n <TabsList>\n {LEVELS.map((l) => (\n <TabsTrigger key={l.value} value={l.value}>\n {l.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n <div className=\"relative w-full sm:w-72\">\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-text-muted\"\n size={16}\n />\n <Input\n className=\"pl-9\"\n placeholder=\"Search courses…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n </div>\n\n {loading && !courses.length ? (\n <LoadingGrid />\n ) : error ? (\n <ErrorView title=\"Couldn't load courses\" error={error} />\n ) : filtered.length === 0 ? (\n <EmptyView\n icon={<BookOpen size={26} />}\n title={search || level !== 'ALL' ? 'No matching courses' : 'No courses published yet'}\n description={\n search || level !== 'ALL'\n ? 'Try a different search or level filter.'\n : 'Published courses will appear here. Check back soon — TechnoSpam is pre-launch.'\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filtered.map((course) => (\n <CourseCard\n key={course.id}\n course={course}\n onOpen={() => navigate(`/courses/course-details-page?id=${course.id}`)}\n />\n ))}\n </div>\n )}\n <LoadMore hasMore={hasMore} loading={loading} onClick={more} />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CoursesCoursesPagePage.js","names":[],"sources":["../../../src/technospam/pages/CoursesCoursesPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { BookOpen, Clock, GraduationCap, Layers, Search, Sparkles } from 'lucide-react';\nimport {\n Badge,\n Button,\n GlassCard,\n Input,\n Tabs,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n EmptyView,\n ErrorView,\n LoadMore,\n LoadingGrid,\n MediaCover,\n PageLayout,\n StatCard,\n StatusBadge,\n topicIcon,\n} from '../components';\nimport { useTechnoSpam, useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport {\n pageArg,\n useCoursesQuery,\n usePageLimit,\n type TecCourse,\n type TecCourseLevel,\n} from '../api/technospamApi';\nimport { formatDuration } from '../utils/format';\nimport { useTechnoSpamAnalytics } from '../hooks/useTechnoSpamAnalytics';\n\nconst LEVELS: Array<{ value: 'ALL' | TecCourseLevel; label: string }> = [\n { value: 'ALL', label: 'All levels' },\n { value: 'BEGINNER', label: 'Beginner' },\n { value: 'INTERMEDIATE', label: 'Intermediate' },\n { value: 'ADVANCED', label: 'Advanced' },\n { value: 'EXPERT', label: 'Expert' },\n];\n\nfunction CourseCard({ course, onOpen }: { course: TecCourse; onOpen: () => void }) {\n return (\n <GlassCard\n className=\"group flex cursor-pointer flex-col overflow-hidden transition-all duration-200 hover:-translate-y-1 hover:shadow-lg\"\n onClick={onOpen}\n >\n <MediaCover\n seed={`${course.topic ?? ''} ${course.title}`}\n icon={topicIcon(course.topic ?? course.title)}\n >\n <StatusBadge status={course.level} kind=\"level\" />\n </MediaCover>\n <div className=\"flex flex-1 flex-col gap-3 p-4\">\n <div className=\"min-w-0\">\n <h3 className=\"truncate text-base font-semibold text-text-primary group-hover:text-accent-primary\">\n {course.title}\n </h3>\n {course.summary ? (\n <p className=\"mt-1 line-clamp-2 text-sm text-text-secondary\">{course.summary}</p>\n ) : null}\n </div>\n <div className=\"mt-auto flex flex-wrap items-center gap-3 text-xs text-text-muted\">\n {course.topic ? (\n <span className=\"inline-flex items-center gap-1\">\n <Layers size={13} /> {course.topic}\n </span>\n ) : null}\n <span className=\"inline-flex items-center gap-1\">\n <Clock size={13} /> {formatDuration(course.estimatedMinutes)}\n </span>\n </div>\n {course.tags.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {course.tags.slice(0, 3).map((t) => (\n <Badge key={t} variant=\"secondary\" className=\"text-[11px]\">\n {t}\n </Badge>\n ))}\n </div>\n ) : null}\n </div>\n </GlassCard>\n );\n}\n\nexport function CoursesCoursesPagePage() {\n const navigate = useTechnoSpamNavigate();\n const { workspaceId } = useTechnoSpam();\n const { emit } = useTechnoSpamAnalytics();\n const [level, setLevel] = useState<'ALL' | TecCourseLevel>('ALL');\n const [search, setSearch] = useState('');\n\n const { limit, more } = usePageLimit();\n const { data, loading, error } = useCoursesQuery({\n status: 'PUBLISHED',\n pagination: pageArg(limit),\n ...(level !== 'ALL' ? { level } : {}),\n });\n\n const courses = data?.tecListCourses.items ?? [];\n const hasMore = data?.tecListCourses.pageInfo.hasMore ?? false;\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n if (!q) return courses;\n return courses.filter(\n (c) =>\n c.title.toLowerCase().includes(q) ||\n (c.topic ?? '').toLowerCase().includes(q) ||\n c.tags.some((t) => t.toLowerCase().includes(q))\n );\n }, [courses, search]);\n\n return (\n <PageLayout\n hero\n title=\"Course Catalog\"\n description=\"Learn technology by doing — practical, project-based courses across the stack.\"\n actions={\n <Button variant=\"outline\" onClick={() => navigate('/courses/my-learning-page')}>\n <GraduationCap size={16} /> My Learning\n </Button>\n }\n >\n <div className=\"mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard label=\"Courses\" value={courses.length} icon={BookOpen} tone=\"blue\" />\n <StatCard\n label=\"Beginner-friendly\"\n value={courses.filter((c) => c.level === 'BEGINNER').length}\n icon={Sparkles}\n tone=\"green\"\n />\n <StatCard\n label=\"Advanced+\"\n value={courses.filter((c) => c.level === 'ADVANCED' || c.level === 'EXPERT').length}\n icon={GraduationCap}\n tone=\"purple\"\n />\n <StatCard\n label=\"Total content\"\n value={formatDuration(courses.reduce((s, c) => s + c.estimatedMinutes, 0))}\n icon={Clock}\n tone=\"teal\"\n />\n </div>\n\n <div className=\"mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <Tabs value={level} onValueChange={(v) => setLevel(v as 'ALL' | TecCourseLevel)}>\n <TabsList>\n {LEVELS.map((l) => (\n <TabsTrigger key={l.value} value={l.value}>\n {l.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n <div className=\"relative w-full sm:w-72\">\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-text-muted\"\n size={16}\n />\n <Input\n className=\"pl-9\"\n placeholder=\"Search courses…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n onBlur={() => {\n const value = search.trim();\n if (value) {\n emit('technospam.search.performed', {\n workspaceId,\n entityType: 'course',\n queryLength: value.length,\n });\n }\n }}\n />\n </div>\n </div>\n\n {loading && !courses.length ? (\n <LoadingGrid />\n ) : error ? (\n <ErrorView title=\"Couldn't load courses\" error={error} />\n ) : filtered.length === 0 ? (\n <EmptyView\n icon={<BookOpen size={26} />}\n title={search || level !== 'ALL' ? 'No matching courses' : 'No courses published yet'}\n description={\n search || level !== 'ALL'\n ? 'Try a different search or level filter.'\n : 'Published courses will appear here. Check back soon — TechnoSpam is pre-launch.'\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filtered.map((course) => (\n <CourseCard\n key={course.id}\n course={course}\n onOpen={() => {\n emit('technospam.course.viewed', {\n workspaceId,\n entityId: course.id,\n entityType: 'TEC_COURSE',\n });\n navigate(`/courses/course-details-page?id=${course.id}`);\n }}\n />\n ))}\n </div>\n )}\n <LoadMore hasMore={hasMore} loading={loading} onClick={more} />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PageLayout as
|
|
3
|
-
import { StatCard as
|
|
4
|
-
import { MediaCover as
|
|
5
|
-
import { formatDate as
|
|
6
|
-
import { StatusBadge as
|
|
7
|
-
import { LoadMore as
|
|
8
|
-
import { EmptyView as
|
|
1
|
+
import { useTechnoSpam as e, useTechnoSpamNavigate as t } from "../providers/TechnoSpamProvider.js";
|
|
2
|
+
import { PageLayout as n } from "../components/PageLayout.js";
|
|
3
|
+
import { StatCard as r } from "../components/StatCard.js";
|
|
4
|
+
import { MediaCover as i } from "../components/MediaCover.js";
|
|
5
|
+
import { formatDate as a, formatMoney as o } from "../utils/format.js";
|
|
6
|
+
import { StatusBadge as s } from "../components/StatusBadge.js";
|
|
7
|
+
import { LoadMore as c } from "../components/LoadMore.js";
|
|
8
|
+
import { EmptyView as l, ErrorView as u, LoadingGrid as d } from "../components/StateViews.js";
|
|
9
9
|
import "../components/index.js";
|
|
10
|
-
import { pageArg as
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
10
|
+
import { pageArg as f, useHackathonsQuery as p, usePageLimit as m } from "../api/technospamApi.js";
|
|
11
|
+
import { useTechnoSpamAnalytics as h } from "../hooks/useTechnoSpamAnalytics.js";
|
|
12
|
+
import { useMemo as g, useState as _ } from "react";
|
|
13
|
+
import { Award as v, CalendarDays as y, Search as b, Sparkles as x, Trophy as S, Users as C } from "lucide-react";
|
|
14
|
+
import { jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
15
|
+
import { Badge as E, GlassCard as D, Input as O, Tabs as k, TabsList as A, TabsTrigger as j } from "@burdenoff/fe-libs/ui";
|
|
15
16
|
//#region src/technospam/pages/HackathonsHackathonsPagePage.tsx
|
|
16
|
-
var
|
|
17
|
+
var M = [
|
|
17
18
|
{
|
|
18
19
|
value: "ALL",
|
|
19
20
|
label: "All"
|
|
@@ -35,61 +36,61 @@ var A = [
|
|
|
35
36
|
label: "Completed"
|
|
36
37
|
}
|
|
37
38
|
];
|
|
38
|
-
function
|
|
39
|
-
return /* @__PURE__ */
|
|
39
|
+
function N({ hackathon: e, onOpen: t }) {
|
|
40
|
+
return /* @__PURE__ */ T(D, {
|
|
40
41
|
className: "group flex cursor-pointer flex-col overflow-hidden transition-all duration-200 hover:-translate-y-1 hover:shadow-lg",
|
|
41
42
|
onClick: t,
|
|
42
|
-
children: [/* @__PURE__ */
|
|
43
|
+
children: [/* @__PURE__ */ w(i, {
|
|
43
44
|
height: "h-32",
|
|
44
45
|
seed: e.theme ?? e.id,
|
|
45
|
-
icon:
|
|
46
|
-
children: /* @__PURE__ */
|
|
47
|
-
}), /* @__PURE__ */
|
|
46
|
+
icon: S,
|
|
47
|
+
children: /* @__PURE__ */ w(s, { status: e.status })
|
|
48
|
+
}), /* @__PURE__ */ T("div", {
|
|
48
49
|
className: "flex flex-1 flex-col gap-3 p-4",
|
|
49
50
|
children: [
|
|
50
|
-
/* @__PURE__ */
|
|
51
|
+
/* @__PURE__ */ T("div", {
|
|
51
52
|
className: "min-w-0",
|
|
52
|
-
children: [/* @__PURE__ */
|
|
53
|
+
children: [/* @__PURE__ */ w("h3", {
|
|
53
54
|
className: "truncate text-base font-semibold text-text-primary group-hover:text-accent-primary",
|
|
54
55
|
children: e.title
|
|
55
|
-
}), e.theme ? /* @__PURE__ */
|
|
56
|
+
}), e.theme ? /* @__PURE__ */ w("p", {
|
|
56
57
|
className: "mt-1 line-clamp-2 text-sm text-text-secondary",
|
|
57
58
|
children: e.theme
|
|
58
59
|
}) : null]
|
|
59
60
|
}),
|
|
60
|
-
/* @__PURE__ */
|
|
61
|
+
/* @__PURE__ */ T("div", {
|
|
61
62
|
className: "mt-auto flex flex-wrap items-center gap-x-4 gap-y-1.5 text-xs text-text-muted",
|
|
62
|
-
children: [/* @__PURE__ */
|
|
63
|
+
children: [/* @__PURE__ */ T("span", {
|
|
63
64
|
className: "inline-flex items-center gap-1",
|
|
64
65
|
children: [
|
|
65
|
-
/* @__PURE__ */
|
|
66
|
+
/* @__PURE__ */ w(y, { size: 13 }),
|
|
66
67
|
" ",
|
|
67
|
-
|
|
68
|
+
a(e.startAt),
|
|
68
69
|
" –",
|
|
69
70
|
" ",
|
|
70
|
-
|
|
71
|
+
a(e.endAt)
|
|
71
72
|
]
|
|
72
|
-
}), /* @__PURE__ */
|
|
73
|
+
}), /* @__PURE__ */ T("span", {
|
|
73
74
|
className: "inline-flex items-center gap-1",
|
|
74
75
|
children: [
|
|
75
|
-
/* @__PURE__ */
|
|
76
|
+
/* @__PURE__ */ w(C, { size: 13 }),
|
|
76
77
|
" Team of ",
|
|
77
78
|
e.maxTeamSize
|
|
78
79
|
]
|
|
79
80
|
})]
|
|
80
81
|
}),
|
|
81
|
-
/* @__PURE__ */
|
|
82
|
+
/* @__PURE__ */ T("div", {
|
|
82
83
|
className: "flex items-center gap-1.5 text-sm font-medium text-accent-teal",
|
|
83
84
|
children: [
|
|
84
|
-
/* @__PURE__ */
|
|
85
|
+
/* @__PURE__ */ w(v, { size: 15 }),
|
|
85
86
|
" ",
|
|
86
|
-
|
|
87
|
+
o(e.prizePool, e.currency),
|
|
87
88
|
" prize pool"
|
|
88
89
|
]
|
|
89
90
|
}),
|
|
90
|
-
e.tags.length ? /* @__PURE__ */
|
|
91
|
+
e.tags.length ? /* @__PURE__ */ w("div", {
|
|
91
92
|
className: "flex flex-wrap gap-1.5",
|
|
92
|
-
children: e.tags.slice(0, 4).map((e) => /* @__PURE__ */
|
|
93
|
+
children: e.tags.slice(0, 4).map((e) => /* @__PURE__ */ w(E, {
|
|
93
94
|
variant: "secondary",
|
|
94
95
|
className: "text-[11px]",
|
|
95
96
|
children: e
|
|
@@ -99,87 +100,101 @@ function j({ hackathon: e, onOpen: t }) {
|
|
|
99
100
|
})]
|
|
100
101
|
});
|
|
101
102
|
}
|
|
102
|
-
function
|
|
103
|
-
let
|
|
104
|
-
pagination:
|
|
105
|
-
...
|
|
106
|
-
}),
|
|
107
|
-
let e =
|
|
108
|
-
return e ?
|
|
109
|
-
}, [
|
|
110
|
-
return /* @__PURE__ */
|
|
103
|
+
function P() {
|
|
104
|
+
let i = t(), { workspaceId: a } = e(), { emit: s } = h(), [y, C] = _("ALL"), [E, D] = _(""), { limit: P, more: F } = m(), { data: I, loading: L, error: R } = p({
|
|
105
|
+
pagination: f(P),
|
|
106
|
+
...y === "ALL" ? {} : { status: y }
|
|
107
|
+
}), z = I?.tecListHackathons.items ?? [], B = I?.tecListHackathons.pageInfo.hasMore ?? !1, V = g(() => {
|
|
108
|
+
let e = E.trim().toLowerCase();
|
|
109
|
+
return e ? z.filter((t) => t.title.toLowerCase().includes(e) || (t.theme ?? "").toLowerCase().includes(e) || t.tags.some((t) => t.toLowerCase().includes(e))) : z;
|
|
110
|
+
}, [z, E]), H = V.filter((e) => e.status === "REGISTRATION_OPEN").length, U = V.reduce((e, t) => e + t.prizePool, 0), W = V[0]?.currency ?? "USD";
|
|
111
|
+
return /* @__PURE__ */ T(n, {
|
|
111
112
|
hero: !0,
|
|
112
113
|
title: "Hackathons",
|
|
113
114
|
description: "Compete, collaborate, and ship real projects with a team in a fixed window.",
|
|
114
115
|
children: [
|
|
115
|
-
/* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ T("div", {
|
|
116
117
|
className: "mb-5 grid grid-cols-1 gap-3 sm:grid-cols-3",
|
|
117
118
|
children: [
|
|
118
|
-
/* @__PURE__ */
|
|
119
|
+
/* @__PURE__ */ w(r, {
|
|
119
120
|
label: "Hackathons",
|
|
120
|
-
value:
|
|
121
|
-
icon:
|
|
121
|
+
value: V.length,
|
|
122
|
+
icon: S,
|
|
122
123
|
tone: "purple"
|
|
123
124
|
}),
|
|
124
|
-
/* @__PURE__ */
|
|
125
|
+
/* @__PURE__ */ w(r, {
|
|
125
126
|
label: "Registration open",
|
|
126
|
-
value:
|
|
127
|
-
icon:
|
|
127
|
+
value: H,
|
|
128
|
+
icon: x,
|
|
128
129
|
tone: "green"
|
|
129
130
|
}),
|
|
130
|
-
/* @__PURE__ */
|
|
131
|
+
/* @__PURE__ */ w(r, {
|
|
131
132
|
label: "Total prize pool",
|
|
132
|
-
value:
|
|
133
|
-
icon:
|
|
133
|
+
value: o(U, W),
|
|
134
|
+
icon: v,
|
|
134
135
|
tone: "amber"
|
|
135
136
|
})
|
|
136
137
|
]
|
|
137
138
|
}),
|
|
138
|
-
/* @__PURE__ */
|
|
139
|
+
/* @__PURE__ */ T("div", {
|
|
139
140
|
className: "mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
|
|
140
|
-
children: [/* @__PURE__ */
|
|
141
|
-
value:
|
|
142
|
-
onValueChange: (e) =>
|
|
143
|
-
children: /* @__PURE__ */
|
|
141
|
+
children: [/* @__PURE__ */ w(k, {
|
|
142
|
+
value: y,
|
|
143
|
+
onValueChange: (e) => C(e),
|
|
144
|
+
children: /* @__PURE__ */ w(A, { children: M.map((e) => /* @__PURE__ */ w(j, {
|
|
144
145
|
value: e.value,
|
|
145
146
|
children: e.label
|
|
146
147
|
}, e.value)) })
|
|
147
|
-
}), /* @__PURE__ */
|
|
148
|
+
}), /* @__PURE__ */ T("div", {
|
|
148
149
|
className: "relative w-full sm:w-72",
|
|
149
|
-
children: [/* @__PURE__ */
|
|
150
|
+
children: [/* @__PURE__ */ w(b, {
|
|
150
151
|
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-text-muted",
|
|
151
152
|
size: 16
|
|
152
|
-
}), /* @__PURE__ */
|
|
153
|
+
}), /* @__PURE__ */ w(O, {
|
|
153
154
|
className: "pl-9",
|
|
154
155
|
placeholder: "Search hackathons…",
|
|
155
|
-
value:
|
|
156
|
-
onChange: (e) =>
|
|
156
|
+
value: E,
|
|
157
|
+
onChange: (e) => D(e.target.value),
|
|
158
|
+
onBlur: () => {
|
|
159
|
+
let e = E.trim();
|
|
160
|
+
e && s("technospam.search.performed", {
|
|
161
|
+
workspaceId: a,
|
|
162
|
+
entityType: "hackathon",
|
|
163
|
+
queryLength: e.length
|
|
164
|
+
});
|
|
165
|
+
}
|
|
157
166
|
})]
|
|
158
167
|
})]
|
|
159
168
|
}),
|
|
160
|
-
|
|
169
|
+
L && !V.length ? /* @__PURE__ */ w(d, {}) : R ? /* @__PURE__ */ w(u, {
|
|
161
170
|
title: "Couldn't load hackathons",
|
|
162
|
-
error:
|
|
163
|
-
}) :
|
|
164
|
-
icon: /* @__PURE__ */ S
|
|
165
|
-
title:
|
|
166
|
-
description:
|
|
167
|
-
}) : /* @__PURE__ */
|
|
171
|
+
error: R
|
|
172
|
+
}) : V.length === 0 ? /* @__PURE__ */ w(l, {
|
|
173
|
+
icon: /* @__PURE__ */ w(S, { size: 26 }),
|
|
174
|
+
title: y === "ALL" ? "No hackathons yet" : "No hackathons in this stage",
|
|
175
|
+
description: y === "ALL" ? "Upcoming hackathons will appear here. Check back soon — TechnoSpam is pre-launch." : "Try a different stage filter."
|
|
176
|
+
}) : /* @__PURE__ */ w("div", {
|
|
168
177
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
169
|
-
children:
|
|
178
|
+
children: V.map((e) => /* @__PURE__ */ w(N, {
|
|
170
179
|
hackathon: e,
|
|
171
|
-
onOpen: () =>
|
|
180
|
+
onOpen: () => {
|
|
181
|
+
s("technospam.hackathon.viewed", {
|
|
182
|
+
workspaceId: a,
|
|
183
|
+
entityId: e.id,
|
|
184
|
+
entityType: "TEC_HACKATHON"
|
|
185
|
+
}), i(`/hackathons/hackathon-details-page?id=${e.id}`);
|
|
186
|
+
}
|
|
172
187
|
}, e.id))
|
|
173
188
|
}),
|
|
174
|
-
/* @__PURE__ */
|
|
175
|
-
hasMore:
|
|
176
|
-
loading:
|
|
177
|
-
onClick:
|
|
189
|
+
/* @__PURE__ */ w(c, {
|
|
190
|
+
hasMore: B,
|
|
191
|
+
loading: L,
|
|
192
|
+
onClick: F
|
|
178
193
|
})
|
|
179
194
|
]
|
|
180
195
|
});
|
|
181
196
|
}
|
|
182
197
|
//#endregion
|
|
183
|
-
export {
|
|
198
|
+
export { P as HackathonsHackathonsPagePage };
|
|
184
199
|
|
|
185
200
|
//# sourceMappingURL=HackathonsHackathonsPagePage.js.map
|