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

138 lines
5.5 KiB
Markdown

# 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.