UNPKG

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
<!DOCTYPE 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>