@burdenoff/microfe-technospam 2026.1101.1 → 2026.1101.2
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/stories/journeys/Problems.stories.d.ts.map +1 -1
- package/dist/technospam/api/technospamApi.d.ts +15 -0
- package/dist/technospam/api/technospamApi.d.ts.map +1 -1
- package/dist/technospam/api/technospamApi.js +200 -151
- package/dist/technospam/api/technospamApi.js.map +1 -1
- package/dist/technospam/components/ProblemsTable.d.ts +19 -0
- package/dist/technospam/components/ProblemsTable.d.ts.map +1 -0
- package/dist/technospam/components/ProblemsTable.js +117 -0
- package/dist/technospam/components/ProblemsTable.js.map +1 -0
- package/dist/technospam/components/index.d.ts +1 -0
- package/dist/technospam/components/index.d.ts.map +1 -1
- package/dist/technospam/components/index.js +2 -1
- package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.js +38 -38
- package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.js.map +1 -1
- package/dist/technospam/pages/ApplicationsProblemsPagePage.d.ts.map +1 -1
- package/dist/technospam/pages/ApplicationsProblemsPagePage.js +197 -144
- package/dist/technospam/pages/ApplicationsProblemsPagePage.js.map +1 -1
- package/dist/technospam/pages/CoursesCourseDetailsPagePage.js +195 -195
- package/dist/technospam/pages/CoursesCourseDetailsPagePage.js.map +1 -1
- package/dist/technospam/pages/CoursesCoursesPagePage.js +26 -26
- package/dist/technospam/pages/CoursesLessonPlayerPagePage.js +36 -36
- package/dist/technospam/pages/CoursesLessonPlayerPagePage.js.map +1 -1
- package/dist/technospam/utils/problemCatalog.d.ts +27 -0
- package/dist/technospam/utils/problemCatalog.d.ts.map +1 -0
- package/dist/technospam/utils/problemCatalog.js +68 -0
- package/dist/technospam/utils/problemCatalog.js.map +1 -0
- package/package.json +1 -1
|
@@ -5,105 +5,107 @@ import { PageLayout as i } from "../components/PageLayout.js";
|
|
|
5
5
|
import { StatCard as a } from "../components/StatCard.js";
|
|
6
6
|
import { MediaCover as o, topicIcon as s } from "../components/MediaCover.js";
|
|
7
7
|
import { StatusBadge as c } from "../components/StatusBadge.js";
|
|
8
|
-
import {
|
|
9
|
-
import { EmptyView as ee, ErrorView as te, LoadingGrid as u } from "../components/StateViews.js";
|
|
8
|
+
import { readProblemCatalogView as l, safeLocalStorage as u, writeProblemCatalogView as ee } from "../utils/problemCatalog.js";
|
|
10
9
|
import { PremiumBadge as d } from "../components/UpgradeGate.js";
|
|
11
|
-
import {
|
|
10
|
+
import { ProblemsTable as f } from "../components/ProblemsTable.js";
|
|
11
|
+
import { LoadMore as te } from "../components/LoadMore.js";
|
|
12
|
+
import { EmptyView as p, ErrorView as m, LoadingGrid as ne } from "../components/StateViews.js";
|
|
13
|
+
import { pageArg as re, usePageLimit as ie, useProblemsQuery as h, useSolvedProblemIds as ae } from "../api/technospamApi.js";
|
|
12
14
|
import "../components/index.js";
|
|
13
|
-
import { TAB_PANEL_FOCUS_CLASS as
|
|
14
|
-
import { useMemo as
|
|
15
|
-
import { Building2 as
|
|
16
|
-
import { jsx as
|
|
17
|
-
import { Badge as
|
|
15
|
+
import { TAB_PANEL_FOCUS_CLASS as oe } from "../lib/a11y.js";
|
|
16
|
+
import { useCallback as g, useMemo as _, useState as v } from "react";
|
|
17
|
+
import { Building2 as y, CheckCircle2 as b, Code2 as x, Flame as S, Gauge as se, Layers as C, LayoutGrid as w, List as ce, Search as le, Tag as T, Trophy as E } from "lucide-react";
|
|
18
|
+
import { jsx as D, jsxs as O } from "react/jsx-runtime";
|
|
19
|
+
import { Badge as k, Button as A, GlassCard as j, Input as ue, Select as M, SelectContent as N, SelectItem as P, SelectTrigger as F, SelectValue as I, Tabs as L, TabsContent as R, TabsList as z, TabsTrigger as B } from "@burdenoff/fe-libs/ui";
|
|
18
20
|
//#region src/technospam/pages/ApplicationsProblemsPagePage.tsx
|
|
19
|
-
function
|
|
21
|
+
function V({ problem: e, solved: t, onOpen: n }) {
|
|
20
22
|
let i = r();
|
|
21
|
-
return /* @__PURE__ */
|
|
23
|
+
return /* @__PURE__ */ O(j, {
|
|
22
24
|
className: "group flex cursor-pointer flex-col overflow-hidden transition-all duration-200 hover:-translate-y-1 hover:shadow-lg",
|
|
23
25
|
onClick: n,
|
|
24
|
-
children: [/* @__PURE__ */
|
|
26
|
+
children: [/* @__PURE__ */ O(o, {
|
|
25
27
|
seed: `${e.topic ?? ""} ${e.difficulty} ${e.title}`,
|
|
26
28
|
icon: s(e.topic ?? e.title),
|
|
27
|
-
children: [t ? /* @__PURE__ */
|
|
29
|
+
children: [t ? /* @__PURE__ */ O("span", {
|
|
28
30
|
className: "inline-flex items-center gap-1 rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[11px] font-medium text-status-success-text ring-1 ring-status-success-border/30",
|
|
29
31
|
children: [
|
|
30
|
-
/* @__PURE__ */
|
|
32
|
+
/* @__PURE__ */ D(b, { size: 12 }),
|
|
31
33
|
" ",
|
|
32
34
|
i("technospam.problems.solved", "Solved")
|
|
33
35
|
]
|
|
34
|
-
}) : /* @__PURE__ */
|
|
36
|
+
}) : /* @__PURE__ */ D("span", {}), /* @__PURE__ */ O("div", {
|
|
35
37
|
className: "flex flex-wrap items-center gap-1.5",
|
|
36
|
-
children: [/* @__PURE__ */
|
|
38
|
+
children: [/* @__PURE__ */ D(c, {
|
|
37
39
|
status: e.difficulty,
|
|
38
40
|
kind: "level"
|
|
39
|
-
}), e.isPremiumOnly ? /* @__PURE__ */
|
|
41
|
+
}), e.isPremiumOnly ? /* @__PURE__ */ D(d, { locked: e.isLocked }) : null]
|
|
40
42
|
})]
|
|
41
|
-
}), /* @__PURE__ */
|
|
43
|
+
}), /* @__PURE__ */ O("div", {
|
|
42
44
|
className: "flex flex-1 flex-col gap-3 p-4",
|
|
43
45
|
children: [
|
|
44
|
-
/* @__PURE__ */
|
|
46
|
+
/* @__PURE__ */ O("div", {
|
|
45
47
|
className: "min-w-0",
|
|
46
|
-
children: [/* @__PURE__ */
|
|
48
|
+
children: [/* @__PURE__ */ D("h3", {
|
|
47
49
|
className: "truncate text-base font-semibold text-text-primary group-hover:text-accent-primary",
|
|
48
50
|
children: e.title
|
|
49
|
-
}), e.statement ? /* @__PURE__ */
|
|
51
|
+
}), e.statement ? /* @__PURE__ */ D("p", {
|
|
50
52
|
className: "mt-1 line-clamp-2 text-sm text-text-secondary",
|
|
51
53
|
children: e.statement
|
|
52
54
|
}) : null]
|
|
53
55
|
}),
|
|
54
|
-
/* @__PURE__ */
|
|
56
|
+
/* @__PURE__ */ O("div", {
|
|
55
57
|
className: "mt-auto flex flex-wrap items-center gap-3 text-xs text-text-muted",
|
|
56
58
|
children: [
|
|
57
|
-
e.topic ? /* @__PURE__ */
|
|
59
|
+
e.topic ? /* @__PURE__ */ O("span", {
|
|
58
60
|
className: "inline-flex items-center gap-1",
|
|
59
61
|
children: [
|
|
60
|
-
/* @__PURE__ */
|
|
62
|
+
/* @__PURE__ */ D(C, { size: 13 }),
|
|
61
63
|
" ",
|
|
62
64
|
e.topic
|
|
63
65
|
]
|
|
64
66
|
}) : null,
|
|
65
|
-
/* @__PURE__ */
|
|
67
|
+
/* @__PURE__ */ O("span", {
|
|
66
68
|
className: "inline-flex items-center gap-1",
|
|
67
69
|
children: [
|
|
68
|
-
/* @__PURE__ */
|
|
70
|
+
/* @__PURE__ */ D(E, { size: 13 }),
|
|
69
71
|
" ",
|
|
70
72
|
i("technospam.problems.points", "{{count}} pts", { count: e.points })
|
|
71
73
|
]
|
|
72
74
|
}),
|
|
73
|
-
e.languages.length ? /* @__PURE__ */
|
|
75
|
+
e.languages.length ? /* @__PURE__ */ O("span", {
|
|
74
76
|
className: "inline-flex items-center gap-1",
|
|
75
77
|
children: [
|
|
76
|
-
/* @__PURE__ */
|
|
78
|
+
/* @__PURE__ */ D(x, { size: 13 }),
|
|
77
79
|
" ",
|
|
78
80
|
e.languages.length === 1 ? i("technospam.problems.languages", "{{count}} lang", { count: e.languages.length }) : i("technospam.problems.languagesPlural", "{{count}} langs", { count: e.languages.length })
|
|
79
81
|
]
|
|
80
82
|
}) : null
|
|
81
83
|
]
|
|
82
84
|
}),
|
|
83
|
-
e.companies.length ? /* @__PURE__ */
|
|
85
|
+
e.companies.length ? /* @__PURE__ */ O("div", {
|
|
84
86
|
className: "flex flex-wrap gap-1.5",
|
|
85
|
-
children: [e.companies.slice(0, 3).map((e) => /* @__PURE__ */
|
|
87
|
+
children: [e.companies.slice(0, 3).map((e) => /* @__PURE__ */ O(k, {
|
|
86
88
|
variant: "outline",
|
|
87
89
|
className: "text-[11px] capitalize",
|
|
88
|
-
children: [/* @__PURE__ */
|
|
90
|
+
children: [/* @__PURE__ */ D(y, {
|
|
89
91
|
size: 10,
|
|
90
92
|
className: "mr-1"
|
|
91
93
|
}), e.replace(/-/g, " ")]
|
|
92
|
-
}, e)), e.interviewFrequency === "HIGH" ? /* @__PURE__ */
|
|
94
|
+
}, e)), e.interviewFrequency === "HIGH" ? /* @__PURE__ */ O(k, {
|
|
93
95
|
variant: "secondary",
|
|
94
96
|
className: "text-[11px] text-status-warning-text",
|
|
95
|
-
children: [/* @__PURE__ */
|
|
97
|
+
children: [/* @__PURE__ */ D(S, {
|
|
96
98
|
size: 10,
|
|
97
99
|
className: "mr-1"
|
|
98
100
|
}), i("technospam.problems.frequentlyAsked", "Frequently asked")]
|
|
99
101
|
}) : null]
|
|
100
102
|
}) : null,
|
|
101
|
-
e.tags.length ? /* @__PURE__ */
|
|
103
|
+
e.tags.length ? /* @__PURE__ */ D("div", {
|
|
102
104
|
className: "flex flex-wrap gap-1.5",
|
|
103
|
-
children: e.tags.slice(0, 3).map((e) => /* @__PURE__ */
|
|
105
|
+
children: e.tags.slice(0, 3).map((e) => /* @__PURE__ */ O(k, {
|
|
104
106
|
variant: "secondary",
|
|
105
107
|
className: "text-[11px]",
|
|
106
|
-
children: [/* @__PURE__ */
|
|
108
|
+
children: [/* @__PURE__ */ D(T, {
|
|
107
109
|
size: 10,
|
|
108
110
|
className: "mr-1"
|
|
109
111
|
}), e]
|
|
@@ -113,25 +115,27 @@ function L({ problem: e, solved: t, onOpen: n }) {
|
|
|
113
115
|
})]
|
|
114
116
|
});
|
|
115
117
|
}
|
|
116
|
-
function
|
|
117
|
-
let o = t(), { currentUser: s, workspaceId: c } = e(), { emit: d } = n(),
|
|
118
|
+
function H() {
|
|
119
|
+
let o = t(), { currentUser: s, workspaceId: c } = e(), { emit: d } = n(), y = r(), C = s?.id, [T, E] = v("ALL"), [k, j] = v("ALL"), [H, de] = v("ALL"), [U, fe] = v(""), [W, pe] = v(() => l(u())), G = g((e) => {
|
|
120
|
+
pe(e), ee(u(), e);
|
|
121
|
+
}, []), me = _(() => [
|
|
118
122
|
{
|
|
119
123
|
value: "ALL",
|
|
120
|
-
label:
|
|
124
|
+
label: y("technospam.problems.filterAll", "All")
|
|
121
125
|
},
|
|
122
126
|
{
|
|
123
127
|
value: "EASY",
|
|
124
|
-
label:
|
|
128
|
+
label: y("technospam.problems.filterEasy", "Easy")
|
|
125
129
|
},
|
|
126
130
|
{
|
|
127
131
|
value: "MEDIUM",
|
|
128
|
-
label:
|
|
132
|
+
label: y("technospam.problems.filterMedium", "Medium")
|
|
129
133
|
},
|
|
130
134
|
{
|
|
131
135
|
value: "HARD",
|
|
132
|
-
label:
|
|
136
|
+
label: y("technospam.problems.filterHard", "Hard")
|
|
133
137
|
}
|
|
134
|
-
], [
|
|
138
|
+
], [y]), he = _(() => [
|
|
135
139
|
{
|
|
136
140
|
value: "google",
|
|
137
141
|
label: "Google"
|
|
@@ -156,7 +160,7 @@ function R() {
|
|
|
156
160
|
value: "netflix",
|
|
157
161
|
label: "Netflix"
|
|
158
162
|
}
|
|
159
|
-
], []),
|
|
163
|
+
], []), ge = _(() => [
|
|
160
164
|
{
|
|
161
165
|
value: "frontend",
|
|
162
166
|
label: "Frontend"
|
|
@@ -181,71 +185,81 @@ function R() {
|
|
|
181
185
|
value: "sre",
|
|
182
186
|
label: "SRE / Infra"
|
|
183
187
|
}
|
|
184
|
-
], []), { limit:
|
|
188
|
+
], []), { limit: _e, more: ve } = ie(), { data: K, loading: q, error: J } = h({
|
|
185
189
|
status: "PUBLISHED",
|
|
186
|
-
pagination:
|
|
187
|
-
...
|
|
188
|
-
...
|
|
189
|
-
...
|
|
190
|
-
}),
|
|
191
|
-
let e =
|
|
192
|
-
return e ?
|
|
193
|
-
}, [
|
|
194
|
-
|
|
190
|
+
pagination: re(_e),
|
|
191
|
+
...T === "ALL" ? {} : { difficulty: T },
|
|
192
|
+
...k === "ALL" ? {} : { company: k },
|
|
193
|
+
...H === "ALL" ? {} : { role: H }
|
|
194
|
+
}), Y = ae(C), X = _(() => K?.tecListProblems?.items ?? [], [K]), Z = K?.tecListProblems?.pageInfo?.hasMore ?? !1, ye = X.filter((e) => Y.has(e.id)).length, be = X.filter((e) => e.difficulty === "EASY").length, xe = X.filter((e) => e.difficulty === "HARD").length, Q = _(() => {
|
|
195
|
+
let e = U.trim().toLowerCase();
|
|
196
|
+
return e ? X.filter((t) => t.title.toLowerCase().includes(e) || (t.topic ?? "").toLowerCase().includes(e) || t.tags.some((t) => t.toLowerCase().includes(e))) : X;
|
|
197
|
+
}, [X, U]), $ = g((e) => {
|
|
198
|
+
d("technospam.problem.viewed", {
|
|
199
|
+
workspaceId: c,
|
|
200
|
+
entityId: e.id,
|
|
201
|
+
entityType: "TEC_PROBLEM"
|
|
202
|
+
}), o(`/applications/problem-details-page?id=${e.id}`);
|
|
203
|
+
}, [
|
|
204
|
+
d,
|
|
205
|
+
o,
|
|
206
|
+
c
|
|
207
|
+
]);
|
|
208
|
+
return /* @__PURE__ */ O(i, {
|
|
195
209
|
hero: !0,
|
|
196
|
-
title:
|
|
197
|
-
description:
|
|
198
|
-
children: [/* @__PURE__ */
|
|
210
|
+
title: y("technospam.problems.title", "Coding Problems"),
|
|
211
|
+
description: y("technospam.problems.description", "Sharpen your problem-solving with hands-on, mentor-judged challenges across topics and difficulty."),
|
|
212
|
+
children: [/* @__PURE__ */ O("div", {
|
|
199
213
|
className: "mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4",
|
|
200
214
|
children: [
|
|
201
|
-
/* @__PURE__ */
|
|
202
|
-
label:
|
|
203
|
-
value:
|
|
204
|
-
icon:
|
|
215
|
+
/* @__PURE__ */ D(a, {
|
|
216
|
+
label: y("technospam.problems.statProblems", "Problems"),
|
|
217
|
+
value: X.length,
|
|
218
|
+
icon: x,
|
|
205
219
|
tone: "blue"
|
|
206
220
|
}),
|
|
207
|
-
/* @__PURE__ */
|
|
208
|
-
label:
|
|
209
|
-
value:
|
|
210
|
-
icon:
|
|
221
|
+
/* @__PURE__ */ D(a, {
|
|
222
|
+
label: y("technospam.problems.statSolved", "Solved"),
|
|
223
|
+
value: ye,
|
|
224
|
+
icon: b,
|
|
211
225
|
tone: "green"
|
|
212
226
|
}),
|
|
213
|
-
/* @__PURE__ */
|
|
214
|
-
label:
|
|
215
|
-
value:
|
|
216
|
-
icon:
|
|
227
|
+
/* @__PURE__ */ D(a, {
|
|
228
|
+
label: y("technospam.problems.statEasy", "Easy"),
|
|
229
|
+
value: be,
|
|
230
|
+
icon: se,
|
|
217
231
|
tone: "teal"
|
|
218
232
|
}),
|
|
219
|
-
/* @__PURE__ */
|
|
220
|
-
label:
|
|
221
|
-
value:
|
|
222
|
-
icon:
|
|
233
|
+
/* @__PURE__ */ D(a, {
|
|
234
|
+
label: y("technospam.problems.statHard", "Hard"),
|
|
235
|
+
value: xe,
|
|
236
|
+
icon: S,
|
|
223
237
|
tone: "amber"
|
|
224
238
|
})
|
|
225
239
|
]
|
|
226
|
-
}), /* @__PURE__ */
|
|
240
|
+
}), /* @__PURE__ */ O(L, {
|
|
227
241
|
className: "gap-0",
|
|
228
|
-
value:
|
|
229
|
-
onValueChange: (e) =>
|
|
242
|
+
value: T,
|
|
243
|
+
onValueChange: (e) => E(e),
|
|
230
244
|
children: [
|
|
231
|
-
/* @__PURE__ */
|
|
245
|
+
/* @__PURE__ */ O("div", {
|
|
232
246
|
className: "mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
|
|
233
|
-
children: [/* @__PURE__ */
|
|
247
|
+
children: [/* @__PURE__ */ D(z, { children: me.map((e) => /* @__PURE__ */ D(B, {
|
|
234
248
|
value: e.value,
|
|
235
249
|
children: e.label
|
|
236
|
-
}, e.value)) }), /* @__PURE__ */
|
|
250
|
+
}, e.value)) }), /* @__PURE__ */ O("div", {
|
|
237
251
|
className: "relative w-full sm:w-72",
|
|
238
|
-
children: [/* @__PURE__ */
|
|
252
|
+
children: [/* @__PURE__ */ D(le, {
|
|
239
253
|
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-text-muted",
|
|
240
254
|
size: 16
|
|
241
|
-
}), /* @__PURE__ */
|
|
255
|
+
}), /* @__PURE__ */ D(ue, {
|
|
242
256
|
className: "pl-9",
|
|
243
|
-
"aria-label":
|
|
244
|
-
placeholder:
|
|
245
|
-
value:
|
|
246
|
-
onChange: (e) =>
|
|
257
|
+
"aria-label": y("technospam.problems.searchLabel", "Search problems"),
|
|
258
|
+
placeholder: y("technospam.problems.searchPlaceholder", "Search problems…"),
|
|
259
|
+
value: U,
|
|
260
|
+
onChange: (e) => fe(e.target.value),
|
|
247
261
|
onBlur: () => {
|
|
248
|
-
let e =
|
|
262
|
+
let e = U.trim();
|
|
249
263
|
e && d("technospam.search.performed", {
|
|
250
264
|
workspaceId: c,
|
|
251
265
|
entityType: "problem",
|
|
@@ -255,72 +269,111 @@ function R() {
|
|
|
255
269
|
})]
|
|
256
270
|
})]
|
|
257
271
|
}),
|
|
258
|
-
/* @__PURE__ */
|
|
272
|
+
/* @__PURE__ */ O("div", {
|
|
259
273
|
className: "mb-4 flex flex-col gap-3 sm:flex-row sm:items-center",
|
|
260
|
-
children: [
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
children:
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
274
|
+
children: [
|
|
275
|
+
/* @__PURE__ */ O(M, {
|
|
276
|
+
value: k,
|
|
277
|
+
onValueChange: j,
|
|
278
|
+
children: [/* @__PURE__ */ D(F, {
|
|
279
|
+
className: "w-full sm:w-48",
|
|
280
|
+
"aria-label": y("technospam.problems.companyFilterLabel", "Filter by company"),
|
|
281
|
+
children: /* @__PURE__ */ D(I, { placeholder: y("technospam.problems.companyPlaceholder", "Company") })
|
|
282
|
+
}), /* @__PURE__ */ O(N, { children: [/* @__PURE__ */ D(P, {
|
|
283
|
+
value: "ALL",
|
|
284
|
+
children: y("technospam.problems.companyAll", "All companies")
|
|
285
|
+
}), he.map((e) => /* @__PURE__ */ D(P, {
|
|
286
|
+
value: e.value,
|
|
287
|
+
children: e.label
|
|
288
|
+
}, e.value))] })]
|
|
289
|
+
}),
|
|
290
|
+
/* @__PURE__ */ O(M, {
|
|
291
|
+
value: H,
|
|
292
|
+
onValueChange: de,
|
|
293
|
+
children: [/* @__PURE__ */ D(F, {
|
|
294
|
+
className: "w-full sm:w-48",
|
|
295
|
+
"aria-label": y("technospam.problems.roleFilterLabel", "Filter by role"),
|
|
296
|
+
children: /* @__PURE__ */ D(I, { placeholder: y("technospam.problems.rolePlaceholder", "Role") })
|
|
297
|
+
}), /* @__PURE__ */ O(N, { children: [/* @__PURE__ */ D(P, {
|
|
298
|
+
value: "ALL",
|
|
299
|
+
children: y("technospam.problems.roleAll", "All roles")
|
|
300
|
+
}), ge.map((e) => /* @__PURE__ */ D(P, {
|
|
301
|
+
value: e.value,
|
|
302
|
+
children: e.label
|
|
303
|
+
}, e.value))] })]
|
|
304
|
+
}),
|
|
305
|
+
/* @__PURE__ */ O("div", {
|
|
306
|
+
role: "group",
|
|
307
|
+
"aria-label": y("technospam.problems.viewLabel", "Catalog layout"),
|
|
308
|
+
className: "inline-flex items-center gap-1 self-start rounded-md border border-border-subtle bg-bg-surface p-1 sm:ml-auto sm:self-auto",
|
|
309
|
+
children: [/* @__PURE__ */ O(A, {
|
|
310
|
+
type: "button",
|
|
311
|
+
size: "sm",
|
|
312
|
+
variant: W === "table" ? "secondary" : "ghost",
|
|
313
|
+
"aria-pressed": W === "table",
|
|
314
|
+
onClick: () => G("table"),
|
|
315
|
+
children: [/* @__PURE__ */ D(ce, {
|
|
316
|
+
size: 14,
|
|
317
|
+
className: "mr-1.5",
|
|
318
|
+
"aria-hidden": "true"
|
|
319
|
+
}), y("technospam.problems.viewTable", "Table")]
|
|
320
|
+
}), /* @__PURE__ */ O(A, {
|
|
321
|
+
type: "button",
|
|
322
|
+
size: "sm",
|
|
323
|
+
variant: W === "cards" ? "secondary" : "ghost",
|
|
324
|
+
"aria-pressed": W === "cards",
|
|
325
|
+
onClick: () => G("cards"),
|
|
326
|
+
children: [/* @__PURE__ */ D(w, {
|
|
327
|
+
size: 14,
|
|
328
|
+
className: "mr-1.5",
|
|
329
|
+
"aria-hidden": "true"
|
|
330
|
+
}), y("technospam.problems.viewCards", "Cards")]
|
|
331
|
+
})]
|
|
332
|
+
})
|
|
333
|
+
]
|
|
289
334
|
}),
|
|
290
|
-
/* @__PURE__ */
|
|
291
|
-
value:
|
|
292
|
-
className:
|
|
293
|
-
children: [
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
},
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
335
|
+
/* @__PURE__ */ O(R, {
|
|
336
|
+
value: T,
|
|
337
|
+
className: oe,
|
|
338
|
+
children: [
|
|
339
|
+
q && !X.length ? /* @__PURE__ */ D(ne, {}) : J ? /* @__PURE__ */ D(m, {
|
|
340
|
+
title: y("technospam.common.errorLoadProblems", "Couldn't load problems"),
|
|
341
|
+
error: J
|
|
342
|
+
}) : Q.length === 0 ? /* @__PURE__ */ D(p, {
|
|
343
|
+
icon: /* @__PURE__ */ D(x, { size: 26 }),
|
|
344
|
+
title: U || T !== "ALL" || k !== "ALL" || H !== "ALL" ? y("technospam.problems.emptySearchTitle", "No matching problems") : y("technospam.problems.emptyDefaultTitle", "No problems published yet"),
|
|
345
|
+
description: U || T !== "ALL" || k !== "ALL" || H !== "ALL" ? y("technospam.problems.emptySearchDesc", "Try a different search, difficulty, company, or role filter.") : y("technospam.problems.emptyDefaultDesc", "Published problems will appear here. Check back soon — TechnoSpam is pre-launch.")
|
|
346
|
+
}) : W === "table" ? /* @__PURE__ */ D(f, {
|
|
347
|
+
problems: Q,
|
|
348
|
+
solvedIds: Y,
|
|
349
|
+
onOpen: $
|
|
350
|
+
}) : /* @__PURE__ */ D("div", {
|
|
351
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
352
|
+
children: Q.map((e) => /* @__PURE__ */ D(V, {
|
|
353
|
+
problem: e,
|
|
354
|
+
solved: Y.has(e.id),
|
|
355
|
+
onOpen: () => $(e)
|
|
356
|
+
}, e.id))
|
|
357
|
+
}),
|
|
358
|
+
Q.length > 0 && !J ? /* @__PURE__ */ D("p", {
|
|
359
|
+
className: "mt-4 text-sm text-text-muted",
|
|
360
|
+
children: Q.length < X.length ? y("technospam.problems.showingFiltered", "Showing {{shown}} of {{total}} loaded problems", {
|
|
361
|
+
shown: Q.length,
|
|
362
|
+
total: X.length
|
|
363
|
+
}) : Z ? y("technospam.problems.showingMore", "Showing 1 to {{count}} problems — load more to see the rest", { count: Q.length }) : y("technospam.problems.showingAll", "Showing all {{count}} problems", { count: Q.length })
|
|
364
|
+
}) : null,
|
|
365
|
+
/* @__PURE__ */ D(te, {
|
|
366
|
+
hasMore: Z,
|
|
367
|
+
loading: q,
|
|
368
|
+
onClick: ve
|
|
369
|
+
})
|
|
370
|
+
]
|
|
318
371
|
})
|
|
319
372
|
]
|
|
320
373
|
})]
|
|
321
374
|
});
|
|
322
375
|
}
|
|
323
376
|
//#endregion
|
|
324
|
-
export {
|
|
377
|
+
export { H as ApplicationsProblemsPagePage };
|
|
325
378
|
|
|
326
379
|
//# sourceMappingURL=ApplicationsProblemsPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApplicationsProblemsPagePage.js","names":[],"sources":["../../../src/technospam/pages/ApplicationsProblemsPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Building2,\n CheckCircle2,\n Code2,\n Flame,\n Gauge,\n Layers,\n Search,\n Tag,\n Trophy,\n} from 'lucide-react';\nimport {\n Badge,\n GlassCard,\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { TAB_PANEL_FOCUS_CLASS } from '../lib/a11y';\nimport {\n EmptyView,\n ErrorView,\n LoadMore,\n LoadingGrid,\n MediaCover,\n PageLayout,\n PremiumBadge,\n StatCard,\n StatusBadge,\n topicIcon,\n} from '../components';\nimport { useTechnoSpam, useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport {\n pageArg,\n usePageLimit,\n useProblemsQuery,\n useSubmissionsQuery,\n type TecProblem,\n type TecProblemDifficulty,\n} from '../api/technospamApi';\nimport { useTechnoSpamAnalytics } from '../hooks/useTechnoSpamAnalytics';\nimport { useTr } from '../hooks/useTr';\n\nfunction ProblemCard({\n problem,\n solved,\n onOpen,\n}: {\n problem: TecProblem;\n solved: boolean;\n onOpen: () => void;\n}) {\n const tr = useTr();\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={`${problem.topic ?? ''} ${problem.difficulty} ${problem.title}`}\n icon={topicIcon(problem.topic ?? problem.title)}\n >\n {solved ? (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[11px] font-medium text-status-success-text ring-1 ring-status-success-border/30\">\n <CheckCircle2 size={12} /> {tr('technospam.problems.solved', 'Solved')}\n </span>\n ) : (\n <span />\n )}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <StatusBadge status={problem.difficulty} kind=\"level\" />\n {problem.isPremiumOnly ? <PremiumBadge locked={problem.isLocked} /> : null}\n </div>\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 {problem.title}\n </h3>\n {problem.statement ? (\n <p className=\"mt-1 line-clamp-2 text-sm text-text-secondary\">{problem.statement}</p>\n ) : null}\n </div>\n <div className=\"mt-auto flex flex-wrap items-center gap-3 text-xs text-text-muted\">\n {problem.topic ? (\n <span className=\"inline-flex items-center gap-1\">\n <Layers size={13} /> {problem.topic}\n </span>\n ) : null}\n <span className=\"inline-flex items-center gap-1\">\n <Trophy size={13} />{' '}\n {tr('technospam.problems.points', '{{count}} pts', { count: problem.points })}\n </span>\n {problem.languages.length ? (\n <span className=\"inline-flex items-center gap-1\">\n <Code2 size={13} />{' '}\n {problem.languages.length === 1\n ? tr('technospam.problems.languages', '{{count}} lang', {\n count: problem.languages.length,\n })\n : tr('technospam.problems.languagesPlural', '{{count}} langs', {\n count: problem.languages.length,\n })}\n </span>\n ) : null}\n </div>\n {problem.companies.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {problem.companies.slice(0, 3).map((c) => (\n <Badge key={c} variant=\"outline\" className=\"text-[11px] capitalize\">\n <Building2 size={10} className=\"mr-1\" />\n {c.replace(/-/g, ' ')}\n </Badge>\n ))}\n {problem.interviewFrequency === 'HIGH' ? (\n <Badge variant=\"secondary\" className=\"text-[11px] text-status-warning-text\">\n <Flame size={10} className=\"mr-1\" />\n {tr('technospam.problems.frequentlyAsked', 'Frequently asked')}\n </Badge>\n ) : null}\n </div>\n ) : null}\n {problem.tags.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {problem.tags.slice(0, 3).map((t) => (\n <Badge key={t} variant=\"secondary\" className=\"text-[11px]\">\n <Tag size={10} className=\"mr-1\" />\n {t}\n </Badge>\n ))}\n </div>\n ) : null}\n </div>\n </GlassCard>\n );\n}\n\nexport function ApplicationsProblemsPagePage() {\n const navigate = useTechnoSpamNavigate();\n const { currentUser, workspaceId } = useTechnoSpam();\n const { emit } = useTechnoSpamAnalytics();\n const tr = useTr();\n const learnerId = currentUser?.id;\n const [difficulty, setDifficulty] = useState<'ALL' | TecProblemDifficulty>('ALL');\n const [company, setCompany] = useState<string>('ALL');\n const [role, setRole] = useState<string>('ALL');\n const [search, setSearch] = useState('');\n\n const difficulties = useMemo(\n () => [\n { value: 'ALL' as const, label: tr('technospam.problems.filterAll', 'All') },\n {\n value: 'EASY' as TecProblemDifficulty,\n label: tr('technospam.problems.filterEasy', 'Easy'),\n },\n {\n value: 'MEDIUM' as TecProblemDifficulty,\n label: tr('technospam.problems.filterMedium', 'Medium'),\n },\n {\n value: 'HARD' as TecProblemDifficulty,\n label: tr('technospam.problems.filterHard', 'Hard'),\n },\n ],\n [tr]\n );\n\n // Curated interview-target lists for the catalog filters. Values follow the\n // backend's lowercase-slug convention (see practice.service.ts normalizeSlug).\n const companies = useMemo(\n () => [\n { value: 'google', label: 'Google' },\n { value: 'amazon', label: 'Amazon' },\n { value: 'meta', label: 'Meta' },\n { value: 'microsoft', label: 'Microsoft' },\n { value: 'apple', label: 'Apple' },\n { value: 'netflix', label: 'Netflix' },\n ],\n []\n );\n\n const roles = useMemo(\n () => [\n { value: 'frontend', label: 'Frontend' },\n { value: 'backend', label: 'Backend' },\n { value: 'fullstack', label: 'Full-Stack' },\n { value: 'data-science', label: 'Data Science' },\n { value: 'mobile', label: 'Mobile' },\n { value: 'sre', label: 'SRE / Infra' },\n ],\n []\n );\n\n const { limit, more } = usePageLimit();\n const { data, loading, error } = useProblemsQuery({\n status: 'PUBLISHED',\n pagination: pageArg(limit),\n ...(difficulty !== 'ALL' ? { difficulty } : {}),\n ...(company !== 'ALL' ? { company } : {}),\n ...(role !== 'ALL' ? { role } : {}),\n });\n const { data: subsData } = useSubmissionsQuery(learnerId ? { learnerId } : {});\n\n const problems = data?.tecListProblems?.items ?? [];\n const hasMore = data?.tecListProblems?.pageInfo?.hasMore ?? false;\n\n const solvedSet = useMemo(\n () =>\n new Set(\n (subsData?.tecListSubmissions?.items ?? [])\n .filter((s) => s.verdict === 'ACCEPTED')\n .map((s) => s.problemId)\n ),\n [subsData]\n );\n\n const solvedCount = problems.filter((p) => solvedSet.has(p.id)).length;\n const easyCount = problems.filter((p) => p.difficulty === 'EASY').length;\n const hardCount = problems.filter((p) => p.difficulty === 'HARD').length;\n\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n if (!q) return problems;\n return problems.filter(\n (p) =>\n p.title.toLowerCase().includes(q) ||\n (p.topic ?? '').toLowerCase().includes(q) ||\n p.tags.some((t) => t.toLowerCase().includes(q))\n );\n }, [problems, search]);\n\n return (\n <PageLayout\n hero\n title={tr('technospam.problems.title', 'Coding Problems')}\n description={tr(\n 'technospam.problems.description',\n 'Sharpen your problem-solving with hands-on, mentor-judged challenges across topics and difficulty.'\n )}\n >\n <div className=\"mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard\n label={tr('technospam.problems.statProblems', 'Problems')}\n value={problems.length}\n icon={Code2}\n tone=\"blue\"\n />\n <StatCard\n label={tr('technospam.problems.statSolved', 'Solved')}\n value={solvedCount}\n icon={CheckCircle2}\n tone=\"green\"\n />\n <StatCard\n label={tr('technospam.problems.statEasy', 'Easy')}\n value={easyCount}\n icon={Gauge}\n tone=\"teal\"\n />\n <StatCard\n label={tr('technospam.problems.statHard', 'Hard')}\n value={hardCount}\n icon={Flame}\n tone=\"amber\"\n />\n </div>\n\n {/* The tabs filter one list, so that list is their tab panel: Radix points every\n trigger's aria-controls at a panel id, and without a TabsContent the id\n resolved to nothing (axe aria-valid-attr-value, critical; BOFF-3157). */}\n <Tabs\n className=\"gap-0\"\n value={difficulty}\n onValueChange={(v) => setDifficulty(v as 'ALL' | TecProblemDifficulty)}\n >\n <div className=\"mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <TabsList>\n {difficulties.map((d) => (\n <TabsTrigger key={d.value} value={d.value}>\n {d.label}\n </TabsTrigger>\n ))}\n </TabsList>\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 aria-label={tr('technospam.problems.searchLabel', 'Search problems')}\n placeholder={tr('technospam.problems.searchPlaceholder', 'Search problems…')}\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: 'problem',\n queryLength: value.length,\n });\n }\n }}\n />\n </div>\n </div>\n\n <div className=\"mb-4 flex flex-col gap-3 sm:flex-row sm:items-center\">\n <Select value={company} onValueChange={setCompany}>\n <SelectTrigger\n className=\"w-full sm:w-48\"\n aria-label={tr('technospam.problems.companyFilterLabel', 'Filter by company')}\n >\n <SelectValue placeholder={tr('technospam.problems.companyPlaceholder', 'Company')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">\n {tr('technospam.problems.companyAll', 'All companies')}\n </SelectItem>\n {companies.map((c) => (\n <SelectItem key={c.value} value={c.value}>\n {c.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select value={role} onValueChange={setRole}>\n <SelectTrigger\n className=\"w-full sm:w-48\"\n aria-label={tr('technospam.problems.roleFilterLabel', 'Filter by role')}\n >\n <SelectValue placeholder={tr('technospam.problems.rolePlaceholder', 'Role')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">{tr('technospam.problems.roleAll', 'All roles')}</SelectItem>\n {roles.map((r) => (\n <SelectItem key={r.value} value={r.value}>\n {r.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <TabsContent value={difficulty} className={TAB_PANEL_FOCUS_CLASS}>\n {loading && !problems.length ? (\n <LoadingGrid />\n ) : error ? (\n <ErrorView\n title={tr('technospam.common.errorLoadProblems', \"Couldn't load problems\")}\n error={error}\n />\n ) : filtered.length === 0 ? (\n <EmptyView\n icon={<Code2 size={26} />}\n title={\n search || difficulty !== 'ALL' || company !== 'ALL' || role !== 'ALL'\n ? tr('technospam.problems.emptySearchTitle', 'No matching problems')\n : tr('technospam.problems.emptyDefaultTitle', 'No problems published yet')\n }\n description={\n search || difficulty !== 'ALL' || company !== 'ALL' || role !== 'ALL'\n ? tr(\n 'technospam.problems.emptySearchDesc',\n 'Try a different search, difficulty, company, or role filter.'\n )\n : tr(\n 'technospam.problems.emptyDefaultDesc',\n 'Published problems will appear here. Check back soon — TechnoSpam is pre-launch.'\n )\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filtered.map((problem) => (\n <ProblemCard\n key={problem.id}\n problem={problem}\n solved={solvedSet.has(problem.id)}\n onOpen={() => {\n emit('technospam.problem.viewed', {\n workspaceId,\n entityId: problem.id,\n entityType: 'TEC_PROBLEM',\n });\n navigate(`/applications/problem-details-page?id=${problem.id}`);\n }}\n />\n ))}\n </div>\n )}\n <LoadMore hasMore={hasMore} loading={loading} onClick={more} />\n </TabsContent>\n </Tabs>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ApplicationsProblemsPagePage.js","names":[],"sources":["../../../src/technospam/pages/ApplicationsProblemsPagePage.tsx"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\nimport {\n Building2,\n CheckCircle2,\n Code2,\n Flame,\n Gauge,\n LayoutGrid,\n Layers,\n List,\n Search,\n Tag,\n Trophy,\n} from 'lucide-react';\nimport {\n Badge,\n Button,\n GlassCard,\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { TAB_PANEL_FOCUS_CLASS } from '../lib/a11y';\nimport {\n EmptyView,\n ErrorView,\n LoadMore,\n LoadingGrid,\n MediaCover,\n PageLayout,\n PremiumBadge,\n ProblemsTable,\n StatCard,\n StatusBadge,\n topicIcon,\n} from '../components';\nimport { useTechnoSpam, useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport {\n pageArg,\n usePageLimit,\n useProblemsQuery,\n useSolvedProblemIds,\n type TecProblem,\n type TecProblemDifficulty,\n} from '../api/technospamApi';\nimport { useTechnoSpamAnalytics } from '../hooks/useTechnoSpamAnalytics';\nimport { useTr } from '../hooks/useTr';\nimport {\n readProblemCatalogView,\n safeLocalStorage,\n writeProblemCatalogView,\n type ProblemCatalogView,\n} from '../utils/problemCatalog';\n\nfunction ProblemCard({\n problem,\n solved,\n onOpen,\n}: {\n problem: TecProblem;\n solved: boolean;\n onOpen: () => void;\n}) {\n const tr = useTr();\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={`${problem.topic ?? ''} ${problem.difficulty} ${problem.title}`}\n icon={topicIcon(problem.topic ?? problem.title)}\n >\n {solved ? (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[11px] font-medium text-status-success-text ring-1 ring-status-success-border/30\">\n <CheckCircle2 size={12} /> {tr('technospam.problems.solved', 'Solved')}\n </span>\n ) : (\n <span />\n )}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <StatusBadge status={problem.difficulty} kind=\"level\" />\n {problem.isPremiumOnly ? <PremiumBadge locked={problem.isLocked} /> : null}\n </div>\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 {problem.title}\n </h3>\n {problem.statement ? (\n <p className=\"mt-1 line-clamp-2 text-sm text-text-secondary\">{problem.statement}</p>\n ) : null}\n </div>\n <div className=\"mt-auto flex flex-wrap items-center gap-3 text-xs text-text-muted\">\n {problem.topic ? (\n <span className=\"inline-flex items-center gap-1\">\n <Layers size={13} /> {problem.topic}\n </span>\n ) : null}\n <span className=\"inline-flex items-center gap-1\">\n <Trophy size={13} />{' '}\n {tr('technospam.problems.points', '{{count}} pts', { count: problem.points })}\n </span>\n {problem.languages.length ? (\n <span className=\"inline-flex items-center gap-1\">\n <Code2 size={13} />{' '}\n {problem.languages.length === 1\n ? tr('technospam.problems.languages', '{{count}} lang', {\n count: problem.languages.length,\n })\n : tr('technospam.problems.languagesPlural', '{{count}} langs', {\n count: problem.languages.length,\n })}\n </span>\n ) : null}\n </div>\n {problem.companies.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {problem.companies.slice(0, 3).map((c) => (\n <Badge key={c} variant=\"outline\" className=\"text-[11px] capitalize\">\n <Building2 size={10} className=\"mr-1\" />\n {c.replace(/-/g, ' ')}\n </Badge>\n ))}\n {problem.interviewFrequency === 'HIGH' ? (\n <Badge variant=\"secondary\" className=\"text-[11px] text-status-warning-text\">\n <Flame size={10} className=\"mr-1\" />\n {tr('technospam.problems.frequentlyAsked', 'Frequently asked')}\n </Badge>\n ) : null}\n </div>\n ) : null}\n {problem.tags.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {problem.tags.slice(0, 3).map((t) => (\n <Badge key={t} variant=\"secondary\" className=\"text-[11px]\">\n <Tag size={10} className=\"mr-1\" />\n {t}\n </Badge>\n ))}\n </div>\n ) : null}\n </div>\n </GlassCard>\n );\n}\n\nexport function ApplicationsProblemsPagePage() {\n const navigate = useTechnoSpamNavigate();\n const { currentUser, workspaceId } = useTechnoSpam();\n const { emit } = useTechnoSpamAnalytics();\n const tr = useTr();\n const learnerId = currentUser?.id;\n const [difficulty, setDifficulty] = useState<'ALL' | TecProblemDifficulty>('ALL');\n const [company, setCompany] = useState<string>('ALL');\n const [role, setRole] = useState<string>('ALL');\n const [search, setSearch] = useState('');\n // The mock's data table is the default layout; the card grid stays available\n // as a compact visual view and the choice is remembered per viewer (BOFF-4077).\n const [view, setView] = useState<ProblemCatalogView>(() =>\n readProblemCatalogView(safeLocalStorage())\n );\n const changeView = useCallback((next: ProblemCatalogView) => {\n setView(next);\n writeProblemCatalogView(safeLocalStorage(), next);\n }, []);\n\n const difficulties = useMemo(\n () => [\n { value: 'ALL' as const, label: tr('technospam.problems.filterAll', 'All') },\n {\n value: 'EASY' as TecProblemDifficulty,\n label: tr('technospam.problems.filterEasy', 'Easy'),\n },\n {\n value: 'MEDIUM' as TecProblemDifficulty,\n label: tr('technospam.problems.filterMedium', 'Medium'),\n },\n {\n value: 'HARD' as TecProblemDifficulty,\n label: tr('technospam.problems.filterHard', 'Hard'),\n },\n ],\n [tr]\n );\n\n // Curated interview-target lists for the catalog filters. Values follow the\n // backend's lowercase-slug convention (see practice.service.ts normalizeSlug).\n const companies = useMemo(\n () => [\n { value: 'google', label: 'Google' },\n { value: 'amazon', label: 'Amazon' },\n { value: 'meta', label: 'Meta' },\n { value: 'microsoft', label: 'Microsoft' },\n { value: 'apple', label: 'Apple' },\n { value: 'netflix', label: 'Netflix' },\n ],\n []\n );\n\n const roles = useMemo(\n () => [\n { value: 'frontend', label: 'Frontend' },\n { value: 'backend', label: 'Backend' },\n { value: 'fullstack', label: 'Full-Stack' },\n { value: 'data-science', label: 'Data Science' },\n { value: 'mobile', label: 'Mobile' },\n { value: 'sre', label: 'SRE / Infra' },\n ],\n []\n );\n\n const { limit, more } = usePageLimit();\n const { data, loading, error } = useProblemsQuery({\n status: 'PUBLISHED',\n pagination: pageArg(limit),\n ...(difficulty !== 'ALL' ? { difficulty } : {}),\n ...(company !== 'ALL' ? { company } : {}),\n ...(role !== 'ALL' ? { role } : {}),\n });\n const solvedSet = useSolvedProblemIds(learnerId);\n\n const problems = useMemo(() => data?.tecListProblems?.items ?? [], [data]);\n const hasMore = data?.tecListProblems?.pageInfo?.hasMore ?? false;\n\n const solvedCount = problems.filter((p) => solvedSet.has(p.id)).length;\n const easyCount = problems.filter((p) => p.difficulty === 'EASY').length;\n const hardCount = problems.filter((p) => p.difficulty === 'HARD').length;\n\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n if (!q) return problems;\n return problems.filter(\n (p) =>\n p.title.toLowerCase().includes(q) ||\n (p.topic ?? '').toLowerCase().includes(q) ||\n p.tags.some((t) => t.toLowerCase().includes(q))\n );\n }, [problems, search]);\n\n const openProblem = useCallback(\n (problem: TecProblem) => {\n emit('technospam.problem.viewed', {\n workspaceId,\n entityId: problem.id,\n entityType: 'TEC_PROBLEM',\n });\n navigate(`/applications/problem-details-page?id=${problem.id}`);\n },\n [emit, navigate, workspaceId]\n );\n\n return (\n <PageLayout\n hero\n title={tr('technospam.problems.title', 'Coding Problems')}\n description={tr(\n 'technospam.problems.description',\n 'Sharpen your problem-solving with hands-on, mentor-judged challenges across topics and difficulty.'\n )}\n >\n <div className=\"mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard\n label={tr('technospam.problems.statProblems', 'Problems')}\n value={problems.length}\n icon={Code2}\n tone=\"blue\"\n />\n <StatCard\n label={tr('technospam.problems.statSolved', 'Solved')}\n value={solvedCount}\n icon={CheckCircle2}\n tone=\"green\"\n />\n <StatCard\n label={tr('technospam.problems.statEasy', 'Easy')}\n value={easyCount}\n icon={Gauge}\n tone=\"teal\"\n />\n <StatCard\n label={tr('technospam.problems.statHard', 'Hard')}\n value={hardCount}\n icon={Flame}\n tone=\"amber\"\n />\n </div>\n\n {/* The tabs filter one list, so that list is their tab panel: Radix points every\n trigger's aria-controls at a panel id, and without a TabsContent the id\n resolved to nothing (axe aria-valid-attr-value, critical; BOFF-3157). */}\n <Tabs\n className=\"gap-0\"\n value={difficulty}\n onValueChange={(v) => setDifficulty(v as 'ALL' | TecProblemDifficulty)}\n >\n <div className=\"mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <TabsList>\n {difficulties.map((d) => (\n <TabsTrigger key={d.value} value={d.value}>\n {d.label}\n </TabsTrigger>\n ))}\n </TabsList>\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 aria-label={tr('technospam.problems.searchLabel', 'Search problems')}\n placeholder={tr('technospam.problems.searchPlaceholder', 'Search problems…')}\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: 'problem',\n queryLength: value.length,\n });\n }\n }}\n />\n </div>\n </div>\n\n <div className=\"mb-4 flex flex-col gap-3 sm:flex-row sm:items-center\">\n <Select value={company} onValueChange={setCompany}>\n <SelectTrigger\n className=\"w-full sm:w-48\"\n aria-label={tr('technospam.problems.companyFilterLabel', 'Filter by company')}\n >\n <SelectValue placeholder={tr('technospam.problems.companyPlaceholder', 'Company')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">\n {tr('technospam.problems.companyAll', 'All companies')}\n </SelectItem>\n {companies.map((c) => (\n <SelectItem key={c.value} value={c.value}>\n {c.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select value={role} onValueChange={setRole}>\n <SelectTrigger\n className=\"w-full sm:w-48\"\n aria-label={tr('technospam.problems.roleFilterLabel', 'Filter by role')}\n >\n <SelectValue placeholder={tr('technospam.problems.rolePlaceholder', 'Role')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">{tr('technospam.problems.roleAll', 'All roles')}</SelectItem>\n {roles.map((r) => (\n <SelectItem key={r.value} value={r.value}>\n {r.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <div\n role=\"group\"\n aria-label={tr('technospam.problems.viewLabel', 'Catalog layout')}\n className=\"inline-flex items-center gap-1 self-start rounded-md border border-border-subtle bg-bg-surface p-1 sm:ml-auto sm:self-auto\"\n >\n <Button\n type=\"button\"\n size=\"sm\"\n variant={view === 'table' ? 'secondary' : 'ghost'}\n aria-pressed={view === 'table'}\n onClick={() => changeView('table')}\n >\n <List size={14} className=\"mr-1.5\" aria-hidden=\"true\" />\n {tr('technospam.problems.viewTable', 'Table')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant={view === 'cards' ? 'secondary' : 'ghost'}\n aria-pressed={view === 'cards'}\n onClick={() => changeView('cards')}\n >\n <LayoutGrid size={14} className=\"mr-1.5\" aria-hidden=\"true\" />\n {tr('technospam.problems.viewCards', 'Cards')}\n </Button>\n </div>\n </div>\n\n <TabsContent value={difficulty} className={TAB_PANEL_FOCUS_CLASS}>\n {loading && !problems.length ? (\n <LoadingGrid />\n ) : error ? (\n <ErrorView\n title={tr('technospam.common.errorLoadProblems', \"Couldn't load problems\")}\n error={error}\n />\n ) : filtered.length === 0 ? (\n <EmptyView\n icon={<Code2 size={26} />}\n title={\n search || difficulty !== 'ALL' || company !== 'ALL' || role !== 'ALL'\n ? tr('technospam.problems.emptySearchTitle', 'No matching problems')\n : tr('technospam.problems.emptyDefaultTitle', 'No problems published yet')\n }\n description={\n search || difficulty !== 'ALL' || company !== 'ALL' || role !== 'ALL'\n ? tr(\n 'technospam.problems.emptySearchDesc',\n 'Try a different search, difficulty, company, or role filter.'\n )\n : tr(\n 'technospam.problems.emptyDefaultDesc',\n 'Published problems will appear here. Check back soon — TechnoSpam is pre-launch.'\n )\n }\n />\n ) : view === 'table' ? (\n <ProblemsTable problems={filtered} solvedIds={solvedSet} onOpen={openProblem} />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filtered.map((problem) => (\n <ProblemCard\n key={problem.id}\n problem={problem}\n solved={solvedSet.has(problem.id)}\n onOpen={() => openProblem(problem)}\n />\n ))}\n </div>\n )}\n {filtered.length > 0 && !error ? (\n <p className=\"mt-4 text-sm text-text-muted\">\n {filtered.length < problems.length\n ? tr(\n 'technospam.problems.showingFiltered',\n 'Showing {{shown}} of {{total}} loaded problems',\n { shown: filtered.length, total: problems.length }\n )\n : hasMore\n ? tr(\n 'technospam.problems.showingMore',\n 'Showing 1 to {{count}} problems — load more to see the rest',\n { count: filtered.length }\n )\n : tr('technospam.problems.showingAll', 'Showing all {{count}} problems', {\n count: filtered.length,\n })}\n </p>\n ) : null}\n <LoadMore hasMore={hasMore} loading={loading} onClick={more} />\n </TabsContent>\n </Tabs>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|