/**
* Line KPI tiles.
*
* OEE gets a hero figure; its three factors sit beside it as their own tiles with
* magnitude meters. Deliberately tiles rather than a chart: these are five
* single headline numbers, and a bar chart of five unrelated measures would be
* harder to read, not easier.
*/
import { useStore } from '../store.js';
function Meter({ value, color }) {
return (
);
}
/** Colour the OEE factors by how bad the loss is, always beside a number. */
function factorColor(v) {
if (v >= 0.95) return 'var(--good)';
if (v >= 0.85) return 'var(--series-1)';
if (v >= 0.70) return 'var(--warning)';
return 'var(--critical)';
}
export function KpiRow() {
const kpi = useStore((s) => (s.frame ? s.frame.kpi : null));
const windowSec = useStore((s) => (s.meta ? s.meta.kpiWindowSec : 1200));
if (!kpi) {
return ;
}
const factors = [
{ label: 'Availability', v: kpi.availability, foot: 'Stoppage losses' },
{ label: 'Performance', v: kpi.performance, foot: 'Micro-stops, slow cycles' },
{ label: 'Quality', v: kpi.quality, foot: 'Rejects at INS-04' },
];
return (
OEE · rolling {Math.round(windowSec / 60)} min
{(kpi.oee * 100).toFixed(1)}%
Availability × Performance × Quality
{factors.map((f) => (
{f.label}
{(f.v * 100).toFixed(1)}%
{f.foot}
))}
Output
{kpi.throughputPerHour.toFixed(0)}/h
{kpi.good.toLocaleString()} good · {kpi.rejected.toLocaleString()} rejected
Energy
{kpi.energyKw.toFixed(0)}kW
{kpi.energyPerUnit > 0 ? `${kpi.energyPerUnit.toFixed(3)} kWh/unit` : '—'}
);
}