Initial commit with Dockerfile and demo code

This commit is contained in:
2026-08-28 18:16:30 +05:30
commit cf2575fd4e
53 changed files with 11602 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
/**
* 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 (
<div className="meter">
<span style={{ width: `${Math.max(0, Math.min(100, value))}%`, background: color }} />
</div>
);
}
/** 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 <div className="card"><div className="empty">Waiting for telemetry…</div></div>;
}
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 (
<div className="kpi-row">
<div className="tile hero">
<span className="label">OEE · rolling {Math.round(windowSec / 60)} min</span>
<span className="value" style={{ color: factorColor(kpi.oee) }}>
{(kpi.oee * 100).toFixed(1)}<span className="unit">%</span>
</span>
<Meter value={kpi.oee * 100} color={factorColor(kpi.oee)} />
<span className="foot">Availability × Performance × Quality</span>
</div>
{factors.map((f) => (
<div className="tile" key={f.label}>
<span className="label">{f.label}</span>
<span className="value">{(f.v * 100).toFixed(1)}<span className="unit">%</span></span>
<Meter value={f.v * 100} color={factorColor(f.v)} />
<span className="foot">{f.foot}</span>
</div>
))}
<div className="tile">
<span className="label">Output</span>
<span className="value">{kpi.throughputPerHour.toFixed(0)}<span className="unit">/h</span></span>
<span className="foot">
{kpi.good.toLocaleString()} good · {kpi.rejected.toLocaleString()} rejected
</span>
</div>
<div className="tile">
<span className="label">Energy</span>
<span className="value">{kpi.energyKw.toFixed(0)}<span className="unit">kW</span></span>
<span className="foot">
{kpi.energyPerUnit > 0 ? `${kpi.energyPerUnit.toFixed(3)} kWh/unit` : '—'}
</span>
</div>
</div>
);
}