work : виджет стал более "горизонтальным"
This commit is contained in:
@@ -220,6 +220,48 @@ export function airQuality(co2) {
|
||||
return { label: "Нужна вентиляция", tone: "bad", pct: Math.min(100, value / 20) };
|
||||
}
|
||||
|
||||
const AIR_METER_STOPS = [
|
||||
[400, [35, 143, 83]],
|
||||
[700, [46, 166, 99]],
|
||||
[820, [82, 181, 111]],
|
||||
[900, [190, 153, 55]],
|
||||
[1200, [214, 128, 45]],
|
||||
[1500, [215, 83, 55]],
|
||||
[2000, [188, 48, 72]],
|
||||
];
|
||||
|
||||
const interpolateChannel = (start, end, amount) => Math.round(start + (end - start) * amount);
|
||||
|
||||
export function airMeterPalette(co2) {
|
||||
const value = Number(co2);
|
||||
if (!Number.isFinite(value)) {
|
||||
return {
|
||||
color: "rgb(105, 137, 158)",
|
||||
glow: "rgba(83, 123, 150, .2)",
|
||||
};
|
||||
}
|
||||
|
||||
const bounded = Math.max(AIR_METER_STOPS[0][0], Math.min(AIR_METER_STOPS.at(-1)[0], value));
|
||||
let lower = AIR_METER_STOPS[0];
|
||||
let upper = AIR_METER_STOPS.at(-1);
|
||||
|
||||
for (let index = 1; index < AIR_METER_STOPS.length; index += 1) {
|
||||
if (bounded <= AIR_METER_STOPS[index][0]) {
|
||||
lower = AIR_METER_STOPS[index - 1];
|
||||
upper = AIR_METER_STOPS[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const amount = upper[0] === lower[0] ? 0 : (bounded - lower[0]) / (upper[0] - lower[0]);
|
||||
const [red, green, blue] = lower[1].map((channel, index) => interpolateChannel(channel, upper[1][index], amount));
|
||||
|
||||
return {
|
||||
color: `rgb(${red}, ${green}, ${blue})`,
|
||||
glow: `rgba(${red}, ${green}, ${blue}, .26)`,
|
||||
};
|
||||
}
|
||||
|
||||
export function modeInfo(status) {
|
||||
const schedule = status?.schedule || {};
|
||||
if (!schedule.available) return { label: "Без расписания", detail: "Недоступно", tone: "muted" };
|
||||
|
||||
+8
-4
@@ -1,4 +1,4 @@
|
||||
import { api, airQuality, configureTheme, isDemo, modeInfo, numberOrDash, setRangeProgress, showToast } from "./api.js";
|
||||
import { api, airMeterPalette, airQuality, configureTheme, isDemo, modeInfo, numberOrDash, setRangeProgress, showToast } from "./api.js";
|
||||
|
||||
const $ = selector => document.querySelector(selector);
|
||||
configureTheme($("#theme-button"));
|
||||
@@ -27,7 +27,6 @@ if (isDemo) $("#demo-note").hidden = false;
|
||||
|
||||
function text(selector, value) { $(selector).textContent = value; }
|
||||
function setPill(selector, label, tone) { const element = $(selector); element.textContent = label; element.className = `pill ${tone}`; }
|
||||
function toneColor(tone) { return `var(--${tone === "bad" ? "red" : tone === "warn" ? "orange" : tone === "good" ? "green" : tone === "info" ? "blue" : "muted"})`; }
|
||||
|
||||
function toggle(selector, active, label = "") {
|
||||
const button = $(selector);
|
||||
@@ -63,11 +62,16 @@ function actionLabel(value) {
|
||||
|
||||
function renderAir(sensor, tion) {
|
||||
const quality = airQuality(sensor.co2);
|
||||
const airTone = ["good", "warn", "bad"].includes(quality.tone) ? quality.tone : "muted";
|
||||
const airPalette = airMeterPalette(sensor.co2);
|
||||
const airCard = $(".co2-card");
|
||||
text("#co2", numberOrDash(sensor.co2));
|
||||
text("#air-label", quality.label);
|
||||
text("#air-advice", quality.tone === "good" ? "Проветривание работает нормально" : quality.tone === "warn" ? "Автоматика при необходимости повысит скорость" : quality.tone === "bad" ? "Рекомендуется усилить вентиляцию" : "Ожидаем показания датчика");
|
||||
$("#air-label").style.color = toneColor(quality.tone);
|
||||
$("#air-label").style.background = `var(--${quality.tone === "bad" ? "red" : quality.tone === "warn" ? "orange" : quality.tone === "good" ? "green" : "glass"}-soft)`;
|
||||
$("#air-label").className = `quality-chip ${airTone}`;
|
||||
airCard.dataset.airTone = airTone;
|
||||
airCard.style.setProperty("--air-color", airPalette.color);
|
||||
airCard.style.setProperty("--air-glow", airPalette.glow);
|
||||
$("#co2-progress").style.width = `${Math.max(0, Math.min(100, quality.pct))}%`;
|
||||
setPill("#sensor-status", sensor.online ? "Online" : "Offline", sensor.online ? "good" : "bad");
|
||||
text("#room-temp", numberOrDash(sensor.temperature ?? tion.in_temp, 1));
|
||||
|
||||
+8
-2
@@ -1,4 +1,4 @@
|
||||
import { api, airQuality, configureTheme, isDemo, modeInfo, numberOrDash, panelUrl, showToast } from "./api.js";
|
||||
import { api, airMeterPalette, airQuality, configureTheme, isDemo, modeInfo, numberOrDash, panelUrl, showToast } from "./api.js";
|
||||
|
||||
const requestedLayout = new URLSearchParams(window.location.search).get("layout");
|
||||
const layoutMode = ["horizontal", "vertical"].includes(requestedLayout) ? requestedLayout : null;
|
||||
@@ -75,7 +75,13 @@ function render(status) {
|
||||
|
||||
setText("#co2", numberOrDash(sensor.co2));
|
||||
setText("#air-label", quality.label);
|
||||
$("#air-label").className = `quality-chip ${toneClass(quality.tone)}`;
|
||||
const airTone = toneClass(quality.tone);
|
||||
const airPalette = airMeterPalette(sensor.co2);
|
||||
const airCard = $(".air-card");
|
||||
$("#air-label").className = `quality-chip ${airTone}`;
|
||||
airCard.dataset.airTone = airTone;
|
||||
airCard.style.setProperty("--air-color", airPalette.color);
|
||||
airCard.style.setProperty("--air-glow", airPalette.glow);
|
||||
$("#co2-progress").style.width = `${Math.max(0, Math.min(100, quality.pct))}%`;
|
||||
setText("#room-temp", numberOrDash(sensor.temperature ?? tion.in_temp, 1));
|
||||
setText("#humidity", numberOrDash(sensor.humidity));
|
||||
|
||||
Reference in New Issue
Block a user