82 lines
2.5 KiB
JavaScript
82 lines
2.5 KiB
JavaScript
/**
|
|
* Прогноз запаса на /feed_consumption.
|
|
*/
|
|
(function (global) {
|
|
const COPY = () => global.WespAnalyticsCopy || {};
|
|
|
|
function escapeHtml(value) {
|
|
return String(value ?? "")
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">");
|
|
}
|
|
|
|
let forecastByComponentId = {};
|
|
|
|
async function fetchForecast() {
|
|
try {
|
|
const resp = await fetch("/api/analytics/stock-forecast");
|
|
if (!resp.ok) return null;
|
|
return await resp.json();
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function renderBanner(data) {
|
|
const el = document.getElementById("stockForecastBanner");
|
|
if (!el) return;
|
|
const text = (data && data.alertBanner) || "";
|
|
if (!text) {
|
|
el.hidden = true;
|
|
el.textContent = "";
|
|
return;
|
|
}
|
|
el.hidden = false;
|
|
el.innerHTML =
|
|
`<strong>${escapeHtml(COPY().stock?.bannerTitle || "Обратите внимание:")}</strong> ` +
|
|
escapeHtml(text);
|
|
}
|
|
|
|
function applyToCards() {
|
|
document.querySelectorAll(".component-card[data-forecast-key], .component-card[data-component-id]").forEach((card) => {
|
|
const key = card.getAttribute("data-forecast-key") || card.getAttribute("data-component-id");
|
|
const fc = forecastByComponentId[key];
|
|
if (!fc) return;
|
|
const adjEl = card.querySelector("[data-stock-days-adjusted]");
|
|
const explEl = card.querySelector("[data-stock-explanation]");
|
|
const label = fc.daysLeftAdjustedLabel || fc.days_left_adjusted_label;
|
|
if (adjEl && label) {
|
|
adjEl.textContent = label;
|
|
const daysVal = fc.daysLeftAdjusted != null ? fc.daysLeftAdjusted : fc.days_left_adjusted;
|
|
adjEl.closest(".info-item")?.classList.toggle(
|
|
"info-item--warn",
|
|
daysVal != null && daysVal <= 2
|
|
);
|
|
}
|
|
if (explEl && fc.explanation) {
|
|
explEl.textContent = fc.explanation;
|
|
explEl.hidden = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
async function refresh() {
|
|
const data = await fetchForecast();
|
|
forecastByComponentId = {};
|
|
(data?.items || []).forEach((item) => {
|
|
const key = item.forecast_key || item.component_id || item.name_key;
|
|
if (key) forecastByComponentId[key] = item;
|
|
});
|
|
renderBanner(data);
|
|
applyToCards();
|
|
return data;
|
|
}
|
|
|
|
function getForecast(componentId) {
|
|
return forecastByComponentId[componentId] || null;
|
|
}
|
|
|
|
global.WespStockForecast = { refresh, getForecast, applyToCards };
|
|
})(typeof window !== "undefined" ? window : globalThis);
|