Files
HealthLog/src/components/labs/reference-range-badge.tsx
T
Marc-André Bombeck b217535b62 chore(v1.22): clear the QA punch-list across Coach, insights, settings
Code-review and design follow-ups before the v1.22 cut. No behaviour change
beyond the items below.

Coach / insights:
- Coach SSE route: a non-provider error raised inside the open producer (e.g. a
  DB failure persisting the reply) now records on the wide event and forwards to
  GlitchTip instead of masquerading as a provider outage; it still surfaces an
  error frame since the stream is open.
- Lab ↔ outcome correlations: hedge faint-tier pairs ("a faint hint, if
  anything … too small to lean on") so the narrated confidence never outruns the
  effect, matching the daily engine.
- Reminder sweep: mint the plan-review reminder and clear the plan's reviewDate
  in one transaction so a half-applied write can't duplicate the reminder.
- Fold the two raw provider-fallback runners onto one shared chain walker.

Design / accessibility:
- Lift sub-44px tap targets to the 44px mobile floor (suggested-action card,
  Coach bubble affordances), brighten the resting timestamp clock for non-text
  contrast, and route the lab chart height through the shared constant.
- Replace ad-hoc arbitrary type sizes with the scale token and static size-11
  icon buttons with the named icon-lg variant.
- Settings: add the missing About card-header descriptions, normalise the
  low-stock numeric widths, and relax the notification-status rows from nested
  cards to a divided list.

Housekeeping:
- Drop three unused exported types (and the now-orphaned source const), re-stamp
  v1.21.5 comments to v1.22, and register the live-judge eval harness as a knip
  entry so the script-only module resolves.
2026-06-27 16:29:58 +02:00

69 lines
2.3 KiB
TypeScript

"use client";
import { ArrowDown, ArrowUp, Minus } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { useTranslations } from "@/lib/i18n/context";
import type { ReferenceRangeStatus } from "@/lib/validations/labs";
/**
* v1.17.1 — reference-range badge.
*
* Renders the server-computed `rangeStatus` as a calm, informative marker.
* The project's no-alarming-colour ethos is a hard rule here: an
* out-of-range value is NOT painted red. It reads as a neutral `secondary`
* badge with a quiet direction arrow (↓ below / ↑ above), exactly the same
* weight as the in-range and unknown states. The number leaving the
* reference window is information a clinician scans — not an alarm to the
* user, who may be perfectly aware of (and managing) the value.
*
* `unknown` (the lab reported no usable bounds) renders nothing — there is
* no verdict to show, and an empty badge would be noise.
*/
export function ReferenceRangeBadge({
status,
compact = false,
}: {
status: ReferenceRangeStatus;
/**
* v1.18.10 (#4) — a quieter, smaller treatment for the labs overview, where
* the badge sits beside the analyte heading and must not compete with it.
* The hero/detail view keeps the default (un-compact) size.
*/
compact?: boolean;
}) {
const { t } = useTranslations();
if (status === "unknown") return null;
// Compact: drop the icon, shrink the text and padding so the badge reads as a
// subtle qualifier of the heading rather than a second focal point.
const compactClass = compact
? "h-auto gap-0.5 px-1.5 py-0 text-xs font-normal [&>svg]:size-2.5"
: "";
if (status === "in-range") {
return (
<Badge
variant="outline"
className={`text-muted-foreground ${compactClass}`.trim()}
>
{compact ? null : <Minus aria-hidden />}
{t("labs.range.inRange")}
</Badge>
);
}
// Below / above — both neutral `secondary`, distinguished only by the
// arrow direction and label. No red, no amber.
const Icon = status === "below" ? ArrowDown : ArrowUp;
const label =
status === "below" ? t("labs.range.below") : t("labs.range.above");
return (
<Badge variant="secondary" className={compactClass || undefined}>
<Icon aria-hidden />
{label}
</Badge>
);
}