synapsis-itp
Version:
Biblioteca de dashboard interativo com Apache ECharts e TanStack Table, com suporte a filtros dinâmicos
244 lines (228 loc) • 8.8 kB
HTML
<html lang="pt-br">
<head>
<meta charset="UTF-8" />
<title>Dashboard de Atendimentos</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5"></script>
<script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script>
<style>
:root {
--cor-fundo: #f1f5f9;
--cor-card: #ffffff;
--cor-texto: #334155;
--cor-borda: #e2e8f0;
--cor-sombra: rgba(100, 116, 139, 0.1);
--cor-primaria: #3b82f6;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
margin: 0;
background-color: var(--cor-fundo);
color: var(--cor-texto);
}
.dashboard-wrapper {
padding: 1.5rem;
}
h1 {
font-size: 1.875rem;
font-weight: 600;
margin-bottom: 0.5rem;
}
#periodo {
font-size: 0.875rem;
color: #64748b;
margin-bottom: 1.5rem;
}
.card {
background-color: var(--cor-card);
border-radius: 0.75rem;
padding: 1.5rem;
box-shadow: 0 4px 6px -1px var(--cor-sombra), 0 2px 4px -2px var(--cor-sombra);
border: 1px solid var(--cor-borda);
}
.dashboard-grid {
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
gap: 1.5rem;
}
/* Layout para telas maiores */
@media (min-width: 1024px) {
.dashboard-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.span-col-3 {
grid-column: span 3 / span 3;
}
.span-col-2 {
grid-column: span 2 / span 2;
}
}
select, input[type="date"], button {
margin: 5px;
padding: 8px 12px;
font-size: 14px;
border-radius: 0.375rem;
border: 1px solid var(--cor-borda);
}
button {
background-color: var(--cor-primaria);
color: white;
font-weight: 500;
cursor: pointer;
border-color: transparent;
}
button:hover {
opacity: 0.9;
}
h3.card-title {
font-size: 1.125rem;
font-weight: 600;
margin-top: 0;
margin-bottom: 1.5rem;
}
.table-responsive-wrapper {
width: 100%;
overflow-x: auto; /* A mágica acontece aqui! */
}
.dashboard-table { width: 100%; border-collapse: collapse; }
.dashboard-table th, .dashboard-table td { padding: 12px 16px; border-bottom: 1px solid var(--cor-borda); text-align: left; }
.dashboard-table thead th { font-weight: 600; font-size: 0.75rem; text-transform: uppercase; color: #64748b; }
</style>
</head>
<body>
<div class="dashboard-wrapper">
<h1>Dashboard de Atendimentos</h1>
<div id="periodo"></div>
<div id="filtros-container" class="card">
<div id="filtroPorPeriodo">
<strong>Filtro Mestre por Período:</strong><br>
<label for="filtro-data-inicio">De:</label>
<input type="date" id="filtro-data-inicio">
<label for="filtro-data-fim" style="margin-left: 10px;">Até:</label>
<input type="date" id="filtro-data-fim">
<button id="btn-aplicar-periodo" style="margin-left: 10px;">Aplicar Período</button>
<button id="btn-limpar-periodo">Limpar Período</button>
</div>
<div id="filtrosDinamicos" style="margin-top: 15px; border-top: 1px solid #eee; padding-top: 15px;">
<strong>Filtros Adicionais:</strong><br>
<select data-campo="atendente" data-aplica-em="estatisticas,tabela,performance,priority,satisfaction,timeline"></select>
<select data-campo="prioridade" data-aplica-em="estatisticas,tabela,performance,priority,satisfaction,timeline"></select>
<select data-campo="nota" data-aplica-em="estatisticas,tabela,performance,priority,satisfaction,timeline"></select>
</div>
</div>
<div class="dashboard-grid">
<div class="card span-col-3">
<h3 class="card-title">Timeline de Atendimentos</h3>
<div id="chartTimeline" style="height: 350px;" data-campo="codigo_atendimento" data-aplica-em="tabela,estatisticas"></div>
</div>
<div class="card span-col-2">
<h3 class="card-title">Performance por Atendente</h3>
<div id="chartPerformance" style="height: 350px;" data-campo="atendente" data-aplica-em="tabela,estatisticas,priority,satisfaction,timeline"></div>
</div>
<div class="card">
<h3 class="card-title">Estatísticas Gerais</h3>
<div id="estatisticas"></div>
<div id="chartEstatistica" style="height: 250px;"></div>
</div>
<div class="card">
<h3 class="card-title">Distribuição de Prioridade</h3>
<div id="chartPriority" style="height: 300px;" data-campo="prioridade" data-aplica-em="tabela,estatisticas,performance,satisfaction,timeline"></div>
</div>
<div class="card">
<h3 class="card-title">Nível de Satisfação</h3>
<div id="chartSatisfaction" style="height: 300px;" data-campo="nota" data-aplica-em="tabela,estatisticas,performance,priority,timeline"></div>
</div>
<div class="card">
<h3 class="card-title">Resumo Estatístico</h3>
<div id="tabelaEstatisticas"></div>
</div>
<div class="card span-col-3">
<h3 class="card-title">Todos os Dados</h3>
<div id="tabelaTodosOsDados"></div>
</div>
</div>
</div>
<script>
window.dashboardConfig = {
jsonPath: './data/dados_atendimento.json',
campos: {
grupo: 'atendente',
valor: 'tempo_resolucao_hrs',
dataPrincipal: 'data_solicitacao'
},
// --- AJUSTE FEITO AQUI ---
// A nova propriedade 'tabelas' foi adicionada para controlar a estrutura das tabelas.
tabelas: {
todosOsDados: {
colunas: [
{ header: 'Cód. Atendimento', key: 'codigo_atendimento' },
{ header: 'Cliente', key: 'cliente' },
{ header: 'Solicitante', key: 'solicitante' },
{ header: 'Atendente Responsável', key: 'atendente' },
{ header: 'Prioridade', key: 'prioridade' },
{ header: 'Nota de Satisfação', key: 'nota' },
{
header: 'Tempo de Resolução',
key: 'tempo_resolucao_hrs',
// Exemplo de formatação: adiciona 'hrs' ao final do valor
format: (valor) => valor ? `${valor} hrs` : '-'
}
]
},
estatisticas: {
colunas: [
{ header: 'Indicador Estatístico', key: 'Indicador' },
{ header: 'Valor', key: 'Valor' }
]
}
},
elements: {
periodo: 'periodo',
estatistica: 'chartEstatistica',
timeline: 'chartTimeline',
performance: 'chartPerformance',
priority: 'chartPriority',
satisfaction: 'chartSatisfaction'
},
timeline: {
title: '', // Título já está no card
axisLabelRotate: 45,
yAxisName: 'Horas',
legendPosition: 'top',
colors: { inicio: '#4caf50', resolucao: '#2196f3' },
seriesNames: { inicio: 'Início', resolucao: 'Resolução' },
tooltipFormatter: d => `Atendimento ${d.codigo_atendimento}: ${d.tempo_resolucao_hrs} hrs`,
},
performance: {
chartTitle: '', // Título já está no card
axisLabelRotate: 0,
yAxisName: 'Média de Resolução (hrs)',
colorScale: v => v > 40 ? '#f44336' : v > 20 ? '#ff9800' : '#4caf50',
tooltipFormatter: d => `${d.name}: ${d.value.toFixed(2)} hrs`,
labelConfig: { show: true, position: 'top', formatter: p => `${p.value.toFixed(1)} hrs` }
},
chartTitles: {
performance: '', priority: '', satisfaction: '' // Títulos já estão nos cards
},
priority: {
radius: '60%',
labels: ['Baixa', 'Média', 'Alta', 'Urgente'],
colors: {
Baixa: '#8bc34a', Média: '#ffeb3b', Alta: '#ff9800', Urgente: '#f44336'
},
labelFormat: { formatter: '{b}: {d}%' }
},
satisfaction: {
radius: [30, 100],
notas: ['Ruim', 'Regular', 'Bom', 'Ótimo', 'Excelente'],
colors: {
Ruim: '#e53935', Regular: '#fb8c00', Bom: '#fdd835', Ótimo: '#43a047', Excelente: '#1e88e5'
},
labelFormat: { formatter: '{b}: {c}' },
labelLine: { smooth: 0.2, length: 10, length2: 20 }
}
};
</script>
<script src="https://cdn.jsdelivr.net/npm/synapsis-itp@1.8.6/dist/index.umd.js"></script>
</body>
</html>