From f88d5eb6b65fc2c2bca161da121b8e6401d1085b Mon Sep 17 00:00:00 2001 From: consultoria-as Date: Tue, 17 Feb 2026 07:18:30 +0000 Subject: [PATCH] Add dashboard with recent invoices, top suppliers, and summary stats Clicking a supplier navigates to facturas filtered by that provider. Co-Authored-By: Claude Opus 4.6 --- src/index.js | 2 + src/public/css/styles.css | 109 +++++++++++++++++++++++++++ src/public/index.html | 4 + src/public/js/app.js | 152 ++++++++++++++++++++++++++++++++++++-- src/routes/dashboard.js | 57 ++++++++++++++ 5 files changed, 319 insertions(+), 5 deletions(-) create mode 100644 src/routes/dashboard.js diff --git a/src/index.js b/src/index.js index f991750..0b708cd 100644 --- a/src/index.js +++ b/src/index.js @@ -7,6 +7,7 @@ const { articulosRouter } = require('./routes/articulos'); const { catalogoRouter } = require('./routes/catalogo'); const { configRouter } = require('./routes/config'); const { printRouter } = require('./routes/print'); +const { dashboardRouter } = require('./routes/dashboard'); const app = express(); const PORT = process.env.PORT || 3000; @@ -20,6 +21,7 @@ app.use(express.json()); app.use(express.static(path.join(__dirname, 'public'))); // API Routes +app.use('/api/dashboard', dashboardRouter(db)); app.use('/api/facturas', facturasRouter(db)); app.use('/api/articulos', articulosRouter(db)); app.use('/api/catalogo', catalogoRouter(db)); diff --git a/src/public/css/styles.css b/src/public/css/styles.css index b0592c0..8bf64bb 100644 --- a/src/public/css/styles.css +++ b/src/public/css/styles.css @@ -686,6 +686,107 @@ input[type="checkbox"] { align-items: center; } +/* ---- Dashboard ---- */ +.dashboard-stats { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 16px; + margin-bottom: 24px; +} + +.stat-card { + background: var(--card-bg); + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: var(--shadow); + padding: 20px; + text-align: center; +} + +.stat-card-accent { + background: var(--primary); + border-color: var(--primary); + color: #ffffff; +} + +.stat-value { + font-size: 28px; + font-weight: 700; + line-height: 1.2; + margin-bottom: 4px; +} + +.stat-card-accent .stat-value { + color: #ffffff; +} + +.stat-label { + font-size: 12px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--text-secondary); +} + +.stat-card-accent .stat-label { + color: rgba(255, 255, 255, 0.8); +} + +.dashboard-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; +} + +.proveedores-grid { + display: grid; + gap: 10px; +} + +.proveedor-chip { + display: flex; + justify-content: space-between; + align-items: center; + padding: 14px 16px; + border: 1px solid var(--border); + border-radius: var(--radius-sm); + cursor: pointer; + transition: all var(--transition); +} + +.proveedor-chip:hover { + background: var(--primary-light); + border-color: var(--primary); +} + +.proveedor-nombre { + font-weight: 600; + font-size: 13px; + color: var(--text); +} + +.proveedor-stats { + display: flex; + gap: 12px; + align-items: center; +} + +.proveedor-count { + font-size: 12px; + font-weight: 600; + color: var(--primary); + background: var(--primary-light); + padding: 2px 8px; + border-radius: 999px; +} + +.proveedor-monto { + font-size: 12px; + font-weight: 600; + color: var(--text-secondary); + font-variant-numeric: tabular-nums; +} + /* ---- Responsive ---- */ @media (max-width: 768px) { body { @@ -761,6 +862,14 @@ input[type="checkbox"] { .search-bar { max-width: 100%; } + + .dashboard-grid { + grid-template-columns: 1fr; + } + + .dashboard-stats { + grid-template-columns: repeat(2, 1fr); + } } @media (max-width: 480px) { diff --git a/src/public/index.html b/src/public/index.html index 9fb4e7b..d114353 100644 --- a/src/public/index.html +++ b/src/public/index.html @@ -12,6 +12,10 @@

Portal Refaccionaria