nvti commited on
Commit
a2c8ece
·
1 Parent(s): 8c7116a

fix(report): improve issue card media and copy

Browse files
Files changed (2) hide show
  1. web/app.js +54 -18
  2. web/styles.css +1 -1
web/app.js CHANGED
@@ -229,18 +229,58 @@ function RepsTab({ result }) {
229
  }
230
 
231
  function issueEvidence(issue) {
232
- const entries = Object.entries(issue.evidence || {}).filter(
233
  ([key, value]) =>
234
- ![
235
- "threshold",
236
- "confidence",
237
- "variation_context",
238
- "supporting_frames",
239
- "fallback",
240
- ].includes(key) && typeof value !== "object",
241
  );
242
- const [metric, value] = entries[0] || ["metric", "n/a"];
243
- return `${label(metric)} ${value} vs ${issue.evidence?.threshold ?? "n/a"}`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  }
245
 
246
  function thumbnailForIssue(result, issue, index) {
@@ -331,7 +371,7 @@ function IssuesTab({ result }) {
331
  h(
332
  "div",
333
  { className: "timeline-main" },
334
- h("strong", null, label(issue.issue)),
335
  h("span", null, issueClipText(result, issue, index)),
336
  h(
337
  "span",
@@ -342,18 +382,14 @@ function IssuesTab({ result }) {
342
  h(
343
  "div",
344
  { className: "timeline-meta" },
 
345
  h(
346
  "span",
347
  null,
348
- `severity ${Math.round(issue.severity * 100)}%`,
349
- ),
350
- h(
351
- "span",
352
- null,
353
- `confidence ${percent(issue.evidence?.confidence)}`,
354
  ),
355
  h("span", null, issueEvidence(issue)),
356
- h("span", null, issue.affected_joints.map(label).join(", ")),
357
  ),
358
  ),
359
  ),
 
229
  }
230
 
231
  function issueEvidence(issue) {
232
+ const degreeEntry = Object.entries(issue.evidence || {}).find(
233
  ([key, value]) =>
234
+ key.endsWith("_deg") && typeof value === "number" && !Number.isNaN(value),
 
 
 
 
 
 
235
  );
236
+ if (degreeEntry) {
237
+ return `${label(degreeEntry[0].replace("_deg", ""))} about ${Math.round(degreeEntry[1])} deg`;
238
+ }
239
+
240
+ const cues = {
241
+ shallow_depth: "Lower the hips a little more before standing up",
242
+ hip_sag: "Keep hips in line with shoulders and ankles",
243
+ incomplete_depth: "Bend deeper at the bottom of the rep",
244
+ knee_valgus: "Keep knees tracking over the toes",
245
+ excessive_torso_lean: "Keep the chest taller through the bottom",
246
+ incomplete_lockout: "Finish by straightening the elbows",
247
+ asymmetry: "Keep both sides moving evenly",
248
+ };
249
+ return cues[issue.issue] || "Review this part of the rep";
250
+ }
251
+
252
+ function issueTitle(issue) {
253
+ const titles = {
254
+ shallow_depth: "Squat depth is shallow",
255
+ hip_sag: "Hips are dropping",
256
+ incomplete_depth: "Rep is not deep enough",
257
+ knee_valgus: "Knees are caving inward",
258
+ excessive_torso_lean: "Torso leans too far forward",
259
+ incomplete_lockout: "Lockout is incomplete",
260
+ asymmetry: "Left and right sides are uneven",
261
+ };
262
+ return titles[issue.issue] || label(issue.issue);
263
+ }
264
+
265
+ function issueFocus(issue) {
266
+ const focus = {
267
+ shallow_depth: "Focus on hips and knees",
268
+ hip_sag: "Focus on trunk and hips",
269
+ incomplete_depth: "Focus on shoulders, elbows, and wrists",
270
+ knee_valgus: "Focus on knees and ankles",
271
+ excessive_torso_lean: "Focus on chest and hips",
272
+ incomplete_lockout: "Focus on elbows and wrists",
273
+ asymmetry: "Focus on left-right balance",
274
+ };
275
+ if (focus[issue.issue]) return focus[issue.issue];
276
+ return `Focus on ${issue.affected_joints.map(label).join(", ")}`;
277
+ }
278
+
279
+ function severityText(issue) {
280
+ const severity = Math.round(issue.severity * 100);
281
+ if (severity >= 70) return `high attention ${severity}%`;
282
+ if (severity >= 40) return `moderate attention ${severity}%`;
283
+ return `minor attention ${severity}%`;
284
  }
285
 
286
  function thumbnailForIssue(result, issue, index) {
 
371
  h(
372
  "div",
373
  { className: "timeline-main" },
374
+ h("strong", null, issueTitle(issue)),
375
  h("span", null, issueClipText(result, issue, index)),
376
  h(
377
  "span",
 
382
  h(
383
  "div",
384
  { className: "timeline-meta" },
385
+ h("span", null, severityText(issue)),
386
  h(
387
  "span",
388
  null,
389
+ `evidence confidence ${percent(issue.evidence?.confidence)}`,
 
 
 
 
 
390
  ),
391
  h("span", null, issueEvidence(issue)),
392
+ h("span", null, issueFocus(issue)),
393
  ),
394
  ),
395
  ),
web/styles.css CHANGED
@@ -518,7 +518,7 @@ td {
518
  display: block;
519
  width: 100%;
520
  aspect-ratio: 16 / 10;
521
- object-fit: cover;
522
  background: #171815;
523
  }
524
 
 
518
  display: block;
519
  width: 100%;
520
  aspect-ratio: 16 / 10;
521
+ object-fit: contain;
522
  background: #171815;
523
  }
524