Replace 5 POS templates with updated design system pages using tokens.css. Add routes for dashboard, config, and reports pages. Create stub JS files for dashboard, config, and reports modules. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
114 lines
4.0 KiB
JavaScript
114 lines
4.0 KiB
JavaScript
// /home/Autopartes/pos/static/js/dashboard.js
|
|
// Dashboard module: KPIs, charts, summary data
|
|
|
|
const Dashboard = (() => {
|
|
function token() {
|
|
return localStorage.getItem('pos_token') || '';
|
|
}
|
|
|
|
function checkAuth() {
|
|
if (!token()) {
|
|
window.location.href = '/pos/login';
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function headers() {
|
|
return { 'Authorization': `Bearer ${token()}`, 'Content-Type': 'application/json' };
|
|
}
|
|
|
|
function fmt(n) {
|
|
return parseFloat(n || 0).toLocaleString('es-MX', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Theme switcher
|
|
// -------------------------------------------------------------------------
|
|
function setTheme(theme) {
|
|
document.documentElement.setAttribute('data-theme', theme);
|
|
try { localStorage.setItem('nexus-theme', theme); } catch(e) {}
|
|
const btnInd = document.getElementById('btn-industrial');
|
|
const btnMod = document.getElementById('btn-modern');
|
|
if (btnInd) btnInd.classList.toggle('active', theme === 'industrial');
|
|
if (btnMod) btnMod.classList.toggle('active', theme === 'modern');
|
|
}
|
|
window.setTheme = setTheme;
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Sidebar toggle (mobile)
|
|
// -------------------------------------------------------------------------
|
|
function toggleSidebar() {
|
|
const sidebar = document.getElementById('sidebar');
|
|
const overlay = document.getElementById('sidebar-overlay');
|
|
if (!sidebar) return;
|
|
const isOpen = sidebar.classList.contains('open');
|
|
sidebar.classList.toggle('open', !isOpen);
|
|
if (overlay) overlay.classList.toggle('open', !isOpen);
|
|
document.body.style.overflow = isOpen ? '' : 'hidden';
|
|
}
|
|
window.toggleSidebar = toggleSidebar;
|
|
|
|
function closeSidebar() {
|
|
const sidebar = document.getElementById('sidebar');
|
|
const overlay = document.getElementById('sidebar-overlay');
|
|
if (sidebar) sidebar.classList.remove('open');
|
|
if (overlay) overlay.classList.remove('open');
|
|
document.body.style.overflow = '';
|
|
}
|
|
window.closeSidebar = closeSidebar;
|
|
|
|
window.addEventListener('resize', function() {
|
|
if (window.innerWidth >= 768) closeSidebar();
|
|
});
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Period selector
|
|
// -------------------------------------------------------------------------
|
|
function setPeriod(btn) {
|
|
btn.closest('.period-selector').querySelectorAll('.period-btn').forEach(function(b) {
|
|
b.classList.remove('active');
|
|
});
|
|
btn.classList.add('active');
|
|
}
|
|
window.setPeriod = setPeriod;
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Placeholder API calls
|
|
// -------------------------------------------------------------------------
|
|
async function loadSalesSummary() {
|
|
// TODO: call /pos/api/cashregister/summary or similar
|
|
}
|
|
|
|
async function loadTopProducts() {
|
|
// TODO: call /pos/api/inventory/products?sort=sold
|
|
}
|
|
|
|
async function loadRecentSales() {
|
|
// TODO: call /pos/api/cashregister/recent
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Init
|
|
// -------------------------------------------------------------------------
|
|
function init() {
|
|
if (!checkAuth()) return;
|
|
|
|
// Restore theme
|
|
try {
|
|
const saved = localStorage.getItem('nexus-theme');
|
|
if (saved === 'industrial' || saved === 'modern') {
|
|
setTheme(saved);
|
|
}
|
|
} catch(e) {}
|
|
|
|
loadSalesSummary();
|
|
loadTopProducts();
|
|
loadRecentSales();
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', init);
|
|
|
|
return { init, loadSalesSummary, loadTopProducts, loadRecentSales, setTheme };
|
|
})();
|