@burdenoff/microfe-technospam 2026.704.2 → 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.
- package/dist/technospam/api/technospamApi.js +233 -150
- package/dist/technospam/api/technospamApi.js.map +1 -1
- package/dist/technospam/components/LoadMore.js +18 -2
- package/dist/technospam/components/LoadMore.js.map +1 -0
- package/dist/technospam/pages/AdminAdminDashboardPagePage.js +664 -334
- package/dist/technospam/pages/AdminAdminDashboardPagePage.js.map +1 -1
- package/dist/technospam/pages/ApplicationsProblemsPagePage.js +79 -72
- package/dist/technospam/pages/ApplicationsProblemsPagePage.js.map +1 -1
- package/dist/technospam/pages/CoursesCourseDetailsPagePage.js +140 -87
- package/dist/technospam/pages/CoursesCourseDetailsPagePage.js.map +1 -1
- package/dist/technospam/pages/CoursesCoursesPagePage.js +75 -68
- package/dist/technospam/pages/CoursesCoursesPagePage.js.map +1 -1
- package/dist/technospam/pages/CoursesMyLearningPagePage.js +3 -0
- package/dist/technospam/pages/CoursesMyLearningPagePage.js.map +1 -1
- package/dist/technospam/pages/HackathonsHackathonsPagePage.js +76 -53
- package/dist/technospam/pages/HackathonsHackathonsPagePage.js.map +1 -1
- package/dist/technospam/pages/MentorshipMentorProfilePagePage.js +36 -35
- package/dist/technospam/pages/MentorshipMentorProfilePagePage.js.map +1 -1
- package/dist/technospam/pages/MentorshipMentorsPagePage.js +112 -103
- package/dist/technospam/pages/MentorshipMentorsPagePage.js.map +1 -1
- package/dist/technospam/pages/MentorshipSessionsPagePage.js +219 -110
- package/dist/technospam/pages/MentorshipSessionsPagePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,55 +2,56 @@ import { useTechnoSpam as e, useTechnoSpamNavigate as t } from "../providers/Tec
|
|
|
2
2
|
import { PageLayout as n } from "../components/PageLayout.js";
|
|
3
3
|
import { StatCard as r } from "../components/StatCard.js";
|
|
4
4
|
import { formatMoney as i } from "../utils/format.js";
|
|
5
|
-
import {
|
|
5
|
+
import { LoadMore as a } from "../components/LoadMore.js";
|
|
6
|
+
import { EmptyView as o, ErrorView as s, LoadingGrid as c } from "../components/StateViews.js";
|
|
6
7
|
import "../components/index.js";
|
|
7
|
-
import { notify as
|
|
8
|
-
import { useBecomeMentor as
|
|
9
|
-
import { useMemo as
|
|
10
|
-
import { Award as
|
|
11
|
-
import { jsx as
|
|
12
|
-
import { Badge as
|
|
8
|
+
import { notify as l } from "../lib/toast.js";
|
|
9
|
+
import { pageArg as u, useBecomeMentor as d, useMentorsQuery as f, usePageLimit as p } from "../api/technospamApi.js";
|
|
10
|
+
import { useMemo as m, useState as h } from "react";
|
|
11
|
+
import { Award as g, MessageSquare as _, Search as v, Sparkles as y, Star as b, UserPlus as x, Users as S, X as C } from "lucide-react";
|
|
12
|
+
import { jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
13
|
+
import { Badge as E, Button as D, GlassCard as O, Input as k, Textarea as A } from "@burdenoff/fe-libs/ui";
|
|
13
14
|
//#region src/technospam/pages/MentorshipMentorsPagePage.tsx
|
|
14
|
-
function
|
|
15
|
-
return /* @__PURE__ */
|
|
15
|
+
function j({ mentor: e, onOpen: t }) {
|
|
16
|
+
return /* @__PURE__ */ T(O, {
|
|
16
17
|
className: "group flex cursor-pointer flex-col gap-3 p-5 transition-shadow hover:shadow-md",
|
|
17
18
|
onClick: t,
|
|
18
19
|
children: [
|
|
19
|
-
/* @__PURE__ */
|
|
20
|
+
/* @__PURE__ */ T("div", {
|
|
20
21
|
className: "flex items-start justify-between gap-3",
|
|
21
|
-
children: [/* @__PURE__ */
|
|
22
|
+
children: [/* @__PURE__ */ T("div", {
|
|
22
23
|
className: "min-w-0",
|
|
23
|
-
children: [/* @__PURE__ */
|
|
24
|
+
children: [/* @__PURE__ */ w("h3", {
|
|
24
25
|
className: "truncate text-base font-semibold text-text-primary group-hover:text-accent-primary",
|
|
25
26
|
children: e.headline
|
|
26
|
-
}), /* @__PURE__ */
|
|
27
|
+
}), /* @__PURE__ */ T("div", {
|
|
27
28
|
className: "mt-1 text-sm font-medium text-text-secondary",
|
|
28
|
-
children: [i(e.hourlyRate, e.currency), /* @__PURE__ */
|
|
29
|
+
children: [i(e.hourlyRate, e.currency), /* @__PURE__ */ w("span", {
|
|
29
30
|
className: "text-text-muted",
|
|
30
31
|
children: " / hr"
|
|
31
32
|
})]
|
|
32
33
|
})]
|
|
33
|
-
}), e.isAcceptingMentees ? /* @__PURE__ */
|
|
34
|
+
}), e.isAcceptingMentees ? /* @__PURE__ */ w(E, {
|
|
34
35
|
variant: "outline",
|
|
35
36
|
className: "shrink-0 border-status-success-border bg-status-success-bg-subtle text-status-success-text",
|
|
36
37
|
children: "Accepting mentees"
|
|
37
|
-
}) : /* @__PURE__ */
|
|
38
|
+
}) : /* @__PURE__ */ w(E, {
|
|
38
39
|
variant: "outline",
|
|
39
40
|
className: "shrink-0 border-border-seam bg-bg-sunken text-text-secondary",
|
|
40
41
|
children: "Not accepting"
|
|
41
42
|
})]
|
|
42
43
|
}),
|
|
43
|
-
e.bio ? /* @__PURE__ */
|
|
44
|
+
e.bio ? /* @__PURE__ */ w("p", {
|
|
44
45
|
className: "line-clamp-2 text-sm text-text-secondary",
|
|
45
46
|
children: e.bio
|
|
46
47
|
}) : null,
|
|
47
|
-
e.expertise.length ? /* @__PURE__ */
|
|
48
|
+
e.expertise.length ? /* @__PURE__ */ T("div", {
|
|
48
49
|
className: "flex flex-wrap gap-1.5",
|
|
49
|
-
children: [e.expertise.slice(0, 4).map((e) => /* @__PURE__ */
|
|
50
|
+
children: [e.expertise.slice(0, 4).map((e) => /* @__PURE__ */ w(E, {
|
|
50
51
|
variant: "secondary",
|
|
51
52
|
className: "text-[11px]",
|
|
52
53
|
children: e
|
|
53
|
-
}, e)), e.expertise.length > 4 ? /* @__PURE__ */
|
|
54
|
+
}, e)), e.expertise.length > 4 ? /* @__PURE__ */ T("span", {
|
|
54
55
|
className: "text-xs text-text-muted",
|
|
55
56
|
children: [
|
|
56
57
|
"+",
|
|
@@ -59,18 +60,18 @@ function O({ mentor: e, onOpen: t }) {
|
|
|
59
60
|
]
|
|
60
61
|
}) : null]
|
|
61
62
|
}) : null,
|
|
62
|
-
/* @__PURE__ */
|
|
63
|
+
/* @__PURE__ */ T("div", {
|
|
63
64
|
className: "mt-auto flex items-center gap-4 pt-1 text-xs text-text-muted",
|
|
64
|
-
children: [/* @__PURE__ */
|
|
65
|
+
children: [/* @__PURE__ */ T("span", {
|
|
65
66
|
className: "inline-flex items-center gap-1",
|
|
66
|
-
children: [/* @__PURE__ */
|
|
67
|
+
children: [/* @__PURE__ */ w(b, {
|
|
67
68
|
size: 13,
|
|
68
69
|
className: "text-accent-teal"
|
|
69
70
|
}), e.ratingAvg > 0 ? e.ratingAvg.toFixed(1) : "New"]
|
|
70
|
-
}), /* @__PURE__ */
|
|
71
|
+
}), /* @__PURE__ */ T("span", {
|
|
71
72
|
className: "inline-flex items-center gap-1",
|
|
72
73
|
children: [
|
|
73
|
-
/* @__PURE__ */
|
|
74
|
+
/* @__PURE__ */ w(_, { size: 13 }),
|
|
74
75
|
" ",
|
|
75
76
|
e.sessionsCount,
|
|
76
77
|
" sessions"
|
|
@@ -80,109 +81,109 @@ function O({ mentor: e, onOpen: t }) {
|
|
|
80
81
|
]
|
|
81
82
|
});
|
|
82
83
|
}
|
|
83
|
-
function
|
|
84
|
-
let [n, r] =
|
|
85
|
-
return /* @__PURE__ */
|
|
84
|
+
function M({ onClose: e, onDone: t }) {
|
|
85
|
+
let [n, r] = h(""), [i, a] = h(""), [o, s] = h(""), [c, u] = h(""), [f, p] = h("USD"), [m, { loading: g }] = d(), _ = n.trim().length > 0 && !g;
|
|
86
|
+
return /* @__PURE__ */ T(O, {
|
|
86
87
|
className: "mb-6 p-5",
|
|
87
|
-
children: [/* @__PURE__ */
|
|
88
|
+
children: [/* @__PURE__ */ T("div", {
|
|
88
89
|
className: "mb-4 flex items-center justify-between",
|
|
89
|
-
children: [/* @__PURE__ */
|
|
90
|
+
children: [/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("h2", {
|
|
90
91
|
className: "text-base font-semibold text-text-primary",
|
|
91
92
|
children: "Become a mentor"
|
|
92
|
-
}), /* @__PURE__ */
|
|
93
|
+
}), /* @__PURE__ */ w("p", {
|
|
93
94
|
className: "text-sm text-text-secondary",
|
|
94
95
|
children: "Share your expertise and start mentoring builders in the community."
|
|
95
|
-
})] }), /* @__PURE__ */
|
|
96
|
+
})] }), /* @__PURE__ */ w(D, {
|
|
96
97
|
variant: "ghost",
|
|
97
98
|
size: "sm",
|
|
98
99
|
onClick: e,
|
|
99
100
|
"aria-label": "Close",
|
|
100
|
-
children: /* @__PURE__ */
|
|
101
|
+
children: /* @__PURE__ */ w(C, { size: 16 })
|
|
101
102
|
})]
|
|
102
|
-
}), /* @__PURE__ */
|
|
103
|
+
}), /* @__PURE__ */ T("div", {
|
|
103
104
|
className: "grid grid-cols-1 gap-4",
|
|
104
105
|
children: [
|
|
105
|
-
/* @__PURE__ */
|
|
106
|
+
/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ T("label", {
|
|
106
107
|
className: "mb-1.5 block text-sm font-medium text-text-primary",
|
|
107
|
-
children: ["Headline ", /* @__PURE__ */
|
|
108
|
+
children: ["Headline ", /* @__PURE__ */ w("span", {
|
|
108
109
|
className: "text-status-error-text",
|
|
109
110
|
children: "*"
|
|
110
111
|
})]
|
|
111
|
-
}), /* @__PURE__ */
|
|
112
|
+
}), /* @__PURE__ */ w(k, {
|
|
112
113
|
placeholder: "e.g. Staff Engineer · Distributed systems & career growth",
|
|
113
114
|
value: n,
|
|
114
115
|
onChange: (e) => r(e.target.value)
|
|
115
116
|
})] }),
|
|
116
|
-
/* @__PURE__ */
|
|
117
|
+
/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
|
|
117
118
|
className: "mb-1.5 block text-sm font-medium text-text-primary",
|
|
118
119
|
children: "Bio"
|
|
119
|
-
}), /* @__PURE__ */
|
|
120
|
+
}), /* @__PURE__ */ w(A, {
|
|
120
121
|
rows: 3,
|
|
121
122
|
placeholder: "Tell mentees about your experience and how you can help.",
|
|
122
123
|
value: i,
|
|
123
124
|
onChange: (e) => a(e.target.value)
|
|
124
125
|
})] }),
|
|
125
|
-
/* @__PURE__ */
|
|
126
|
-
/* @__PURE__ */
|
|
126
|
+
/* @__PURE__ */ T("div", { children: [
|
|
127
|
+
/* @__PURE__ */ w("label", {
|
|
127
128
|
className: "mb-1.5 block text-sm font-medium text-text-primary",
|
|
128
129
|
children: "Expertise"
|
|
129
130
|
}),
|
|
130
|
-
/* @__PURE__ */
|
|
131
|
+
/* @__PURE__ */ w(k, {
|
|
131
132
|
placeholder: "React, System design, Career coaching",
|
|
132
133
|
value: o,
|
|
133
134
|
onChange: (e) => s(e.target.value)
|
|
134
135
|
}),
|
|
135
|
-
/* @__PURE__ */
|
|
136
|
+
/* @__PURE__ */ w("p", {
|
|
136
137
|
className: "mt-1 text-xs text-text-muted",
|
|
137
138
|
children: "Comma-separated topics."
|
|
138
139
|
})
|
|
139
140
|
] }),
|
|
140
|
-
/* @__PURE__ */
|
|
141
|
+
/* @__PURE__ */ T("div", {
|
|
141
142
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
142
|
-
children: [/* @__PURE__ */
|
|
143
|
-
/* @__PURE__ */
|
|
143
|
+
children: [/* @__PURE__ */ T("div", { children: [
|
|
144
|
+
/* @__PURE__ */ w("label", {
|
|
144
145
|
className: "mb-1.5 block text-sm font-medium text-text-primary",
|
|
145
146
|
children: "Hourly rate"
|
|
146
147
|
}),
|
|
147
|
-
/* @__PURE__ */
|
|
148
|
+
/* @__PURE__ */ w(k, {
|
|
148
149
|
type: "number",
|
|
149
150
|
min: 0,
|
|
150
151
|
placeholder: "0",
|
|
151
|
-
value:
|
|
152
|
-
onChange: (e) =>
|
|
152
|
+
value: c,
|
|
153
|
+
onChange: (e) => u(e.target.value)
|
|
153
154
|
}),
|
|
154
|
-
/* @__PURE__ */
|
|
155
|
+
/* @__PURE__ */ w("p", {
|
|
155
156
|
className: "mt-1 text-xs text-text-muted",
|
|
156
157
|
children: "Whole number. Leave 0 for free."
|
|
157
158
|
})
|
|
158
|
-
] }), /* @__PURE__ */
|
|
159
|
+
] }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
|
|
159
160
|
className: "mb-1.5 block text-sm font-medium text-text-primary",
|
|
160
161
|
children: "Currency"
|
|
161
|
-
}), /* @__PURE__ */
|
|
162
|
+
}), /* @__PURE__ */ w(k, {
|
|
162
163
|
placeholder: "USD",
|
|
163
|
-
value:
|
|
164
|
-
onChange: (e) =>
|
|
164
|
+
value: f,
|
|
165
|
+
onChange: (e) => p(e.target.value)
|
|
165
166
|
})] })]
|
|
166
167
|
}),
|
|
167
|
-
/* @__PURE__ */
|
|
168
|
+
/* @__PURE__ */ T("div", {
|
|
168
169
|
className: "flex flex-wrap items-center gap-2",
|
|
169
|
-
children: [/* @__PURE__ */
|
|
170
|
+
children: [/* @__PURE__ */ T(D, {
|
|
170
171
|
onClick: async () => {
|
|
171
172
|
if (!_) return;
|
|
172
173
|
let e = { headline: n.trim() };
|
|
173
174
|
i.trim() && (e.bio = i.trim());
|
|
174
175
|
let r = o.split(",").map((e) => e.trim()).filter(Boolean);
|
|
175
176
|
r.length && (e.expertise = r);
|
|
176
|
-
let a = Number.parseInt(
|
|
177
|
-
!Number.isNaN(a) && a >= 0 && (e.hourlyRate = a),
|
|
177
|
+
let a = Number.parseInt(c, 10);
|
|
178
|
+
!Number.isNaN(a) && a >= 0 && (e.hourlyRate = a), f.trim() && (e.currency = f.trim().toUpperCase()), (await m({ variables: { input: e } })).data?.tecBecomeMentor && (l.success("Mentor profile created", "Your profile is pending review."), t());
|
|
178
179
|
},
|
|
179
180
|
disabled: !_,
|
|
180
181
|
children: [
|
|
181
|
-
/* @__PURE__ */ x
|
|
182
|
+
/* @__PURE__ */ w(x, { size: 16 }),
|
|
182
183
|
" ",
|
|
183
184
|
g ? "Submitting…" : "Submit profile"
|
|
184
185
|
]
|
|
185
|
-
}), /* @__PURE__ */
|
|
186
|
+
}), /* @__PURE__ */ w(D, {
|
|
186
187
|
variant: "outline",
|
|
187
188
|
onClick: e,
|
|
188
189
|
disabled: g,
|
|
@@ -193,91 +194,99 @@ function k({ onClose: e, onDone: t }) {
|
|
|
193
194
|
})]
|
|
194
195
|
});
|
|
195
196
|
}
|
|
196
|
-
function
|
|
197
|
-
let i = t(), { currentUser:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}, [
|
|
201
|
-
|
|
197
|
+
function N() {
|
|
198
|
+
let i = t(), { currentUser: l } = e(), [d, b] = h(""), [C, E] = h(!1), { limit: A, more: N } = p(), { data: P, loading: F, error: I, refetch: L } = f({
|
|
199
|
+
status: "ACTIVE",
|
|
200
|
+
pagination: u(A)
|
|
201
|
+
}), R = P?.tecListMentors.items ?? [], z = P?.tecListMentors.pageInfo.hasMore ?? !1, B = l?.id, V = !!(B && R.some((e) => e.userId === B)), H = m(() => {
|
|
202
|
+
let e = d.trim().toLowerCase();
|
|
203
|
+
return e ? R.filter((t) => t.headline.toLowerCase().includes(e) || t.expertise.some((t) => t.toLowerCase().includes(e))) : R;
|
|
204
|
+
}, [R, d]), U = R.filter((e) => e.isAcceptingMentees).length;
|
|
205
|
+
return /* @__PURE__ */ T(n, {
|
|
202
206
|
hero: !0,
|
|
203
207
|
title: "Find a Mentor",
|
|
204
208
|
description: "Connect with experienced builders for 1:1 guidance, code review, and career coaching.",
|
|
205
|
-
actions: /* @__PURE__ */
|
|
209
|
+
actions: /* @__PURE__ */ T(D, {
|
|
206
210
|
variant: "outline",
|
|
207
211
|
onClick: () => i("/mentorship/sessions-page"),
|
|
208
|
-
children: [/* @__PURE__ */
|
|
212
|
+
children: [/* @__PURE__ */ w(_, { size: 16 }), " My sessions"]
|
|
209
213
|
}),
|
|
210
214
|
children: [
|
|
211
|
-
|
|
215
|
+
V ? /* @__PURE__ */ T(O, {
|
|
212
216
|
className: "mb-6 flex items-center gap-3 p-4",
|
|
213
|
-
children: [/* @__PURE__ */
|
|
217
|
+
children: [/* @__PURE__ */ w("span", {
|
|
214
218
|
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-status-success-bg-subtle text-status-success-text",
|
|
215
|
-
children: /* @__PURE__ */
|
|
216
|
-
}), /* @__PURE__ */
|
|
219
|
+
children: /* @__PURE__ */ w(g, { size: 20 })
|
|
220
|
+
}), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("div", {
|
|
217
221
|
className: "text-sm font-semibold text-text-primary",
|
|
218
222
|
children: "You're a mentor"
|
|
219
|
-
}), /* @__PURE__ */
|
|
223
|
+
}), /* @__PURE__ */ w("div", {
|
|
220
224
|
className: "text-xs text-text-secondary",
|
|
221
225
|
children: "Your mentor profile is live. Mentees can request sessions with you."
|
|
222
226
|
})] })]
|
|
223
|
-
}) :
|
|
224
|
-
onClose: () =>
|
|
227
|
+
}) : C ? /* @__PURE__ */ w(M, {
|
|
228
|
+
onClose: () => E(!1),
|
|
225
229
|
onDone: () => {
|
|
226
|
-
|
|
230
|
+
E(!1), L();
|
|
227
231
|
}
|
|
228
232
|
}) : null,
|
|
229
|
-
/* @__PURE__ */
|
|
233
|
+
/* @__PURE__ */ T("div", {
|
|
230
234
|
className: "mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4",
|
|
231
|
-
children: [/* @__PURE__ */
|
|
235
|
+
children: [/* @__PURE__ */ w(r, {
|
|
232
236
|
label: "Mentors",
|
|
233
|
-
value:
|
|
234
|
-
icon:
|
|
235
|
-
}), /* @__PURE__ */
|
|
237
|
+
value: R.length,
|
|
238
|
+
icon: S
|
|
239
|
+
}), /* @__PURE__ */ w(r, {
|
|
236
240
|
label: "Accepting mentees",
|
|
237
|
-
value:
|
|
238
|
-
icon:
|
|
241
|
+
value: U,
|
|
242
|
+
icon: y
|
|
239
243
|
})]
|
|
240
244
|
}),
|
|
241
|
-
/* @__PURE__ */
|
|
245
|
+
/* @__PURE__ */ T("div", {
|
|
242
246
|
className: "mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
|
|
243
|
-
children: [/* @__PURE__ */
|
|
247
|
+
children: [/* @__PURE__ */ T("div", {
|
|
244
248
|
className: "relative w-full sm:w-80",
|
|
245
|
-
children: [/* @__PURE__ */
|
|
249
|
+
children: [/* @__PURE__ */ w(v, {
|
|
246
250
|
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-text-muted",
|
|
247
251
|
size: 16
|
|
248
|
-
}), /* @__PURE__ */
|
|
252
|
+
}), /* @__PURE__ */ w(k, {
|
|
249
253
|
className: "pl-9",
|
|
250
254
|
placeholder: "Search by headline or expertise…",
|
|
251
|
-
value:
|
|
252
|
-
onChange: (e) =>
|
|
255
|
+
value: d,
|
|
256
|
+
onChange: (e) => b(e.target.value)
|
|
253
257
|
})]
|
|
254
|
-
}), !
|
|
255
|
-
onClick: () =>
|
|
256
|
-
children: [/* @__PURE__ */ x
|
|
258
|
+
}), !V && !C ? /* @__PURE__ */ T(D, {
|
|
259
|
+
onClick: () => E(!0),
|
|
260
|
+
children: [/* @__PURE__ */ w(x, { size: 16 }), " Become a mentor"]
|
|
257
261
|
}) : null]
|
|
258
262
|
}),
|
|
259
|
-
|
|
263
|
+
F && !R.length ? /* @__PURE__ */ w(c, {}) : I ? /* @__PURE__ */ w(s, {
|
|
260
264
|
title: "Couldn't load mentors",
|
|
261
|
-
error:
|
|
262
|
-
}) :
|
|
263
|
-
icon: /* @__PURE__ */
|
|
264
|
-
title:
|
|
265
|
-
description:
|
|
266
|
-
action: !
|
|
267
|
-
onClick: () =>
|
|
265
|
+
error: I
|
|
266
|
+
}) : H.length === 0 ? /* @__PURE__ */ w(o, {
|
|
267
|
+
icon: /* @__PURE__ */ w(S, { size: 26 }),
|
|
268
|
+
title: d ? "No matching mentors" : "No mentors yet",
|
|
269
|
+
description: d ? "Try a different search term." : "Active mentors will appear here. TechnoSpam is pre-launch — be one of the first to sign up.",
|
|
270
|
+
action: !d && !V ? /* @__PURE__ */ w(D, {
|
|
271
|
+
onClick: () => E(!0),
|
|
268
272
|
children: "Become a mentor"
|
|
269
273
|
}) : void 0
|
|
270
|
-
}) : /* @__PURE__ */
|
|
274
|
+
}) : /* @__PURE__ */ w("div", {
|
|
271
275
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
272
|
-
children:
|
|
276
|
+
children: H.map((e) => /* @__PURE__ */ w(j, {
|
|
273
277
|
mentor: e,
|
|
274
278
|
onOpen: () => i(`/mentorship/mentor-profile-page?id=${e.id}`)
|
|
275
279
|
}, e.id))
|
|
280
|
+
}),
|
|
281
|
+
/* @__PURE__ */ w(a, {
|
|
282
|
+
hasMore: z,
|
|
283
|
+
loading: F,
|
|
284
|
+
onClick: N
|
|
276
285
|
})
|
|
277
286
|
]
|
|
278
287
|
});
|
|
279
288
|
}
|
|
280
289
|
//#endregion
|
|
281
|
-
export {
|
|
290
|
+
export { N as MentorshipMentorsPagePage };
|
|
282
291
|
|
|
283
292
|
//# sourceMappingURL=MentorshipMentorsPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MentorshipMentorsPagePage.js","names":[],"sources":["../../../src/technospam/pages/MentorshipMentorsPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { Award, MessageSquare, Search, Sparkles, Star, UserPlus, Users, X } from 'lucide-react';\nimport { Badge, Button, GlassCard, Input, Textarea } from '@burdenoff/fe-libs/ui';\nimport { EmptyView, ErrorView, LoadingGrid, PageLayout, StatCard } from '../components';\nimport { useTechnoSpam, useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport { useBecomeMentor, useMentorsQuery, type TecMentor } from '../api/technospamApi';\nimport { formatMoney } from '../utils/format';\nimport { notify } from '../lib/toast';\n\nfunction MentorCard({ mentor, onOpen }: { mentor: TecMentor; onOpen: () => void }) {\n return (\n <GlassCard\n className=\"group flex cursor-pointer flex-col gap-3 p-5 transition-shadow hover:shadow-md\"\n onClick={onOpen}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <h3 className=\"truncate text-base font-semibold text-text-primary group-hover:text-accent-primary\">\n {mentor.headline}\n </h3>\n <div className=\"mt-1 text-sm font-medium text-text-secondary\">\n {formatMoney(mentor.hourlyRate, mentor.currency)}\n <span className=\"text-text-muted\"> / hr</span>\n </div>\n </div>\n {mentor.isAcceptingMentees ? (\n <Badge\n variant=\"outline\"\n className=\"shrink-0 border-status-success-border bg-status-success-bg-subtle text-status-success-text\"\n >\n Accepting mentees\n </Badge>\n ) : (\n <Badge\n variant=\"outline\"\n className=\"shrink-0 border-border-seam bg-bg-sunken text-text-secondary\"\n >\n Not accepting\n </Badge>\n )}\n </div>\n\n {mentor.bio ? <p className=\"line-clamp-2 text-sm text-text-secondary\">{mentor.bio}</p> : null}\n\n {mentor.expertise.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {mentor.expertise.slice(0, 4).map((skill) => (\n <Badge key={skill} variant=\"secondary\" className=\"text-[11px]\">\n {skill}\n </Badge>\n ))}\n {mentor.expertise.length > 4 ? (\n <span className=\"text-xs text-text-muted\">+{mentor.expertise.length - 4} more</span>\n ) : null}\n </div>\n ) : null}\n\n <div className=\"mt-auto flex items-center gap-4 pt-1 text-xs text-text-muted\">\n <span className=\"inline-flex items-center gap-1\">\n <Star size={13} className=\"text-accent-teal\" />\n {mentor.ratingAvg > 0 ? mentor.ratingAvg.toFixed(1) : 'New'}\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <MessageSquare size={13} /> {mentor.sessionsCount} sessions\n </span>\n </div>\n </GlassCard>\n );\n}\n\nfunction BecomeMentorForm({ onClose, onDone }: { onClose: () => void; onDone: () => void }) {\n const [headline, setHeadline] = useState('');\n const [bio, setBio] = useState('');\n const [expertise, setExpertise] = useState('');\n const [hourlyRate, setHourlyRate] = useState('');\n const [currency, setCurrency] = useState('USD');\n const [becomeMentor, { loading }] = useBecomeMentor();\n\n const canSubmit = headline.trim().length > 0 && !loading;\n\n const handleSubmit = async () => {\n if (!canSubmit) return;\n const input: {\n headline: string;\n bio?: string;\n expertise?: string[];\n hourlyRate?: number;\n currency?: string;\n } = { headline: headline.trim() };\n if (bio.trim()) input.bio = bio.trim();\n const exp = expertise\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n if (exp.length) input.expertise = exp;\n const rate = Number.parseInt(hourlyRate, 10);\n if (!Number.isNaN(rate) && rate >= 0) input.hourlyRate = rate;\n if (currency.trim()) input.currency = currency.trim().toUpperCase();\n\n const res = await becomeMentor({ variables: { input } });\n if (res.data?.tecBecomeMentor) {\n notify.success('Mentor profile created', 'Your profile is pending review.');\n onDone();\n }\n };\n\n return (\n <GlassCard className=\"mb-6 p-5\">\n <div className=\"mb-4 flex items-center justify-between\">\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">Become a mentor</h2>\n <p className=\"text-sm text-text-secondary\">\n Share your expertise and start mentoring builders in the community.\n </p>\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={onClose} aria-label=\"Close\">\n <X size={16} />\n </Button>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Headline <span className=\"text-status-error-text\">*</span>\n </label>\n <Input\n placeholder=\"e.g. Staff Engineer · Distributed systems & career growth\"\n value={headline}\n onChange={(e) => setHeadline(e.target.value)}\n />\n </div>\n\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Bio</label>\n <Textarea\n rows={3}\n placeholder=\"Tell mentees about your experience and how you can help.\"\n value={bio}\n onChange={(e) => setBio(e.target.value)}\n />\n </div>\n\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Expertise</label>\n <Input\n placeholder=\"React, System design, Career coaching\"\n value={expertise}\n onChange={(e) => setExpertise(e.target.value)}\n />\n <p className=\"mt-1 text-xs text-text-muted\">Comma-separated topics.</p>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Hourly rate\n </label>\n <Input\n type=\"number\"\n min={0}\n placeholder=\"0\"\n value={hourlyRate}\n onChange={(e) => setHourlyRate(e.target.value)}\n />\n <p className=\"mt-1 text-xs text-text-muted\">Whole number. Leave 0 for free.</p>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Currency</label>\n <Input\n placeholder=\"USD\"\n value={currency}\n onChange={(e) => setCurrency(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button onClick={handleSubmit} disabled={!canSubmit}>\n <UserPlus size={16} /> {loading ? 'Submitting…' : 'Submit profile'}\n </Button>\n <Button variant=\"outline\" onClick={onClose} disabled={loading}>\n Cancel\n </Button>\n </div>\n </div>\n </GlassCard>\n );\n}\n\nexport function MentorshipMentorsPagePage() {\n const navigate = useTechnoSpamNavigate();\n const { currentUser } = useTechnoSpam();\n const [search, setSearch] = useState('');\n const [showForm, setShowForm] = useState(false);\n\n const { data, loading, error, refetch } = useMentorsQuery({ status: 'ACTIVE' });\n\n const mentors = data?.tecListMentors.items ?? [];\n const userId = currentUser?.id;\n const alreadyMentor = Boolean(userId && mentors.some((m) => m.userId === userId));\n\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n if (!q) return mentors;\n return mentors.filter(\n (m) =>\n m.headline.toLowerCase().includes(q) ||\n m.expertise.some((skill) => skill.toLowerCase().includes(q))\n );\n }, [mentors, search]);\n\n const accepting = mentors.filter((m) => m.isAcceptingMentees).length;\n\n return (\n <PageLayout\n hero\n title=\"Find a Mentor\"\n description=\"Connect with experienced builders for 1:1 guidance, code review, and career coaching.\"\n actions={\n <Button variant=\"outline\" onClick={() => navigate('/mentorship/sessions-page')}>\n <MessageSquare size={16} /> My sessions\n </Button>\n }\n >\n {alreadyMentor ? (\n <GlassCard className=\"mb-6 flex items-center gap-3 p-4\">\n <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-status-success-bg-subtle text-status-success-text\">\n <Award size={20} />\n </span>\n <div>\n <div className=\"text-sm font-semibold text-text-primary\">You're a mentor</div>\n <div className=\"text-xs text-text-secondary\">\n Your mentor profile is live. Mentees can request sessions with you.\n </div>\n </div>\n </GlassCard>\n ) : showForm ? (\n <BecomeMentorForm\n onClose={() => setShowForm(false)}\n onDone={() => {\n setShowForm(false);\n void refetch();\n }}\n />\n ) : null}\n\n <div className=\"mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard label=\"Mentors\" value={mentors.length} icon={Users} />\n <StatCard label=\"Accepting mentees\" value={accepting} icon={Sparkles} />\n </div>\n\n <div className=\"mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"relative w-full sm:w-80\">\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 by headline or expertise…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n {!alreadyMentor && !showForm ? (\n <Button onClick={() => setShowForm(true)}>\n <UserPlus size={16} /> Become a mentor\n </Button>\n ) : null}\n </div>\n\n {loading && !mentors.length ? (\n <LoadingGrid />\n ) : error ? (\n <ErrorView title=\"Couldn't load mentors\" error={error} />\n ) : filtered.length === 0 ? (\n <EmptyView\n icon={<Users size={26} />}\n title={search ? 'No matching mentors' : 'No mentors yet'}\n description={\n search\n ? 'Try a different search term.'\n : 'Active mentors will appear here. TechnoSpam is pre-launch — be one of the first to sign up.'\n }\n action={\n !search && !alreadyMentor ? (\n <Button onClick={() => setShowForm(true)}>Become a mentor</Button>\n ) : undefined\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filtered.map((mentor) => (\n <MentorCard\n key={mentor.id}\n mentor={mentor}\n onOpen={() => navigate(`/mentorship/mentor-profile-page?id=${mentor.id}`)}\n />\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MentorshipMentorsPagePage.js","names":[],"sources":["../../../src/technospam/pages/MentorshipMentorsPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { Award, MessageSquare, Search, Sparkles, Star, UserPlus, Users, X } from 'lucide-react';\nimport { Badge, Button, GlassCard, Input, Textarea } from '@burdenoff/fe-libs/ui';\nimport { EmptyView, ErrorView, LoadMore, LoadingGrid, PageLayout, StatCard } from '../components';\nimport { useTechnoSpam, useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport {\n pageArg,\n useBecomeMentor,\n useMentorsQuery,\n usePageLimit,\n type TecMentor,\n} from '../api/technospamApi';\nimport { formatMoney } from '../utils/format';\nimport { notify } from '../lib/toast';\n\nfunction MentorCard({ mentor, onOpen }: { mentor: TecMentor; onOpen: () => void }) {\n return (\n <GlassCard\n className=\"group flex cursor-pointer flex-col gap-3 p-5 transition-shadow hover:shadow-md\"\n onClick={onOpen}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <h3 className=\"truncate text-base font-semibold text-text-primary group-hover:text-accent-primary\">\n {mentor.headline}\n </h3>\n <div className=\"mt-1 text-sm font-medium text-text-secondary\">\n {formatMoney(mentor.hourlyRate, mentor.currency)}\n <span className=\"text-text-muted\"> / hr</span>\n </div>\n </div>\n {mentor.isAcceptingMentees ? (\n <Badge\n variant=\"outline\"\n className=\"shrink-0 border-status-success-border bg-status-success-bg-subtle text-status-success-text\"\n >\n Accepting mentees\n </Badge>\n ) : (\n <Badge\n variant=\"outline\"\n className=\"shrink-0 border-border-seam bg-bg-sunken text-text-secondary\"\n >\n Not accepting\n </Badge>\n )}\n </div>\n\n {mentor.bio ? <p className=\"line-clamp-2 text-sm text-text-secondary\">{mentor.bio}</p> : null}\n\n {mentor.expertise.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {mentor.expertise.slice(0, 4).map((skill) => (\n <Badge key={skill} variant=\"secondary\" className=\"text-[11px]\">\n {skill}\n </Badge>\n ))}\n {mentor.expertise.length > 4 ? (\n <span className=\"text-xs text-text-muted\">+{mentor.expertise.length - 4} more</span>\n ) : null}\n </div>\n ) : null}\n\n <div className=\"mt-auto flex items-center gap-4 pt-1 text-xs text-text-muted\">\n <span className=\"inline-flex items-center gap-1\">\n <Star size={13} className=\"text-accent-teal\" />\n {mentor.ratingAvg > 0 ? mentor.ratingAvg.toFixed(1) : 'New'}\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <MessageSquare size={13} /> {mentor.sessionsCount} sessions\n </span>\n </div>\n </GlassCard>\n );\n}\n\nfunction BecomeMentorForm({ onClose, onDone }: { onClose: () => void; onDone: () => void }) {\n const [headline, setHeadline] = useState('');\n const [bio, setBio] = useState('');\n const [expertise, setExpertise] = useState('');\n const [hourlyRate, setHourlyRate] = useState('');\n const [currency, setCurrency] = useState('USD');\n const [becomeMentor, { loading }] = useBecomeMentor();\n\n const canSubmit = headline.trim().length > 0 && !loading;\n\n const handleSubmit = async () => {\n if (!canSubmit) return;\n const input: {\n headline: string;\n bio?: string;\n expertise?: string[];\n hourlyRate?: number;\n currency?: string;\n } = { headline: headline.trim() };\n if (bio.trim()) input.bio = bio.trim();\n const exp = expertise\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n if (exp.length) input.expertise = exp;\n const rate = Number.parseInt(hourlyRate, 10);\n if (!Number.isNaN(rate) && rate >= 0) input.hourlyRate = rate;\n if (currency.trim()) input.currency = currency.trim().toUpperCase();\n\n const res = await becomeMentor({ variables: { input } });\n if (res.data?.tecBecomeMentor) {\n notify.success('Mentor profile created', 'Your profile is pending review.');\n onDone();\n }\n };\n\n return (\n <GlassCard className=\"mb-6 p-5\">\n <div className=\"mb-4 flex items-center justify-between\">\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">Become a mentor</h2>\n <p className=\"text-sm text-text-secondary\">\n Share your expertise and start mentoring builders in the community.\n </p>\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={onClose} aria-label=\"Close\">\n <X size={16} />\n </Button>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Headline <span className=\"text-status-error-text\">*</span>\n </label>\n <Input\n placeholder=\"e.g. Staff Engineer · Distributed systems & career growth\"\n value={headline}\n onChange={(e) => setHeadline(e.target.value)}\n />\n </div>\n\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Bio</label>\n <Textarea\n rows={3}\n placeholder=\"Tell mentees about your experience and how you can help.\"\n value={bio}\n onChange={(e) => setBio(e.target.value)}\n />\n </div>\n\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Expertise</label>\n <Input\n placeholder=\"React, System design, Career coaching\"\n value={expertise}\n onChange={(e) => setExpertise(e.target.value)}\n />\n <p className=\"mt-1 text-xs text-text-muted\">Comma-separated topics.</p>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Hourly rate\n </label>\n <Input\n type=\"number\"\n min={0}\n placeholder=\"0\"\n value={hourlyRate}\n onChange={(e) => setHourlyRate(e.target.value)}\n />\n <p className=\"mt-1 text-xs text-text-muted\">Whole number. Leave 0 for free.</p>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Currency</label>\n <Input\n placeholder=\"USD\"\n value={currency}\n onChange={(e) => setCurrency(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button onClick={handleSubmit} disabled={!canSubmit}>\n <UserPlus size={16} /> {loading ? 'Submitting…' : 'Submit profile'}\n </Button>\n <Button variant=\"outline\" onClick={onClose} disabled={loading}>\n Cancel\n </Button>\n </div>\n </div>\n </GlassCard>\n );\n}\n\nexport function MentorshipMentorsPagePage() {\n const navigate = useTechnoSpamNavigate();\n const { currentUser } = useTechnoSpam();\n const [search, setSearch] = useState('');\n const [showForm, setShowForm] = useState(false);\n\n const { limit, more } = usePageLimit();\n const { data, loading, error, refetch } = useMentorsQuery({\n status: 'ACTIVE',\n pagination: pageArg(limit),\n });\n\n const mentors = data?.tecListMentors.items ?? [];\n const hasMore = data?.tecListMentors.pageInfo.hasMore ?? false;\n const userId = currentUser?.id;\n const alreadyMentor = Boolean(userId && mentors.some((m) => m.userId === userId));\n\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n if (!q) return mentors;\n return mentors.filter(\n (m) =>\n m.headline.toLowerCase().includes(q) ||\n m.expertise.some((skill) => skill.toLowerCase().includes(q))\n );\n }, [mentors, search]);\n\n const accepting = mentors.filter((m) => m.isAcceptingMentees).length;\n\n return (\n <PageLayout\n hero\n title=\"Find a Mentor\"\n description=\"Connect with experienced builders for 1:1 guidance, code review, and career coaching.\"\n actions={\n <Button variant=\"outline\" onClick={() => navigate('/mentorship/sessions-page')}>\n <MessageSquare size={16} /> My sessions\n </Button>\n }\n >\n {alreadyMentor ? (\n <GlassCard className=\"mb-6 flex items-center gap-3 p-4\">\n <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-status-success-bg-subtle text-status-success-text\">\n <Award size={20} />\n </span>\n <div>\n <div className=\"text-sm font-semibold text-text-primary\">You're a mentor</div>\n <div className=\"text-xs text-text-secondary\">\n Your mentor profile is live. Mentees can request sessions with you.\n </div>\n </div>\n </GlassCard>\n ) : showForm ? (\n <BecomeMentorForm\n onClose={() => setShowForm(false)}\n onDone={() => {\n setShowForm(false);\n void refetch();\n }}\n />\n ) : null}\n\n <div className=\"mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard label=\"Mentors\" value={mentors.length} icon={Users} />\n <StatCard label=\"Accepting mentees\" value={accepting} icon={Sparkles} />\n </div>\n\n <div className=\"mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"relative w-full sm:w-80\">\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 by headline or expertise…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n {!alreadyMentor && !showForm ? (\n <Button onClick={() => setShowForm(true)}>\n <UserPlus size={16} /> Become a mentor\n </Button>\n ) : null}\n </div>\n\n {loading && !mentors.length ? (\n <LoadingGrid />\n ) : error ? (\n <ErrorView title=\"Couldn't load mentors\" error={error} />\n ) : filtered.length === 0 ? (\n <EmptyView\n icon={<Users size={26} />}\n title={search ? 'No matching mentors' : 'No mentors yet'}\n description={\n search\n ? 'Try a different search term.'\n : 'Active mentors will appear here. TechnoSpam is pre-launch — be one of the first to sign up.'\n }\n action={\n !search && !alreadyMentor ? (\n <Button onClick={() => setShowForm(true)}>Become a mentor</Button>\n ) : undefined\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filtered.map((mentor) => (\n <MentorCard\n key={mentor.id}\n mentor={mentor}\n onOpen={() => navigate(`/mentorship/mentor-profile-page?id=${mentor.id}`)}\n />\n ))}\n </div>\n )}\n <LoadMore hasMore={hasMore} loading={loading} onClick={more} />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|