@burdenoff/microfe-technospam 2026.830.1 → 2026.1024.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApplicationsProblemDetailsPagePage.d.ts","sourceRoot":"","sources":["../../../src/technospam/pages/ApplicationsProblemDetailsPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ApplicationsProblemDetailsPagePage.d.ts","sourceRoot":"","sources":["../../../src/technospam/pages/ApplicationsProblemDetailsPagePage.tsx"],"names":[],"mappings":"AAuFA,wBAAgB,kCAAkC,gCA0XjD"}
|
|
@@ -4,63 +4,63 @@ import { PageLayout as n } from "../components/PageLayout.js";
|
|
|
4
4
|
import { StatCard as r } from "../components/StatCard.js";
|
|
5
5
|
import { formatDateTime as i, humanizeEnum as a } from "../utils/format.js";
|
|
6
6
|
import { StatusBadge as o } from "../components/StatusBadge.js";
|
|
7
|
-
import { EmptyView as s, ErrorView as c, LoadingRows as
|
|
8
|
-
import { TagStrip as
|
|
9
|
-
import { PremiumBadge as
|
|
10
|
-
import { CodePanel as
|
|
7
|
+
import { EmptyView as s, ErrorView as c, LoadingRows as ee } from "../components/StateViews.js";
|
|
8
|
+
import { TagStrip as te } from "../components/TagStrip.js";
|
|
9
|
+
import { PremiumBadge as ne, UpgradeGate as l } from "../components/UpgradeGate.js";
|
|
10
|
+
import { CodePanel as re, IoBlock as u, TestResultsPanel as ie } from "../components/SubmissionViews.js";
|
|
11
11
|
import "../components/index.js";
|
|
12
|
-
import { notify as
|
|
13
|
-
import { useProblemQuery as
|
|
14
|
-
import { useEffect as
|
|
15
|
-
import { Clock as
|
|
16
|
-
import { useSearchParams as
|
|
17
|
-
import { jsx as
|
|
18
|
-
import { Badge as
|
|
12
|
+
import { notify as d } from "../lib/toast.js";
|
|
13
|
+
import { useProblemQuery as ae, useRegradeSubmission as oe, useSubmissionsQuery as se, useSubmitSolution as ce } from "../api/technospamApi.js";
|
|
14
|
+
import { useEffect as f, useMemo as p, useRef as m, useState as h } from "react";
|
|
15
|
+
import { Clock as g, Code2 as _, FileText as v, FlaskConical as le, Layers as y, RefreshCw as b, Send as ue, Trophy as x } from "lucide-react";
|
|
16
|
+
import { useSearchParams as S } from "react-router";
|
|
17
|
+
import { jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
18
|
+
import { Badge as de, Button as T, GlassCard as E, Select as fe, SelectContent as pe, SelectItem as me, SelectTrigger as he, SelectValue as ge, Skeleton as D, Textarea as _e } from "@burdenoff/fe-libs/ui";
|
|
19
19
|
//#region src/technospam/pages/ApplicationsProblemDetailsPagePage.tsx
|
|
20
|
-
var
|
|
20
|
+
var O = [
|
|
21
21
|
"javascript",
|
|
22
22
|
"python",
|
|
23
23
|
"typescript"
|
|
24
|
-
];
|
|
25
|
-
function
|
|
26
|
-
return /* @__PURE__ */
|
|
24
|
+
], ve = 3e3, ye = 3 * 6e4;
|
|
25
|
+
function be({ s: e }) {
|
|
26
|
+
return /* @__PURE__ */ w("div", {
|
|
27
27
|
className: "rounded-lg border border-transparent px-2 py-3 transition-colors hover:border-border-seam hover:bg-bg-sunken",
|
|
28
|
-
children: [/* @__PURE__ */
|
|
28
|
+
children: [/* @__PURE__ */ w("div", {
|
|
29
29
|
className: "flex flex-wrap items-center gap-x-4 gap-y-1",
|
|
30
30
|
children: [
|
|
31
|
-
/* @__PURE__ */
|
|
32
|
-
/* @__PURE__ */
|
|
31
|
+
/* @__PURE__ */ C(o, { status: e.verdict }),
|
|
32
|
+
/* @__PURE__ */ w("span", {
|
|
33
33
|
className: "inline-flex items-center gap-1 text-sm font-medium text-text-primary",
|
|
34
34
|
children: [
|
|
35
|
-
/* @__PURE__ */
|
|
35
|
+
/* @__PURE__ */ C(_, { size: 13 }),
|
|
36
36
|
" ",
|
|
37
37
|
a(e.language)
|
|
38
38
|
]
|
|
39
39
|
}),
|
|
40
|
-
/* @__PURE__ */
|
|
40
|
+
/* @__PURE__ */ w("span", {
|
|
41
41
|
className: "inline-flex items-center gap-1 text-xs text-text-muted",
|
|
42
42
|
children: [
|
|
43
|
-
/* @__PURE__ */
|
|
43
|
+
/* @__PURE__ */ C(g, { size: 12 }),
|
|
44
44
|
" ",
|
|
45
45
|
e.runtimeMs,
|
|
46
46
|
" ms"
|
|
47
47
|
]
|
|
48
48
|
}),
|
|
49
|
-
/* @__PURE__ */
|
|
49
|
+
/* @__PURE__ */ w("span", {
|
|
50
50
|
className: "inline-flex items-center gap-1 text-xs text-text-muted",
|
|
51
51
|
children: [
|
|
52
|
-
/* @__PURE__ */
|
|
52
|
+
/* @__PURE__ */ C(x, { size: 12 }),
|
|
53
53
|
" ",
|
|
54
54
|
e.pointsAwarded,
|
|
55
55
|
" pts"
|
|
56
56
|
]
|
|
57
57
|
}),
|
|
58
|
-
/* @__PURE__ */
|
|
58
|
+
/* @__PURE__ */ C("span", {
|
|
59
59
|
className: "ml-auto text-xs text-text-muted",
|
|
60
60
|
children: i(e.createdAt)
|
|
61
61
|
})
|
|
62
62
|
]
|
|
63
|
-
}), e.totalCount > 0 ? /* @__PURE__ */
|
|
63
|
+
}), e.totalCount > 0 ? /* @__PURE__ */ w("p", {
|
|
64
64
|
className: "mt-1 px-0.5 text-xs text-text-muted",
|
|
65
65
|
children: [
|
|
66
66
|
"Passed ",
|
|
@@ -72,267 +72,296 @@ function ge({ s: e }) {
|
|
|
72
72
|
}) : null]
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
|
-
function
|
|
76
|
-
let [i] =
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
workspaceId:
|
|
80
|
-
entityId:
|
|
75
|
+
function k() {
|
|
76
|
+
let [i] = S(), k = i.get("id") ?? "", { currentUser: xe, workspaceId: A } = e(), j = xe?.id, { emit: M } = t(), { data: Se, loading: N, error: P, refetch: F } = ae(k);
|
|
77
|
+
f(() => {
|
|
78
|
+
k && M("technospam.problem.viewed", {
|
|
79
|
+
workspaceId: A,
|
|
80
|
+
entityId: k,
|
|
81
81
|
entityType: "TEC_PROBLEM"
|
|
82
82
|
});
|
|
83
83
|
}, [
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
k,
|
|
85
|
+
A,
|
|
86
|
+
M
|
|
87
87
|
]);
|
|
88
|
-
let { data:
|
|
89
|
-
...
|
|
90
|
-
problemId:
|
|
91
|
-
}), [
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}, [
|
|
95
|
-
let
|
|
96
|
-
if (!
|
|
97
|
-
if (!
|
|
98
|
-
|
|
88
|
+
let { data: I, loading: Ce, error: L, refetch: R } = se({
|
|
89
|
+
...j ? { learnerId: j } : {},
|
|
90
|
+
problemId: k
|
|
91
|
+
}), [we, { loading: z }] = ce(), [Te, { loading: B }] = oe(), V = Se?.tecProblem ?? null, H = p(() => V?.languages?.length ? V.languages : O, [V]), [U, W] = h(""), [G, K] = h(""), q = m(!1);
|
|
92
|
+
f(() => {
|
|
93
|
+
V && !q.current && (W(V.languages[0] ?? O[0]), K(V.starterCode ?? ""), q.current = !0);
|
|
94
|
+
}, [V]);
|
|
95
|
+
let J = p(() => [...I?.tecListSubmissions?.items ?? []].sort((e, t) => new Date(t.createdAt).getTime() - new Date(e.createdAt).getTime()), [I]), Ee = async () => {
|
|
96
|
+
if (!k) return;
|
|
97
|
+
if (!U) {
|
|
98
|
+
d.error("Pick a language", "Choose a language before submitting.");
|
|
99
99
|
return;
|
|
100
100
|
}
|
|
101
|
-
if (!
|
|
102
|
-
|
|
101
|
+
if (!G.trim()) {
|
|
102
|
+
d.error("Add your solution", "Write some code before submitting.");
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
105
|
-
|
|
106
|
-
workspaceId:
|
|
107
|
-
entityId:
|
|
105
|
+
M("technospam.problem.submit_clicked", {
|
|
106
|
+
workspaceId: A,
|
|
107
|
+
entityId: k,
|
|
108
108
|
entityType: "TEC_PROBLEM",
|
|
109
|
-
language:
|
|
109
|
+
language: U
|
|
110
110
|
});
|
|
111
|
-
let e = await
|
|
112
|
-
problemId:
|
|
113
|
-
language:
|
|
114
|
-
code:
|
|
111
|
+
let e = await we({ variables: { input: {
|
|
112
|
+
problemId: k,
|
|
113
|
+
language: U,
|
|
114
|
+
code: G
|
|
115
115
|
} } });
|
|
116
116
|
if (e.data?.tecSubmitSolution) {
|
|
117
|
-
|
|
118
|
-
workspaceId:
|
|
119
|
-
entityId:
|
|
117
|
+
M("technospam.problem.submitted", {
|
|
118
|
+
workspaceId: A,
|
|
119
|
+
entityId: k,
|
|
120
120
|
entityType: "TEC_PROBLEM",
|
|
121
121
|
submissionId: e.data.tecSubmitSolution.id
|
|
122
122
|
});
|
|
123
123
|
let t = e.data.tecSubmitSolution;
|
|
124
|
-
t.verdict === "PENDING" ?
|
|
124
|
+
t.verdict === "PENDING" ? d.info("Solution submitted", "Grading has started — your verdict will appear here in a moment.") : t.verdict === "ACCEPTED" ? d.success("Accepted", `Passed all ${t.totalCount} test cases.`) : d.error(a(t.verdict), `Passed ${t.passedCount} of ${t.totalCount} test cases.`), await Promise.all([F(), R()]);
|
|
125
|
+
}
|
|
126
|
+
}, De = async (e) => {
|
|
127
|
+
let t = (await Te({ variables: { id: e } })).data?.tecRegradeSubmission;
|
|
128
|
+
t && (t.verdict === "PENDING" ? d.error("Still pending", "The grader is not available yet. Please try again shortly.") : d.success("Grading complete", `Verdict: ${a(t.verdict)}.`), await Promise.all([F(), R()]));
|
|
129
|
+
}, Y = J.find((e) => (e.testResults?.length ?? 0) > 0) ?? null, X = J[0] ?? null, Z = X?.verdict === "PENDING" ? X.id : null, [Q, Oe] = h(null), ke = Z !== null && Q !== Z;
|
|
130
|
+
f(() => {
|
|
131
|
+
if (!Z || Q === Z) return;
|
|
132
|
+
let e = Date.now(), t = window.setInterval(() => {
|
|
133
|
+
if (Date.now() - e > ye) {
|
|
134
|
+
window.clearInterval(t), Oe(Z);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
R();
|
|
138
|
+
}, ve);
|
|
139
|
+
return () => window.clearInterval(t);
|
|
140
|
+
}, [
|
|
141
|
+
Z,
|
|
142
|
+
Q,
|
|
143
|
+
R
|
|
144
|
+
]);
|
|
145
|
+
let $ = m(null);
|
|
146
|
+
return f(() => {
|
|
147
|
+
if (Z) {
|
|
148
|
+
$.current = Z;
|
|
149
|
+
return;
|
|
125
150
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
151
|
+
let e = $.current;
|
|
152
|
+
if (!e) return;
|
|
153
|
+
let t = J.find((t) => t.id === e);
|
|
154
|
+
!t || t.verdict === "PENDING" || ($.current = null, t.verdict === "ACCEPTED" ? d.success("Accepted", `Passed all ${t.totalCount} test cases.`) : d.error(a(t.verdict), `Passed ${t.passedCount} of ${t.totalCount} test cases.`), F());
|
|
155
|
+
}, [
|
|
156
|
+
Z,
|
|
157
|
+
J,
|
|
158
|
+
F
|
|
159
|
+
]), N && !V ? /* @__PURE__ */ w(n, {
|
|
131
160
|
title: "Problem",
|
|
132
161
|
backPath: "/applications/problems-page",
|
|
133
|
-
children: [/* @__PURE__ */
|
|
134
|
-
}) :
|
|
162
|
+
children: [/* @__PURE__ */ C(D, { className: "mb-4 h-28 w-full rounded-xl" }), /* @__PURE__ */ C(D, { className: "h-72 w-full rounded-xl" })]
|
|
163
|
+
}) : P || !V ? /* @__PURE__ */ C(n, {
|
|
135
164
|
title: "Problem",
|
|
136
165
|
backPath: "/applications/problems-page",
|
|
137
|
-
children:
|
|
166
|
+
children: P ? /* @__PURE__ */ C(c, {
|
|
138
167
|
title: "Couldn't load problem",
|
|
139
|
-
error:
|
|
140
|
-
}) : /* @__PURE__ */
|
|
168
|
+
error: P
|
|
169
|
+
}) : /* @__PURE__ */ C(s, {
|
|
141
170
|
title: "Problem not found",
|
|
142
171
|
description: "This problem may have been unpublished."
|
|
143
172
|
})
|
|
144
|
-
}) : /* @__PURE__ */
|
|
173
|
+
}) : /* @__PURE__ */ w(n, {
|
|
145
174
|
hero: !0,
|
|
146
175
|
backPath: "/applications/problems-page",
|
|
147
|
-
title:
|
|
148
|
-
description:
|
|
176
|
+
title: V.title,
|
|
177
|
+
description: V.topic ?? void 0,
|
|
149
178
|
children: [
|
|
150
|
-
/* @__PURE__ */
|
|
179
|
+
/* @__PURE__ */ w("div", {
|
|
151
180
|
className: "mb-5 flex flex-wrap items-center gap-2",
|
|
152
181
|
children: [
|
|
153
|
-
/* @__PURE__ */
|
|
154
|
-
status:
|
|
182
|
+
/* @__PURE__ */ C(o, {
|
|
183
|
+
status: V.difficulty,
|
|
155
184
|
kind: "level"
|
|
156
185
|
}),
|
|
157
|
-
/* @__PURE__ */
|
|
158
|
-
|
|
186
|
+
/* @__PURE__ */ C(o, { status: V.status }),
|
|
187
|
+
V.topic ? /* @__PURE__ */ w(de, {
|
|
159
188
|
variant: "outline",
|
|
160
189
|
className: "gap-1",
|
|
161
190
|
children: [
|
|
162
|
-
/* @__PURE__ */
|
|
191
|
+
/* @__PURE__ */ C(y, { size: 12 }),
|
|
163
192
|
" ",
|
|
164
|
-
|
|
193
|
+
V.topic
|
|
165
194
|
]
|
|
166
195
|
}) : null,
|
|
167
|
-
|
|
168
|
-
/* @__PURE__ */
|
|
196
|
+
V.isPremiumOnly ? /* @__PURE__ */ C(ne, { locked: V.isLocked }) : null,
|
|
197
|
+
/* @__PURE__ */ C(te, { tags: V.tags })
|
|
169
198
|
]
|
|
170
199
|
}),
|
|
171
|
-
/* @__PURE__ */
|
|
200
|
+
/* @__PURE__ */ w("div", {
|
|
172
201
|
className: "mb-6 grid grid-cols-2 gap-3 sm:grid-cols-4",
|
|
173
202
|
children: [
|
|
174
|
-
/* @__PURE__ */
|
|
203
|
+
/* @__PURE__ */ C(r, {
|
|
175
204
|
label: "Points",
|
|
176
|
-
value:
|
|
177
|
-
icon:
|
|
205
|
+
value: V.points,
|
|
206
|
+
icon: x,
|
|
178
207
|
tone: "amber"
|
|
179
208
|
}),
|
|
180
|
-
/* @__PURE__ */
|
|
209
|
+
/* @__PURE__ */ C(r, {
|
|
181
210
|
label: "Languages",
|
|
182
|
-
value:
|
|
183
|
-
icon:
|
|
211
|
+
value: H.length,
|
|
212
|
+
icon: _,
|
|
184
213
|
tone: "blue"
|
|
185
214
|
}),
|
|
186
|
-
/* @__PURE__ */
|
|
215
|
+
/* @__PURE__ */ C(r, {
|
|
187
216
|
label: "Difficulty",
|
|
188
|
-
value: a(
|
|
189
|
-
icon:
|
|
217
|
+
value: a(V.difficulty),
|
|
218
|
+
icon: y,
|
|
190
219
|
tone: "purple"
|
|
191
220
|
}),
|
|
192
|
-
/* @__PURE__ */
|
|
221
|
+
/* @__PURE__ */ C(r, {
|
|
193
222
|
label: "My submissions",
|
|
194
|
-
value:
|
|
195
|
-
icon:
|
|
223
|
+
value: J.length,
|
|
224
|
+
icon: v,
|
|
196
225
|
tone: "teal"
|
|
197
226
|
})
|
|
198
227
|
]
|
|
199
228
|
}),
|
|
200
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ w("div", {
|
|
201
230
|
className: "grid grid-cols-1 gap-5 lg:grid-cols-3",
|
|
202
|
-
children: [/* @__PURE__ */
|
|
231
|
+
children: [/* @__PURE__ */ w("div", {
|
|
203
232
|
className: "space-y-5 lg:col-span-2",
|
|
204
233
|
children: [
|
|
205
|
-
/* @__PURE__ */ E
|
|
234
|
+
/* @__PURE__ */ w(E, {
|
|
206
235
|
className: "p-5",
|
|
207
|
-
children: [/* @__PURE__ */
|
|
236
|
+
children: [/* @__PURE__ */ C("h2", {
|
|
208
237
|
className: "mb-2 text-base font-semibold text-text-primary",
|
|
209
238
|
children: "Problem statement"
|
|
210
|
-
}),
|
|
239
|
+
}), V.isLocked ? /* @__PURE__ */ C(l, { description: "This problem's statement is part of a paid TechnoSpam plan. Ask a workspace admin to upgrade to unlock it." }) : V.statement ? /* @__PURE__ */ C("p", {
|
|
211
240
|
className: "whitespace-pre-wrap text-sm leading-relaxed text-text-secondary",
|
|
212
|
-
children:
|
|
213
|
-
}) : /* @__PURE__ */
|
|
241
|
+
children: V.statement
|
|
242
|
+
}) : /* @__PURE__ */ C("p", {
|
|
214
243
|
className: "py-4 text-center text-sm text-text-muted",
|
|
215
244
|
children: "The statement for this problem is being prepared."
|
|
216
245
|
})]
|
|
217
246
|
}),
|
|
218
|
-
|
|
247
|
+
V.isLocked ? /* @__PURE__ */ C(l, {
|
|
219
248
|
compact: !0,
|
|
220
249
|
description: "Starter code and sample test cases unlock with a paid TechnoSpam plan."
|
|
221
|
-
}) :
|
|
250
|
+
}) : V.starterCode ? /* @__PURE__ */ w(E, {
|
|
222
251
|
className: "p-5",
|
|
223
|
-
children: [/* @__PURE__ */
|
|
252
|
+
children: [/* @__PURE__ */ C("h2", {
|
|
224
253
|
className: "mb-3 text-base font-semibold text-text-primary",
|
|
225
254
|
children: "Starter code"
|
|
226
|
-
}), /* @__PURE__ */
|
|
227
|
-
label: a(
|
|
255
|
+
}), /* @__PURE__ */ C(re, {
|
|
256
|
+
label: a(H[0] ?? "code"),
|
|
228
257
|
bodyClassName: "max-h-72",
|
|
229
|
-
children:
|
|
258
|
+
children: V.starterCode
|
|
230
259
|
})]
|
|
231
260
|
}) : null,
|
|
232
|
-
/* @__PURE__ */ E
|
|
261
|
+
/* @__PURE__ */ w(E, {
|
|
233
262
|
className: "p-5",
|
|
234
263
|
children: [
|
|
235
|
-
/* @__PURE__ */
|
|
264
|
+
/* @__PURE__ */ w("div", {
|
|
236
265
|
className: "mb-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",
|
|
237
|
-
children: [/* @__PURE__ */
|
|
266
|
+
children: [/* @__PURE__ */ C("h2", {
|
|
238
267
|
className: "text-base font-semibold text-text-primary",
|
|
239
268
|
children: "Submit a solution"
|
|
240
|
-
}), /* @__PURE__ */
|
|
269
|
+
}), /* @__PURE__ */ w("div", {
|
|
241
270
|
className: "flex items-center gap-2",
|
|
242
|
-
children: [/* @__PURE__ */
|
|
271
|
+
children: [/* @__PURE__ */ C("span", {
|
|
243
272
|
className: "text-sm text-text-secondary",
|
|
244
273
|
children: "Language"
|
|
245
|
-
}), /* @__PURE__ */
|
|
246
|
-
value:
|
|
247
|
-
onValueChange:
|
|
248
|
-
children: [/* @__PURE__ */
|
|
274
|
+
}), /* @__PURE__ */ w(fe, {
|
|
275
|
+
value: U,
|
|
276
|
+
onValueChange: W,
|
|
277
|
+
children: [/* @__PURE__ */ C(he, {
|
|
249
278
|
className: "w-full sm:w-48",
|
|
250
|
-
children: /* @__PURE__ */
|
|
251
|
-
}), /* @__PURE__ */
|
|
279
|
+
children: /* @__PURE__ */ C(ge, { placeholder: "Choose a language" })
|
|
280
|
+
}), /* @__PURE__ */ C(pe, { children: H.map((e) => /* @__PURE__ */ C(me, {
|
|
252
281
|
value: e,
|
|
253
282
|
children: a(e)
|
|
254
283
|
}, e)) })]
|
|
255
284
|
})]
|
|
256
285
|
})]
|
|
257
286
|
}),
|
|
258
|
-
/* @__PURE__ */
|
|
287
|
+
/* @__PURE__ */ w("div", {
|
|
259
288
|
className: "overflow-hidden rounded-xl border border-border-strong bg-bg-sunken shadow-sm",
|
|
260
|
-
children: [/* @__PURE__ */
|
|
289
|
+
children: [/* @__PURE__ */ w("div", {
|
|
261
290
|
className: "flex items-center justify-between gap-2 border-b border-border-seam bg-bg-canvas/40 px-4 py-2",
|
|
262
|
-
children: [/* @__PURE__ */
|
|
291
|
+
children: [/* @__PURE__ */ w("div", {
|
|
263
292
|
className: "flex items-center gap-1.5",
|
|
264
293
|
children: [
|
|
265
|
-
/* @__PURE__ */
|
|
266
|
-
/* @__PURE__ */
|
|
267
|
-
/* @__PURE__ */
|
|
294
|
+
/* @__PURE__ */ C("span", { className: "h-2.5 w-2.5 rounded-full bg-status-error-border" }),
|
|
295
|
+
/* @__PURE__ */ C("span", { className: "h-2.5 w-2.5 rounded-full bg-status-warning-border" }),
|
|
296
|
+
/* @__PURE__ */ C("span", { className: "h-2.5 w-2.5 rounded-full bg-status-success-border" })
|
|
268
297
|
]
|
|
269
|
-
}), /* @__PURE__ */
|
|
298
|
+
}), /* @__PURE__ */ w("span", {
|
|
270
299
|
className: "inline-flex items-center gap-1.5 font-mono text-xs text-text-muted",
|
|
271
300
|
children: [
|
|
272
|
-
/* @__PURE__ */
|
|
301
|
+
/* @__PURE__ */ C(_, { size: 13 }),
|
|
273
302
|
" ",
|
|
274
|
-
|
|
303
|
+
U ? a(U) : "solution"
|
|
275
304
|
]
|
|
276
305
|
})]
|
|
277
|
-
}), /* @__PURE__ */
|
|
278
|
-
value:
|
|
279
|
-
onChange: (e) =>
|
|
306
|
+
}), /* @__PURE__ */ C(_e, {
|
|
307
|
+
value: G,
|
|
308
|
+
onChange: (e) => K(e.target.value),
|
|
280
309
|
placeholder: "Write your solution…",
|
|
281
310
|
className: "min-h-[280px] resize-y rounded-none border-0 bg-transparent font-mono text-xs leading-relaxed focus-visible:ring-0 focus-visible:ring-offset-0",
|
|
282
311
|
spellCheck: !1
|
|
283
312
|
})]
|
|
284
313
|
}),
|
|
285
|
-
/* @__PURE__ */
|
|
314
|
+
/* @__PURE__ */ w(T, {
|
|
286
315
|
className: "mt-4 w-full",
|
|
287
|
-
onClick:
|
|
288
|
-
disabled:
|
|
316
|
+
onClick: Ee,
|
|
317
|
+
disabled: z || !G.trim(),
|
|
289
318
|
children: [
|
|
290
|
-
/* @__PURE__ */
|
|
319
|
+
/* @__PURE__ */ C(ue, { size: 16 }),
|
|
291
320
|
" ",
|
|
292
|
-
|
|
321
|
+
z ? "Running test cases…" : "Run & submit"
|
|
293
322
|
]
|
|
294
323
|
}),
|
|
295
|
-
/* @__PURE__ */
|
|
324
|
+
/* @__PURE__ */ C("p", {
|
|
296
325
|
className: "mt-2 text-center text-xs text-text-muted",
|
|
297
326
|
children: "Your code runs against this problem's test cases in an isolated sandbox."
|
|
298
327
|
})
|
|
299
328
|
]
|
|
300
329
|
}),
|
|
301
|
-
|
|
330
|
+
V.publicTestCases?.length ? /* @__PURE__ */ w(E, {
|
|
302
331
|
className: "p-5",
|
|
303
332
|
children: [
|
|
304
|
-
/* @__PURE__ */
|
|
333
|
+
/* @__PURE__ */ w("h2", {
|
|
305
334
|
className: "mb-1 flex items-center gap-2 text-base font-semibold text-text-primary",
|
|
306
|
-
children: [/* @__PURE__ */
|
|
335
|
+
children: [/* @__PURE__ */ C(le, { size: 16 }), " Sample test cases"]
|
|
307
336
|
}),
|
|
308
|
-
/* @__PURE__ */
|
|
337
|
+
/* @__PURE__ */ C("p", {
|
|
309
338
|
className: "mb-3 text-sm text-text-secondary",
|
|
310
339
|
children: "Your solution reads each input from stdin and must print the expected output. Hidden test cases are also run when you submit."
|
|
311
340
|
}),
|
|
312
|
-
/* @__PURE__ */
|
|
341
|
+
/* @__PURE__ */ C("div", {
|
|
313
342
|
className: "space-y-3",
|
|
314
|
-
children:
|
|
343
|
+
children: V.publicTestCases.map((e) => /* @__PURE__ */ w("div", {
|
|
315
344
|
className: "rounded-xl border border-border-seam p-3",
|
|
316
|
-
children: [/* @__PURE__ */
|
|
345
|
+
children: [/* @__PURE__ */ w("div", {
|
|
317
346
|
className: "mb-2 flex flex-wrap items-center gap-x-3 gap-y-1",
|
|
318
|
-
children: [/* @__PURE__ */
|
|
347
|
+
children: [/* @__PURE__ */ C("span", {
|
|
319
348
|
className: "text-sm font-medium text-text-primary",
|
|
320
349
|
children: e.name
|
|
321
|
-
}), /* @__PURE__ */
|
|
350
|
+
}), /* @__PURE__ */ w("span", {
|
|
322
351
|
className: "inline-flex items-center gap-1 text-xs text-text-muted",
|
|
323
352
|
children: [
|
|
324
|
-
/* @__PURE__ */
|
|
353
|
+
/* @__PURE__ */ C(g, { size: 12 }),
|
|
325
354
|
" ",
|
|
326
355
|
e.timeLimitMs,
|
|
327
356
|
" ms limit"
|
|
328
357
|
]
|
|
329
358
|
})]
|
|
330
|
-
}), /* @__PURE__ */
|
|
359
|
+
}), /* @__PURE__ */ w("div", {
|
|
331
360
|
className: "grid grid-cols-1 gap-2 sm:grid-cols-2",
|
|
332
|
-
children: [/* @__PURE__ */
|
|
361
|
+
children: [/* @__PURE__ */ C(u, {
|
|
333
362
|
label: "Input",
|
|
334
363
|
value: e.input
|
|
335
|
-
}), /* @__PURE__ */
|
|
364
|
+
}), /* @__PURE__ */ C(u, {
|
|
336
365
|
label: "Expected output",
|
|
337
366
|
value: e.expectedOutput
|
|
338
367
|
})]
|
|
@@ -341,56 +370,62 @@ function j() {
|
|
|
341
370
|
})
|
|
342
371
|
]
|
|
343
372
|
}) : null,
|
|
344
|
-
|
|
345
|
-
className: "p-5",
|
|
346
|
-
children: [/* @__PURE__ */ T("h2", {
|
|
347
|
-
className: "mb-3 text-base font-semibold text-text-primary",
|
|
348
|
-
children: "Latest run"
|
|
349
|
-
}), /* @__PURE__ */ T(te, { submission: Q })]
|
|
350
|
-
}) : $ && $.verdict === "PENDING" ? /* @__PURE__ */ E(O, {
|
|
373
|
+
Z ? /* @__PURE__ */ w(E, {
|
|
351
374
|
className: "p-5",
|
|
352
375
|
children: [
|
|
353
|
-
/* @__PURE__ */
|
|
376
|
+
/* @__PURE__ */ C("h2", {
|
|
354
377
|
className: "mb-2 text-base font-semibold text-text-primary",
|
|
355
378
|
children: "Latest run"
|
|
356
379
|
}),
|
|
357
|
-
/* @__PURE__ */
|
|
380
|
+
ke ? /* @__PURE__ */ w("p", {
|
|
381
|
+
className: "mb-3 inline-flex items-center gap-2 text-sm text-text-secondary",
|
|
382
|
+
children: [/* @__PURE__ */ C(b, {
|
|
383
|
+
size: 14,
|
|
384
|
+
className: "animate-spin"
|
|
385
|
+
}), "Grading your submission — the grader is starting up. Your verdict will appear here automatically."]
|
|
386
|
+
}) : /* @__PURE__ */ C("p", {
|
|
358
387
|
className: "mb-3 text-sm text-text-secondary",
|
|
359
|
-
children: "Your most recent submission has not been graded yet — the grader was unavailable
|
|
388
|
+
children: "Your most recent submission has not been graded yet — the grader was unavailable. You can re-run it without resubmitting your code."
|
|
360
389
|
}),
|
|
361
|
-
/* @__PURE__ */
|
|
390
|
+
/* @__PURE__ */ w(T, {
|
|
362
391
|
variant: "outline",
|
|
363
|
-
onClick: () => void
|
|
364
|
-
disabled:
|
|
392
|
+
onClick: () => void De(Z),
|
|
393
|
+
disabled: B,
|
|
365
394
|
children: [
|
|
366
|
-
/* @__PURE__ */
|
|
395
|
+
/* @__PURE__ */ C(b, { size: 16 }),
|
|
367
396
|
" ",
|
|
368
|
-
|
|
397
|
+
B ? "Re-running…" : "Re-run grader"
|
|
369
398
|
]
|
|
370
399
|
})
|
|
371
400
|
]
|
|
401
|
+
}) : Y ? /* @__PURE__ */ w(E, {
|
|
402
|
+
className: "p-5",
|
|
403
|
+
children: [/* @__PURE__ */ C("h2", {
|
|
404
|
+
className: "mb-3 text-base font-semibold text-text-primary",
|
|
405
|
+
children: "Latest run"
|
|
406
|
+
}), /* @__PURE__ */ C(ie, { submission: Y })]
|
|
372
407
|
}) : null
|
|
373
408
|
]
|
|
374
|
-
}), /* @__PURE__ */
|
|
409
|
+
}), /* @__PURE__ */ C("div", {
|
|
375
410
|
className: "lg:col-span-1",
|
|
376
|
-
children: /* @__PURE__ */ E
|
|
411
|
+
children: /* @__PURE__ */ w(E, {
|
|
377
412
|
className: "p-5",
|
|
378
|
-
children: [/* @__PURE__ */
|
|
413
|
+
children: [/* @__PURE__ */ C("h2", {
|
|
379
414
|
className: "mb-3 text-base font-semibold text-text-primary",
|
|
380
415
|
children: "My submissions"
|
|
381
|
-
}),
|
|
416
|
+
}), Ce && !J.length ? /* @__PURE__ */ C(ee, {
|
|
382
417
|
count: 3,
|
|
383
418
|
height: "h-12"
|
|
384
|
-
}) :
|
|
419
|
+
}) : L ? /* @__PURE__ */ C(c, {
|
|
385
420
|
title: "Couldn't load submissions",
|
|
386
|
-
error:
|
|
387
|
-
}) :
|
|
388
|
-
icon: /* @__PURE__ */
|
|
421
|
+
error: L
|
|
422
|
+
}) : J.length === 0 ? /* @__PURE__ */ C(s, {
|
|
423
|
+
icon: /* @__PURE__ */ C(v, { size: 24 }),
|
|
389
424
|
title: "No submissions yet",
|
|
390
425
|
description: "Submit a solution above to see your verdicts and points here."
|
|
391
|
-
}) : /* @__PURE__ */
|
|
426
|
+
}) : /* @__PURE__ */ C("div", {
|
|
392
427
|
className: "space-y-1",
|
|
393
|
-
children:
|
|
428
|
+
children: J.map((e) => /* @__PURE__ */ C(be, { s: e }, e.id))
|
|
394
429
|
})]
|
|
395
430
|
})
|
|
396
431
|
})]
|
|
@@ -399,6 +434,6 @@ function j() {
|
|
|
399
434
|
});
|
|
400
435
|
}
|
|
401
436
|
//#endregion
|
|
402
|
-
export {
|
|
437
|
+
export { k as ApplicationsProblemDetailsPagePage };
|
|
403
438
|
|
|
404
439
|
//# sourceMappingURL=ApplicationsProblemDetailsPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApplicationsProblemDetailsPagePage.js","names":[],"sources":["../../../src/technospam/pages/ApplicationsProblemDetailsPagePage.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport { useSearchParams } from 'react-router';\nimport {\n Clock,\n Code2,\n FileText,\n FlaskConical,\n Layers,\n RefreshCw,\n Send,\n Tag,\n Trophy,\n} from 'lucide-react';\nimport {\n Badge,\n Button,\n GlassCard,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Skeleton,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport {\n CodePanel,\n EmptyView,\n ErrorView,\n IoBlock,\n LoadingRows,\n PageLayout,\n PremiumBadge,\n StatCard,\n StatusBadge,\n TagStrip,\n TestResultsPanel,\n UpgradeGate,\n} from '../components';\nimport { useTechnoSpam } from '../providers/TechnoSpamProvider';\nimport {\n useProblemQuery,\n useRegradeSubmission,\n useSubmissionsQuery,\n useSubmitSolution,\n type TecSubmission,\n} from '../api/technospamApi';\nimport { formatDateTime, humanizeEnum } from '../utils/format';\nimport { notify } from '../lib/toast';\nimport { useTechnoSpamAnalytics } from '../hooks/useTechnoSpamAnalytics';\n\nconst FALLBACK_LANGUAGES = ['javascript', 'python', 'typescript'];\n\nfunction SubmissionRow({ s }: { s: TecSubmission }) {\n return (\n <div className=\"rounded-lg border border-transparent px-2 py-3 transition-colors hover:border-border-seam hover:bg-bg-sunken\">\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1\">\n <StatusBadge status={s.verdict} />\n <span className=\"inline-flex items-center gap-1 text-sm font-medium text-text-primary\">\n <Code2 size={13} /> {humanizeEnum(s.language)}\n </span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Clock size={12} /> {s.runtimeMs} ms\n </span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Trophy size={12} /> {s.pointsAwarded} pts\n </span>\n <span className=\"ml-auto text-xs text-text-muted\">{formatDateTime(s.createdAt)}</span>\n </div>\n {s.totalCount > 0 ? (\n <p className=\"mt-1 px-0.5 text-xs text-text-muted\">\n Passed {s.passedCount} of {s.totalCount} test cases\n </p>\n ) : null}\n </div>\n );\n}\n\nexport function ApplicationsProblemDetailsPagePage() {\n const [params] = useSearchParams();\n const id = params.get('id') ?? '';\n const { currentUser, workspaceId } = useTechnoSpam();\n const learnerId = currentUser?.id;\n const { emit } = useTechnoSpamAnalytics();\n\n const { data, loading, error, refetch } = useProblemQuery(id);\n\n useEffect(() => {\n if (id) {\n emit('technospam.problem.viewed', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n });\n }\n }, [id, workspaceId, emit]);\n const {\n data: subsData,\n loading: subsLoading,\n error: subsError,\n refetch: refetchSubs,\n } = useSubmissionsQuery({ ...(learnerId ? { learnerId } : {}), problemId: id });\n const [submit, { loading: submitting }] = useSubmitSolution();\n const [regrade, { loading: regrading }] = useRegradeSubmission();\n\n const problem = data?.tecProblem ?? null;\n\n const languages = useMemo(\n () => (problem?.languages?.length ? problem.languages : FALLBACK_LANGUAGES),\n [problem]\n );\n\n const [language, setLanguage] = useState('');\n const [code, setCode] = useState('');\n const initedRef = useRef(false);\n\n useEffect(() => {\n if (problem && !initedRef.current) {\n setLanguage(problem.languages[0] ?? FALLBACK_LANGUAGES[0]!);\n setCode(problem.starterCode ?? '');\n initedRef.current = true;\n }\n }, [problem]);\n\n const submissions = useMemo(\n () =>\n [...(subsData?.tecListSubmissions?.items ?? [])].sort(\n (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n ),\n [subsData]\n );\n\n const handleSubmit = async () => {\n if (!id) return;\n if (!language) {\n notify.error('Pick a language', 'Choose a language before submitting.');\n return;\n }\n if (!code.trim()) {\n notify.error('Add your solution', 'Write some code before submitting.');\n return;\n }\n emit('technospam.problem.submit_clicked', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n language,\n });\n const res = await submit({ variables: { input: { problemId: id, language, code } } });\n if (res.data?.tecSubmitSolution) {\n emit('technospam.problem.submitted', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n submissionId: res.data.tecSubmitSolution.id,\n });\n const graded = res.data.tecSubmitSolution;\n if (graded.verdict === 'PENDING') {\n notify.info(\n 'Solution submitted',\n 'The grader is not available right now — your submission was saved and can be re-run.'\n );\n } else if (graded.verdict === 'ACCEPTED') {\n notify.success('Accepted', `Passed all ${graded.totalCount} test cases.`);\n } else {\n notify.error(\n humanizeEnum(graded.verdict),\n `Passed ${graded.passedCount} of ${graded.totalCount} test cases.`\n );\n }\n await Promise.all([refetch(), refetchSubs()]);\n }\n };\n\n const handleRegrade = async (submissionId: string) => {\n const res = await regrade({ variables: { id: submissionId } });\n const graded = res.data?.tecRegradeSubmission;\n if (!graded) return;\n if (graded.verdict === 'PENDING') {\n notify.error('Still pending', 'The grader is not available yet. Please try again shortly.');\n } else {\n notify.success('Grading complete', `Verdict: ${humanizeEnum(graded.verdict)}.`);\n }\n await Promise.all([refetch(), refetchSubs()]);\n };\n\n /** Most recent submission that actually carries grading detail. */\n const latestGraded = submissions.find((s) => (s.testResults?.length ?? 0) > 0) ?? null;\n const latestSubmission = submissions[0] ?? null;\n\n if (loading && !problem) {\n return (\n <PageLayout title=\"Problem\" backPath=\"/applications/problems-page\">\n <Skeleton className=\"mb-4 h-28 w-full rounded-xl\" />\n <Skeleton className=\"h-72 w-full rounded-xl\" />\n </PageLayout>\n );\n }\n\n if (error || !problem) {\n return (\n <PageLayout title=\"Problem\" backPath=\"/applications/problems-page\">\n {error ? (\n <ErrorView title=\"Couldn't load problem\" error={error} />\n ) : (\n <EmptyView\n title=\"Problem not found\"\n description=\"This problem may have been unpublished.\"\n />\n )}\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n hero\n backPath=\"/applications/problems-page\"\n title={problem.title}\n description={problem.topic ?? undefined}\n >\n <div className=\"mb-5 flex flex-wrap items-center gap-2\">\n <StatusBadge status={problem.difficulty} kind=\"level\" />\n <StatusBadge status={problem.status} />\n {problem.topic ? (\n <Badge variant=\"outline\" className=\"gap-1\">\n <Layers size={12} /> {problem.topic}\n </Badge>\n ) : null}\n {problem.isPremiumOnly ? <PremiumBadge locked={problem.isLocked} /> : null}\n <TagStrip tags={problem.tags} />\n </div>\n\n <div className=\"mb-6 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard label=\"Points\" value={problem.points} icon={Trophy} tone=\"amber\" />\n <StatCard label=\"Languages\" value={languages.length} icon={Code2} tone=\"blue\" />\n <StatCard\n label=\"Difficulty\"\n value={humanizeEnum(problem.difficulty)}\n icon={Layers}\n tone=\"purple\"\n />\n <StatCard label=\"My submissions\" value={submissions.length} icon={FileText} tone=\"teal\" />\n </div>\n\n <div className=\"grid grid-cols-1 gap-5 lg:grid-cols-3\">\n <div className=\"space-y-5 lg:col-span-2\">\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-2 text-base font-semibold text-text-primary\">Problem statement</h2>\n {problem.isLocked ? (\n // BOFF-4416: the API already nulled `statement` for a locked\n // premium problem — this explains why, rather than showing the\n // generic \"being prepared\" message used for a real content gap.\n <UpgradeGate description=\"This problem's statement is part of a paid TechnoSpam plan. Ask a workspace admin to upgrade to unlock it.\" />\n ) : problem.statement ? (\n <p className=\"whitespace-pre-wrap text-sm leading-relaxed text-text-secondary\">\n {problem.statement}\n </p>\n ) : (\n <p className=\"py-4 text-center text-sm text-text-muted\">\n The statement for this problem is being prepared.\n </p>\n )}\n </GlassCard>\n\n {problem.isLocked ? (\n <UpgradeGate\n compact\n description=\"Starter code and sample test cases unlock with a paid TechnoSpam plan.\"\n />\n ) : problem.starterCode ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">Starter code</h2>\n <CodePanel label={humanizeEnum(languages[0] ?? 'code')} bodyClassName=\"max-h-72\">\n {problem.starterCode}\n </CodePanel>\n </GlassCard>\n ) : null}\n\n <GlassCard className=\"p-5\">\n <div className=\"mb-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n <h2 className=\"text-base font-semibold text-text-primary\">Submit a solution</h2>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-secondary\">Language</span>\n <Select value={language} onValueChange={setLanguage}>\n <SelectTrigger className=\"w-full sm:w-48\">\n <SelectValue placeholder=\"Choose a language\" />\n </SelectTrigger>\n <SelectContent>\n {languages.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeEnum(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"overflow-hidden rounded-xl border border-border-strong bg-bg-sunken shadow-sm\">\n <div className=\"flex items-center justify-between gap-2 border-b border-border-seam bg-bg-canvas/40 px-4 py-2\">\n <div className=\"flex items-center gap-1.5\">\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-error-border\" />\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-warning-border\" />\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-success-border\" />\n </div>\n <span className=\"inline-flex items-center gap-1.5 font-mono text-xs text-text-muted\">\n <Code2 size={13} /> {language ? humanizeEnum(language) : 'solution'}\n </span>\n </div>\n <Textarea\n value={code}\n onChange={(e) => setCode(e.target.value)}\n placeholder=\"Write your solution…\"\n className=\"min-h-[280px] resize-y rounded-none border-0 bg-transparent font-mono text-xs leading-relaxed focus-visible:ring-0 focus-visible:ring-offset-0\"\n spellCheck={false}\n />\n </div>\n\n <Button\n className=\"mt-4 w-full\"\n onClick={handleSubmit}\n disabled={submitting || !code.trim()}\n >\n <Send size={16} /> {submitting ? 'Running test cases…' : 'Run & submit'}\n </Button>\n <p className=\"mt-2 text-center text-xs text-text-muted\">\n Your code runs against this problem's test cases in an isolated sandbox.\n </p>\n </GlassCard>\n\n {problem.publicTestCases?.length ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-1 flex items-center gap-2 text-base font-semibold text-text-primary\">\n <FlaskConical size={16} /> Sample test cases\n </h2>\n <p className=\"mb-3 text-sm text-text-secondary\">\n Your solution reads each input from stdin and must print the expected output. Hidden\n test cases are also run when you submit.\n </p>\n <div className=\"space-y-3\">\n {problem.publicTestCases.map((testCase) => (\n <div key={testCase.id} className=\"rounded-xl border border-border-seam p-3\">\n <div className=\"mb-2 flex flex-wrap items-center gap-x-3 gap-y-1\">\n <span className=\"text-sm font-medium text-text-primary\">{testCase.name}</span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Clock size={12} /> {testCase.timeLimitMs} ms limit\n </span>\n </div>\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2\">\n <IoBlock label=\"Input\" value={testCase.input} />\n <IoBlock label=\"Expected output\" value={testCase.expectedOutput} />\n </div>\n </div>\n ))}\n </div>\n </GlassCard>\n ) : null}\n\n {latestGraded ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">Latest run</h2>\n <TestResultsPanel submission={latestGraded} />\n </GlassCard>\n ) : latestSubmission && latestSubmission.verdict === 'PENDING' ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-2 text-base font-semibold text-text-primary\">Latest run</h2>\n <p className=\"mb-3 text-sm text-text-secondary\">\n Your most recent submission has not been graded yet — the grader was unavailable\n when you submitted. You can re-run it without resubmitting your code.\n </p>\n <Button\n variant=\"outline\"\n onClick={() => void handleRegrade(latestSubmission.id)}\n disabled={regrading}\n >\n <RefreshCw size={16} /> {regrading ? 'Re-running…' : 'Re-run grader'}\n </Button>\n </GlassCard>\n ) : null}\n </div>\n\n <div className=\"lg:col-span-1\">\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">My submissions</h2>\n {subsLoading && !submissions.length ? (\n <LoadingRows count={3} height=\"h-12\" />\n ) : subsError ? (\n <ErrorView title=\"Couldn't load submissions\" error={subsError} />\n ) : submissions.length === 0 ? (\n <EmptyView\n icon={<FileText size={24} />}\n title=\"No submissions yet\"\n description=\"Submit a solution above to see your verdicts and points here.\"\n />\n ) : (\n <div className=\"space-y-1\">\n {submissions.map((s) => (\n <SubmissionRow key={s.id} s={s} />\n ))}\n </div>\n )}\n </GlassCard>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ApplicationsProblemDetailsPagePage.js","names":[],"sources":["../../../src/technospam/pages/ApplicationsProblemDetailsPagePage.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport { useSearchParams } from 'react-router';\nimport {\n Clock,\n Code2,\n FileText,\n FlaskConical,\n Layers,\n RefreshCw,\n Send,\n Tag,\n Trophy,\n} from 'lucide-react';\nimport {\n Badge,\n Button,\n GlassCard,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Skeleton,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport {\n CodePanel,\n EmptyView,\n ErrorView,\n IoBlock,\n LoadingRows,\n PageLayout,\n PremiumBadge,\n StatCard,\n StatusBadge,\n TagStrip,\n TestResultsPanel,\n UpgradeGate,\n} from '../components';\nimport { useTechnoSpam } from '../providers/TechnoSpamProvider';\nimport {\n useProblemQuery,\n useRegradeSubmission,\n useSubmissionsQuery,\n useSubmitSolution,\n type TecSubmission,\n} from '../api/technospamApi';\nimport { formatDateTime, humanizeEnum } from '../utils/format';\nimport { notify } from '../lib/toast';\nimport { useTechnoSpamAnalytics } from '../hooks/useTechnoSpamAnalytics';\n\nconst FALLBACK_LANGUAGES = ['javascript', 'python', 'typescript'];\n\n/**\n * A submission made while the grading sandbox is cold comes back PENDING and is\n * graded in the background (BOFF-4414). Poll the submissions list until the\n * verdict lands, giving up after a few minutes so a genuinely failed grade\n * falls back to the manual re-run button.\n */\nconst PENDING_POLL_INTERVAL_MS = 3_000;\nconst PENDING_POLL_MAX_MS = 3 * 60_000;\n\nfunction SubmissionRow({ s }: { s: TecSubmission }) {\n return (\n <div className=\"rounded-lg border border-transparent px-2 py-3 transition-colors hover:border-border-seam hover:bg-bg-sunken\">\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1\">\n <StatusBadge status={s.verdict} />\n <span className=\"inline-flex items-center gap-1 text-sm font-medium text-text-primary\">\n <Code2 size={13} /> {humanizeEnum(s.language)}\n </span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Clock size={12} /> {s.runtimeMs} ms\n </span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Trophy size={12} /> {s.pointsAwarded} pts\n </span>\n <span className=\"ml-auto text-xs text-text-muted\">{formatDateTime(s.createdAt)}</span>\n </div>\n {s.totalCount > 0 ? (\n <p className=\"mt-1 px-0.5 text-xs text-text-muted\">\n Passed {s.passedCount} of {s.totalCount} test cases\n </p>\n ) : null}\n </div>\n );\n}\n\nexport function ApplicationsProblemDetailsPagePage() {\n const [params] = useSearchParams();\n const id = params.get('id') ?? '';\n const { currentUser, workspaceId } = useTechnoSpam();\n const learnerId = currentUser?.id;\n const { emit } = useTechnoSpamAnalytics();\n\n const { data, loading, error, refetch } = useProblemQuery(id);\n\n useEffect(() => {\n if (id) {\n emit('technospam.problem.viewed', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n });\n }\n }, [id, workspaceId, emit]);\n const {\n data: subsData,\n loading: subsLoading,\n error: subsError,\n refetch: refetchSubs,\n } = useSubmissionsQuery({ ...(learnerId ? { learnerId } : {}), problemId: id });\n const [submit, { loading: submitting }] = useSubmitSolution();\n const [regrade, { loading: regrading }] = useRegradeSubmission();\n\n const problem = data?.tecProblem ?? null;\n\n const languages = useMemo(\n () => (problem?.languages?.length ? problem.languages : FALLBACK_LANGUAGES),\n [problem]\n );\n\n const [language, setLanguage] = useState('');\n const [code, setCode] = useState('');\n const initedRef = useRef(false);\n\n useEffect(() => {\n if (problem && !initedRef.current) {\n setLanguage(problem.languages[0] ?? FALLBACK_LANGUAGES[0]!);\n setCode(problem.starterCode ?? '');\n initedRef.current = true;\n }\n }, [problem]);\n\n const submissions = useMemo(\n () =>\n [...(subsData?.tecListSubmissions?.items ?? [])].sort(\n (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n ),\n [subsData]\n );\n\n const handleSubmit = async () => {\n if (!id) return;\n if (!language) {\n notify.error('Pick a language', 'Choose a language before submitting.');\n return;\n }\n if (!code.trim()) {\n notify.error('Add your solution', 'Write some code before submitting.');\n return;\n }\n emit('technospam.problem.submit_clicked', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n language,\n });\n const res = await submit({ variables: { input: { problemId: id, language, code } } });\n if (res.data?.tecSubmitSolution) {\n emit('technospam.problem.submitted', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n submissionId: res.data.tecSubmitSolution.id,\n });\n const graded = res.data.tecSubmitSolution;\n if (graded.verdict === 'PENDING') {\n notify.info(\n 'Solution submitted',\n 'Grading has started — your verdict will appear here in a moment.'\n );\n } else if (graded.verdict === 'ACCEPTED') {\n notify.success('Accepted', `Passed all ${graded.totalCount} test cases.`);\n } else {\n notify.error(\n humanizeEnum(graded.verdict),\n `Passed ${graded.passedCount} of ${graded.totalCount} test cases.`\n );\n }\n await Promise.all([refetch(), refetchSubs()]);\n }\n };\n\n const handleRegrade = async (submissionId: string) => {\n const res = await regrade({ variables: { id: submissionId } });\n const graded = res.data?.tecRegradeSubmission;\n if (!graded) return;\n if (graded.verdict === 'PENDING') {\n notify.error('Still pending', 'The grader is not available yet. Please try again shortly.');\n } else {\n notify.success('Grading complete', `Verdict: ${humanizeEnum(graded.verdict)}.`);\n }\n await Promise.all([refetch(), refetchSubs()]);\n };\n\n /** Most recent submission that actually carries grading detail. */\n const latestGraded = submissions.find((s) => (s.testResults?.length ?? 0) > 0) ?? null;\n const latestSubmission = submissions[0] ?? null;\n const pendingId = latestSubmission?.verdict === 'PENDING' ? latestSubmission.id : null;\n\n // Poll while the newest submission is still being graded in the background.\n const [pollExpiredFor, setPollExpiredFor] = useState<string | null>(null);\n const polling = pendingId !== null && pollExpiredFor !== pendingId;\n useEffect(() => {\n if (!pendingId || pollExpiredFor === pendingId) return undefined;\n const startedAt = Date.now();\n const timer = window.setInterval(() => {\n if (Date.now() - startedAt > PENDING_POLL_MAX_MS) {\n window.clearInterval(timer);\n setPollExpiredFor(pendingId);\n return;\n }\n void refetchSubs();\n }, PENDING_POLL_INTERVAL_MS);\n return () => window.clearInterval(timer);\n }, [pendingId, pollExpiredFor, refetchSubs]);\n\n // Announce the verdict once a background-graded submission settles.\n const awaitedIdRef = useRef<string | null>(null);\n useEffect(() => {\n if (pendingId) {\n awaitedIdRef.current = pendingId;\n return;\n }\n const awaitedId = awaitedIdRef.current;\n if (!awaitedId) return;\n const settled = submissions.find((s) => s.id === awaitedId);\n if (!settled || settled.verdict === 'PENDING') return;\n awaitedIdRef.current = null;\n if (settled.verdict === 'ACCEPTED') {\n notify.success('Accepted', `Passed all ${settled.totalCount} test cases.`);\n } else {\n notify.error(\n humanizeEnum(settled.verdict),\n `Passed ${settled.passedCount} of ${settled.totalCount} test cases.`\n );\n }\n void refetch();\n }, [pendingId, submissions, refetch]);\n\n if (loading && !problem) {\n return (\n <PageLayout title=\"Problem\" backPath=\"/applications/problems-page\">\n <Skeleton className=\"mb-4 h-28 w-full rounded-xl\" />\n <Skeleton className=\"h-72 w-full rounded-xl\" />\n </PageLayout>\n );\n }\n\n if (error || !problem) {\n return (\n <PageLayout title=\"Problem\" backPath=\"/applications/problems-page\">\n {error ? (\n <ErrorView title=\"Couldn't load problem\" error={error} />\n ) : (\n <EmptyView\n title=\"Problem not found\"\n description=\"This problem may have been unpublished.\"\n />\n )}\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n hero\n backPath=\"/applications/problems-page\"\n title={problem.title}\n description={problem.topic ?? undefined}\n >\n <div className=\"mb-5 flex flex-wrap items-center gap-2\">\n <StatusBadge status={problem.difficulty} kind=\"level\" />\n <StatusBadge status={problem.status} />\n {problem.topic ? (\n <Badge variant=\"outline\" className=\"gap-1\">\n <Layers size={12} /> {problem.topic}\n </Badge>\n ) : null}\n {problem.isPremiumOnly ? <PremiumBadge locked={problem.isLocked} /> : null}\n <TagStrip tags={problem.tags} />\n </div>\n\n <div className=\"mb-6 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard label=\"Points\" value={problem.points} icon={Trophy} tone=\"amber\" />\n <StatCard label=\"Languages\" value={languages.length} icon={Code2} tone=\"blue\" />\n <StatCard\n label=\"Difficulty\"\n value={humanizeEnum(problem.difficulty)}\n icon={Layers}\n tone=\"purple\"\n />\n <StatCard label=\"My submissions\" value={submissions.length} icon={FileText} tone=\"teal\" />\n </div>\n\n <div className=\"grid grid-cols-1 gap-5 lg:grid-cols-3\">\n <div className=\"space-y-5 lg:col-span-2\">\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-2 text-base font-semibold text-text-primary\">Problem statement</h2>\n {problem.isLocked ? (\n // BOFF-4416: the API already nulled `statement` for a locked\n // premium problem — this explains why, rather than showing the\n // generic \"being prepared\" message used for a real content gap.\n <UpgradeGate description=\"This problem's statement is part of a paid TechnoSpam plan. Ask a workspace admin to upgrade to unlock it.\" />\n ) : problem.statement ? (\n <p className=\"whitespace-pre-wrap text-sm leading-relaxed text-text-secondary\">\n {problem.statement}\n </p>\n ) : (\n <p className=\"py-4 text-center text-sm text-text-muted\">\n The statement for this problem is being prepared.\n </p>\n )}\n </GlassCard>\n\n {problem.isLocked ? (\n <UpgradeGate\n compact\n description=\"Starter code and sample test cases unlock with a paid TechnoSpam plan.\"\n />\n ) : problem.starterCode ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">Starter code</h2>\n <CodePanel label={humanizeEnum(languages[0] ?? 'code')} bodyClassName=\"max-h-72\">\n {problem.starterCode}\n </CodePanel>\n </GlassCard>\n ) : null}\n\n <GlassCard className=\"p-5\">\n <div className=\"mb-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n <h2 className=\"text-base font-semibold text-text-primary\">Submit a solution</h2>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-secondary\">Language</span>\n <Select value={language} onValueChange={setLanguage}>\n <SelectTrigger className=\"w-full sm:w-48\">\n <SelectValue placeholder=\"Choose a language\" />\n </SelectTrigger>\n <SelectContent>\n {languages.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeEnum(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"overflow-hidden rounded-xl border border-border-strong bg-bg-sunken shadow-sm\">\n <div className=\"flex items-center justify-between gap-2 border-b border-border-seam bg-bg-canvas/40 px-4 py-2\">\n <div className=\"flex items-center gap-1.5\">\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-error-border\" />\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-warning-border\" />\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-success-border\" />\n </div>\n <span className=\"inline-flex items-center gap-1.5 font-mono text-xs text-text-muted\">\n <Code2 size={13} /> {language ? humanizeEnum(language) : 'solution'}\n </span>\n </div>\n <Textarea\n value={code}\n onChange={(e) => setCode(e.target.value)}\n placeholder=\"Write your solution…\"\n className=\"min-h-[280px] resize-y rounded-none border-0 bg-transparent font-mono text-xs leading-relaxed focus-visible:ring-0 focus-visible:ring-offset-0\"\n spellCheck={false}\n />\n </div>\n\n <Button\n className=\"mt-4 w-full\"\n onClick={handleSubmit}\n disabled={submitting || !code.trim()}\n >\n <Send size={16} /> {submitting ? 'Running test cases…' : 'Run & submit'}\n </Button>\n <p className=\"mt-2 text-center text-xs text-text-muted\">\n Your code runs against this problem's test cases in an isolated sandbox.\n </p>\n </GlassCard>\n\n {problem.publicTestCases?.length ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-1 flex items-center gap-2 text-base font-semibold text-text-primary\">\n <FlaskConical size={16} /> Sample test cases\n </h2>\n <p className=\"mb-3 text-sm text-text-secondary\">\n Your solution reads each input from stdin and must print the expected output. Hidden\n test cases are also run when you submit.\n </p>\n <div className=\"space-y-3\">\n {problem.publicTestCases.map((testCase) => (\n <div key={testCase.id} className=\"rounded-xl border border-border-seam p-3\">\n <div className=\"mb-2 flex flex-wrap items-center gap-x-3 gap-y-1\">\n <span className=\"text-sm font-medium text-text-primary\">{testCase.name}</span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Clock size={12} /> {testCase.timeLimitMs} ms limit\n </span>\n </div>\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2\">\n <IoBlock label=\"Input\" value={testCase.input} />\n <IoBlock label=\"Expected output\" value={testCase.expectedOutput} />\n </div>\n </div>\n ))}\n </div>\n </GlassCard>\n ) : null}\n\n {pendingId ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-2 text-base font-semibold text-text-primary\">Latest run</h2>\n {polling ? (\n <p className=\"mb-3 inline-flex items-center gap-2 text-sm text-text-secondary\">\n <RefreshCw size={14} className=\"animate-spin\" />\n Grading your submission — the grader is starting up. Your verdict will appear here\n automatically.\n </p>\n ) : (\n <p className=\"mb-3 text-sm text-text-secondary\">\n Your most recent submission has not been graded yet — the grader was unavailable.\n You can re-run it without resubmitting your code.\n </p>\n )}\n <Button\n variant=\"outline\"\n onClick={() => void handleRegrade(pendingId)}\n disabled={regrading}\n >\n <RefreshCw size={16} /> {regrading ? 'Re-running…' : 'Re-run grader'}\n </Button>\n </GlassCard>\n ) : latestGraded ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">Latest run</h2>\n <TestResultsPanel submission={latestGraded} />\n </GlassCard>\n ) : null}\n </div>\n\n <div className=\"lg:col-span-1\">\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">My submissions</h2>\n {subsLoading && !submissions.length ? (\n <LoadingRows count={3} height=\"h-12\" />\n ) : subsError ? (\n <ErrorView title=\"Couldn't load submissions\" error={subsError} />\n ) : submissions.length === 0 ? (\n <EmptyView\n icon={<FileText size={24} />}\n title=\"No submissions yet\"\n description=\"Submit a solution above to see your verdicts and points here.\"\n />\n ) : (\n <div className=\"space-y-1\">\n {submissions.map((s) => (\n <SubmissionRow key={s.id} s={s} />\n ))}\n </div>\n )}\n </GlassCard>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|