Files

188 lines
8.5 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Redator de SD — RMDS / SES-MG</title>
<link rel="stylesheet" href="styles.css" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📋</text></svg>" />
</head>
<body>
<header class="appbar">
<h1>Redator de SD</h1>
<span class="sub">RMDS · PE 29/2025 — SES-MG × Isis Saúde</span>
<span class="spacer"></span>
<span id="statusChip" class="chip-status">carregando…</span>
<a href="#/" id="navHome" class="btn btn-sm">Nova SD</a>
<a href="#/validar" id="navValidar" class="btn btn-sm">Validar JSON</a>
<a href="#/base" id="navBase" class="btn btn-sm">Base de Conhecimento</a>
<button id="btnTema" class="btn btn-sm" type="button" title="Tema">🌗</button>
<button id="btnSair" class="btn btn-sm" hidden>Sair</button>
</header>
<!-- Aviso de configuração -->
<div id="avisoConfig" class="aviso" hidden>
⚠ Chave de API não configurada. Copie <code>app\.env.example</code> para <code>app\.env</code>,
preencha <code>ANTHROPIC_API_KEY</code> e reinicie o servidor.
</div>
<!-- Login (usuário único) -->
<main id="telaLogin" hidden>
<form id="formLogin" class="panel login-box">
<h2>Entrar</h2>
<label>Usuário<br><input type="text" id="loginUsuario" autocomplete="username" required></label>
<label>Senha<br><input type="password" id="loginSenha" autocomplete="current-password" required></label>
<div id="loginErro" class="login-erro" hidden></div>
<button type="submit" class="btn btn-primary" id="btnLogin">Entrar</button>
</form>
</main>
<!-- Tela inicial: lista + nova demanda -->
<main id="telaHome" hidden>
<section class="panel nova-demanda">
<h2>Nova SD</h2>
<p class="hint">Cole a demanda do jeito que ela chegou — trecho de ata, e-mail encaminhado, mensagem.
Não precisa organizar. O redator lê, compara com a base e pergunta só o que faltar.</p>
<textarea id="demandaInput" rows="5" placeholder="Ex.: a secretaria quer implementar um sistema de..."></textarea>
<div class="btnrow">
<button id="btnIniciar" class="btn btn-primary">Iniciar entrevista</button>
<label class="sel-modelo">Modelo
<select id="selModelo"></select>
</label>
</div>
<p class="hint" style="margin:8px 0 0">O modelo fica fixo para a SD inteira (trocar no meio
descartaria o cache da conversa). Lista configurável em <code>LLM_MODELOS</code> no .env.</p>
</section>
<section class="panel">
<h2>SDs em andamento</h2>
<div id="listaSds" class="lista-sds"></div>
</section>
<section class="panel">
<h2>Saldo dos pools de UST</h2>
<div id="saldosBox" class="saldos"></div>
</section>
</main>
<!-- Tela da entrevista: chat + painel -->
<main id="telaConversa" class="conversa" hidden>
<section class="coluna-chat">
<div id="mensagens" class="mensagens"></div>
<div id="opcoes" class="opcoes"></div>
<form id="formMsg" class="form-msg">
<textarea id="msgInput" rows="2" placeholder="Responda ao redator… (Enter envia, Shift+Enter quebra linha)"></textarea>
<button type="submit" class="btn btn-primary" id="btnEnviarMsg">Enviar</button>
</form>
<div id="usoBox" class="uso"></div>
</section>
<aside class="coluna-painel" id="slotPainelConversa">
<div id="painel">
<div class="painel-vazio" id="painelVazio">O painel do documento aparece aqui assim que o redator
registrar os primeiros campos da SD.</div>
<div id="painelConteudo" hidden>
<section class="pbloco" id="pResumo"></section>
<section class="pbloco">
<h3>Quadro de entregáveis</h3>
<div id="pQuadro" class="twrap"></div>
</section>
<section class="pbloco">
<h3>Trava de integridade — artefatos</h3>
<div id="pArtefatos"></div>
</section>
<section class="pbloco">
<h3>Checklist de validação</h3>
<div id="pChecklist"></div>
</section>
<section class="pbloco">
<h3>Pendências</h3>
<ul id="pPendencias" class="pend-list"></ul>
</section>
<section class="pbloco" id="pExport">
<h3>Fechamento</h3>
<div id="pBloqueios" class="lock-msg"></div>
<div class="btnrow">
<button class="btn" id="btnDocumento">Documento / imprimir (PDF)</button>
<button class="btn" id="btnBaixar">Baixar .json</button>
<button class="btn btn-primary" id="btnEnviarSd">Marcar como enviada</button>
</div>
<p class="hint" style="margin-top:8px">O documento abre em uma aba pronta para imprimir
(Ctrl+P → salvar como PDF). Enquanto houver pendência bloqueante, ele sai com marca de rascunho.</p>
</section>
</div>
</div>
</aside>
</main>
<!-- Validação de JSON externo -->
<main id="telaValidar" class="conversa" hidden>
<section class="coluna-chat">
<div class="panel">
<h2>Validar JSON externo</h2>
<p class="hint">Cole aqui o JSON de uma SD que não nasceu neste app (ex.: redigida no Claude ou
recebida de um colega). O app recalcula UST e datas, roda o checklist do contrato e libera o
documento para impressão — sem salvar nada.</p>
<textarea id="jsonExterno" rows="14" spellcheck="false"
placeholder='Cole o JSON da SD (formato schema-sd.json)…'></textarea>
<div id="validarErro" class="login-erro" hidden></div>
<div class="btnrow" style="margin-top:10px">
<button class="btn btn-primary" id="btnValidarJson">Validar</button>
<button class="btn" id="btnImportarJson">Importar JSON</button>
<button class="btn" id="btnLimparJson">Limpar</button>
<button class="btn" id="btnVoltarValidar">Voltar</button>
</div>
<input type="file" id="arquivoJson" accept=".json,application/json" hidden>
</div>
</section>
<aside class="coluna-painel" id="slotPainelValidar"></aside>
</main>
<!-- Alimentar base de conhecimento: upload de SD real → extração → revisão → gravação -->
<main id="telaBase" hidden>
<section class="panel">
<h2>Alimentar base de conhecimento</h2>
<p class="hint">Envie o documento de uma SD real (<strong>.pdf</strong>, <strong>.md</strong> ou <strong>.txt</strong>
se estiver em .docx, exporte como PDF). O app lê o documento, extrai o registro estruturado
(itens, UST por item, período, status) e sugere capacidades reutilizáveis. Nada é gravado
sem a sua revisão abaixo.</p>
<div class="btnrow">
<button class="btn btn-primary" id="btnEscolherDoc">Enviar documento</button>
<label class="sel-modelo">Modelo
<select id="selModeloBase"></select>
</label>
<button class="btn" id="btnVoltarBase">Voltar</button>
</div>
<input type="file" id="arquivoDoc" accept=".pdf,.md,.txt,application/pdf,text/markdown,text/plain" hidden>
<div id="baseErro" class="login-erro" hidden style="margin-top:10px"></div>
<div id="baseExtraindo" class="hint" hidden style="margin-top:10px">⏳ Lendo o documento e extraindo o registro… isso leva de 30 segundos a 2 minutos.</div>
<div id="baseUso" class="uso" style="margin-top:6px"></div>
</section>
<section class="panel" id="baseRevisao" hidden>
<h2>Revisão antes de gravar</h2>
<div class="pbloco">
<h3>Conferência (em código)</h3>
<div id="baseConferencia"></div>
</div>
<div class="pbloco" id="baseObsBloco" hidden>
<h3>Observações do extrator</h3>
<ul id="baseObs" class="pend-list"></ul>
</div>
<div class="pbloco">
<h3>Registro da SD (edite se necessário e reconfira)</h3>
<textarea id="baseSdJson" rows="16" spellcheck="false"></textarea>
</div>
<div class="pbloco">
<h3>Capacidades sugeridas (desmarque as que não devem entrar)</h3>
<div id="baseCaps"></div>
</div>
<div class="btnrow">
<button class="btn" id="btnReconferir">Reconferir</button>
<button class="btn btn-primary" id="btnGravarBase">Gravar na base</button>
</div>
<div id="baseOk" class="lock-msg open" hidden style="margin-top:10px"></div>
</section>
</main>
<script src="app.js"></script>
</body>
</html>