Documentos Pacientes, Template Documentos Pacientes Saas, Documentos prontuários, Documentos Externos, Visualização Externa, Permissão de Visualização, Render Otimização

This commit is contained in:
Leonardo
2026-03-30 14:08:19 -03:00
parent 0658e2e9bf
commit d088a89fb7
112 changed files with 115867 additions and 5266 deletions

445
mvp-assessment.html Normal file
View File

@@ -0,0 +1,445 @@
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AgenciaPsi — Avaliação MVP</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: #0f172a;
color: #e2e8f0;
min-height: 100vh;
padding: 2rem;
}
h1 { font-size: 1.8rem; font-weight: 700; color: #f8fafc; }
h2 { font-size: 1.1rem; font-weight: 600; color: #94a3b8; text-transform: uppercase; letter-spacing: .08em; margin-bottom: 1rem; }
.subtitle { color: #64748b; margin-top: .3rem; margin-bottom: 2rem; font-size: .95rem; }
.grid { display: grid; gap: 1.5rem; }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.card {
background: #1e293b;
border: 1px solid #334155;
border-radius: 12px;
padding: 1.5rem;
}
.kpi { text-align: center; }
.kpi .value { font-size: 2.5rem; font-weight: 800; line-height: 1; }
.kpi .label { font-size: .8rem; color: #64748b; margin-top: .4rem; text-transform: uppercase; letter-spacing: .06em; }
.green { color: #4ade80; }
.yellow { color: #fbbf24; }
.red { color: #f87171; }
.blue { color: #60a5fa; }
/* Progress bars */
.progress-list { display: flex; flex-direction: column; gap: .9rem; }
.progress-item { }
.progress-header { display: flex; justify-content: space-between; margin-bottom: .35rem; font-size: .88rem; }
.progress-label { color: #cbd5e1; }
.progress-pct { font-weight: 700; }
.bar-bg { background: #0f172a; border-radius: 999px; height: 8px; overflow: hidden; }
.bar-fill { height: 100%; border-radius: 999px; transition: width .6s ease; }
.fill-green { background: linear-gradient(90deg, #22c55e, #4ade80); }
.fill-yellow { background: linear-gradient(90deg, #d97706, #fbbf24); }
.fill-red { background: linear-gradient(90deg, #dc2626, #f87171); }
.fill-blue { background: linear-gradient(90deg, #2563eb, #60a5fa); }
/* Badges */
.badge { display: inline-block; padding: .2rem .6rem; border-radius: 999px; font-size: .75rem; font-weight: 600; }
.badge-green { background: #052e16; color: #4ade80; border: 1px solid #166534; }
.badge-yellow { background: #1c1508; color: #fbbf24; border: 1px solid #854d0e; }
.badge-red { background: #1c0a0a; color: #f87171; border: 1px solid #991b1b; }
/* Feature table */
.feature-row {
display: flex; align-items: center; justify-content: space-between;
padding: .6rem 0;
border-bottom: 1px solid #1e293b;
font-size: .88rem;
}
.feature-row:last-child { border-bottom: none; }
.feature-name { color: #cbd5e1; }
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: .5rem; flex-shrink: 0; }
.dot-green { background: #4ade80; }
.dot-yellow { background: #fbbf24; }
.dot-red { background: #f87171; }
/* Timeline */
.timeline { display: flex; flex-direction: column; gap: 0; }
.tl-item { display: flex; gap: 1rem; }
.tl-line { display: flex; flex-direction: column; align-items: center; }
.tl-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; margin-top: .2rem; }
.tl-connector { width: 2px; background: #334155; flex: 1; min-height: 1.5rem; }
.tl-item:last-child .tl-connector { display: none; }
.tl-content { padding-bottom: 1.2rem; }
.tl-title { font-size: .9rem; font-weight: 600; color: #f1f5f9; }
.tl-desc { font-size: .8rem; color: #64748b; margin-top: .2rem; line-height: 1.4; }
/* Donut center */
.chart-wrap { position: relative; }
.donut-center {
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
text-align: center; pointer-events: none;
}
.donut-center .big { font-size: 2rem; font-weight: 800; color: #f8fafc; }
.donut-center .sm { font-size: .7rem; color: #64748b; text-transform: uppercase; letter-spacing: .06em; }
canvas { max-width: 100%; }
@media (max-width: 900px) {
.grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<h1>AgenciaPsi — Avaliação MVP</h1>
<p class="subtitle">Snapshot de 25 de março de 2026 &nbsp;·&nbsp; ~487 componentes Vue &nbsp;·&nbsp; v5.0.0</p>
<!-- KPIs -->
<div class="grid grid-4" style="margin-bottom:1.5rem">
<div class="card kpi">
<div class="value green">78%</div>
<div class="label">Pronto para MVP</div>
</div>
<div class="card kpi">
<div class="value blue">487</div>
<div class="label">Componentes Vue</div>
</div>
<div class="card kpi">
<div class="value green">10</div>
<div class="label">Módulos prontos</div>
</div>
<div class="card kpi">
<div class="value red">2</div>
<div class="label">Gaps críticos</div>
</div>
</div>
<!-- Donut + Progresso por módulo -->
<div class="grid grid-2" style="margin-bottom:1.5rem">
<div class="card">
<h2>Completude por Módulo</h2>
<div class="progress-list">
<div class="progress-item">
<div class="progress-header"><span class="progress-label">Autenticação & Permissões</span><span class="progress-pct green">100%</span></div>
<div class="bar-bg"><div class="bar-fill fill-green" style="width:100%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">Agenda / Calendário</span><span class="progress-pct green">95%</span></div>
<div class="bar-bg"><div class="bar-fill fill-green" style="width:95%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">Pacientes (CRUD + Prontuário)</span><span class="progress-pct green">90%</span></div>
<div class="bar-bg"><div class="bar-fill fill-green" style="width:90%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">Financeiro</span><span class="progress-pct green">85%</span></div>
<div class="bar-bg"><div class="bar-fill fill-green" style="width:85%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">Agendador Público</span><span class="progress-pct green">90%</span></div>
<div class="bar-bg"><div class="bar-fill fill-green" style="width:90%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">Configurações (15 págs)</span><span class="progress-pct green">88%</span></div>
<div class="bar-bg"><div class="bar-fill fill-green" style="width:88%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">WhatsApp / SMS / Email</span><span class="progress-pct yellow">75%</span></div>
<div class="bar-bg"><div class="bar-fill fill-yellow" style="width:75%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">SaaS Admin</span><span class="progress-pct yellow">80%</span></div>
<div class="bar-bg"><div class="bar-fill fill-yellow" style="width:80%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">Dashboard da Clínica</span><span class="progress-pct yellow">35%</span></div>
<div class="bar-bg"><div class="bar-fill fill-yellow" style="width:35%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">Relatórios</span><span class="progress-pct yellow">40%</span></div>
<div class="bar-bg"><div class="bar-fill fill-yellow" style="width:40%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">Gateway de Pagamento</span><span class="progress-pct red">10%</span></div>
<div class="bar-bg"><div class="bar-fill fill-red" style="width:10%"></div></div>
</div>
<div class="progress-item">
<div class="progress-header"><span class="progress-label">Testes Automatizados</span><span class="progress-pct red">15%</span></div>
<div class="bar-bg"><div class="bar-fill fill-red" style="width:15%"></div></div>
</div>
</div>
</div>
<div class="card" style="display:flex; flex-direction:column; gap:1.5rem">
<div>
<h2>Status Geral</h2>
<div class="chart-wrap" style="max-width:260px; margin:0 auto; position:relative">
<canvas id="donutChart" height="260"></canvas>
<div class="donut-center">
<div class="big">78%</div>
<div class="sm">MVP Ready</div>
</div>
</div>
</div>
<div>
<h2>Distribuição de Módulos</h2>
<canvas id="barChart" height="160"></canvas>
</div>
</div>
</div>
<!-- Features / gaps -->
<div class="grid grid-2" style="margin-bottom:1.5rem">
<div class="card">
<h2>Funcionalidades — Checklist</h2>
<div>
<!-- Prontos -->
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">Autenticação (login, reset, sessão)</span></span><span class="badge badge-green">Pronto</span></div>
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">Calendário + Recorrências</span></span><span class="badge badge-green">Pronto</span></div>
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">CRUD de Pacientes + Prontuário</span></span><span class="badge badge-green">Pronto</span></div>
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">Dashboard Financeiro</span></span><span class="badge badge-green">Pronto</span></div>
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">Agendador Público (/agendar/:slug)</span></span><span class="badge badge-green">Pronto</span></div>
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">15 Páginas de Configurações</span></span><span class="badge badge-green">Pronto</span></div>
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">WhatsApp + SMS (Twilio)</span></span><span class="badge badge-green">Pronto</span></div>
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">Templates de Email (Jodit)</span></span><span class="badge badge-green">Pronto</span></div>
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">Multi-tenant</span></span><span class="badge badge-green">Pronto</span></div>
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">Dark mode + 3 temas</span></span><span class="badge badge-green">Pronto</span></div>
<div class="feature-row"><span><span class="dot dot-green"></span><span class="feature-name">SaaS Admin (planos, assinaturas)</span></span><span class="badge badge-green">Pronto</span></div>
<!-- Parcial -->
<div class="feature-row"><span><span class="dot dot-yellow"></span><span class="feature-name">Dashboard da Clínica</span></span><span class="badge badge-yellow">Parcial</span></div>
<div class="feature-row"><span><span class="dot dot-yellow"></span><span class="feature-name">Relatórios</span></span><span class="badge badge-yellow">Parcial</span></div>
<div class="feature-row"><span><span class="dot dot-yellow"></span><span class="feature-name">Onboarding / Setup Wizard</span></span><span class="badge badge-yellow">Parcial</span></div>
<div class="feature-row"><span><span class="dot dot-yellow"></span><span class="feature-name">Validação de formulários (CPF/CNPJ)</span></span><span class="badge badge-yellow">Parcial</span></div>
<div class="feature-row"><span><span class="dot dot-yellow"></span><span class="feature-name">Mobile responsiveness</span></span><span class="badge badge-yellow">Não testado</span></div>
<!-- Faltando -->
<div class="feature-row"><span><span class="dot dot-red"></span><span class="feature-name">Gateway de Pagamento (Stripe)</span></span><span class="badge badge-red">Faltando</span></div>
<div class="feature-row"><span><span class="dot dot-red"></span><span class="feature-name">Testes E2E</span></span><span class="badge badge-red">Faltando</span></div>
<div class="feature-row"><span><span class="dot dot-red"></span><span class="feature-name">Export PDF / Excel</span></span><span class="badge badge-red">Faltando</span></div>
<div class="feature-row"><span><span class="dot dot-red"></span><span class="feature-name">Google Calendar sync</span></span><span class="badge badge-red">Faltando</span></div>
</div>
</div>
<div class="card">
<h2>Radar de Módulos</h2>
<canvas id="radarChart" height="300"></canvas>
</div>
</div>
<!-- Roadmap / Timeline -->
<div class="card" style="margin-bottom:1.5rem">
<h2>Roadmap para Lançamento</h2>
<div class="grid grid-3" style="gap:2rem">
<div>
<div style="display:flex; align-items:center; gap:.5rem; margin-bottom:1rem">
<span class="dot dot-red" style="width:10px;height:10px"></span>
<span style="font-weight:700; color:#f87171">Fase 1 — Antes do MVP</span>
<span style="color:#64748b; font-size:.8rem">(12 semanas)</span>
</div>
<div class="timeline">
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#ef4444"></div><div class="tl-connector"></div></div>
<div class="tl-content"><div class="tl-title">Gateway de Pagamento</div><div class="tl-desc">Integrar Stripe ou PagSeguro. Cobrança real de assinaturas e sessões avulsas.</div></div>
</div>
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#ef4444"></div><div class="tl-connector"></div></div>
<div class="tl-content"><div class="tl-title">Testes dos Fluxos Críticos</div><div class="tl-desc">Login → criar sessão → agendador público → cobrança.</div></div>
</div>
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#f97316"></div><div class="tl-connector"></div></div>
<div class="tl-content"><div class="tl-title">Dashboard da Clínica</div><div class="tl-desc">Expandir com KPIs reais (espelhar dashboard do terapeuta).</div></div>
</div>
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#f97316"></div><div class="tl-connector"></div></div>
<div class="tl-content"><div class="tl-title">Mobile — Teste em Produção</div><div class="tl-desc">Tailwind implementado mas nunca testado em dispositivos reais.</div></div>
</div>
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#eab308"></div></div>
<div class="tl-content"><div class="tl-title">Validação de Formulários</div><div class="tl-desc">CPF, CNPJ, telefone no cadastro de pacientes.</div></div>
</div>
</div>
</div>
<div>
<div style="display:flex; align-items:center; gap:.5rem; margin-bottom:1rem">
<span class="dot dot-yellow" style="width:10px;height:10px"></span>
<span style="font-weight:700; color:#fbbf24">Fase 2 — Pós-MVP</span>
<span style="color:#64748b; font-size:.8rem">(1 mês)</span>
</div>
<div class="timeline">
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#eab308"></div><div class="tl-connector"></div></div>
<div class="tl-content"><div class="tl-title">Relatórios PDF / Excel</div><div class="tl-desc">Export de lançamentos, sessões, e KPIs para relatórios mensais.</div></div>
</div>
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#eab308"></div><div class="tl-connector"></div></div>
<div class="tl-content"><div class="tl-title">Google Calendar Sync</div><div class="tl-desc">Sincronização bidirecional com o Google Calendar.</div></div>
</div>
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#eab308"></div><div class="tl-connector"></div></div>
<div class="tl-content"><div class="tl-title">Analytics / Tracking</div><div class="tl-desc">Rastrear adoção de features e comportamento de usuários.</div></div>
</div>
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#84cc16"></div></div>
<div class="tl-content"><div class="tl-title">Webhooks Twilio (entrada)</div><div class="tl-desc">Receber e processar mensagens WhatsApp de pacientes.</div></div>
</div>
</div>
</div>
<div>
<div style="display:flex; align-items:center; gap:.5rem; margin-bottom:1rem">
<span class="dot dot-green" style="width:10px;height:10px"></span>
<span style="font-weight:700; color:#4ade80">Fase 3 — Expansão</span>
<span style="color:#64748b; font-size:.8rem">(23 meses)</span>
</div>
<div class="timeline">
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#22c55e"></div><div class="tl-connector"></div></div>
<div class="tl-content"><div class="tl-title">App Mobile</div><div class="tl-desc">React Native ou Flutter para terapeuta e paciente.</div></div>
</div>
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#22c55e"></div><div class="tl-connector"></div></div>
<div class="tl-content"><div class="tl-title">Videochamada Integrada</div><div class="tl-desc">Sessões online sem sair da plataforma.</div></div>
</div>
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#22c55e"></div><div class="tl-connector"></div></div>
<div class="tl-content"><div class="tl-title">API REST Pública</div><div class="tl-desc">Integrações de terceiros (CRMs, plataformas de saúde).</div></div>
</div>
<div class="tl-item">
<div class="tl-line"><div class="tl-dot" style="background:#22c55e"></div></div>
<div class="tl-content"><div class="tl-title">IA / Prontuário Inteligente</div><div class="tl-desc">Sugestões de diagnóstico e análise de sessões.</div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Tabela de rotas -->
<div class="card">
<h2>Cobertura de Rotas por Área</h2>
<canvas id="routesChart" height="100"></canvas>
</div>
<script>
// Donut
new Chart(document.getElementById('donutChart'), {
type: 'doughnut',
data: {
labels: ['Pronto', 'Parcial', 'Faltando'],
datasets: [{
data: [78, 14, 8],
backgroundColor: ['#22c55e', '#f59e0b', '#ef4444'],
borderWidth: 0,
hoverOffset: 6,
}]
},
options: {
cutout: '72%',
plugins: { legend: { display: false } },
animation: { animateScale: true }
}
});
// Bar — módulos
new Chart(document.getElementById('barChart'), {
type: 'bar',
data: {
labels: ['Auth', 'Agenda', 'Pacientes', 'Financ.', 'Agenda. Pub.', 'Config.', 'Comun.', 'SaaS', 'Dash. Clín.', 'Relat.', 'Pagto.', 'Testes'],
datasets: [{
data: [100, 95, 90, 85, 90, 88, 75, 80, 35, 40, 10, 15],
backgroundColor: [
'#22c55e','#22c55e','#22c55e','#22c55e','#22c55e','#22c55e',
'#f59e0b','#f59e0b',
'#f59e0b','#f59e0b',
'#ef4444','#ef4444'
],
borderRadius: 4,
}]
},
options: {
plugins: { legend: { display: false } },
scales: {
y: { min: 0, max: 100, ticks: { color: '#64748b', callback: v => v + '%' }, grid: { color: '#1e293b' } },
x: { ticks: { color: '#64748b', font: { size: 10 } }, grid: { display: false } }
}
}
});
// Radar
new Chart(document.getElementById('radarChart'), {
type: 'radar',
data: {
labels: ['Agenda', 'Pacientes', 'Financeiro', 'Comunicação', 'Pagamento', 'Testes', 'Relatórios', 'Mobile', 'Auth', 'Config'],
datasets: [
{
label: 'Implementado',
data: [95, 90, 85, 75, 10, 15, 40, 60, 100, 88],
borderColor: '#22c55e',
backgroundColor: 'rgba(34,197,94,0.15)',
pointBackgroundColor: '#22c55e',
borderWidth: 2,
},
{
label: 'Meta MVP',
data: [95, 90, 90, 80, 80, 70, 60, 80, 100, 88],
borderColor: '#60a5fa',
backgroundColor: 'rgba(96,165,250,0.05)',
pointBackgroundColor: '#60a5fa',
borderWidth: 1.5,
borderDash: [5, 5],
}
]
},
options: {
plugins: {
legend: {
labels: { color: '#94a3b8', font: { size: 11 } }
}
},
scales: {
r: {
min: 0, max: 100,
ticks: { display: false },
grid: { color: '#334155' },
pointLabels: { color: '#94a3b8', font: { size: 11 } },
angleLines: { color: '#334155' },
}
}
}
});
// Horizontal bar — rotas por área
new Chart(document.getElementById('routesChart'), {
type: 'bar',
data: {
labels: ['SaaS Admin', 'Configurações', 'Terapeuta', 'Clínica (Admin)', 'Auth', 'Público', 'Portal Paciente', 'Supervisor'],
datasets: [{
label: 'Nº de rotas',
data: [24, 15, 14, 13, 6, 5, 3, 3],
backgroundColor: ['#7c3aed','#2563eb','#059669','#0891b2','#d97706','#64748b','#db2777','#0d9488'],
borderRadius: 4,
}]
},
options: {
indexAxis: 'y',
plugins: { legend: { display: false } },
scales: {
x: { ticks: { color: '#64748b' }, grid: { color: '#334155' } },
y: { ticks: { color: '#cbd5e1' }, grid: { display: false } }
}
}
});
</script>
</body>
</html>