feat(ui): humidity, CO2 pill per room and 24h pressure sparkline
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -122,3 +122,49 @@ export function msUntil(now, tz, hour, minute = 0) {
|
||||
if (diff <= 0) diff += 86400;
|
||||
return Math.max(1000, diff * 1000 - now.getMilliseconds());
|
||||
}
|
||||
|
||||
/** CO₂-niveau volgens de Netatmo-drempels: tot 1000 goed, tot 1500 matig, daarboven slecht. */
|
||||
export function co2Level(ppm) {
|
||||
if (!isNum(ppm)) return { level: 'unknown', label: DASH };
|
||||
if (ppm <= 1000) return { level: 'good', label: 'goed' };
|
||||
if (ppm <= 1500) return { level: 'medium', label: 'matig' };
|
||||
return { level: 'bad', label: 'slecht' };
|
||||
}
|
||||
|
||||
/** 48 -> "48%"; null -> "–" */
|
||||
export function fPct(v) {
|
||||
return isNum(v) ? `${Math.round(v)}%` : DASH;
|
||||
}
|
||||
|
||||
/** 1014.2 -> "1014 hPa"; null -> "–" */
|
||||
export function fHpa(v) {
|
||||
return isNum(v) ? `${Math.round(v)} hPa` : DASH;
|
||||
}
|
||||
|
||||
/** Laagste en hoogste waarde van een reeks (null-waarden genegeerd), of null zonder geldige waarden. */
|
||||
export function seriesRange(values) {
|
||||
const nums = values.filter(isNum);
|
||||
if (nums.length === 0) return null;
|
||||
return { min: Math.min(...nums), max: Math.max(...nums) };
|
||||
}
|
||||
|
||||
/**
|
||||
* SVG-pad voor een sparkline: punten gelijkmatig over de breedte, waarden geschaald op min..max
|
||||
* met `pad` px marge. Een vlakke reeks wordt een lijn door het midden. Minder dan 2 punten -> "".
|
||||
*/
|
||||
export function sparklinePath(values, w, h, pad = 3) {
|
||||
const range = seriesRange(values);
|
||||
if (!range || values.length < 2) return '';
|
||||
const span = range.max - range.min;
|
||||
const innerW = w - 2 * pad;
|
||||
const innerH = h - 2 * pad;
|
||||
const step = innerW / (values.length - 1);
|
||||
const parts = [];
|
||||
values.forEach((v, i) => {
|
||||
if (!isNum(v)) return;
|
||||
const x = pad + i * step;
|
||||
const y = span === 0 ? h / 2 : pad + innerH - ((v - range.min) / span) * innerH;
|
||||
parts.push(`${parts.length === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`);
|
||||
});
|
||||
return parts.join(' ');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user