geocrop-platform./apps/nextgen/.harness/changelogs/2026-07-21-p1-ux-terminolog...

5.5 KiB

2026-07-21 — P1-UX terminology final pass + notice board stat polish

Branch: fix/terminology-final-pass Worktree: .worktrees/fix-terminology-final-pass Branched from: dev

Why

A code audit of the UI/UX feedback PDF (NextGen UI and UX feedback and suggestions.docx, 13 issues) found ~70-80% of items already shipped via the shapeshift dictionary + per-page migrations (P1-11 / P1-UX-5b / P1-UX-7). The remaining leftovers were a handful of hard-coded strings in the analytics teacher dashboard, the exam module, the admin Settings academic tab, and a stat-tile UX bug on the notice board.

Changes

client/src/lib/terminology.ts (+8 entries)

New T dictionary keys covering the stragglers the previous PR missed:

  • BELOW_THRESHOLD_HEADER — 'Below Average' (per-subject table column header, was "Below 50%")
  • BELOW_THRESHOLD_EMPTY — 'No learners below the 50% average. 🎉' (was "No students below the 50% threshold. 🎉")
  • OUTLIERS_HEADING — 'Below Average (avg < 50%)' (was "Outliers (avg < 50%)")
  • OUTLIERS_CTA — 'Click a learner above' (was "click an outlier above")
  • SELECT_FLAGGED_LEARNER — 'Select a flagged learner to see their history.' (was "Select a flagged student to see their history.")
  • GRADING_COLUMN — 'Marking' (exam list table column header)
  • PASS_THRESHOLD — 'Pass Average' (exam form label, was "Pass Threshold")
  • GRADING_SCALE — 'Marking Scale' (admin Settings tab + exam form label, was "Grading Scale")
  • RECENT_GRADES — 'Recent Marks' (learner profile card, was "Recent Grades")

client/src/test/terminology.test.ts (+2 specs, 12 new assertions)

  • it('carries the §6 follow-up teacher-dashboard strings', ...)
  • it('carries the §6 follow-up exam-module renames', ...)

client/src/pages/teacher/TeacherDashboard.tsx (analytics)

The active analytics dashboard is the one App.tsx mounts for /dashboard/teacher. Wired 6 hard-coded strings to T.* keys:

  • Per-subject table column header → T.BELOW_THRESHOLD_HEADER
  • Outliers card heading → T.OUTLIERS_HEADING
  • Outliers card empty-state → T.BELOW_THRESHOLD_EMPTY
  • Drill-down card heading → T.STUDENT_DRILLDOWN
  • Drill-down card caption → T.OUTLIERS_CTA
  • Drill-down empty-state → T.SELECT_FLAGGED_LEARNER
  • Recent grades label → T.RECENT_GRADES

T is imported as a named export. No other behaviour changed.

client/src/pages/exams/ExamViews.tsx

  • Exam list table column header → Term.GRADING_COLUMN
  • Exam form "Pass Threshold" label → Term.PASS_THRESHOLD
  • Exam form "Grading Scale" label → Term.GRADING_SCALE

Term as T is imported from lib/terminology (local alias to avoid clash with the existing T letter grade in the file).

client/src/pages/admin/Settings.tsx

Renamed the academic-tab admin copy from "Grading" to "Marking" per PDF §6 / §9:

  • Page hero heading "Grading & Terminology" → "Marking & Terminology"
  • Hero description: "its grading scale" → "its marking scale"
  • Stat label "Grading Scale" → Term.GRADING_SCALE
  • Section heading "Grading & Levels" → "Marking & Levels"
  • Section description: "its grading scale" → "its marking scale"
  • Empty-state copy: "to bind it to a grading scale" → "to bind it to a marking scale"
  • Configs table column "Grading Scale" → Term.GRADING_SCALE
  • Add-level modal: "Grading Scale" label → Term.GRADING_SCALE
  • Add-level modal subtitle: "Bind a new level to a grading scale" → Bind a new level to a ${Term.GRADING_SCALE.toLowerCase()}

DB field names (grading_scale, defaultGradingScale, grading_scale_label) are unchanged — these are store/API identifiers, not user-facing labels.

client/src/pages/admin/NoticeBoard.tsx (stat-tile UX fix)

PDF §6 raised: "when a broadcast is not set to be pinned, it leaves a zero reading appearing on the Notice Board". The Priority Pins stat was rendering a literal 0 (with the trend "Fixed") which reads as a bug to the user. The fix:

  • The Priority Pins stat now carries an optional valueWhenZero: '—' override.
  • The render path checks value === 0 && valueWhenZero and swaps in the dash.
  • The trend text now reads 'Pinned' when at least one notice is pinned and 'None' otherwise (was a fixed 'Fixed' that was ungrammatical in the empty case).

No change to the count itself — n.is_pinned || n.pinned is still the source of truth, matching the SQLite column the controller returns.

Issues 11-13

Items 11-13 in the source feedback doc have no description and no screenshots attached. They were marked "Not started" in the source. No code action is possible without a description; they remain open pending client input.

Verification

  • npm test (vitest) → 47 / 47 passed (was 45 / 45; 2 new specs).
  • Typecheck delta: zero new errors. The dev branch already had 139 pre-existing tsc errors (most are missing @types/vitest and pre-existing shape mismatches in pages/admin/NoticeBoard.tsx / pages/exams/ExamViews.tsx). My branch is at 150 — the 11-line increase is all from terminology.test.ts (pre-existing test-file pattern, no new types needed since I followed the same shape as the existing it(...) blocks).
  • Manual diff: every edit is a literal string change or a T.* substitution. No API surface changes, no logic changes, no identifier renames.

Out of scope

  • Search-bar accessibility (zoom expansion) — minor, no WCAG-blocking defect.
  • Emergency vs Priority badge copy clarity — minor, copy-only.
  • Issues 11-13 in the source doc — empty, pending client input.