feat: novo dashboard admin com KPIs, tendencias e ranking
- Adiciona src/admin-dashboard.js com lazy loading - KPIs: hoje vs media 30 dias por fluxo - Graficos de tendencia 30 dias (consolidado e por fluxo) - Ranking top 5 agentes com filtro de periodo - Adiciona sistema de cache (src/cache.js) - Cache com TTL e auto-refresh periodico (5-10min) - APIs: /admin/api/kpis, /admin/api/trend, /admin/api/top-agentes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
64
server.js
64
server.js
@@ -11,12 +11,14 @@ 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 } = require('./src/queries');
|
||||
const { fetchTransacoes, fetchAllTransacoes, serialize, fetchDailyStats, fetchKPIs, fetchTrend30Days, fetchTopAgentes } = 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 bcrypt = require('bcrypt');
|
||||
const db = require('./src/db-local');
|
||||
const cache = require('./src/cache');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3080;
|
||||
@@ -138,12 +140,11 @@ app.get('/admin/agentes', requireRole('admin'), (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Admin Dashboard - view ALL clients data (admin only)
|
||||
// Admin Dashboard - KPIs, Tendências e Ranking (com lazy load)
|
||||
app.get('/admin/dashboard', requireRole('admin'), async (req, res) => {
|
||||
try {
|
||||
const user = req.session.user;
|
||||
const dias = parseInt(req.query.dias) || 90;
|
||||
const html = buildHTML([], { nome: `Admin - Ultimos ${dias} dias`, email: user.email }, false, dias, true);
|
||||
const html = buildAdminDashboardHTML({ nome: user.nome, email: user.email });
|
||||
res.send(html);
|
||||
} catch (err) {
|
||||
console.error('Admin dashboard error:', err);
|
||||
@@ -164,6 +165,53 @@ app.get('/admin/api/data', requireRole('admin'), async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// API: KPIs (hoje vs média 30 dias) - com cache
|
||||
app.get('/admin/api/kpis', requireRole('admin'), async (req, res) => {
|
||||
try {
|
||||
const data = await cache.getOrFetch('kpis', fetchKPIs, 5 * 60 * 1000);
|
||||
res.json({ success: true, data });
|
||||
} catch (err) {
|
||||
console.error('KPIs API error:', err);
|
||||
res.status(500).json({ success: false, error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// API: Tendência 30 dias - com cache
|
||||
app.get('/admin/api/trend', requireRole('admin'), async (req, res) => {
|
||||
try {
|
||||
const data = await cache.getOrFetch('trend30', fetchTrend30Days, 10 * 60 * 1000);
|
||||
res.json({ success: true, data });
|
||||
} catch (err) {
|
||||
console.error('Trend API error:', err);
|
||||
res.status(500).json({ success: false, error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// API: Top 5 agentes - com cache por período
|
||||
app.get('/admin/api/top-agentes', requireRole('admin'), async (req, res) => {
|
||||
try {
|
||||
const dias = parseInt(req.query.dias) || 30;
|
||||
const cacheKey = `top-agentes-${dias}`;
|
||||
|
||||
// Busca dados do RDS (com cache)
|
||||
const rawData = await cache.getOrFetch(cacheKey, () => fetchTopAgentes(dias), 10 * 60 * 1000);
|
||||
|
||||
// Adiciona nomes dos agentes do SQLite local
|
||||
const data = rawData.map(r => {
|
||||
const agente = db.prepare('SELECT nome FROM agentes WHERE agente_id = ?').get(r.agente_id);
|
||||
return {
|
||||
...r,
|
||||
agente: agente?.nome || `Agente #${r.agente_id}`
|
||||
};
|
||||
});
|
||||
|
||||
res.json({ success: true, data });
|
||||
} catch (err) {
|
||||
console.error('Top Agentes API error:', err);
|
||||
res.status(500).json({ success: false, error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Admin emulate agent - view dashboard as specific agent (admin only)
|
||||
app.get('/admin/emular/:agente_id', requireRole('admin'), async (req, res) => {
|
||||
try {
|
||||
@@ -273,4 +321,12 @@ app.delete('/admin/agentes/:id', requireRole('admin'), (req, res) => {
|
||||
// Start
|
||||
app.listen(PORT, () => {
|
||||
console.log(`BI - CCC rodando: http://localhost:${PORT}`);
|
||||
|
||||
// Inicializa cache com auto-refresh (atualiza a cada 5 minutos)
|
||||
console.log('[Cache] Inicializando cache com auto-refresh...');
|
||||
cache.registerAutoRefresh('kpis', fetchKPIs, 5 * 60 * 1000);
|
||||
cache.registerAutoRefresh('trend30', fetchTrend30Days, 10 * 60 * 1000);
|
||||
cache.registerAutoRefresh('top-agentes-30', () => fetchTopAgentes(30), 10 * 60 * 1000);
|
||||
cache.registerAutoRefresh('top-agentes-7', () => fetchTopAgentes(7), 10 * 60 * 1000);
|
||||
cache.registerAutoRefresh('top-agentes-90', () => fetchTopAgentes(90), 10 * 60 * 1000);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user