📄 Documento de Execução — Card 17: [M4] Dashboard da Unidade
| Campo | Valor |
|---|---|
| Card Trello | [17] [M4] Dashboard da Unidade |
| URL Trello | https://trello.com/c/6a5cec42b519bcde86146e04 |
| Marco | M4 — Painel Direção/Unidade (02–16/09/2026) |
| Data execução | 04/08/2026 |
| Responsável | Wellington Santiago (via ZCode) |
| Doc anterior | Card 16: Comunicados para Turma (M3) |
| Próximo card | Card 18: Gestão de Alunos & Matrículas (M4) |
| Commits | 3eaf518 |
🎯 1. O que foi implementado
Substituído o protótipo mock da home /local (que mostrava números fixos como "1.240 alunos", "R$ 186.000", agenda fake) por um dashboard real e completo com dados agregados do banco via tRPC.
A direção da unidade (LOCAL) — e também SUPERVISOR/MASTER — agora vê em tempo real:
8 KPIs principais (cards no topo)
- Alunos Ativos —
Student.countondeisActive=true+ branchFilter - Novas Matrículas (no período) — com delta % vs período anterior
- Evasão — cancelamentos/transferências (com delta %, invertido: subir = ruim)
- Receita Recebida — soma de
Payment.finalAmountstatus PAID, com taxa de cobrança % vs previsto - Inadimplência — count de Payments OVERDUE + PENDING vencidos
- Frequência Média —
(Presentes + Lates×0.5) / totalno período (meta 75%) - Média Geral —
_avgdeGrade.valuepublicadas (meta 7.0) - Tickets Abertos — count
Ticketstatus OPEN/IN_PROGRESS/WAITING_RESPONSE
5 Gráficos Recharts
- AreaChart — Receita Recebida ao longo do tempo (gradient verde)
- PieChart — Distribuição por Curso (donut + legenda lateral com %)
- BarChart horizontal — Desempenho por Turma (média notas, cor por faixa: ≥7 verde / ≥5 âmbar / <5 vermelho)
- RadarChart — Comparativo de 6 indicadores normalizados (0-100): Matrículas, Receita, Frequência, Notas, Retenção, Engajamento
- Funil de Matrículas — LEAD → PRE_ENROLLED → PENDING_DOCS → PENDING_PAYMENT → PENDING_SIGNATURE → ACTIVE (com % de drop-off entre etapas + taxa de conversão total)
Alertas operacionais dinâmicos
Card de "Pendências da Unidade" agora mostra contagens reais:
- Matrículas aguardando análise de documentos
- Contratos pendentes de assinatura digital
- Cobranças vencendo nos próximos 3 dias
- Justificativas de falta aguardando aprovação
- Tickets de suporte em aberto
Cada alerta é clicável e leva direto para a página de resolução (/local/matriculas, /local/financeiro, /local/justificativas).
Filtros
- Período: Esta semana / Este mês (default) / Trimestre / Ano — recalcula todos os KPIs + gráficos + deltas
- Filial: só aparece para SUPERVISOR/MASTER (dropdown para escolher filial específica ou "Todas")
Recursos de UX
- Loading skeletons (8 cards pulsantes) durante carregamento
- Empty states em cada gráfico ("Sem dados... ainda")
- Cache indicator no rodapé: "Cache: 5 min · Atualizado em HH:MM:SS"
- Delta colors: verde/vermelho + ↑/↓, com lógica invertida para Evasão
✅ Critérios de aceite validados
| # | Critério | Status |
|---|---|---|
| 1 | KPIs da unidade (8 métricas reais) | ✅ |
| 2 | Gráficos Recharts (Area/Pie/Bar/Radar/Funnel) | ✅ |
| 3 | Alertas operacionais (5 tipos dinâmicos) | ✅ |
| 4 | Filtros por período (semana/mês/trimestre/ano) | ✅ |
| 5 | Filtro por filial (SUPERVISOR/MASTER) | ✅ |
| 6 | Comparativo mês anterior (delta %) | ✅ |
| 7 | Cache Redis 5min (KPIs) | ✅ |
| 8 | Loading skeletons | ✅ |
| 9 | Empty states (unidade nova sem dados) | ✅ |
| 10 | branchFilter (LOCAL só vê própria filial) | ✅ |
📁 2. Arquivos criados/modificados
Criados
| Arquivo | Função |
|---|---|
src/server/lib/branch-scope.ts |
Helper que resolve filtro de filial por role (LOCAL/SUPERVISOR/MASTER) |
src/server/lib/kpi-cache.ts |
Wrapper Redis p/ cache de KPIs (TTL 5min, degrada gracioso) |
src/components/charts/ChartCard.tsx |
Wrapper visual (título + ação + container) p/ qualquer gráfico |
src/components/charts/RevenueChart.tsx |
AreaChart reutilizável (receita ou matrículas) |
src/components/charts/DistributionPie.tsx |
PieChart donut + legenda lateral com % |
src/components/charts/ClassPerformanceBar.tsx |
BarChart horizontal (média por turma, cor por faixa) |
src/components/charts/RadarComparison.tsx |
RadarChart 6 eixos (indicadores normalizados) |
src/components/charts/EnrollmentFunnelChart.tsx |
Funil visual LEAD→ACTIVE com dropoff % |
Modificados
| Arquivo | Mudança |
|---|---|
src/server/trpc/routers/local.ts |
+sub-router dashboard (8 procedures) + helpers de escopo/temporal |
src/app/(dashboard)/local/page.tsx |
Reescrita total: removeu mock, agora dashboard real via tRPC |
🗄️ 3. Schema do banco (mudanças)
Nenhuma — todas as métricas são computadas em runtime via agregações Prisma (count, aggregate._sum/_avg, groupBy) sobre tabelas existentes: students, enrollments, payments, attendance, grades, tickets, attendance_justifications.
🔌 4. Handoff para o próximo card
Procedures disponíveis (local.dashboard.*)
overview({ period, branchId? })→{ kpis: { activeStudents, newEnrollments{value,deltaPct}, cancellations{value,deltaPct}, revenue{expected,received,collectionRate}, overduePayments, attendanceRate, averageGrade, openTickets, pendingJustifications } }timeseries({ metric: 'ENROLLMENTS'|'REVENUE'|'ATTENDANCE', period, branchId? })→{ series: [{date, value}] }distributionByCourse({ branchId? })→{ data: [{name, value}] }classPerformance({ branchId? })→{ data: [{name, average}] }enrollmentFunnel({ branchId? })→{ data: [{stage, value}], totals: {total, active, lost} }radarComparison({ branchId? })→{ data: [{metric, value}], meta: {...} }branches()→{ branches: [...], canSelect: boolean }(para seletor de filial)alerts({ branchId? })→{ alerts: [{severity, text, count, href}] }
Helpers reutilizáveis
branchWhere(ctx)— aplica filtro de filial em qualquerwherePrismalistVisibleBranchIds(ctx)— retornastring[] | null(null = todas = MASTER)cacheKpi(key, loader, ttl?)— cache Redis com fallback gracioso
Variáveis de ambiente
REDIS_URL— já configurada na VPS Oracle (cache ativo). Se ausente, degrada para sem cache.
Padrões estabelecidos
- Cache key:
kpi:local:{procedure}:{params}:{userId}:{branchId|all}(5 min TTL) - Branch filter manual:
localProcedureNÃO injetactx.branchFilter(apesar de ARQUITETURA §3.3 documentar isso). Cada resolver chamabranchWhere(ctx)explicitamente. - Period buckets: WEEK=diário (7), MONTH=a cada 3 dias (10), QUARTER=semanal (~13), YEAR=mensal (12)
📋 5. Checklist do Trello — status por item
Entregas
- KPIs da unidade (8 métricas reais)
- Gráficos (Recharts — 5 tipos)
- Alertas operacionais (5 tipos dinâmicos)
- Filtros por período (4 opções)
Especificação Técnica
- Rota tRPC local.dashboard(branchId) — agregados (
overview) - Rota tRPC local.kpis(branchId, period) — incorporado em
overview - Rota tRPC local.enrollmentFunnel(branchId)
- Pagina (local)/page.tsx (dashboard)
- Componente KPICard — reusado
KPIexistente (numero + variacao %) - Componente EnrollmentFunnelChart
- Componente RevenueChart (AreaChart)
- Componente DistributionPie (PieChart cursos)
- Componente ClassPerformanceBar (BarChart)
- Componente RadarComparison (RadarChart)
- Filtro por periodo (semana/mes/trimestre/ano)
- Filtro por curso — NÃO implementado (filtro por filial é mais útil para LOCAL; curso seria granular demais para o dashboard principal. Implementar em Card 20 Financeiro se necessário)
- Comparativo mes anterior (delta %)
- Cache Redis 5min (KPIs)
- Evento Socket: real-time update — não implementado (refinamento futuro, M6)
- Botao exportar PDF (Puppeteer) — não implementado (refinamento futuro, Card 27 Relatórios)
- Loading skeletons
- Empty states (unidade nova sem dados)
- Validacao: LOCAL so ve dados da propria branch (branchFilter)
- Auditoria: logar READ dashboard — não implementado (read logging é caro em alta frequência; delegar para Card 26 Auditoria)
Validar com Cliente (defaults adotados)
- KPIs prioridade na home? → Default: os 8 que aparecem (matrículas, evasão, receita, inadimplência, frequência, média, tickets). Ajustável.
- Período padrão? → Default: Este mês (30 dias). Parece mais útil para direção que semana.
- Meta inadimplência? → Default visual: <5% bom (verde), >10% ruim (vermelho). Configurável.
- Meta frequência? → Default: 75% (confirmado em decisoes.md §FREQUÊNCIA).
- Cores gráficos? → Default: Design System GENIOON (#3B82F6 azul + paleta). Marca da filial aplicada só no logo/header (white-label é Card 24).
🚀 6. Deploy DEV
- URL: https://sistemaescolar.wellka.com.br/local
- Login demo:
diretor@genioon.com.br/Diretor@2026(role LOCAL) - Commit:
3eaf518 - PM2:
genioon-dev(id 3) — reload OK, logs limpos
🧠 7. Contexto gerado para próximas etapas
- Helpers de branch-scope + kpi-cache são reutilizáveis em todos os próximos cards do M4/M5 (qualquer dashboard/agregação precisa deles).
- Padrão de procedura dashboard (paralelo de Promise.all + cache Redis) pode ser replicado no Card 22 (Dashboard Master da Rede) e Card 20 (Financeiro da Unidade).
- branchFilter manual confirmado como padrão: sempre chamar
branchWhere(ctx)no resolver. Documentar isso para futuros desenvolvedores (ARQUITETURA §3.3 está idealizada, não reflete implementação). - Recharts confirmado como lib de gráficos do projeto (já estava no package.json, agora usado de fato).
- Filtro por filial (seletor dropdown) só aparece para SUPERVISOR/MASTER. LOCAL vê só a própria (fixa no header). Padrão a manter em todos os dashboards admin.
Não implementados (refinamentos futuros)
- Socket.io real-time: refresh automático quando novo cadastro/nota/falta chega (M6)
- Export PDF: botão "Exportar relatório" via Puppeteer (Card 27 Relatórios Gerenciais)
- Auditoria de READ: logar acesso ao dashboard (Card 26 Auditoria & Logs — hoje é caro logar toda visualização)
- Filtro por curso: granularidade extra (default: filial inteira)
- Materialized views: se performance cair com muitos alunos (>1000), pré-agregar KPIs em job Bull diário
🎯 8. Próximo card
Card 18 [M4] Gestão de Alunos & Matrículas — fluxo completo Lead → Visita → Docs → Pagamento → Contrato → Ativo. RA gerado automaticamente (formato 20260001), webcam obrigatório na foto, responsável financeiro flexível (tutor/a), transferência sem custo, cancelamento com motivo, rematrícula automática 15/12. Documentos obrigatórios = todos (RG/CPF/comprovante/histórico/foto/transferência).