settings-site: phase 4 client refactor (split app.js into focused modules, shared dropdown helper, strict-CSP-ready)
This commit is contained in:
52
settings-site/public/js/util.js
Normal file
52
settings-site/public/js/util.js
Normal file
@@ -0,0 +1,52 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
let csrfToken = '';
|
||||
|
||||
async function fetchCsrfToken() {
|
||||
const res = await fetch('/api/csrf-token', { credentials: 'same-origin' });
|
||||
if (!res.ok) throw new Error('Failed to fetch CSRF token');
|
||||
const data = await res.json();
|
||||
csrfToken = data.csrfToken;
|
||||
return csrfToken;
|
||||
}
|
||||
|
||||
function csrfHeaders(base = {}) {
|
||||
return { ...base, 'x-csrf-token': csrfToken };
|
||||
}
|
||||
|
||||
function showToast(message, type = 'success') {
|
||||
const toast = document.createElement('div');
|
||||
toast.className = `toast toast-${type}`;
|
||||
toast.textContent = message;
|
||||
document.getElementById('toast-container').appendChild(toast);
|
||||
setTimeout(() => toast.remove(), 3500);
|
||||
}
|
||||
|
||||
function formatLocalDateTime(d) {
|
||||
const pad = n => String(n).padStart(2, '0');
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
||||
}
|
||||
|
||||
const MOBILE_BREAKPOINT = 900;
|
||||
|
||||
function isMobileViewport() {
|
||||
return window.innerWidth <= MOBILE_BREAKPOINT;
|
||||
}
|
||||
|
||||
function setSidebarOpen(open) {
|
||||
document.body.classList.toggle('sidebar-open', open);
|
||||
const toggle = document.getElementById('menu-toggle');
|
||||
if (toggle) toggle.setAttribute('aria-expanded', String(open));
|
||||
}
|
||||
|
||||
window.Util = {
|
||||
fetchCsrfToken,
|
||||
csrfHeaders,
|
||||
showToast,
|
||||
formatLocalDateTime,
|
||||
isMobileViewport,
|
||||
setSidebarOpen,
|
||||
MOBILE_BREAKPOINT
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user