Files
Alert-Hub-System/app/static/js/app.js
T

74 lines
2.6 KiB
JavaScript
Raw Normal View History

2026-09-13 19:59:54 +01:00
// ====== Theme toggle =======================================================
(function () {
const btn = document.getElementById('theme-toggle');
if (!btn) return;
btn.addEventListener('click', () => {
const root = document.documentElement;
const next = root.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
root.setAttribute('data-theme', next);
try { localStorage.setItem('alerthub-theme', next); } catch (_) {}
});
})();
// ====== Countdown timer ====================================================
// Each .countdown element has data-expires="YYYY-MM-DD" and renders 4 cells
// for days / hours / minutes / seconds. Updates every second.
(function () {
const els = document.querySelectorAll('.countdown[data-expires]');
if (!els.length) return;
function pad(n) { return n < 10 ? '0' + n : '' + n; }
function render() {
const now = new Date();
els.forEach((el) => {
const target = new Date(el.dataset.expires + 'T23:59:59');
let diff = (target.getTime() - now.getTime()) / 1000;
const card = el.closest('.alert-card');
const negative = diff < 0;
diff = Math.abs(diff);
const days = Math.floor(diff / 86400);
const hours = Math.floor((diff % 86400) / 3600);
const minutes = Math.floor((diff % 3600) / 60);
const seconds = Math.floor(diff % 60);
const segs = el.querySelectorAll('.countdown-value');
if (segs.length === 4) {
segs[0].textContent = days;
segs[1].textContent = pad(hours);
segs[2].textContent = pad(minutes);
segs[3].textContent = pad(seconds);
}
if (card) {
card.classList.remove('is-warning', 'is-critical', 'is-expired');
if (negative) {
card.classList.add('is-expired');
} else if (days < 7) {
card.classList.add('is-critical');
} else if (days < 30) {
card.classList.add('is-warning');
}
}
const dotLabel = el.parentElement && el.parentElement.querySelector('.alert-state-text');
if (dotLabel) {
if (negative) dotLabel.textContent = 'EXPIRED';
else if (days < 7) dotLabel.textContent = 'CRITICAL';
else if (days < 30) dotLabel.textContent = 'WARNING';
else dotLabel.textContent = 'NOMINAL';
}
});
}
render();
setInterval(render, 1000);
})();
// ====== Confirm-on-click for destructive actions ===========================
document.querySelectorAll('form[data-confirm]').forEach((form) => {
form.addEventListener('submit', (e) => {
if (!window.confirm(form.dataset.confirm)) e.preventDefault();
});
});