Skip to content

refactor(status): TermStatus single source of truth (#238 phase 1)#246

Merged
HugoFara merged 1 commit into
mainfrom
refactor/term-status-single-source
Jun 30, 2026
Merged

refactor(status): TermStatus single source of truth (#238 phase 1)#246
HugoFara merged 1 commit into
mainfrom
refactor/term-status-single-source

Conversation

@HugoFara

Copy link
Copy Markdown
Owner

Implements Phase 1 of #238 — making the word-status model a single source of truth. The FSRS scheduling work (Phase 2) is intentionally not in this PR; it stays parked pending the product decisions in the issue.

What this does

One integer status (1–5 learning, 98 ignored, 99 well-known) was modelled ad-hoc: the literal [1,2,3,4,5,98,99] and === 5 || === 99 checks recurred across ~11 PHP files, and label/order/class tables were re-defined across ~5 TS files. This collapses all of that onto the existing TermStatus value object (backend) + one frontend store, with the model exposed once over the API.

Backend

  • TermStatus is now authoritative. Added abbreviation(), cssClass(), colourHex(), order(), displayName() (localized), the static isValid() / values() / isKnownValue() / isIgnoredValue() / isLearningValue() (non-throwing, safe on unvalidated input), and definitions() — the single ordered value / name / abbr / cssClass / colour / order / isKnown / isLearning / isIgnored table.
  • TermStatusService & StatusHelper delegate to the VO. getStatuses(), getStatusColor(), isValidStatus() and the is{Learning,Known,Ignored}Status() helpers are now thin adapters; the duplicated name/abbr/colour tables are gone.
  • Scattered literals replaced with TermStatus::isValid() / values() / isKnownValue() / isIgnoredValue() across the Review, Vocabulary and Admin modules.
  • New endpoint GET /api/v1/settings/status-definitions returns TermStatus::definitions().

Frontend

  • New shared/stores/statuses.ts is the single TS source for status labels/abbr/order/class, localized through the shared common.status_* i18n keys (so PHP and TS resolve identical text from one source).
  • text_status_chart.ts, texts_grouped_app.ts, html_utils.ts, term_edit_modal.ts and the app_data.ts statuses proxy now resolve from it.

Scope discipline / what's intentionally left

  • The per-status scheduling formulas are untouched (SCORE_FORMULA_*, calculateScore, makeScoreRandomInsertUpdate) — that's Phase 2.
  • Chart colour palettes (statistics_charts.ts, text_status_chart.ts) are left as-is: they diverge from each other and from the CSS --lwt-status* variables, so unifying them is a visual change, not a model cleanup. The reading view already single-sources its colours from CSS.
  • word_popover.ts / multi_word_modal.ts keep their local lists — those encode popover-specific presentation (Bulma button colours, short Known/Ignore badges), not the status model.

No behaviour or wire-format change in English; the only user-visible nuance is label normalization toward "Learned (5)" consistency and localization of previously-hardcoded English labels.

Verification

All gates green locally: phpcs --standard=PSR12, psalm --threads=1, composer test:no-coverage (9093 pass, 43 skipped — the DB-present local run), npm run typecheck, npm run lint, npm test (4432 pass), npm run build:all, and php bin/check-locales.php (100%). Added TermStatus VO coverage and a status-definitions endpoint test.

Promote the TermStatus value object to the authoritative word-status model
and remove the model's scattered re-definitions across PHP and TypeScript.

Backend:
- TermStatus gains abbreviation/cssClass/colourHex/order/displayName accessors,
  static isValid()/values()/isKnownValue()/isIgnoredValue()/isLearningValue(),
  and a definitions() exporter (the one ordered status table).
- TermStatusService.getStatuses()/getStatusColor()/isValidStatus()/
  is{Learning,Known,Ignored}Status() and StatusHelper now delegate to the VO.
  Scheduling members (SCORE_FORMULA_*, calculateScore, makeScoreRandomInsertUpdate)
  are deliberately untouched — they are Phase 2 (FSRS).
- Replaced in_array($status,[1,2,3,4,5,98,99]), array_fill_keys([...]) and
  === 5 || === 99 / === 98 checks across Review/Vocabulary/Admin with VO calls.
- New endpoint GET /api/v1/settings/status-definitions returns definitions().

Frontend:
- New shared/stores/statuses.ts is the single TS status source (labels/abbr/
  order/class), localized via the shared common.status_* i18n keys.
- text_status_chart.ts, texts_grouped_app.ts, html_utils.ts, term_edit_modal.ts
  and the app_data.ts statuses proxy now resolve from it.

No behaviour or wire-format change. Chart colour palettes and the
popover/multi-word presentation lists are left as documented follow-ups.

Tests: +TermStatus VO coverage, +status-definitions endpoint test.
@HugoFara HugoFara merged commit 0c7b8e4 into main Jun 30, 2026
14 checks passed
@HugoFara HugoFara deleted the refactor/term-status-single-source branch June 30, 2026 23:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant