Files
foodlinkk-command-center/cockpit/static/js/dashboard-layout.js
T
2026-06-09 10:41:13 +00:00

98 lines
3.5 KiB
JavaScript

(function (global) {
var WIDGET_META = {
kpis: { title: 'CEO KPI\'s', icon: '📊' },
executive: { title: 'Alles op een rij', icon: '📋' },
briefing: { title: 'Herman briefing', icon: '📝' },
retail: { title: 'Retail operatie', icon: '🏪' },
analytics: { title: 'Data & analytics', icon: '📈' },
approvals: { title: 'Agent goedkeuringen', icon: '✓' },
feed: { title: 'Agent feed', icon: '⚡' },
};
function loadPrefs() {
return fetch('/api/preferences/ui').then(function (r) { return r.json(); }).catch(function () {
return { dashboard_layout: Object.keys(WIDGET_META), global_viz_mode: 'neo-bars', viz_modes: {} };
});
}
function saveLayout(order) {
return fetch('/api/preferences/ui', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ dashboard_layout: order }),
});
}
function saveViz(globalMode, vizModes) {
return fetch('/api/preferences/ui', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ global_viz_mode: globalMode, viz_modes: vizModes || {} }),
});
}
function applyOrder(container, order) {
if (!container) return;
var map = {};
Array.from(container.children).forEach(function (el) {
if (el.dataset && el.dataset.widget) map[el.dataset.widget] = el;
});
order.forEach(function (id) {
if (map[id]) container.appendChild(map[id]);
});
}
function initDrag(container, onReorder) {
if (!container) return;
var dragEl = null;
Array.from(container.querySelectorAll('[data-widget]')).forEach(function (el) {
el.setAttribute('draggable', 'true');
el.classList.add('hm-widget-draggable');
el.addEventListener('dragstart', function (ev) {
dragEl = el;
el.classList.add('hm-widget-dragging');
ev.dataTransfer.effectAllowed = 'move';
});
el.addEventListener('dragend', function () {
el.classList.remove('hm-widget-dragging');
dragEl = null;
var order = Array.from(container.querySelectorAll('[data-widget]')).map(function (n) { return n.dataset.widget; });
if (onReorder) onReorder(order);
});
el.addEventListener('dragover', function (ev) {
ev.preventDefault();
if (!dragEl || dragEl === el) return;
var rect = el.getBoundingClientRect();
var after = ev.clientY > rect.top + rect.height / 2;
if (after) el.after(dragEl); else el.before(dragEl);
});
});
}
function buildVizSelector(container, prefs, onChange) {
if (!container || !global.VizEngine) return;
container.innerHTML = '<label class="viz-global-label">Visualisatie:</label>' +
global.VizEngine.MODES.map(function (m) {
var active = prefs.global_viz_mode === m.id ? ' active' : '';
return '<button type="button" class="viz-mode-btn' + active + '" data-viz="' + m.id + '">' + m.label + '</button>';
}).join('');
container.querySelectorAll('.viz-mode-btn').forEach(function (btn) {
btn.addEventListener('click', function () {
container.querySelectorAll('.viz-mode-btn').forEach(function (b) { b.classList.remove('active'); });
btn.classList.add('active');
if (onChange) onChange(btn.dataset.viz);
});
});
}
global.DashboardLayout = {
WIDGET_META: WIDGET_META,
loadPrefs: loadPrefs,
saveLayout: saveLayout,
saveViz: saveViz,
applyOrder: applyOrder,
initDrag: initDrag,
buildVizSelector: buildVizSelector,
};
})(window);