"use client"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { useTranslations } from "@/lib/i18n/context"; /** * A horizontal range bar with green/yellow/red zones showing where * the current value falls relative to a target range. The marker dot * carries a tooltip with the current value + the target range + a * delta sentence (e.g. "6 mmHg above target band"). * * Behaviour is unchanged from the v1.4.22 inline version; only the * file boundary moves. */ export interface RangeBarProps { value: number; min: number; max: number; unit: string; orangeMin?: number; orangeMax?: number; } export function RangeBar({ value, min, max, unit, orangeMin, orangeMax, }: RangeBarProps) { const { t } = useTranslations(); const span = max - min; const defaultOrangeWidth = span * 0.3; const computedOrangeMin = min - defaultOrangeWidth; const computedOrangeMax = max + defaultOrangeWidth; const effectiveOrangeMin = orangeMin != null ? Math.min(orangeMin, min) : computedOrangeMin; const effectiveOrangeMax = orangeMax != null ? Math.max(orangeMax, max) : computedOrangeMax; const orangeSpan = Math.max(1, effectiveOrangeMax - effectiveOrangeMin); const sidePadding = Math.max(1, orangeSpan * 0.18); const visualMin = effectiveOrangeMin - sidePadding; const visualMax = effectiveOrangeMax + sidePadding; const visualSpan = visualMax - visualMin; const clampedValue = Math.max(visualMin, Math.min(visualMax, value)); const rawPosition = ((clampedValue - visualMin) / visualSpan) * 100; const EDGE_PADDING_PERCENT = 4; const position = Math.max( EDGE_PADDING_PERCENT, Math.min(100 - EDGE_PADDING_PERCENT, rawPosition), ); // Zone boundaries (percent of visual bar) const greenStart = Math.max(0, ((min - visualMin) / visualSpan) * 100); const greenEnd = Math.min(100, ((max - visualMin) / visualSpan) * 100); const yellowLeftStart = Math.max( 0, ((effectiveOrangeMin - visualMin) / visualSpan) * 100, ); const yellowRightEnd = Math.min( 100, ((effectiveOrangeMax - visualMin) / visualSpan) * 100, ); // Determine marker color const inGreen = value >= min && value <= max; const inYellow = !inGreen && value >= effectiveOrangeMin && value <= effectiveOrangeMax; const markerColor = inGreen ? "var(--dracula-green)" : inYellow ? "var(--dracula-orange)" : "var(--dracula-red)"; const minLabelPosition = Math.max(5, Math.min(95, greenStart)); const maxLabelPosition = Math.max(5, Math.min(95, greenEnd)); // Delta to target range const delta = value < min ? min - value : value > max ? value - max : 0; const deltaText = delta > 0 ? value < min ? t("targets.belowTarget", { delta: delta.toFixed(1), unit }) : t("targets.aboveTarget", { delta: delta.toFixed(1), unit }) : t("targets.inTarget"); return (
{/* Red background (full bar) — Dracula `--dracula-red` so the chart palette stays aligned with PR-badge, alerts, and the marker dot itself. Raw Tailwind palettes drift from the theme over time and never get dark-mode tuned. */}
{/* Orange (caution) side zones — `--dracula-orange` matches the marker's out-of-band tint. */}
{/* In-band green zone — `--dracula-green`. */}
{/* Current value marker with tooltip */}

{t("targets.currentValue", { value: String(value), unit })}

{t("targets.targetRangeValue", { min: String(min), max: String(max), unit, })}

{deltaText}

{min} {unit} {max} {unit}
); }