From e24fcd64e3f438a783186e60d267410d075776b4 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 14 Feb 2026 10:52:55 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20admin=20BI=20executive=20dashboard=20-?= =?UTF-8?q?=20vis=C3=A3o=20estrat=C3=A9gica=20completa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Novo dashboard admin-only (/admin/bi) com BI profissional: - 5 hero KPIs: receita spread, volume USD, transações, clientes ativos, ticket médio - Revenue por corredor (donut) + spread médio + volume diário (dual-axis chart) - Top 10 clientes por volume + taxa retenção + clientes em risco (30+ dias) - Volume stacked por corredor + netting entrada/saída + ranking agentes - Filtros: 7d, 30d, 90d, este mês, ou período custom - Comparativo automático vs período anterior em todos os KPIs - Responsivo mobile (5→2→1 cols) + trading terminal USD/BRL Co-Authored-By: Claude Opus 4.6 --- server.js | 33 +- src/admin-bi.js | 777 +++++++++++++++++++++++++++++++++++++++++++++ src/queries.js | 261 ++++++++++++++- src/ui-template.js | 3 +- 4 files changed, 1071 insertions(+), 3 deletions(-) create mode 100644 src/admin-bi.js diff --git a/server.js b/server.js index 4dee13b..350326a 100644 --- a/server.js +++ b/server.js @@ -11,11 +11,12 @@ const express = require('express'); const session = require('express-session'); const path = require('path'); const { authenticate, requireAuth, requireRole, createAgente, createUser } = require('./src/auth'); -const { fetchTransacoes, fetchAllTransacoes, serialize, fetchDailyStats, fetchKPIs, fetchTrend30Days, fetchTopAgentes, fetchTrendByPeriod, fetchKPIsByPeriod } = require('./src/queries'); +const { fetchTransacoes, fetchAllTransacoes, serialize, fetchDailyStats, fetchKPIs, fetchTrend30Days, fetchTopAgentes, fetchTrendByPeriod, fetchKPIsByPeriod, fetchBIData } = require('./src/queries'); const { buildHTML } = require('./src/dashboard'); const { buildAdminHTML } = require('./src/admin-panel'); const { buildAdminHomeHTML } = require('./src/admin-home'); const { buildAdminDashboardHTML } = require('./src/admin-dashboard'); +const { buildAdminBIHTML } = require('./src/admin-bi'); const bcrypt = require('bcrypt'); const db = require('./src/db-local'); const cache = require('./src/cache'); @@ -324,6 +325,36 @@ app.get('/admin/dashboard', requireRole('admin'), (req, res) => { res.redirect('/corporate/dashboard'); }); +// --- Admin BI Dashboard (admin only) --- +app.get('/admin/bi', requireRole('admin'), (req, res) => { + try { + const html = buildAdminBIHTML(req.session.user); + res.send(html); + } catch (err) { + console.error('Admin BI error:', err); + res.status(500).send('Erro ao carregar BI: ' + err.message); + } +}); + +app.get('/admin/api/bi', requireRole('admin'), async (req, res) => { + try { + const start = req.query.start; + const end = req.query.end; + if (!start || !end) return res.status(400).json({ error: 'start and end required' }); + + const getAgenteName = (agenteId) => { + const row = db.prepare('SELECT nome FROM agentes WHERE agente_id = ?').get(agenteId); + return row ? row.nome : null; + }; + + const data = await fetchBIData(start, end, getAgenteName); + res.json(data); + } catch (err) { + console.error('Admin BI API error:', err); + res.status(500).json({ error: err.message }); + } +}); + // Create user (admin only) app.post('/admin/agentes', requireRole('admin'), async (req, res) => { const { nome, email, agente_id, senha, role } = req.body; diff --git a/src/admin-bi.js b/src/admin-bi.js new file mode 100644 index 0000000..88097d4 --- /dev/null +++ b/src/admin-bi.js @@ -0,0 +1,777 @@ +/** + * Admin BI Dashboard - Business Intelligence Executive View + * Admin-only: comprehensive KPIs, revenue analysis, client intelligence, operational metrics + */ +const { buildHeader, buildFooter, buildHead } = require('./ui-template'); + +function buildAdminBIHTML(user) { + const role = user.role || 'admin'; + const pageScripts = '