mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
A ratio (cholesterol/HDL, albumin/globulin) or an index such as INR has no unit, and every lab write path refuses a numeric value without one. That refusal stays: an empty unit usually means the extraction dropped it. Instead the value is stored as the UCUM unity "1", chosen on purpose. The unit field when a marker is defined, on a scanned report's row and in the document review edit now carries a "No unit" checkbox that sets "1". The CSV import takes 1 in the unit column, as the template and the import sheet say; an empty cell is still refused, and other spellings such as "ratio" or "-" stay the literal unit they always were. "1" compares as a unit of its own: it matches only itself, so it is refused under a marker kept in mg/dL and the other way round. Refs #1313
62 lines
2.0 KiB
TypeScript
62 lines
2.0 KiB
TypeScript
/**
|
|
* Shared lab-value number formatting.
|
|
*
|
|
* Every surface that prints a lab reading (the list card, the detail history,
|
|
* the chart tooltip, the doctor report PDF, the clinician share page) prints
|
|
* it through here, so a reading reads the same everywhere. The precision rule
|
|
* is the recorded-number rule in `src/lib/format/recorded-number.ts`: a
|
|
* reading keeps every digit it was stored with (TSH 0.004, PSA 0.034, a
|
|
* troponin of 0.0012 never shortened), and a reading converted from the unit
|
|
* its report printed keeps the precision of the printed figure.
|
|
*
|
|
* The digits themselves come from the caller's locale number formatter, so a
|
|
* German reader sees "1,8 mIU/L" where an English one sees "1.8 mIU/L". This
|
|
* module only decides the precision.
|
|
*/
|
|
import { withLabUnit } from "@/lib/labs/dimensionless";
|
|
import {
|
|
formatRecordedNumber,
|
|
type FractionDigitsFormat,
|
|
} from "@/lib/format/recorded-number";
|
|
|
|
/**
|
|
* A lab number in the reader's locale. `printed` is the figure the source
|
|
* report printed when the number was converted from it (`sourceValue`).
|
|
*/
|
|
export type LabNumberFormat = (
|
|
value: number,
|
|
printed?: number | null,
|
|
) => string;
|
|
|
|
export function formatLabValue(
|
|
value: number,
|
|
formatNumber: FractionDigitsFormat,
|
|
printed?: number | null,
|
|
): string {
|
|
return formatRecordedNumber(value, formatNumber, printed);
|
|
}
|
|
|
|
/**
|
|
* Render a reading's display value: a qualitative row (numeric `value` is
|
|
* null) shows its `valueText` verbatim; a numeric row shows the formatted
|
|
* number plus its unit (none for a dimensionless reading). One helper so the list card, the history rows, and
|
|
* the detail header stay consistent.
|
|
*/
|
|
export function formatLabReading(
|
|
reading: {
|
|
value: number | null;
|
|
valueText: string | null;
|
|
unit: string;
|
|
sourceValue?: number | null;
|
|
},
|
|
formatNumber: LabNumberFormat,
|
|
): string {
|
|
if (reading.value === null) {
|
|
return reading.valueText ?? "";
|
|
}
|
|
return withLabUnit(
|
|
formatNumber(reading.value, reading.sourceValue),
|
|
reading.unit,
|
|
);
|
|
}
|