ROADMAP item #1.3 #13. exceljs e jspdf ja estavam no package.json
mas as paginas de relatorio so renderizavam UI — zero export.
src/services/reportExport.service.js (novo) com 3 funcoes:
- exportSessionsToPDF: layout HTML→PDF via pdf.service.js (header
com branding tenant, KPI grid, tabela A4 com striping)
- exportSessionsToXLSX: ExcelJS workbook formatado (titulo + subtitle
+ KPIs inline + tabela com header escuro + alternating row + frozen
header). Import dinamico — exceljs e pesado, so carrega no click.
- exportSessionsToCSV: vanilla (sem deps) com BOM UTF-8 + separador
';' (Excel-friendly em pt-BR)
3 botoes em ambas paginas:
- RelatoriosPage.vue (/therapist/relatorios): icones pi-file-pdf +
pi-file-excel + pi-table no header (rounded), tooltip, disabled
quando total=0 ou loading, toast de sucesso/erro
- MelissaRelatorios.vue (Melissa secao): mesma logica, botoes nativos
.mr-head-btn no padrao Melissa
Filtro de status da tabela e respeitado no export (exporta o que
o usuario esta vendo). KPIs incluidos no PDF e XLSX.
§1.3 UX = 3/4 fechado: #10 (busca global) + #11 (recently viewed) +
#13 (relatorios export). #12 (papel timbrado) bloqueado em codigo
externo do UniaoApp.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Card novo pra clínica e terapeuta com 3 métricas + sparkline:
- Tempo médio (e mediana) de 1ª resposta no período
- Taxa de SLA cumprido — % de respostas dentro do threshold configurado
- Contagem total de respostas no período
- Sparkline da evolução com indicador de tendência (melhorando/piorando)
- Ranking top 5 terapeutas (só no ClinicDashboard)
Filtro de período: 7/30/90 dias (muda granularidade do bucket:
1/7/15 dias pra sparkline com ~5-6 pontos).
Banco (migration 20260423000006):
- Helper interno _first_response_runs: identifica "runs" de inbound
(sequências do paciente sem outbound entre) e calcula delta até a
próxima outbound. Evita contar múltiplas mensagens repetidas do
paciente. responder_id vem de conversation_assignments.
- first_response_stats: agregados (count, avg, median, min, max,
sla_compliance_rate baseado em conversation_sla_rules).
- first_response_by_therapist: ranking com avg e count por assigned_to.
- first_response_evolution: série temporal com bucket alinhado a
p_from (p_from + bucket_index * N days). Parâmetro p_bucket_days
deixa o frontend escolher granularidade por período.
Todas SECURITY DEFINER + GRANT authenticated/service_role. Filtro
opcional por therapist_id nas funções que aplicam.
Frontend:
- useFirstResponseAnalytics composable wraps as 3 RPCs com cache
via Promise.all paralelo. Helper formatSeconds (Ns/Xmin/Xh).
- FirstResponseCard.vue renderiza sparkline SVG nativo
(sem lib extra), cor da taxa SLA por threshold (verde ≥80%,
âmbar ≥50%, vermelho).
- Integrado em ClinicDashboard (visão global) e TherapistDashboard
(filtrado por ownerId, sem ranking).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>