@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,189 +6,298 @@ import { StatusBadge as o } from "../components/StatusBadge.js";
6
6
  import { EmptyView as s, ErrorView as c, LoadingRows as l } from "../components/StateViews.js";
7
7
  import "../components/index.js";
8
8
  import { notify as u } from "../lib/toast.js";
9
- import { useCancelSession as d, useMentorsQuery as f, useSessionsQuery as p } from "../api/technospamApi.js";
10
- import { useState as m } from "react";
11
- import { CalendarClock as h, Clock as g, MessageSquare as _, Users as v, Video as y, X as b } from "lucide-react";
12
- import { jsx as x, jsxs as S } from "react/jsx-runtime";
13
- import { Button as C, GlassCard as w, Tabs as T, TabsList as E, TabsTrigger as D } from "@burdenoff/fe-libs/ui";
9
+ import { useCancelSession as d, useCompleteSession as f, useConfirmSession as p, useMentorsQuery as m, useSessionsQuery as h } from "../api/technospamApi.js";
10
+ import { useState as g } from "react";
11
+ import { CalendarClock as _, Check as v, CheckCircle2 as y, Clock as b, MessageSquare as x, Users as S, Video as C, X as w } from "lucide-react";
12
+ import { jsx as T, jsxs as E } from "react/jsx-runtime";
13
+ import { Button as D, GlassCard as O, Input as k, Tabs as A, TabsList as j, TabsTrigger as M } from "@burdenoff/fe-libs/ui";
14
14
  //#region src/technospam/pages/MentorshipSessionsPagePage.tsx
15
- var O = new Set(["REQUESTED", "CONFIRMED"]);
16
- function k({ session: e, showMentor: t, onCancel: n, cancelling: r }) {
17
- let s = O.has(e.status);
18
- return /* @__PURE__ */ S(w, {
19
- className: "flex flex-col gap-3 p-4 sm:flex-row sm:items-center sm:justify-between",
20
- children: [/* @__PURE__ */ S("div", {
21
- className: "flex items-start gap-3",
22
- children: [/* @__PURE__ */ x("span", {
23
- className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-accent-wash text-accent-primary",
24
- children: /* @__PURE__ */ x(y, { size: 18 })
25
- }), /* @__PURE__ */ S("div", {
26
- className: "min-w-0",
15
+ var N = new Set(["REQUESTED", "CONFIRMED"]);
16
+ function P({ session: e, showMentor: t, isMentor: n, onCancel: r, onConfirm: s, onComplete: c, busy: l }) {
17
+ let u = N.has(e.status), [d, f] = g("none"), [p, m] = g(""), [h, x] = g("5"), [S, A] = g("");
18
+ return /* @__PURE__ */ E(O, {
19
+ className: "flex flex-col gap-3 p-4",
20
+ children: [
21
+ /* @__PURE__ */ E("div", {
22
+ className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
23
+ children: [/* @__PURE__ */ E("div", {
24
+ className: "flex items-start gap-3",
25
+ children: [/* @__PURE__ */ T("span", {
26
+ className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-accent-wash text-accent-primary",
27
+ children: /* @__PURE__ */ T(C, { size: 18 })
28
+ }), /* @__PURE__ */ E("div", {
29
+ className: "min-w-0",
30
+ children: [
31
+ /* @__PURE__ */ E("div", {
32
+ className: "flex flex-wrap items-center gap-2",
33
+ children: [
34
+ /* @__PURE__ */ T("span", {
35
+ className: "truncate text-sm font-semibold text-text-primary",
36
+ children: e.topic
37
+ }),
38
+ /* @__PURE__ */ T(o, { status: e.status }),
39
+ e.rating ? /* @__PURE__ */ E("span", {
40
+ className: "text-xs text-text-muted",
41
+ children: [
42
+ "★ ",
43
+ e.rating,
44
+ "/5"
45
+ ]
46
+ }) : null
47
+ ]
48
+ }),
49
+ t && e.mentor?.headline ? /* @__PURE__ */ E("div", {
50
+ className: "mt-0.5 truncate text-xs text-text-secondary",
51
+ children: ["with ", e.mentor.headline]
52
+ }) : null,
53
+ /* @__PURE__ */ E("div", {
54
+ className: "mt-1 flex flex-wrap items-center gap-3 text-xs text-text-muted",
55
+ children: [/* @__PURE__ */ E("span", {
56
+ className: "inline-flex items-center gap-1",
57
+ children: [
58
+ /* @__PURE__ */ T(_, { size: 13 }),
59
+ " ",
60
+ i(e.scheduledAt)
61
+ ]
62
+ }), /* @__PURE__ */ E("span", {
63
+ className: "inline-flex items-center gap-1",
64
+ children: [
65
+ /* @__PURE__ */ T(b, { size: 13 }),
66
+ " ",
67
+ a(e.durationMinutes)
68
+ ]
69
+ })]
70
+ }),
71
+ e.agenda ? /* @__PURE__ */ T("p", {
72
+ className: "mt-1 line-clamp-2 text-xs text-text-secondary",
73
+ children: e.agenda
74
+ }) : null
75
+ ]
76
+ })]
77
+ }), /* @__PURE__ */ E("div", {
78
+ className: "flex shrink-0 flex-wrap items-center gap-2",
79
+ children: [
80
+ e.meetingUrl ? /* @__PURE__ */ E(D, {
81
+ variant: "outline",
82
+ size: "sm",
83
+ onClick: () => window.open(e.meetingUrl ?? "", "_blank", "noopener,noreferrer"),
84
+ children: [/* @__PURE__ */ T(C, { size: 15 }), " Join"]
85
+ }) : null,
86
+ n && e.status === "REQUESTED" ? /* @__PURE__ */ E(D, {
87
+ variant: "outline",
88
+ size: "sm",
89
+ onClick: () => f(d === "confirm" ? "none" : "confirm"),
90
+ children: [/* @__PURE__ */ T(v, { size: 15 }), " Confirm"]
91
+ }) : null,
92
+ n && e.status === "CONFIRMED" ? /* @__PURE__ */ E(D, {
93
+ variant: "outline",
94
+ size: "sm",
95
+ onClick: () => f(d === "complete" ? "none" : "complete"),
96
+ children: [/* @__PURE__ */ T(y, { size: 15 }), " Mark complete"]
97
+ }) : null,
98
+ u ? /* @__PURE__ */ E(D, {
99
+ variant: "ghost",
100
+ size: "sm",
101
+ onClick: () => r(e.id),
102
+ disabled: l,
103
+ children: [/* @__PURE__ */ T(w, { size: 15 }), " Cancel"]
104
+ }) : null
105
+ ]
106
+ })]
107
+ }),
108
+ d === "confirm" ? /* @__PURE__ */ E("div", {
109
+ className: "flex flex-col gap-2 rounded-lg border border-border-seam bg-bg-sunken p-3 sm:flex-row sm:items-center",
110
+ children: [/* @__PURE__ */ T(k, {
111
+ className: "flex-1",
112
+ placeholder: "Meeting link (e.g. https://meet.…)",
113
+ value: p,
114
+ onChange: (e) => m(e.target.value)
115
+ }), /* @__PURE__ */ T(D, {
116
+ size: "sm",
117
+ onClick: async () => {
118
+ await s(e.id, p.trim()), f("none"), m("");
119
+ },
120
+ disabled: l,
121
+ children: "Confirm session"
122
+ })]
123
+ }) : null,
124
+ d === "complete" ? /* @__PURE__ */ E("div", {
125
+ className: "flex flex-col gap-2 rounded-lg border border-border-seam bg-bg-sunken p-3",
27
126
  children: [
28
- /* @__PURE__ */ S("div", {
29
- className: "flex flex-wrap items-center gap-2",
30
- children: [/* @__PURE__ */ x("span", {
31
- className: "truncate text-sm font-semibold text-text-primary",
32
- children: e.topic
33
- }), /* @__PURE__ */ x(o, { status: e.status })]
34
- }),
35
- t && e.mentor?.headline ? /* @__PURE__ */ S("div", {
36
- className: "mt-0.5 truncate text-xs text-text-secondary",
37
- children: ["with ", e.mentor.headline]
38
- }) : null,
39
- /* @__PURE__ */ S("div", {
40
- className: "mt-1 flex flex-wrap items-center gap-3 text-xs text-text-muted",
41
- children: [/* @__PURE__ */ S("span", {
42
- className: "inline-flex items-center gap-1",
43
- children: [
44
- /* @__PURE__ */ x(h, { size: 13 }),
45
- " ",
46
- i(e.scheduledAt)
47
- ]
48
- }), /* @__PURE__ */ S("span", {
49
- className: "inline-flex items-center gap-1",
50
- children: [
51
- /* @__PURE__ */ x(g, { size: 13 }),
52
- " ",
53
- a(e.durationMinutes)
54
- ]
127
+ /* @__PURE__ */ E("div", {
128
+ className: "flex items-center gap-2",
129
+ children: [/* @__PURE__ */ T("label", {
130
+ className: "text-xs text-text-secondary",
131
+ children: "Rating (1–5)"
132
+ }), /* @__PURE__ */ T(k, {
133
+ type: "number",
134
+ min: 1,
135
+ max: 5,
136
+ className: "w-20",
137
+ value: h,
138
+ onChange: (e) => x(e.target.value)
55
139
  })]
56
140
  }),
57
- e.agenda ? /* @__PURE__ */ x("p", {
58
- className: "mt-1 line-clamp-2 text-xs text-text-secondary",
59
- children: e.agenda
60
- }) : null
141
+ /* @__PURE__ */ T(k, {
142
+ placeholder: "Feedback for the mentee (optional)",
143
+ value: S,
144
+ onChange: (e) => A(e.target.value)
145
+ }),
146
+ /* @__PURE__ */ T("div", { children: /* @__PURE__ */ T(D, {
147
+ size: "sm",
148
+ onClick: async () => {
149
+ await c(e.id, Math.min(5, Math.max(1, Number(h) || 5)), S.trim()), f("none");
150
+ },
151
+ disabled: l,
152
+ children: "Complete session"
153
+ }) })
61
154
  ]
62
- })]
63
- }), /* @__PURE__ */ S("div", {
64
- className: "flex shrink-0 items-center gap-2",
65
- children: [e.meetingUrl ? /* @__PURE__ */ S(C, {
66
- variant: "outline",
67
- size: "sm",
68
- onClick: () => window.open(e.meetingUrl ?? "", "_blank", "noopener,noreferrer"),
69
- children: [/* @__PURE__ */ x(y, { size: 15 }), " Join"]
70
- }) : null, s ? /* @__PURE__ */ S(C, {
71
- variant: "ghost",
72
- size: "sm",
73
- onClick: () => n(e.id),
74
- disabled: r,
75
- children: [/* @__PURE__ */ x(b, { size: 15 }), " Cancel"]
76
- }) : null]
77
- })]
155
+ }) : null
156
+ ]
78
157
  });
79
158
  }
80
- function A({ loading: e, error: t, sessions: n, showMentor: r, emptyTitle: i, emptyDescription: a, emptyAction: o, onCancel: u, cancellingId: d }) {
81
- return e && n.length === 0 ? /* @__PURE__ */ x(l, {
159
+ function F({ loading: e, error: t, sessions: n, showMentor: r, emptyTitle: i, emptyDescription: a, emptyAction: o, isMentor: u, onCancel: d, onConfirm: f, onComplete: p, busyId: m }) {
160
+ return e && n.length === 0 ? /* @__PURE__ */ T(l, {
82
161
  count: 3,
83
162
  height: "h-24"
84
- }) : t ? /* @__PURE__ */ x(c, {
163
+ }) : t ? /* @__PURE__ */ T(c, {
85
164
  title: "Couldn't load sessions",
86
165
  error: t
87
- }) : n.length === 0 ? /* @__PURE__ */ x(s, {
88
- icon: /* @__PURE__ */ x(_, { size: 26 }),
166
+ }) : n.length === 0 ? /* @__PURE__ */ T(s, {
167
+ icon: /* @__PURE__ */ T(x, { size: 26 }),
89
168
  title: i,
90
169
  description: a,
91
170
  action: o
92
- }) : /* @__PURE__ */ x("div", {
171
+ }) : /* @__PURE__ */ T("div", {
93
172
  className: "space-y-3",
94
- children: [...n].sort((e, t) => new Date(t.scheduledAt).getTime() - new Date(e.scheduledAt).getTime()).map((e) => /* @__PURE__ */ x(k, {
173
+ children: [...n].sort((e, t) => new Date(t.scheduledAt).getTime() - new Date(e.scheduledAt).getTime()).map((e) => /* @__PURE__ */ T(P, {
95
174
  session: e,
96
175
  showMentor: r,
97
- onCancel: u,
98
- cancelling: d === e.id
176
+ isMentor: u,
177
+ onCancel: d,
178
+ onConfirm: f,
179
+ onComplete: p,
180
+ busy: m === e.id
99
181
  }, e.id))
100
182
  });
101
183
  }
102
- function j() {
103
- let i = t(), { currentUser: a } = e(), [o, c] = m("mentee"), [h, g] = m(null), y = a?.id, b = p(y ? { menteeId: y } : {}), w = f({}), O = w.data?.tecListMentors.items.find((e) => e.userId === a?.id), k = O?.id, j = p(k ? { mentorId: k } : {}), [M] = d(), N = y ? b.data?.tecListSessions ?? [] : [], P = k ? j.data?.tecListSessions ?? [] : [], F = async (e) => {
104
- g(e);
184
+ function I() {
185
+ let i = t(), { currentUser: a } = e(), [o, c] = g("mentee"), [_, v] = g(null), y = a?.id, b = h(y ? { menteeId: y } : {}), C = m({}), w = C.data?.tecListMentors.items.find((e) => e.userId === a?.id), O = w?.id, k = h(O ? { mentorId: O } : {}), [N] = d(), [P] = p(), [I] = f(), L = y ? b.data?.tecListSessions ?? [] : [], R = O ? k.data?.tecListSessions ?? [] : [], z = async (e) => {
186
+ v(e);
187
+ try {
188
+ (await N({ variables: { id: e } })).data?.tecCancelSession && u.success("Session cancelled", "The session has been cancelled.");
189
+ } finally {
190
+ v(null);
191
+ }
192
+ }, B = async (e, t) => {
193
+ v(e);
194
+ try {
195
+ (await P({ variables: {
196
+ id: e,
197
+ meetingUrl: t || void 0
198
+ } })).data?.tecConfirmSession && (u.success("Session confirmed", "The mentee has been notified."), await k.refetch());
199
+ } finally {
200
+ v(null);
201
+ }
202
+ }, V = async (e, t, n) => {
203
+ v(e);
105
204
  try {
106
- (await M({ variables: { id: e } })).data?.tecCancelSession && u.success("Session cancelled", "The session has been cancelled.");
205
+ (await I({ variables: {
206
+ id: e,
207
+ rating: t,
208
+ feedback: n || void 0
209
+ } })).data?.tecCompleteSession && (u.success("Session completed", "Nice work — the session is wrapped up."), await k.refetch());
107
210
  } finally {
108
- g(null);
211
+ v(null);
109
212
  }
110
213
  };
111
- return a?.id ? /* @__PURE__ */ S(n, {
214
+ return a?.id ? /* @__PURE__ */ E(n, {
112
215
  hero: !0,
113
216
  title: "My Sessions",
114
217
  description: "Manage the mentorship sessions you've booked and the ones you host.",
115
- actions: /* @__PURE__ */ S(C, {
218
+ actions: /* @__PURE__ */ E(D, {
116
219
  variant: "outline",
117
220
  onClick: () => i("/mentorship/mentors-page"),
118
- children: [/* @__PURE__ */ x(v, { size: 16 }), " Find a mentor"]
221
+ children: [/* @__PURE__ */ T(S, { size: 16 }), " Find a mentor"]
119
222
  }),
120
223
  children: [
121
- /* @__PURE__ */ S("div", {
224
+ /* @__PURE__ */ E("div", {
122
225
  className: "mb-5 grid grid-cols-2 gap-3 sm:max-w-md",
123
- children: [/* @__PURE__ */ x(r, {
226
+ children: [/* @__PURE__ */ T(r, {
124
227
  label: "As mentee",
125
- value: N.length,
126
- icon: _
127
- }), /* @__PURE__ */ x(r, {
228
+ value: L.length,
229
+ icon: x
230
+ }), /* @__PURE__ */ T(r, {
128
231
  label: "As mentor",
129
- value: k ? P.length : 0,
130
- icon: v
232
+ value: O ? R.length : 0,
233
+ icon: S
131
234
  })]
132
235
  }),
133
- /* @__PURE__ */ x(T, {
236
+ /* @__PURE__ */ T(A, {
134
237
  value: o,
135
238
  onValueChange: (e) => c(e),
136
239
  className: "mb-4",
137
- children: /* @__PURE__ */ S(E, { children: [/* @__PURE__ */ x(D, {
240
+ children: /* @__PURE__ */ E(j, { children: [/* @__PURE__ */ T(M, {
138
241
  value: "mentee",
139
242
  children: "As mentee"
140
- }), /* @__PURE__ */ x(D, {
243
+ }), /* @__PURE__ */ T(M, {
141
244
  value: "mentor",
142
245
  children: "As mentor"
143
246
  })] })
144
247
  }),
145
- o === "mentee" ? /* @__PURE__ */ x(A, {
248
+ o === "mentee" ? /* @__PURE__ */ T(F, {
146
249
  loading: b.loading,
147
250
  error: b.error,
148
- sessions: N,
251
+ sessions: L,
149
252
  showMentor: !0,
150
253
  emptyTitle: "No sessions booked yet",
151
254
  emptyDescription: "Find a mentor and request a session to get personalized guidance.",
152
- emptyAction: /* @__PURE__ */ x(C, {
255
+ emptyAction: /* @__PURE__ */ T(D, {
153
256
  onClick: () => i("/mentorship/mentors-page"),
154
257
  children: "Find a mentor"
155
258
  }),
156
- onCancel: F,
157
- cancellingId: h
158
- }) : w.loading && !O ? /* @__PURE__ */ x(l, {
259
+ isMentor: !1,
260
+ onCancel: z,
261
+ onConfirm: B,
262
+ onComplete: V,
263
+ busyId: _
264
+ }) : C.loading && !w ? /* @__PURE__ */ T(l, {
159
265
  count: 3,
160
266
  height: "h-24"
161
- }) : k ? /* @__PURE__ */ x(A, {
162
- loading: j.loading,
163
- error: j.error,
164
- sessions: P,
267
+ }) : O ? /* @__PURE__ */ T(F, {
268
+ loading: k.loading,
269
+ error: k.error,
270
+ sessions: R,
165
271
  showMentor: !1,
166
272
  emptyTitle: "No sessions to host yet",
167
273
  emptyDescription: "When mentees request time with you, their sessions will show up here.",
168
- onCancel: F,
169
- cancellingId: h
170
- }) : /* @__PURE__ */ x(s, {
171
- icon: /* @__PURE__ */ x(v, { size: 26 }),
274
+ isMentor: !0,
275
+ onCancel: z,
276
+ onConfirm: B,
277
+ onComplete: V,
278
+ busyId: _
279
+ }) : /* @__PURE__ */ T(s, {
280
+ icon: /* @__PURE__ */ T(S, { size: 26 }),
172
281
  title: "You're not a mentor yet",
173
282
  description: "Create a mentor profile to start hosting sessions and helping others build.",
174
- action: /* @__PURE__ */ x(C, {
283
+ action: /* @__PURE__ */ T(D, {
175
284
  onClick: () => i("/mentorship/mentors-page"),
176
285
  children: "Become a mentor"
177
286
  })
178
287
  })
179
288
  ]
180
- }) : /* @__PURE__ */ x(n, {
289
+ }) : /* @__PURE__ */ T(n, {
181
290
  hero: !0,
182
291
  title: "My Sessions",
183
292
  description: "Track your mentorship sessions.",
184
- children: /* @__PURE__ */ x(s, {
185
- icon: /* @__PURE__ */ x(_, { size: 26 }),
293
+ children: /* @__PURE__ */ T(s, {
294
+ icon: /* @__PURE__ */ T(x, { size: 26 }),
186
295
  title: "Sign in to view your sessions",
187
296
  description: "Your booked and hosted mentorship sessions will appear here once you're signed in."
188
297
  })
189
298
  });
190
299
  }
191
300
  //#endregion
192
- export { j as MentorshipSessionsPagePage };
301
+ export { I as MentorshipSessionsPagePage };
193
302
 
194
303
  //# sourceMappingURL=MentorshipSessionsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MentorshipSessionsPagePage.js","names":[],"sources":["../../../src/technospam/pages/MentorshipSessionsPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { CalendarClock, Clock, MessageSquare, Users, Video, X } from 'lucide-react';\nimport { Button, GlassCard, Tabs, TabsList, TabsTrigger } from '@burdenoff/fe-libs/ui';\nimport {\n EmptyView,\n ErrorView,\n LoadingRows,\n PageLayout,\n StatCard,\n StatusBadge,\n} from '../components';\nimport { useTechnoSpam, useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport {\n useCancelSession,\n useMentorsQuery,\n useSessionsQuery,\n type TecMentorSession,\n} from '../api/technospamApi';\nimport { formatDateTime, formatDuration } from '../utils/format';\nimport { notify } from '../lib/toast';\n\ntype Perspective = 'mentee' | 'mentor';\n\nconst CANCELLABLE = new Set(['REQUESTED', 'CONFIRMED']);\n\nfunction SessionRow({\n session,\n showMentor,\n onCancel,\n cancelling,\n}: {\n session: TecMentorSession;\n showMentor: boolean;\n onCancel: (id: string) => void;\n cancelling: boolean;\n}) {\n const canCancel = CANCELLABLE.has(session.status);\n return (\n <GlassCard className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-start gap-3\">\n <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-accent-wash text-accent-primary\">\n <Video size={18} />\n </span>\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"truncate text-sm font-semibold text-text-primary\">\n {session.topic}\n </span>\n <StatusBadge status={session.status} />\n </div>\n {showMentor && session.mentor?.headline ? (\n <div className=\"mt-0.5 truncate text-xs text-text-secondary\">\n with {session.mentor.headline}\n </div>\n ) : null}\n <div className=\"mt-1 flex flex-wrap items-center gap-3 text-xs text-text-muted\">\n <span className=\"inline-flex items-center gap-1\">\n <CalendarClock size={13} /> {formatDateTime(session.scheduledAt)}\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <Clock size={13} /> {formatDuration(session.durationMinutes)}\n </span>\n </div>\n {session.agenda ? (\n <p className=\"mt-1 line-clamp-2 text-xs text-text-secondary\">{session.agenda}</p>\n ) : null}\n </div>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {session.meetingUrl ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => window.open(session.meetingUrl ?? '', '_blank', 'noopener,noreferrer')}\n >\n <Video size={15} /> Join\n </Button>\n ) : null}\n {canCancel ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onCancel(session.id)}\n disabled={cancelling}\n >\n <X size={15} /> Cancel\n </Button>\n ) : null}\n </div>\n </GlassCard>\n );\n}\n\nfunction SessionsList({\n loading,\n error,\n sessions,\n showMentor,\n emptyTitle,\n emptyDescription,\n emptyAction,\n onCancel,\n cancellingId,\n}: {\n loading: boolean;\n error?: { message?: string };\n sessions: TecMentorSession[];\n showMentor: boolean;\n emptyTitle: string;\n emptyDescription: string;\n emptyAction?: React.ReactNode;\n onCancel: (id: string) => void;\n cancellingId: string | null;\n}) {\n if (loading && sessions.length === 0) return <LoadingRows count={3} height=\"h-24\" />;\n if (error) return <ErrorView title=\"Couldn't load sessions\" error={error} />;\n if (sessions.length === 0) {\n return (\n <EmptyView\n icon={<MessageSquare size={26} />}\n title={emptyTitle}\n description={emptyDescription}\n action={emptyAction}\n />\n );\n }\n const sorted = [...sessions].sort(\n (a, b) => new Date(b.scheduledAt).getTime() - new Date(a.scheduledAt).getTime()\n );\n return (\n <div className=\"space-y-3\">\n {sorted.map((session) => (\n <SessionRow\n key={session.id}\n session={session}\n showMentor={showMentor}\n onCancel={onCancel}\n cancelling={cancellingId === session.id}\n />\n ))}\n </div>\n );\n}\n\nexport function MentorshipSessionsPagePage() {\n const navigate = useTechnoSpamNavigate();\n const { currentUser } = useTechnoSpam();\n const [tab, setTab] = useState<Perspective>('mentee');\n const [cancellingId, setCancellingId] = useState<string | null>(null);\n\n const menteeId = currentUser?.id;\n\n // As mentee: sessions the current user booked.\n const menteeQ = useSessionsQuery(menteeId ? { menteeId } : {});\n\n // Resolve whether the current user is a mentor, to load their mentor sessions.\n const mentorsQ = useMentorsQuery({});\n const myMentor = mentorsQ.data?.tecListMentors.items.find((m) => m.userId === currentUser?.id);\n const mentorId = myMentor?.id;\n const mentorQ = useSessionsQuery(mentorId ? { mentorId } : {});\n\n const [cancelSession] = useCancelSession();\n\n const menteeSessions = menteeId ? (menteeQ.data?.tecListSessions ?? []) : [];\n const mentorSessions = mentorId ? (mentorQ.data?.tecListSessions ?? []) : [];\n\n const handleCancel = async (id: string) => {\n setCancellingId(id);\n try {\n const res = await cancelSession({ variables: { id } });\n if (res.data?.tecCancelSession) {\n notify.success('Session cancelled', 'The session has been cancelled.');\n }\n } finally {\n setCancellingId(null);\n }\n };\n\n if (!currentUser?.id) {\n return (\n <PageLayout hero title=\"My Sessions\" description=\"Track your mentorship sessions.\">\n <EmptyView\n icon={<MessageSquare size={26} />}\n title=\"Sign in to view your sessions\"\n description=\"Your booked and hosted mentorship sessions will appear here once you're signed in.\"\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n hero\n title=\"My Sessions\"\n description=\"Manage the mentorship sessions you've booked and the ones you host.\"\n actions={\n <Button variant=\"outline\" onClick={() => navigate('/mentorship/mentors-page')}>\n <Users size={16} /> Find a mentor\n </Button>\n }\n >\n <div className=\"mb-5 grid grid-cols-2 gap-3 sm:max-w-md\">\n <StatCard label=\"As mentee\" value={menteeSessions.length} icon={MessageSquare} />\n <StatCard label=\"As mentor\" value={mentorId ? mentorSessions.length : 0} icon={Users} />\n </div>\n\n <Tabs value={tab} onValueChange={(v) => setTab(v as Perspective)} className=\"mb-4\">\n <TabsList>\n <TabsTrigger value=\"mentee\">As mentee</TabsTrigger>\n <TabsTrigger value=\"mentor\">As mentor</TabsTrigger>\n </TabsList>\n </Tabs>\n\n {tab === 'mentee' ? (\n <SessionsList\n loading={menteeQ.loading}\n error={menteeQ.error}\n sessions={menteeSessions}\n showMentor\n emptyTitle=\"No sessions booked yet\"\n emptyDescription=\"Find a mentor and request a session to get personalized guidance.\"\n emptyAction={\n <Button onClick={() => navigate('/mentorship/mentors-page')}>Find a mentor</Button>\n }\n onCancel={handleCancel}\n cancellingId={cancellingId}\n />\n ) : mentorsQ.loading && !myMentor ? (\n <LoadingRows count={3} height=\"h-24\" />\n ) : !mentorId ? (\n <EmptyView\n icon={<Users size={26} />}\n title=\"You're not a mentor yet\"\n description=\"Create a mentor profile to start hosting sessions and helping others build.\"\n action={\n <Button onClick={() => navigate('/mentorship/mentors-page')}>Become a mentor</Button>\n }\n />\n ) : (\n <SessionsList\n loading={mentorQ.loading}\n error={mentorQ.error}\n sessions={mentorSessions}\n showMentor={false}\n emptyTitle=\"No sessions to host yet\"\n emptyDescription=\"When mentees request time with you, their sessions will show up here.\"\n onCancel={handleCancel}\n cancellingId={cancellingId}\n />\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MentorshipSessionsPagePage.js","names":[],"sources":["../../../src/technospam/pages/MentorshipSessionsPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n CalendarClock,\n Check,\n CheckCircle2,\n Clock,\n MessageSquare,\n Users,\n Video,\n X,\n} from 'lucide-react';\nimport { Button, GlassCard, Input, Tabs, TabsList, TabsTrigger } from '@burdenoff/fe-libs/ui';\nimport {\n EmptyView,\n ErrorView,\n LoadingRows,\n PageLayout,\n StatCard,\n StatusBadge,\n} from '../components';\nimport { useTechnoSpam, useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport {\n useCancelSession,\n useCompleteSession,\n useConfirmSession,\n useMentorsQuery,\n useSessionsQuery,\n type TecMentorSession,\n} from '../api/technospamApi';\nimport { formatDateTime, formatDuration } from '../utils/format';\nimport { notify } from '../lib/toast';\n\ntype Perspective = 'mentee' | 'mentor';\n\nconst CANCELLABLE = new Set(['REQUESTED', 'CONFIRMED']);\n\nfunction SessionRow({\n session,\n showMentor,\n isMentor,\n onCancel,\n onConfirm,\n onComplete,\n busy,\n}: {\n session: TecMentorSession;\n showMentor: boolean;\n isMentor: boolean;\n onCancel: (id: string) => void;\n onConfirm: (id: string, meetingUrl: string) => Promise<void>;\n onComplete: (id: string, rating: number, feedback: string) => Promise<void>;\n busy: boolean;\n}) {\n const canCancel = CANCELLABLE.has(session.status);\n const [mode, setMode] = useState<'none' | 'confirm' | 'complete'>('none');\n const [meetingUrl, setMeetingUrl] = useState('');\n const [rating, setRating] = useState('5');\n const [feedback, setFeedback] = useState('');\n\n const submitConfirm = async () => {\n await onConfirm(session.id, meetingUrl.trim());\n setMode('none');\n setMeetingUrl('');\n };\n const submitComplete = async () => {\n await onComplete(session.id, Math.min(5, Math.max(1, Number(rating) || 5)), feedback.trim());\n setMode('none');\n };\n\n return (\n <GlassCard className=\"flex flex-col gap-3 p-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-start gap-3\">\n <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-accent-wash text-accent-primary\">\n <Video size={18} />\n </span>\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"truncate text-sm font-semibold text-text-primary\">\n {session.topic}\n </span>\n <StatusBadge status={session.status} />\n {session.rating ? (\n <span className=\"text-xs text-text-muted\">★ {session.rating}/5</span>\n ) : null}\n </div>\n {showMentor && session.mentor?.headline ? (\n <div className=\"mt-0.5 truncate text-xs text-text-secondary\">\n with {session.mentor.headline}\n </div>\n ) : null}\n <div className=\"mt-1 flex flex-wrap items-center gap-3 text-xs text-text-muted\">\n <span className=\"inline-flex items-center gap-1\">\n <CalendarClock size={13} /> {formatDateTime(session.scheduledAt)}\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <Clock size={13} /> {formatDuration(session.durationMinutes)}\n </span>\n </div>\n {session.agenda ? (\n <p className=\"mt-1 line-clamp-2 text-xs text-text-secondary\">{session.agenda}</p>\n ) : null}\n </div>\n </div>\n <div className=\"flex shrink-0 flex-wrap items-center gap-2\">\n {session.meetingUrl ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => window.open(session.meetingUrl ?? '', '_blank', 'noopener,noreferrer')}\n >\n <Video size={15} /> Join\n </Button>\n ) : null}\n {isMentor && session.status === 'REQUESTED' ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setMode(mode === 'confirm' ? 'none' : 'confirm')}\n >\n <Check size={15} /> Confirm\n </Button>\n ) : null}\n {isMentor && session.status === 'CONFIRMED' ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setMode(mode === 'complete' ? 'none' : 'complete')}\n >\n <CheckCircle2 size={15} /> Mark complete\n </Button>\n ) : null}\n {canCancel ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onCancel(session.id)} disabled={busy}>\n <X size={15} /> Cancel\n </Button>\n ) : null}\n </div>\n </div>\n\n {mode === 'confirm' ? (\n <div className=\"flex flex-col gap-2 rounded-lg border border-border-seam bg-bg-sunken p-3 sm:flex-row sm:items-center\">\n <Input\n className=\"flex-1\"\n placeholder=\"Meeting link (e.g. https://meet.…)\"\n value={meetingUrl}\n onChange={(e) => setMeetingUrl(e.target.value)}\n />\n <Button size=\"sm\" onClick={submitConfirm} disabled={busy}>\n Confirm session\n </Button>\n </div>\n ) : null}\n {mode === 'complete' ? (\n <div className=\"flex flex-col gap-2 rounded-lg border border-border-seam bg-bg-sunken p-3\">\n <div className=\"flex items-center gap-2\">\n <label className=\"text-xs text-text-secondary\">Rating (1–5)</label>\n <Input\n type=\"number\"\n min={1}\n max={5}\n className=\"w-20\"\n value={rating}\n onChange={(e) => setRating(e.target.value)}\n />\n </div>\n <Input\n placeholder=\"Feedback for the mentee (optional)\"\n value={feedback}\n onChange={(e) => setFeedback(e.target.value)}\n />\n <div>\n <Button size=\"sm\" onClick={submitComplete} disabled={busy}>\n Complete session\n </Button>\n </div>\n </div>\n ) : null}\n </GlassCard>\n );\n}\n\nfunction SessionsList({\n loading,\n error,\n sessions,\n showMentor,\n emptyTitle,\n emptyDescription,\n emptyAction,\n isMentor,\n onCancel,\n onConfirm,\n onComplete,\n busyId,\n}: {\n loading: boolean;\n error?: { message?: string };\n sessions: TecMentorSession[];\n showMentor: boolean;\n emptyTitle: string;\n emptyDescription: string;\n emptyAction?: React.ReactNode;\n isMentor: boolean;\n onCancel: (id: string) => void;\n onConfirm: (id: string, meetingUrl: string) => Promise<void>;\n onComplete: (id: string, rating: number, feedback: string) => Promise<void>;\n busyId: string | null;\n}) {\n if (loading && sessions.length === 0) return <LoadingRows count={3} height=\"h-24\" />;\n if (error) return <ErrorView title=\"Couldn't load sessions\" error={error} />;\n if (sessions.length === 0) {\n return (\n <EmptyView\n icon={<MessageSquare size={26} />}\n title={emptyTitle}\n description={emptyDescription}\n action={emptyAction}\n />\n );\n }\n const sorted = [...sessions].sort(\n (a, b) => new Date(b.scheduledAt).getTime() - new Date(a.scheduledAt).getTime()\n );\n return (\n <div className=\"space-y-3\">\n {sorted.map((session) => (\n <SessionRow\n key={session.id}\n session={session}\n showMentor={showMentor}\n isMentor={isMentor}\n onCancel={onCancel}\n onConfirm={onConfirm}\n onComplete={onComplete}\n busy={busyId === session.id}\n />\n ))}\n </div>\n );\n}\n\nexport function MentorshipSessionsPagePage() {\n const navigate = useTechnoSpamNavigate();\n const { currentUser } = useTechnoSpam();\n const [tab, setTab] = useState<Perspective>('mentee');\n const [cancellingId, setCancellingId] = useState<string | null>(null);\n\n const menteeId = currentUser?.id;\n\n // As mentee: sessions the current user booked.\n const menteeQ = useSessionsQuery(menteeId ? { menteeId } : {});\n\n // Resolve whether the current user is a mentor, to load their mentor sessions.\n const mentorsQ = useMentorsQuery({});\n const myMentor = mentorsQ.data?.tecListMentors.items.find((m) => m.userId === currentUser?.id);\n const mentorId = myMentor?.id;\n const mentorQ = useSessionsQuery(mentorId ? { mentorId } : {});\n\n const [cancelSession] = useCancelSession();\n const [confirmSession] = useConfirmSession();\n const [completeSession] = useCompleteSession();\n\n const menteeSessions = menteeId ? (menteeQ.data?.tecListSessions ?? []) : [];\n const mentorSessions = mentorId ? (mentorQ.data?.tecListSessions ?? []) : [];\n\n const handleCancel = async (id: string) => {\n setCancellingId(id);\n try {\n const res = await cancelSession({ variables: { id } });\n if (res.data?.tecCancelSession) {\n notify.success('Session cancelled', 'The session has been cancelled.');\n }\n } finally {\n setCancellingId(null);\n }\n };\n\n const handleConfirm = async (id: string, meetingUrl: string) => {\n setCancellingId(id);\n try {\n const res = await confirmSession({\n variables: { id, meetingUrl: meetingUrl || undefined },\n });\n if (res.data?.tecConfirmSession) {\n notify.success('Session confirmed', 'The mentee has been notified.');\n await mentorQ.refetch();\n }\n } finally {\n setCancellingId(null);\n }\n };\n\n const handleComplete = async (id: string, rating: number, feedback: string) => {\n setCancellingId(id);\n try {\n const res = await completeSession({\n variables: { id, rating, feedback: feedback || undefined },\n });\n if (res.data?.tecCompleteSession) {\n notify.success('Session completed', 'Nice work — the session is wrapped up.');\n await mentorQ.refetch();\n }\n } finally {\n setCancellingId(null);\n }\n };\n\n if (!currentUser?.id) {\n return (\n <PageLayout hero title=\"My Sessions\" description=\"Track your mentorship sessions.\">\n <EmptyView\n icon={<MessageSquare size={26} />}\n title=\"Sign in to view your sessions\"\n description=\"Your booked and hosted mentorship sessions will appear here once you're signed in.\"\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n hero\n title=\"My Sessions\"\n description=\"Manage the mentorship sessions you've booked and the ones you host.\"\n actions={\n <Button variant=\"outline\" onClick={() => navigate('/mentorship/mentors-page')}>\n <Users size={16} /> Find a mentor\n </Button>\n }\n >\n <div className=\"mb-5 grid grid-cols-2 gap-3 sm:max-w-md\">\n <StatCard label=\"As mentee\" value={menteeSessions.length} icon={MessageSquare} />\n <StatCard label=\"As mentor\" value={mentorId ? mentorSessions.length : 0} icon={Users} />\n </div>\n\n <Tabs value={tab} onValueChange={(v) => setTab(v as Perspective)} className=\"mb-4\">\n <TabsList>\n <TabsTrigger value=\"mentee\">As mentee</TabsTrigger>\n <TabsTrigger value=\"mentor\">As mentor</TabsTrigger>\n </TabsList>\n </Tabs>\n\n {tab === 'mentee' ? (\n <SessionsList\n loading={menteeQ.loading}\n error={menteeQ.error}\n sessions={menteeSessions}\n showMentor\n emptyTitle=\"No sessions booked yet\"\n emptyDescription=\"Find a mentor and request a session to get personalized guidance.\"\n emptyAction={\n <Button onClick={() => navigate('/mentorship/mentors-page')}>Find a mentor</Button>\n }\n isMentor={false}\n onCancel={handleCancel}\n onConfirm={handleConfirm}\n onComplete={handleComplete}\n busyId={cancellingId}\n />\n ) : mentorsQ.loading && !myMentor ? (\n <LoadingRows count={3} height=\"h-24\" />\n ) : !mentorId ? (\n <EmptyView\n icon={<Users size={26} />}\n title=\"You're not a mentor yet\"\n description=\"Create a mentor profile to start hosting sessions and helping others build.\"\n action={\n <Button onClick={() => navigate('/mentorship/mentors-page')}>Become a mentor</Button>\n }\n />\n ) : (\n <SessionsList\n loading={mentorQ.loading}\n error={mentorQ.error}\n sessions={mentorSessions}\n showMentor={false}\n emptyTitle=\"No sessions to host yet\"\n emptyDescription=\"When mentees request time with you, their sessions will show up here.\"\n isMentor\n onCancel={handleCancel}\n onConfirm={handleConfirm}\n onComplete={handleComplete}\n busyId={cancellingId}\n />\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-technospam",
3
- "version": "2026.704.1",
3
+ "version": "2026.705.1",
4
4
  "description": "Burdenoff TechnoSpam Microfrontend",
5
5
  "type": "module",
6
6
  "files": [