feat: sistema de observação por voz - fase 1
- FAB flutuante para gravar observação - Modal com timer + waveform animado - Botão sair para desistir - MediaRecorder API (webm/opus) - Transcrição via OpenAI Whisper - Relatório estruturado via GPT - Salva em .md com frontmatter (data/hora/timestamp) - Índice JSON para consulta posterior - Rotas: transcrever, salvar, listar observações - multer para upload de áudio
This commit is contained in:
+63
-2
@@ -102,8 +102,15 @@
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Overlay para fechar sidebar clicando fora no mobile -->
|
||||
<div class="sidebar-overlay" id="sidebarOverlay"></div>
|
||||
<!-- FAB: Nova Observação por Voz -->
|
||||
<button class="fab-record" id="fabRecord" title="Nova Observação (gravar)">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Overlay para fechar sidebar clicando fora no mobile -->
|
||||
<div class="sidebar-overlay" id="sidebarOverlay"></div>
|
||||
|
||||
<!-- Área principal do Chat -->
|
||||
<main class="chat-area">
|
||||
@@ -247,6 +254,60 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Modal de Gravação de Observação -->
|
||||
<div id="recordModal" class="settings-modal" style="display: none;">
|
||||
<div class="settings-modal-content record-modal-content">
|
||||
<div class="record-modal-header">
|
||||
<button id="btnExitRecord" class="btn-exit-record" title="Sair e descartar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
|
||||
</svg>
|
||||
<span>Sair</span>
|
||||
</button>
|
||||
<h3>🎤 Nova Observação</h3>
|
||||
<div style="width: 60px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="record-modal-body">
|
||||
<!-- Estado: gravando -->
|
||||
<div id="recordStateRecording" class="record-state" style="display: none;">
|
||||
<div class="record-timer" id="recordTimer">00:00</div>
|
||||
<div class="record-waveform" id="recordWaveform">
|
||||
<div class="wave-bar"></div><div class="wave-bar"></div><div class="wave-bar"></div>
|
||||
<div class="wave-bar"></div><div class="wave-bar"></div><div class="wave-bar"></div>
|
||||
<div class="wave-bar"></div><div class="wave-bar"></div><div class="wave-bar"></div>
|
||||
<div class="wave-bar"></div><div class="wave-bar"></div><div class="wave-bar"></div>
|
||||
</div>
|
||||
<p class="record-hint">Fale livremente sobre a observação...</p>
|
||||
<button id="btnStopRecord" class="btn-stop-record">
|
||||
<div class="stop-icon"></div>
|
||||
<span>Parar</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Estado: processando -->
|
||||
<div id="recordStateProcessing" class="record-state" style="display: none;">
|
||||
<div class="record-spinner"></div>
|
||||
<p>Analisando sua observação...</p>
|
||||
<small style="color: var(--text-muted);">Transcrevendo e gerando relatório</small>
|
||||
</div>
|
||||
|
||||
<!-- Estado: prévia -->
|
||||
<div id="recordStatePreview" class="record-state" style="display: none;">
|
||||
<div class="preview-header">
|
||||
<h4>📋 Relatório Gerado</h4>
|
||||
<span id="previewDateTime"></span>
|
||||
</div>
|
||||
<div id="reportContent" class="report-content"></div>
|
||||
<div class="preview-actions">
|
||||
<button id="btnDiscardReport" class="btn-discard">Descartar</button>
|
||||
<button id="btnSaveReport" class="btn-save-report">Salvar</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal de Configurações do Agente -->
|
||||
<div id="settingsModal" class="settings-modal" style="display: none;">
|
||||
<div class="settings-modal-content settings-modal-large">
|
||||
|
||||
Reference in New Issue
Block a user