diff --git a/pos/app.py b/pos/app.py index fe55968..cb474fd 100644 --- a/pos/app.py +++ b/pos/app.py @@ -66,6 +66,18 @@ def create_app(): def pos_accounting(): return render_template('accounting.html') + @app.route('/pos/dashboard') + def pos_dashboard(): + return render_template('dashboard.html') + + @app.route('/pos/config') + def pos_config(): + return render_template('config.html') + + @app.route('/pos/reports') + def pos_reports(): + return render_template('reports.html') + @app.route('/pos/static/') def pos_static(filename): return send_from_directory('static', filename) diff --git a/pos/static/js/config.js b/pos/static/js/config.js new file mode 100644 index 0000000..ea97695 --- /dev/null +++ b/pos/static/js/config.js @@ -0,0 +1,139 @@ +// /home/Autopartes/pos/static/js/config.js +// Config module: branches, employees, theme, system settings + +const Config = (() => { + const API = '/pos/api/config'; + + 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' }; + } + + // ------------------------------------------------------------------------- + // Theme switcher + // ------------------------------------------------------------------------- + function setTheme(theme) { + document.documentElement.setAttribute('data-theme', theme); + try { localStorage.setItem('nexus-theme', theme); } catch(e) {} + + document.querySelectorAll('.theme-btn').forEach(function(btn) { + btn.classList.toggle('is-active', btn.dataset.themeTarget === theme); + }); + + document.querySelectorAll('.theme-option').forEach(function(opt) { + opt.classList.remove('is-selected'); + }); + var idx = theme === 'industrial' ? 0 : 1; + var opts = document.querySelectorAll('.theme-option'); + if (opts[idx]) opts[idx].classList.add('is-selected'); + } + window.setTheme = setTheme; + + function selectThemeOption(theme) { + setTheme(theme); + } + window.selectThemeOption = selectThemeOption; + + // ------------------------------------------------------------------------- + // Live clock + // ------------------------------------------------------------------------- + function updateClock() { + var now = new Date(); + var hh = String(now.getHours()).padStart(2, '0'); + var mm = String(now.getMinutes()).padStart(2, '0'); + var el = document.getElementById('live-clock'); + if (el) el.textContent = hh + ':' + mm; + } + + // ------------------------------------------------------------------------- + // API calls using existing config_bp endpoints + // ------------------------------------------------------------------------- + async function loadBranches() { + try { + const res = await fetch(`${API}/branches`, { headers: headers() }); + if (!res.ok) throw new Error('Failed to load branches'); + return await res.json(); + } catch (e) { + console.error('Config.loadBranches:', e); + return []; + } + } + + async function loadEmployees() { + try { + const res = await fetch(`${API}/employees`, { headers: headers() }); + if (!res.ok) throw new Error('Failed to load employees'); + return await res.json(); + } catch (e) { + console.error('Config.loadEmployees:', e); + return []; + } + } + + async function saveBranch(data) { + const res = await fetch(`${API}/branches`, { + method: 'POST', + headers: headers(), + body: JSON.stringify(data) + }); + if (!res.ok) { + const err = await res.json().catch(() => ({ error: res.statusText })); + throw new Error(err.error || 'Save failed'); + } + return res.json(); + } + + async function saveEmployee(data) { + const res = await fetch(`${API}/employees`, { + method: 'POST', + headers: headers(), + body: JSON.stringify(data) + }); + if (!res.ok) { + const err = await res.json().catch(() => ({ error: res.statusText })); + throw new Error(err.error || 'Save failed'); + } + return res.json(); + } + + // ------------------------------------------------------------------------- + // Init + // ------------------------------------------------------------------------- + function init() { + if (!checkAuth()) return; + + // Restore theme + try { + var saved = localStorage.getItem('nexus-theme'); + if (saved === 'industrial' || saved === 'modern') { + setTheme(saved); + } + } catch(e) {} + + // Start clock + updateClock(); + setInterval(updateClock, 30000); + + // Load initial data + loadBranches(); + loadEmployees(); + } + + document.addEventListener('DOMContentLoaded', init); + + return { + init, setTheme, selectThemeOption, + loadBranches, loadEmployees, saveBranch, saveEmployee + }; +})(); diff --git a/pos/static/js/dashboard.js b/pos/static/js/dashboard.js new file mode 100644 index 0000000..746b910 --- /dev/null +++ b/pos/static/js/dashboard.js @@ -0,0 +1,113 @@ +// /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 }; +})(); diff --git a/pos/static/js/reports.js b/pos/static/js/reports.js new file mode 100644 index 0000000..46dec64 --- /dev/null +++ b/pos/static/js/reports.js @@ -0,0 +1,99 @@ +// /home/Autopartes/pos/static/js/reports.js +// Reports module: sales reports, inventory reports, financial reports + +const Reports = (() => { + 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) {} + var btnInd = document.getElementById('btn-industrial'); + var btnMod = document.getElementById('btn-modern'); + if (btnInd) btnInd.classList.toggle('is-active', theme === 'industrial'); + if (btnMod) btnMod.classList.toggle('is-active', theme === 'modern'); + } + window.setTheme = setTheme; + + // ------------------------------------------------------------------------- + // Tab switcher + // ------------------------------------------------------------------------- + function switchTab(id, btn) { + document.querySelectorAll('.tab-panel').forEach(function(p) { p.classList.remove('is-active'); }); + document.querySelectorAll('.tab-btn').forEach(function(b) { b.classList.remove('is-active'); }); + var panel = document.getElementById('panel-' + id); + if (panel) panel.classList.add('is-active'); + if (btn) btn.classList.add('is-active'); + } + window.switchTab = switchTab; + + // ------------------------------------------------------------------------- + // Live clock + // ------------------------------------------------------------------------- + function updateClock() { + var el = document.getElementById('live-clock'); + if (!el) return; + var now = new Date(); + var pad = function(n) { return String(n).padStart(2, '0'); }; + el.textContent = pad(now.getHours()) + ':' + pad(now.getMinutes()) + ':' + pad(now.getSeconds()); + } + + // ------------------------------------------------------------------------- + // Placeholder API calls + // ------------------------------------------------------------------------- + async function loadSalesReport(params) { + // TODO: call /pos/api/cashregister/... with date range + } + + async function loadInventoryReport() { + // TODO: call /pos/api/inventory/products for stock report + } + + async function loadFinancialReport(params) { + // TODO: call /pos/api/accounting/... for financial reports + } + + // ------------------------------------------------------------------------- + // Init + // ------------------------------------------------------------------------- + function init() { + if (!checkAuth()) return; + + // Restore theme + try { + var saved = localStorage.getItem('nexus-theme') || 'industrial'; + setTheme(saved); + } catch(e) {} + + // Start clock + updateClock(); + setInterval(updateClock, 1000); + } + + document.addEventListener('DOMContentLoaded', init); + + return { + init, setTheme, switchTab, + loadSalesReport, loadInventoryReport, loadFinancialReport, fmt + }; +})(); diff --git a/pos/templates/accounting.html b/pos/templates/accounting.html index a75d9b3..31524f5 100644 --- a/pos/templates/accounting.html +++ b/pos/templates/accounting.html @@ -1,292 +1,2255 @@ - + - - - Contabilidad - Nexus POS - - + [data-theme="industrial"] .theme-bar { + background: rgba(13, 13, 13, 0.95); + border-bottom-color: var(--color-primary-muted); + } + + .theme-bar__left { + display: flex; + align-items: center; + gap: var(--space-3); + } + + .theme-bar__store { + display: flex; + align-items: center; + gap: var(--space-2); + font-family: var(--font-heading); + font-weight: var(--heading-weight-primary); + font-size: 0.75rem; + letter-spacing: var(--tracking-widest); + text-transform: uppercase; + color: var(--color-text-accent); + } + + .theme-bar__dot { + width: 6px; + height: 6px; + background: var(--color-success); + border-radius: var(--radius-full); + box-shadow: 0 0 6px var(--color-success); + animation: blink 2.5s ease-in-out infinite; + } + + @keyframes blink { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.35; } + } + + .theme-bar__sep { + width: 1px; + height: 16px; + background: var(--color-border); + } + + .theme-bar__label { + font-size: var(--text-caption); + color: var(--color-text-muted); + letter-spacing: var(--tracking-wide); + text-transform: uppercase; + } + + .theme-bar__right { + display: flex; + align-items: center; + gap: var(--space-2); + } + + .theme-btn { + display: inline-flex; + align-items: center; + gap: var(--space-1); + padding: 2px var(--space-3); + border: 1px solid var(--color-border); + border-radius: var(--radius-full); + background: transparent; + color: var(--color-text-secondary); + font-family: var(--font-body); + font-size: var(--text-caption); + font-weight: var(--font-weight-semibold); + cursor: pointer; + transition: var(--transition-fast); + letter-spacing: var(--tracking-wide); + } + + .theme-btn:hover { + border-color: var(--color-primary); + color: var(--color-primary); + } + + .theme-btn.is-active { + background: var(--color-primary); + border-color: var(--color-primary); + color: var(--color-text-inverse); + } + + .theme-btn__swatch { + width: 8px; + height: 8px; + border-radius: var(--radius-full); + } + + .theme-btn--industrial .theme-btn__swatch { background: #F5A623; } + .theme-btn--modern .theme-btn__swatch { background: #FF6B35; } + + /* ========================================================================= + APP LAYOUT + ========================================================================= */ + + .app-shell { + display: flex; + height: 100vh; + padding-top: 36px; + } + + /* ========================================================================= + SIDEBAR + ========================================================================= */ + + .sidebar { + width: 260px; + flex-shrink: 0; + display: flex; + flex-direction: column; + background: var(--color-bg-elevated); + border-right: 1px solid var(--color-border); + overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); + } + + .sidebar::-webkit-scrollbar { width: 4px; } + .sidebar::-webkit-scrollbar-track { background: var(--scrollbar-track); } + .sidebar::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: var(--radius-full); } + + .sidebar__brand { + display: flex; + align-items: center; + gap: var(--space-3); + padding: var(--space-4) var(--space-4) var(--space-3); + border-bottom: 1px solid var(--color-border); + flex-shrink: 0; + } + + .brand-logo { + width: 36px; + height: 36px; + display: flex; + align-items: center; + justify-content: center; + background: var(--color-primary); + color: var(--color-text-inverse); + font-family: var(--font-heading); + font-weight: var(--heading-weight-primary); + font-size: 1.125rem; + letter-spacing: -0.04em; + flex-shrink: 0; + } + + [data-theme="industrial"] .brand-logo { + clip-path: polygon(0 0, calc(100% - 9px) 0, 100% 9px, 100% 100%, 0 100%); + } + + [data-theme="modern"] .brand-logo { + border-radius: var(--radius-md); + } + + .brand-name__primary { + font-family: var(--font-heading); + font-weight: var(--heading-weight-primary); + font-size: 0.9375rem; + letter-spacing: var(--tracking-wide); + text-transform: uppercase; + color: var(--color-text-primary); + line-height: 1; + } + + .brand-name__sub { + font-size: var(--text-caption); + color: var(--color-text-muted); + letter-spacing: var(--tracking-wider); + text-transform: uppercase; + margin-top: 2px; + } + + .sidebar__nav { + flex: 1; + padding: var(--space-3) 0; + } + + .nav-section-label { + padding: var(--space-3) var(--space-4) var(--space-1); + font-size: 0.6875rem; + font-weight: var(--font-weight-semibold); + letter-spacing: var(--tracking-widest); + text-transform: uppercase; + color: var(--color-text-muted); + } + + .nav-item { + display: flex; + align-items: center; + gap: var(--space-3); + padding: var(--space-2) var(--space-4); + color: var(--color-text-secondary); + text-decoration: none; + font-size: var(--text-body-sm); + font-weight: var(--font-weight-regular); + border-left: 3px solid transparent; + transition: var(--transition-fast); + cursor: pointer; + } + + .nav-item:hover { + background: var(--color-surface-2); + color: var(--color-text-primary); + } + + .nav-item.is-active { + background: var(--color-primary-muted); + color: var(--color-primary); + border-left-color: var(--color-primary); + font-weight: var(--font-weight-semibold); + } + + .nav-item__icon { + width: 18px; + height: 18px; + flex-shrink: 0; + opacity: 0.7; + } + + .nav-item.is-active .nav-item__icon { + opacity: 1; + } + + .sidebar__footer { + padding: var(--space-3) var(--space-4); + border-top: 1px solid var(--color-border); + display: flex; + align-items: center; + gap: var(--space-2); + } + + .sidebar__user-avatar { + width: 28px; + height: 28px; + border-radius: var(--radius-full); + background: var(--color-primary); + color: var(--color-text-inverse); + display: flex; + align-items: center; + justify-content: center; + font-size: var(--text-caption); + font-weight: var(--font-weight-bold); + flex-shrink: 0; + } + + .sidebar__user-info { flex: 1; overflow: hidden; } + + .sidebar__user-name { + font-size: var(--text-body-sm); + font-weight: var(--font-weight-semibold); + color: var(--color-text-primary); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .sidebar__user-role { + font-size: var(--text-caption); + color: var(--color-text-muted); + } + + /* ========================================================================= + MAIN CONTENT + ========================================================================= */ + + .main { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; + min-width: 0; + } + + .page-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--space-4) var(--space-6); + background: var(--color-bg-elevated); + border-bottom: 1px solid var(--color-border); + flex-shrink: 0; + } + + [data-theme="industrial"] .page-header { + background: var(--color-surface-1); + } + + .page-header__title-group { display: flex; flex-direction: column; gap: 2px; } + + .page-header__eyebrow { + font-size: var(--text-caption); + font-weight: var(--font-weight-semibold); + letter-spacing: var(--tracking-widest); + text-transform: uppercase; + color: var(--color-text-muted); + } + + .page-header__title { + font-family: var(--font-heading); + font-weight: var(--heading-weight-primary); + font-size: var(--text-h4); + letter-spacing: var(--heading-tracking-h4); + color: var(--color-text-primary); + line-height: 1.2; + } + + [data-theme="industrial"] .page-header__title { + text-transform: uppercase; + } + + .page-header__actions { + display: flex; + align-items: center; + gap: var(--space-3); + } + + /* ---- Summary Cards ---- */ + + .summary-strip { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-4); + padding: var(--space-4) var(--space-6); + background: var(--color-bg-base); + border-bottom: 1px solid var(--color-border); + flex-shrink: 0; + } + + [data-theme="modern"] .summary-strip { + background: transparent; + } + + .summary-card { + background: var(--color-bg-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + padding: var(--space-4) var(--space-5); + display: flex; + align-items: flex-start; + gap: var(--space-3); + box-shadow: var(--shadow-sm); + transition: var(--transition-normal); + } + + .summary-card:hover { + box-shadow: var(--shadow-md); + border-color: var(--color-border-strong); + } + + [data-theme="industrial"] .summary-card { + border-left: 3px solid var(--color-primary); + } + + [data-theme="modern"] .summary-card { + background: var(--color-bg-overlay); + } + + .summary-card__icon { + width: 38px; + height: 38px; + border-radius: var(--radius-md); + background: var(--color-primary-muted); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + } + + .summary-card__icon svg { + width: 20px; + height: 20px; + stroke: var(--color-primary); + fill: none; + stroke-width: 1.75; + stroke-linecap: round; + stroke-linejoin: round; + } + + .summary-card__icon--success { background: rgba(34,197,94,.12); } + .summary-card__icon--success svg { stroke: var(--color-success); } + .summary-card__icon--error { background: rgba(239,68,68,.12); } + .summary-card__icon--error svg { stroke: var(--color-error); } + .summary-card__icon--warning { background: rgba(234,179,8,.12); } + .summary-card__icon--warning svg { stroke: var(--color-warning); } + + .summary-card__body { flex: 1; min-width: 0; } + + .summary-card__label { + font-size: var(--text-caption); + font-weight: var(--font-weight-semibold); + letter-spacing: var(--tracking-wider); + text-transform: uppercase; + color: var(--color-text-muted); + margin-bottom: var(--space-1); + } + + .summary-card__value { + font-family: var(--font-heading); + font-weight: var(--heading-weight-primary); + font-size: 1.5rem; + color: var(--color-text-primary); + line-height: 1.1; + } + + .summary-card__sub { + font-size: var(--text-caption); + color: var(--color-text-muted); + margin-top: 2px; + } + + .summary-card__delta { + font-size: var(--text-caption); + font-weight: var(--font-weight-semibold); + margin-top: 2px; + } + + .summary-card__delta--up { color: var(--color-success); } + .summary-card__delta--down { color: var(--color-error); } + + /* ---- Tabs Row ---- */ + + .tabs-row { + display: flex; + align-items: stretch; + gap: 0; + padding: 0 var(--space-6); + background: var(--color-bg-elevated); + border-bottom: 1px solid var(--color-border); + flex-shrink: 0; + overflow-x: auto; + scrollbar-width: none; + } + + .tabs-row::-webkit-scrollbar { display: none; } + + [data-theme="industrial"] .tabs-row { + background: var(--color-surface-1); + } + + .tab-btn { + display: inline-flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-3) var(--space-4); + border: none; + border-bottom: 2px solid transparent; + background: transparent; + color: var(--color-text-muted); + font-family: var(--font-body); + font-size: var(--text-body-sm); + font-weight: var(--font-weight-semibold); + cursor: pointer; + white-space: nowrap; + transition: var(--transition-fast); + letter-spacing: var(--tracking-wide); + text-transform: uppercase; + position: relative; + } + + .tab-btn:hover { + color: var(--color-text-primary); + background: var(--color-surface-2); + } + + .tab-btn.is-active { + color: var(--color-primary); + border-bottom-color: var(--color-primary); + } + + .tab-btn__badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 18px; + height: 18px; + padding: 0 var(--space-1); + border-radius: var(--radius-full); + background: var(--color-primary-muted); + color: var(--color-primary); + font-size: 0.6875rem; + font-weight: var(--font-weight-bold); + } + + .tab-btn.is-active .tab-btn__badge { + background: var(--color-primary); + color: var(--color-text-inverse); + } + + .tab-btn__badge--alert { + background: rgba(239,68,68,.15); + color: var(--color-error); + } + + .tab-btn.is-active .tab-btn__badge--alert { + background: var(--color-error); + color: #fff; + } + + /* ---- Tab Panels ---- */ + + .tab-panels { + flex: 1; + overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); + } + + .tab-panels::-webkit-scrollbar { width: 6px; } + .tab-panels::-webkit-scrollbar-track { background: var(--scrollbar-track); } + .tab-panels::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: var(--radius-full); } + + .tab-panel { + display: none; + padding: var(--space-5) var(--space-6); + } + + .tab-panel.is-active { + display: block; + } + + /* ========================================================================= + TOOLBAR + ========================================================================= */ + + .toolbar { + display: flex; + align-items: center; + gap: var(--space-3); + margin-bottom: var(--space-4); + flex-wrap: wrap; + } + + .search-box { + display: flex; + align-items: center; + gap: var(--space-2); + background: var(--color-bg-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + padding: 0 var(--space-3); + height: 36px; + flex: 1; + min-width: 200px; + max-width: 360px; + transition: var(--transition-fast); + } + + .search-box:focus-within { + border-color: var(--color-border-focus); + box-shadow: var(--shadow-accent); + } + + .search-box svg { + width: 15px; + height: 15px; + stroke: var(--color-text-muted); + fill: none; + stroke-width: 2; + stroke-linecap: round; + flex-shrink: 0; + } + + .search-box input { + flex: 1; + background: transparent; + border: none; + outline: none; + color: var(--color-text-primary); + font-family: var(--font-body); + font-size: var(--text-body-sm); + } + + .search-box input::placeholder { + color: var(--color-text-muted); + } + + .select-filter { + height: 36px; + padding: 0 var(--space-3); + background: var(--color-bg-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + color: var(--color-text-secondary); + font-family: var(--font-body); + font-size: var(--text-body-sm); + cursor: pointer; + outline: none; + transition: var(--transition-fast); + } + + .select-filter:focus { + border-color: var(--color-border-focus); + box-shadow: var(--shadow-accent); + } + + .toolbar__spacer { flex: 1; } + + /* ========================================================================= + BUTTONS + ========================================================================= */ + + .btn { + display: inline-flex; + align-items: center; + gap: var(--space-2); + padding: 0 var(--space-4); + height: 36px; + border-radius: var(--radius-md); + font-family: var(--font-body); + font-size: var(--text-body-sm); + font-weight: var(--font-weight-semibold); + letter-spacing: var(--tracking-wide); + cursor: pointer; + border: 1px solid transparent; + transition: var(--transition-fast); + text-decoration: none; + white-space: nowrap; + } + + .btn svg { + width: 15px; + height: 15px; + stroke: currentColor; + fill: none; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; + flex-shrink: 0; + } + + .btn--primary { + background: var(--btn-primary-bg); + color: var(--btn-primary-text); + border-color: var(--btn-primary-border); + } + + .btn--primary:hover { + background: var(--btn-primary-bg-hover); + } + + .btn--secondary { + background: var(--btn-secondary-bg); + color: var(--btn-secondary-text); + border-color: var(--btn-secondary-border); + } + + .btn--secondary:hover { + background: var(--btn-secondary-bg-hover); + } + + .btn--ghost { + background: var(--btn-ghost-bg); + color: var(--btn-ghost-text); + border-color: var(--btn-ghost-border); + } + + .btn--ghost:hover { + background: var(--color-surface-2); + border-color: var(--color-border-strong); + color: var(--color-text-primary); + } + + .btn--danger { + background: var(--btn-danger-bg); + color: var(--btn-danger-text); + } + + .btn--sm { + height: 28px; + padding: 0 var(--space-3); + font-size: var(--text-caption); + } + + /* ========================================================================= + DATA TABLE + ========================================================================= */ + + .table-wrapper { + background: var(--color-bg-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + overflow: hidden; + box-shadow: var(--shadow-sm); + } + + [data-theme="modern"] .table-wrapper { + background: var(--color-bg-overlay); + } + + .data-table { + width: 100%; + border-collapse: collapse; + font-size: var(--text-body-sm); + } + + .data-table thead { + background: var(--color-surface-2); + border-bottom: 1px solid var(--color-border); + } + + [data-theme="industrial"] .data-table thead { + background: var(--color-surface-3); + } + + .data-table th { + padding: var(--space-3) var(--space-4); + text-align: left; + font-size: var(--text-caption); + font-weight: var(--font-weight-semibold); + letter-spacing: var(--tracking-wider); + text-transform: uppercase; + color: var(--color-text-muted); + white-space: nowrap; + } + + .data-table th:first-child { padding-left: var(--space-5); } + .data-table th:last-child { padding-right: var(--space-5); } + + .data-table tbody tr { + border-bottom: 1px solid var(--color-border); + transition: background var(--duration-fast) var(--ease-in-out); + } + + .data-table tbody tr:last-child { + border-bottom: none; + } + + .data-table tbody tr:hover { + background: var(--color-surface-2); + } + + .data-table td { + padding: var(--space-3) var(--space-4); + color: var(--color-text-secondary); + vertical-align: middle; + } + + .data-table td:first-child { padding-left: var(--space-5); } + .data-table td:last-child { padding-right: var(--space-5); } + + .data-table .td--primary { + color: var(--color-text-primary); + font-weight: var(--font-weight-semibold); + } + + .data-table .td--mono { + font-family: var(--font-mono); + font-size: 0.8125rem; + color: var(--color-text-accent); + } + + .data-table .td--amount { + font-family: var(--font-mono); + font-size: 0.8125rem; + color: var(--color-text-primary); + font-weight: var(--font-weight-semibold); + } + + .data-table .td--right { + text-align: right; + } + + /* ========================================================================= + BADGES + ========================================================================= */ + + .badge { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px var(--space-2); + border-radius: var(--radius-full); + font-size: 0.6875rem; + font-weight: var(--font-weight-bold); + letter-spacing: var(--tracking-wide); + text-transform: uppercase; + white-space: nowrap; + } + + .badge::before { + content: ''; + width: 5px; + height: 5px; + border-radius: var(--radius-full); + background: currentColor; + flex-shrink: 0; + } + + .badge--ok { + background: rgba(34, 197, 94, 0.15); + color: var(--color-success); + } + + .badge--pending { + background: var(--color-primary-muted); + color: var(--color-primary); + } + + .badge--overdue { + background: rgba(239, 68, 68, 0.15); + color: var(--color-error); + } + + .badge--partial { + background: rgba(234, 179, 8, 0.15); + color: var(--color-warning); + } + + .badge--info { + background: rgba(99, 102, 241, 0.15); + color: #818cf8; + } + + .badge--closed { + background: rgba(115, 115, 115, 0.15); + color: var(--color-text-muted); + } + + /* ========================================================================= + PAGINATION + ========================================================================= */ + + .pagination { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--space-3) var(--space-5); + border-top: 1px solid var(--color-border); + font-size: var(--text-caption); + color: var(--color-text-muted); + } + + .pagination__pages { + display: flex; + align-items: center; + gap: var(--space-1); + } + + .pagination__btn { + width: 28px; + height: 28px; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + background: transparent; + color: var(--color-text-secondary); + font-size: var(--text-caption); + cursor: pointer; + transition: var(--transition-fast); + } + + .pagination__btn:hover { + border-color: var(--color-primary); + color: var(--color-primary); + } + + .pagination__btn.is-active { + background: var(--color-primary); + border-color: var(--color-primary); + color: var(--color-text-inverse); + } + + /* ========================================================================= + FINANCIAL CARDS / REPORT PANELS + ========================================================================= */ + + .finance-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: var(--space-4); + } + + .finance-card { + background: var(--color-bg-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + padding: var(--space-5); + box-shadow: var(--shadow-sm); + } + + [data-theme="modern"] .finance-card { + background: var(--color-bg-overlay); + } + + .finance-card__header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: var(--space-4); + } + + .finance-card__title { + font-family: var(--font-heading); + font-weight: var(--heading-weight-secondary); + font-size: var(--text-body); + color: var(--color-text-primary); + text-transform: uppercase; + letter-spacing: var(--tracking-wide); + } + + .finance-card__row { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--space-2) 0; + border-bottom: 1px solid var(--color-border); + font-size: var(--text-body-sm); + } + + .finance-card__row:last-child { + border-bottom: none; + } + + .finance-card__row--total { + border-top: 2px solid var(--color-border-strong); + border-bottom: none; + font-weight: var(--font-weight-bold); + padding-top: var(--space-3); + margin-top: var(--space-2); + } + + .finance-card__row-label { + color: var(--color-text-secondary); + } + + .finance-card__row-value { + font-family: var(--font-mono); + font-weight: var(--font-weight-semibold); + color: var(--color-text-primary); + } + + .finance-card__row-value--positive { color: var(--color-success); } + .finance-card__row-value--negative { color: var(--color-error); } + + /* Balance sheet indented rows */ + .finance-card__row--indent { + padding-left: var(--space-5); + } + + .finance-card__row--section { + font-weight: var(--font-weight-semibold); + color: var(--color-text-primary); + padding-top: var(--space-3); + margin-top: var(--space-2); + border-top: 1px solid var(--color-border); + border-bottom: none; + } + + /* ========================================================================= + CHART PLACEHOLDER + ========================================================================= */ + + .chart-placeholder { + background: var(--color-bg-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + padding: var(--space-8); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: var(--space-3); + min-height: 200px; + box-shadow: var(--shadow-sm); + } + + [data-theme="modern"] .chart-placeholder { + background: var(--color-bg-overlay); + } + + .chart-placeholder svg { + width: 48px; + height: 48px; + stroke: var(--color-text-muted); + fill: none; + stroke-width: 1.5; + stroke-linecap: round; + stroke-linejoin: round; + opacity: 0.5; + } + + .chart-placeholder__label { + font-size: var(--text-body-sm); + color: var(--color-text-muted); + font-style: italic; + } + + /* ========================================================================= + CONCILIATION MATCH ROWS + ========================================================================= */ + + .match-row { + display: grid; + grid-template-columns: 1fr auto 1fr; + gap: var(--space-4); + align-items: center; + padding: var(--space-3) var(--space-4); + background: var(--color-bg-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + margin-bottom: var(--space-3); + } + + [data-theme="modern"] .match-row { + background: var(--color-bg-overlay); + } + + .match-row__side { + display: flex; + flex-direction: column; + gap: 2px; + } + + .match-row__label { + font-size: var(--text-caption); + color: var(--color-text-muted); + text-transform: uppercase; + letter-spacing: var(--tracking-wider); + } + + .match-row__amount { + font-family: var(--font-mono); + font-weight: var(--font-weight-semibold); + color: var(--color-text-primary); + } + + .match-row__desc { + font-size: var(--text-caption); + color: var(--color-text-secondary); + } + + .match-row__connector { + display: flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + border-radius: var(--radius-full); + background: var(--color-primary-muted); + } + + .match-row__connector svg { + width: 18px; + height: 18px; + stroke: var(--color-primary); + fill: none; + stroke-width: 2; + stroke-linecap: round; + } + + .match-row--matched { + border-color: var(--color-success); + background: rgba(34, 197, 94, 0.04); + } + + .match-row--unmatched { + border-color: var(--color-warning); + } + + /* ========================================================================= + CHECKLIST (Cierre de Mes) + ========================================================================= */ + + .checklist { + display: flex; + flex-direction: column; + gap: var(--space-3); + } + + .checklist-item { + display: flex; + align-items: center; + gap: var(--space-3); + padding: var(--space-3) var(--space-4); + background: var(--color-bg-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + transition: var(--transition-fast); + } + + [data-theme="modern"] .checklist-item { + background: var(--color-bg-overlay); + } + + .checklist-item:hover { + border-color: var(--color-border-strong); + } + + .checklist-item__check { + width: 22px; + height: 22px; + border-radius: var(--radius-sm); + border: 2px solid var(--color-border-strong); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + cursor: pointer; + transition: var(--transition-fast); + } + + .checklist-item__check svg { + width: 14px; + height: 14px; + stroke: transparent; + stroke-width: 2.5; + fill: none; + stroke-linecap: round; + stroke-linejoin: round; + } + + .checklist-item--done .checklist-item__check { + background: var(--color-success); + border-color: var(--color-success); + } + + .checklist-item--done .checklist-item__check svg { + stroke: #fff; + } + + .checklist-item__body { flex: 1; } + + .checklist-item__title { + font-weight: var(--font-weight-semibold); + color: var(--color-text-primary); + font-size: var(--text-body-sm); + } + + .checklist-item--done .checklist-item__title { + text-decoration: line-through; + color: var(--color-text-muted); + } + + .checklist-item__desc { + font-size: var(--text-caption); + color: var(--color-text-muted); + margin-top: 2px; + } + + .checklist-item__badge { + flex-shrink: 0; + } + + /* ========================================================================= + SECTION HEADER (within tabs) + ========================================================================= */ + + .section-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: var(--space-4); + } + + .section-title { + font-family: var(--font-heading); + font-weight: var(--heading-weight-secondary); + font-size: var(--text-h5); + color: var(--color-text-primary); + letter-spacing: var(--heading-tracking-h5); + } + + [data-theme="industrial"] .section-title { + text-transform: uppercase; + } + + /* ========================================================================= + RESPONSIVE + ========================================================================= */ + + @media (max-width: 1024px) { + .sidebar { width: 60px; } + .brand-name__primary, + .brand-name__sub, + .nav-section-label, + .sidebar__user-info { display: none; } + .sidebar__brand { justify-content: center; padding: var(--space-3); } + .nav-item { justify-content: center; padding: var(--space-2) var(--space-2); border-left: none; border-bottom: 3px solid transparent; } + .nav-item.is-active { border-left: none; border-bottom-color: var(--color-primary); } + .sidebar__footer { justify-content: center; } + .summary-strip { grid-template-columns: repeat(2, 1fr); } + } + + @media (max-width: 768px) { + .summary-strip { grid-template-columns: 1fr; } + .finance-grid { grid-template-columns: 1fr; } + } + + + -
-
-

Contabilidad

-
- POS - Facturacion -
-
-
-
Catalogo de Cuentas
-
Polizas
-
Balanza
-
Estado de Resultados
-
Balance General
-
Antiguedad Saldos
-
Periodos
-
+ - -
-
-

Catalogo de Cuentas

- -
-
-
- - -
-
-

Polizas Contables

- -
-
- - - - - - -
-
-
-
- - -
-

Balanza de Comprobacion

-
- - - - - -
-
-
- - -
-

Estado de Resultados

-
- - - - - -
-
-
- - -
-

Balance General

-
- - - -
-
-
- - -
-

Antiguedad de Saldos

-
-
- - -
-

Periodos Fiscales

-
-
- - - - -
-
-
-
+
+
+
+ + Nexus Autoparts +
+
+ Design System Preview
- - - - -
-