saas-docs/tmp: SQL de import direto pra doc Cronometro
Script usado pra importar a doc 02-cronometro-melissa.json diretamente no banco via psql (mesmo padrao da doc Busca global). DO block com dollar quoting ($HTML$ e $FAQ$) pra evitar escape hell no HTML conteudo + nos FAQs. Importacao executada em 2026-05-22. Doc id=e87d4d33-7f5c-454e-a2ff- 0f92505b7c3c + 12 FAQ itens vinculados. Path: database-novo/tmp/import-doc-cronometro.sql — pasta tmp pra artefatos de operacao (nao parte do schema canonico). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,168 @@
|
|||||||
|
-- Importacao da doc do Cronometro de sessao (Melissa)
|
||||||
|
-- Gerado a partir de development/saas-docs/02-cronometro-melissa.json
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
DO $IMPORT$
|
||||||
|
DECLARE
|
||||||
|
v_doc_id uuid;
|
||||||
|
BEGIN
|
||||||
|
-- 1) Cria a doc principal
|
||||||
|
INSERT INTO public.saas_docs (
|
||||||
|
titulo, conteudo, categoria, exibir_no_faq, tipo_acesso,
|
||||||
|
pagina_path, ordem, ativo, medias
|
||||||
|
) VALUES (
|
||||||
|
'Cronômetro de sessão',
|
||||||
|
$HTML$<h2>Cronômetro de sessão</h2>
|
||||||
|
|
||||||
|
<p>O <strong>cronômetro de sessão</strong> acompanha o tempo decorrido durante o atendimento e é integrado com a agenda. Quando aberto a partir de uma sessão em andamento, ele já vem com o paciente pré-selecionado e dispara automaticamente.</p>
|
||||||
|
|
||||||
|
<h3>1. Três jeitos de abrir</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Pelo botão <strong>⏱</strong> ao lado do relógio gigante do dashboard (abre vazio, escolha o paciente — ou deixe como atividade livre)</li>
|
||||||
|
<li>Pelo botão <strong>⏱</strong> que aparece sobre os cards de sessão em curso na timeline horizontal/vertical do dashboard</li>
|
||||||
|
<li>Pelo CTA <strong>"Iniciar cronômetro"</strong> no card <em>"Próximo paciente"</em> quando a sessão está em andamento</li>
|
||||||
|
</ul>
|
||||||
|
<p>Os dois últimos pré-selecionam o paciente da sessão e disparam o timer automaticamente.</p>
|
||||||
|
|
||||||
|
<h3>2. Sessão em curso na timeline</h3>
|
||||||
|
<p>Quando uma sessão entra em andamento (horário atual entre início e fim do evento), aparece um ícone <strong>⏱</strong> pulsando no canto superior direito do card do evento. O pulso é sutil, em verde — só pra sinalizar que dá pra cronometrar dali.</p>
|
||||||
|
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px; background: #6366f1; color: white; padding: 4px 10px; border-radius: 4px; max-width: 320px; position: relative; margin: 12px 0; font-family: 'Segoe UI', sans-serif;">
|
||||||
|
<span style="font-size: 0.85rem; font-weight: 600;">11:00 – Larissa Almeida</span>
|
||||||
|
<span style="position: absolute; top: 3px; right: 3px; width: 22px; height: 22px; display: grid; place-items: center; background: rgba(0,0,0,0.45); border: 1px solid rgba(255,255,255,0.4); border-radius: 999px; color: white; box-shadow: 0 0 0 4px rgba(16,185,129,0.25);">
|
||||||
|
<i class="pi pi-stopwatch" style="font-size: 0.7rem;"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>Clicar no <strong>⏱</strong> <strong>não abre o evento</strong> — abre o cronômetro pré-configurado pra essa sessão.</p>
|
||||||
|
|
||||||
|
<h3>3. Programado vs tempo real</h3>
|
||||||
|
<p>Quando aberto via timeline ou card "Próximo paciente", o cronômetro mostra o <strong>horário programado original da sessão</strong> sob o select de paciente. Se você abriu depois do horário previsto, aparece um badge laranja <strong>"atrasada X min"</strong>.</p>
|
||||||
|
|
||||||
|
<div style="background: rgba(15,23,42,0.85); color: #cbd5e1; padding: 14px; border-radius: 10px; max-width: 360px; font-family: 'Segoe UI', sans-serif; margin: 12px 0;">
|
||||||
|
<label style="font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.15em; color: rgba(255,255,255,0.5); display: block; margin-bottom: 8px;">Paciente / atividade</label>
|
||||||
|
<div style="background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.15); padding: 9px 14px; border-radius: 10px; font-size: 0.9rem;">Larissa Almeida</div>
|
||||||
|
<div style="display: flex; align-items: center; gap: 6px; margin-top: 8px; padding: 4px 0;">
|
||||||
|
<i class="pi pi-calendar" style="font-size: 0.7rem; color: rgba(255,255,255,0.55);"></i>
|
||||||
|
<span style="font-size: 0.78rem; color: rgba(255,255,255,0.7);">Programado: 11:00 – 11:50</span>
|
||||||
|
<span style="margin-left: 4px; padding: 1px 8px; border-radius: 999px; background: rgba(251,146,60,0.18); color: rgb(253,186,116); font-size: 0.7rem; font-weight: 500; border: 1px solid rgba(251,146,60,0.35);">atrasada 8 min</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>⚠️ <strong>O cronômetro NÃO desconta o tempo de atraso automaticamente.</strong> Ele conta a duração configurada cheia (50min padrão) a partir do clique. A info "atrasada" é só pra você decidir se quer encerrar antes ou estender.</p>
|
||||||
|
|
||||||
|
<h3>4. Anatomia do dialog</h3>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Header:</strong> rótulo "Cronômetro" + status (<em>Pronto</em> / <em>Em andamento</em> / <em>Pausado</em>)</li>
|
||||||
|
<li><strong>Botão Minimizar:</strong> recolhe pro chip no dock</li>
|
||||||
|
<li><strong>Botão X (Encerrar sem salvar):</strong> descarta a sessão (com confirmação se houver atividade)</li>
|
||||||
|
<li><strong>Select de paciente:</strong> pode trocar manualmente; opção <em>"— Atividade livre"</em> pra usos sem paciente</li>
|
||||||
|
<li><strong>Programado + badge de atraso:</strong> só aparece quando aberto via evento da agenda</li>
|
||||||
|
<li><strong>Display gigante mm:ss:</strong> vira vermelho quando passa do tempo planejado (mostra <code>-mm:ss</code>)</li>
|
||||||
|
<li><strong>±5 min:</strong> estende ou encurta o tempo configurado a qualquer momento</li>
|
||||||
|
<li><strong>Botão grande inferior:</strong> ▶ Começar / ⏹ Parar</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>5. Minimizar e restaurar</h3>
|
||||||
|
<p>Click no <strong>botão minimizar</strong> (ou click fora do dialog) <strong>recolhe</strong> o cronômetro pra um <strong>chip flutuante no dock</strong> (canto inferior esquerdo, ao lado do ψ). O timer continua rodando em background. Click no chip restaura o dialog em tela cheia.</p>
|
||||||
|
|
||||||
|
<div style="display: inline-flex; align-items: center; gap: 10px; padding: 8px 14px 8px 12px; background: rgba(15,23,42,0.85); border: 1px solid rgba(255,255,255,0.18); border-radius: 999px; color: #cbd5e1; font-family: 'Segoe UI', sans-serif; box-shadow: 0 8px 24px rgba(0,0,0,0.25); margin: 12px 0;">
|
||||||
|
<i class="pi pi-stopwatch" style="font-size: 0.85rem; color: #6ee7b7;"></i>
|
||||||
|
<span style="font-variant-numeric: tabular-nums; font-weight: 500; font-size: 0.85rem;">48:13</span>
|
||||||
|
<span style="font-size: 0.72rem; color: rgba(255,255,255,0.6); padding-left: 6px; border-left: 1px solid rgba(255,255,255,0.18);">Larissa Almeida</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>Em mobile (telas <768px), o chip mostra só o ícone + tempo — sem o nome do paciente — pra caber no dock estreito. O nome continua acessível ao restaurar.</p>
|
||||||
|
|
||||||
|
<h3>6. Parar (salva) vs Fechar (descarta)</h3>
|
||||||
|
<p>Duas ações diferentes pra terminar — a escolha importa:</p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>⏹ Parar</strong> (botão grande inferior): encerra a contagem e <strong>SALVA o tempo decorrido no banco</strong> (evento <code>session-end</code> com elapsed em segundos). Caminho normal de fim de sessão.</li>
|
||||||
|
<li><strong>X Encerrar sem salvar</strong> (header): descarta. Pede <strong>confirmação</strong> se há sessão em andamento ou tempo decorrido — não fecha por acidente. Se o cronômetro está limpo (não iniciado, sem tempo), fecha direto.</li>
|
||||||
|
<li><strong>Click fora / Minimizar</strong>: NÃO encerra. Esconde o dialog e mantém o timer rodando como chip no dock.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>7. Quando o tempo acaba</h3>
|
||||||
|
<p>Aos <strong>50 minutos cronometrados</strong> (ou conforme configurado), o sistema toca um <strong>som curto</strong> uma única vez. O display vira <strong>vermelho</strong> e continua contando em negativo (mostra <code>-mm:ss</code>). <strong>Não há corte automático</strong> — você decide quando parar.</p>
|
||||||
|
|
||||||
|
<p>O toque pode ser trocado em <strong>Configurações → Cronômetro → Som de término</strong>. Opções: sino, gong, soft, silêncio.</p>
|
||||||
|
|
||||||
|
<h3>8. Persistência (reload-safe)</h3>
|
||||||
|
<p>Se você fechar a aba ou recarregar o navegador com cronômetro ativo, ao voltar o sistema <strong>retoma exatamente de onde parou</strong> — descontando automaticamente o tempo passado entre fechar e abrir. O snapshot fica no <code>localStorage</code> do navegador, atualizado a cada mudança de estado.</p>
|
||||||
|
|
||||||
|
<p><strong>Limite de segurança:</strong> se passar de 24h sem voltar à aba, o restore não acumula o tempo perdido (proteção contra mudanças do relógio do sistema).</p>
|
||||||
|
|
||||||
|
<h3>9. Cronômetro já ativo</h3>
|
||||||
|
<p>Existe <strong>um cronômetro por vez</strong>. Se você clicar no <strong>⏱</strong> de outra sessão enquanto há cronômetro rodando, o sistema mostra um toast <strong>"Cronômetro já ativo"</strong> com o nome do paciente atual — <strong>e não troca</strong>. Pare o cronômetro atual antes de iniciar outro.</p>
|
||||||
|
|
||||||
|
<h3>10. Atividade livre (sem paciente)</h3>
|
||||||
|
<p>Você pode abrir o cronômetro sem paciente (botão ⏱ do dashboard, sem clicar em evento específico) e selecionar <em>"— Atividade livre (sem paciente)"</em> no dropdown. Útil pra:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Pausa cronometrada</li>
|
||||||
|
<li>Pomodoro pessoal</li>
|
||||||
|
<li>Atendimento informal não cadastrado</li>
|
||||||
|
</ul>
|
||||||
|
<p>Atividade livre <strong>não emite session-end</strong> ao parar (não há paciente pra vincular o tempo).</p>
|
||||||
|
|
||||||
|
<h3>⚠️ Notas pro desenvolvedor</h3>
|
||||||
|
<p>Atualmente o componente <code>MelissaCronometro.vue</code> <strong>não tem atributos <code>id</code></strong> em seus elementos. Para o sistema de highlight da ajuda funcionar (links <code>data-highlight</code>), sugere-se adicionar:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>id="crono-trigger-hero"</code> no botão ⏱ ao lado do relógio (<code>MelissaHeroClock.vue</code>)</li>
|
||||||
|
<li><code>id="crono-trigger-timeline"</code> nos botões ⏱ overlay (<code>MelissaTimelineHoje.vue</code>)</li>
|
||||||
|
<li><code>id="crono-dialog"</code> no panel principal (<code>.mc-panel</code>)</li>
|
||||||
|
<li><code>id="crono-stop-btn"</code> no botão Parar (caminho do salvamento)</li>
|
||||||
|
<li><code>id="crono-close-btn"</code> no X (caminho do descarte)</li>
|
||||||
|
</ul>$HTML$,
|
||||||
|
'Sessão',
|
||||||
|
true,
|
||||||
|
'usuario',
|
||||||
|
'/melissa',
|
||||||
|
2,
|
||||||
|
true,
|
||||||
|
'[{"tipo": "imagem", "url": ""}]'::jsonb
|
||||||
|
)
|
||||||
|
RETURNING id INTO v_doc_id;
|
||||||
|
|
||||||
|
-- 2) Insere os 12 FAQ items vinculados
|
||||||
|
INSERT INTO public.saas_faq_itens (doc_id, pergunta, resposta, ordem, ativo) VALUES
|
||||||
|
(v_doc_id, 'Como começo o cronômetro da Larissa que chegou agora pra sessão?',
|
||||||
|
$FAQ$Quando o horário programado da Larissa estiver dentro da janela do evento (já começou na agenda), aparece um botão <strong>⏱</strong> pulsando em verde no canto superior direito do card da sessão na timeline. Clique nele — o cronômetro abre com a Larissa pré-selecionada e <strong>já começa a contar automaticamente</strong>. Alternativa: clique no botão <em>"Iniciar cronômetro"</em> no card "Próximo paciente" do dashboard (mesmo efeito).$FAQ$, 0, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'O cronômetro continua se eu fechar a aba do navegador?',
|
||||||
|
$FAQ$<strong>Sim.</strong> O estado é salvo no <code>localStorage</code> a cada mudança (paciente, play, pause, ajustes). Ao reabrir a aba (ou recarregar), o cronômetro retoma do ponto correto — o tempo passado entre fechar e abrir é descontado automaticamente. Limite: se passar de 24h, o sistema não acumula esse tempo (proteção contra mudanças do relógio do sistema).$FAQ$, 1, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'Cliquei no X com sessão rodando, perdi o tempo?',
|
||||||
|
$FAQ$Não, o sistema <strong>pede confirmação antes</strong>. Quando há sessão em andamento ou tempo decorrido sem salvar, aparece um diálogo <em>"Encerrar sessão sem salvar?"</em>. Você precisa clicar em <strong>"Encerrar sem salvar"</strong> (botão vermelho) pra confirmar o descarte. Se o cronômetro estiver limpo (não iniciado, sem tempo), o X fecha direto — não há nada pra preservar.$FAQ$, 2, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'Posso ter dois cronômetros rodando ao mesmo tempo?',
|
||||||
|
$FAQ$Não. Existe <strong>um cronômetro por vez</strong>. Se você clicar no <strong>⏱</strong> de outra sessão enquanto já há um cronômetro ativo, o sistema mostra um toast <em>"Cronômetro já ativo — sessão de X em andamento"</em> e <strong>não troca</strong>. Pare ou descarte o atual antes de iniciar outro.$FAQ$, 3, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'O que significa o badge laranja "atrasada 8 min"?',
|
||||||
|
$FAQ$Significa que <strong>o cronômetro foi aberto 8 minutos depois do horário programado</strong> da sessão na agenda. Por exemplo: sessão programada pra 11:00, você inicia o cronômetro às 11:08. O badge é apenas informativo — o cronômetro continua contando a duração configurada cheia (50min padrão) a partir do clique. Você decide se vai encerrar antes pra terminar no horário previsto ou deixar rodar pra dar a sessão completa.$FAQ$, 4, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'O cronômetro desconta o tempo de atraso automaticamente?',
|
||||||
|
$FAQ$<strong>Não.</strong> A decisão fica com você. Cada clínica e cada terapeuta tem uma política diferente pra atraso (alguns dão sessão cheia, outros encerram no horário programado, outros estendem). O cronômetro mostra a info do atraso pra você decidir, mas conta sempre a duração configurada cheia a partir do clique.$FAQ$, 5, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'Que som toca quando o tempo acaba?',
|
||||||
|
$FAQ$Por padrão, um <strong>som de sino curto</strong>, uma única vez. Você pode trocar em <strong>Configurações → Cronômetro → Som de término</strong>. Opções: sino, gong, soft, silêncio. O som toca <strong>exatamente na transição</strong> de tempo positivo pra zero/negativo — não repete. Depois disso o display continua contando em negativo (vermelho) até você parar.$FAQ$, 6, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'Como adiciono mais tempo na sessão sem reiniciar?',
|
||||||
|
$FAQ$Use os botões <strong>+5 min</strong> e <strong>-5 min</strong> ao redor do display gigante. Funcionam a qualquer momento — antes, durante ou depois do tempo acabar. Cada clique soma ou desconta 5 minutos. Se o tempo já está negativo (passou do limite), +5min volta a contagem pra positivo.$FAQ$, 7, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'Onde fica salvo o tempo final da sessão?',
|
||||||
|
$FAQ$Quando você clica em <strong>⏹ Parar</strong>, o tempo cronometrado é gravado no banco vinculado à sessão da agenda (na tabela <code>agenda_eventos</code>, campo de duração real). Esse caminho é o oficial — <strong>fechar pelo X descarta sem salvar</strong>. Sessões com menos de 5 segundos cronometrados são ignoradas (proteção contra start/stop acidentais).$FAQ$, 8, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'Posso usar o cronômetro pra coisas que não são sessão de paciente?',
|
||||||
|
$FAQ$Sim. Selecione <em>"— Atividade livre (sem paciente)"</em> no dropdown de paciente. Útil pra pausa cronometrada, pomodoro pessoal, atendimento informal não cadastrado. Atividade livre <strong>não dispara session-end</strong> ao parar — não há paciente pra vincular o tempo no DB.$FAQ$, 9, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'Como minimizo o cronômetro pra continuar trabalhando?',
|
||||||
|
$FAQ$Clique no botão <strong>minimizar</strong> no header (ícone <code>—</code>) ou simplesmente <strong>clique fora do dialog</strong>. O cronômetro vira um chip flutuante no dock (canto inferior esquerdo, ao lado do ψ) e continua contando em background. Pra restaurar: clique no chip. Em mobile, o chip mostra só ícone + tempo (sem nome) pra caber no dock estreito.$FAQ$, 10, true),
|
||||||
|
|
||||||
|
(v_doc_id, 'Como mudo o paciente no cronômetro já aberto?',
|
||||||
|
$FAQ$Basta clicar no <strong>select de paciente</strong> e escolher outro. A troca é imediata — não reinicia o tempo decorrido (a contagem continua igual). Útil quando você abriu o cronômetro no paciente errado e quer corrigir sem perder o tempo já contado. Mas atenção: o <em>session-end</em> ao parar vai vincular o tempo ao paciente que estiver selecionado <em>no momento da parada</em>.$FAQ$, 11, true);
|
||||||
|
|
||||||
|
RAISE NOTICE 'Doc criada: id=%, faq_itens=12', v_doc_id;
|
||||||
|
END;
|
||||||
|
$IMPORT$;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
Reference in New Issue
Block a user