Files
Leonardo b0b636c660 log: sessao 22/05 - Melissa UX overhaul + 5 saas-docs (Fases 2-5)
Sessao completa de ~14 commits. 2 grandes blocos:

BLOCO 1 — Melissa UI overhaul: tray bottom-right (substitui topbar
band), mobile collapse parcial em <md, busca global unificada
(MelissaBusca ganha "Ir para [data]", popover da agenda deletado),
dock com 4 builtins, hero resumo com cancelado/remarcado, settings+
ajuda click-outside, cronometro evento-aware (botao ⏱ na timeline +
sessionPlan + confirm fechar), documents edit in-place via
document_generated.documento_id, wire-up dos 5 botoes do preview.

BLOCO 2 — 5 docs saas novas (03-07 em development/saas-docs/) +
SQL imports + 60 FAQs total. Cobertura: aba Documentos paciente,
pagina Templates, Assinatura eletronica, Emissao de recibo
profissional, Relatorios + 3 formatos de export.

Memorias adicionadas:
- feedback_tailwind_utility_load_order (hidden perde pra CSS base
  do componente por ordem de carga Vite)
- project_documents_reedit_in_place (linkage documento_id + editingDocId)

PROXIMA SESSAO (23/05): Fase 6 restante (C12 antecipar UX iter —
unico item de codigo da lista de ontem), Fase 7 restante (regressao
Agenda C7-C13, validacao manual). Antes/depois: panorama MVP no
ROADMAP canonico — ainda restam #12 papel timbrado, #15 NFS-e,
§1.5 Sentry, Asaas Fase B, M4 cutover, validacao centralizada
de forms.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 20:37:10 -03:00

1645 lines
84 KiB
Markdown
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.
# Wiki Log
Chronological, append-only record of everything that's happened in this wiki.
**Format:**
```
## [YYYY-MM-DD HH:MM] <type> | <title>
<optional detail line>
```
**Types:** `session`, `ingest`, `query`, `lint`, `rebuild`
**Quick access:** `grep "^## \[" log.md | tail -5` gives you the last 5 entries.
---
## [2026-05-22 dia] session | Melissa UX overhaul + 5 docs saas (Fases 2-5)
Touched: none codigo durable; 5 docs saas novas em development/saas-docs/
Sessao longa (~12 commits codigo + 5 docs). 2 grandes blocos:
BLOCO 1 — Melissa UI overhaul (manha):
- Tray no canto inf. direito (substitui topbar band do topo): busca +
plan-DEV + bell + ajuda + cog. Sibling de .melissa-dock (fora de
.win11-summary) pra ficar interativa com secao aberta. Em <md (768px)
collapse parcial — bell/help/cog/plan-DEV viram popup vertical no
botao ⋮; dot vermelho no ⋮ quando ha notificacoes nao lidas.
- Busca global unificada: MelissaBusca ganha parser de data (hoje/
amanha/ontem/DD/MM/YYYY) + card azul "Ir para [data]" + emit
goto-date. Popover da agenda (MelissaAgendaSearchPopover) deletado;
Ctrl+K so vive na MelissaBusca. Lupa unica fica so na .melissa-tray
(removida das toolbars de secoes pra evitar pollution mobile).
- Dock: 4 builtins (Agenda · Pacientes · WhatsApp · Financeiro). MRU
oculto em <md via @media (utility 'hidden' do tailwind perdia pro
.dock-pin{display:grid} por carga).
- Hero resumo: contagem "(x foi cancelado, x foi remarcado)" depois
do chip atendimentos com gramatica plural.
- Settings + Ajuda fecham ao clicar fora (mousedown capture + watch
open). Cog ref + data-ajuda-toggle ignoram trigger pra evitar
close+reopen.
- Cronometro: pre-selecao paciente + autostart quando aberto via
botao ⏱ na timeline (sessao em curso) ou card "Proximo paciente".
abrir(opts) com { pacienteId, autostart, sessionPlan }. sessionPlan
exibe "Programado: HH:MM HH:MM" + badge "atrasada X min"; NAO
desconta atraso auto. Confirm fechar quando ha sessao rodando/
decorrido sem salvar. Chip minimizado oculta nome do paciente em
<md (so icone + tempo).
- Documents: linkage document_generated.documento_id agora preenchido
no INSERT (era sempre NULL). Modo edit in-place via editingDocId:
busca template+dados_preenchidos via loadGeneratedFromDocId, popula
vars, pula pra step 'edit'; save substitui PDF no Storage e
atualiza documents (preserva id+audit). Header amber "Editar
documento" + botao "Substituir documento". Backfill SQL pra docs
antigos (3 linkados, 5 orfaos no DB local).
- DocumentPreviewDialog: wire-up dos 5 botoes da sidebar (download/
editar/share/sign/delete) que estavam caindo no vazio.
BLOCO 2 — saas-docs (tarde):
Padrao igual da 01-busca-global-melissa.json — JSON-fonte +
SQL de import direto via $HTML$/$FAQ$ dollar quoting. 5 docs novas
(03 a 07), cada uma com 12 FAQ itens:
- 03 Documentos do paciente — pagina_path /melissa/paciente,
categoria Documentos
- 04 Templates de documentos — pagina_path /melissa/documentos-
templates, categoria Documentos
- 05 Assinatura eletronica — pagina_path /melissa/paciente,
categoria Documentos
- 06 Recibo profissional — pagina_path /melissa/agenda, categoria
Financeiro (cobre fluxo do AgendaEventoFinanceiroPanel)
- 07 Relatorios e exportacao — pagina_path /melissa/relatorios,
categoria Relatorios
Todas importadas no DB local via docker exec psql. Total acumulado:
7 docs ativas em saas_docs (busca + cronometro + os 5 novos).
PROXIMA SESSAO (retomar 23/05):
- Fase 6 RESTANTE: C12 UX iter (cronometro/sessao antecipar pgto —
flow DB ja ok, UX obscura adiada em 20/05). Unico item de codigo
da lista de ontem.
- Fase 7 RESTANTE: Regressao Agenda C7-C13 (validacao manual; eu
nao executo, so listo plano de teste se quiser).
- Antes/depois: olhada no ROADMAP.md canonico pra panorama MVP
real. Itens visiveis ainda no horizonte: #12 papel timbrado
(bloqueado, codigo no UniaoApp), #15 NFS-e (esforco L), §1.5
Sentry+qualidade, Asaas Fase B (bloqueado), M4 cutover billing
(depende decisoes #2/#3/#6), validacao centralizada CPF/CNPJ/tel.
ITENS TESTADOS HOJE (✅): tray + busca unificada + cronometro
evento-aware + edicao in-place de docs gerados + Fase 2.7-2.9
(gerar PDF, vars CRP/UF, tipo_documento='outro').
PUSH: 12 commits pushados (c17c547..701d9f4) usando workaround SSL
(git -c http.sslVerify=false push). Credenciais pediram 1x, depois
cacheou pra sessao toda.
## [2026-05-20 18:30] session | C12 deferred + C13 prep (lock ja existia em Fase 6)
Touched: none (codigo + HANDOFF; memoria project_c12_antecipar_iterar)
Detalhes:
C12 (antecipar pagamento) — DB OK + watch sync resolveu snapshot
stale, mas UX ficou confusa em ciclos antecipar/revogar/re-antecipar.
Adiado pra iterar pos-Rail/Clinica. 5 bugs adicionais corrigidos:
- Re-antecipar reusava record cancelled (notes confusas). Fix: filter
cancelled em existRec query
- Popover snapshot stale apos materializacao virtual->real. Fix:
watch em M.eventos com lookup por id + recurrence_id/date
- normalizeForMelissa nao expunha owner_id/tenant_id/billing_contract_id
-> RPC create_financial_record_for_session erro "null in owner_id".
Fix: expor explicit + fallback em handler
- onAnteciparPagamento fechava popover -> agora mantem aberto e watch
sincroniza
- Quick "Revogar pagamento" button alternando "Antecipar pagamento"
quando isAntecipacaoAtiva (paid + agendado)
C13 — prep:
- Lock "edit cobrada imutavel" JA esta implementado (Fase 6 do
commit 1feb711). Message azul com cadeado + AgendaEventoFinanceiro
Panel embedded quando occFinancialRecord existe. Card "Aplicar
alteracoes em" oculto pra simplificar.
- Pacientes pra testar: Joao Almeida (R$ 40 maquininha avulsa) ou
Andre Green 20/05 (R$ 40 PIX, pacote saldo)
- User vai testar; sem mudanca de codigo prevista. Validacao visual.
Total acumulado no dia: 14 commits, ~14 bugs corrigidos, 3 features
novas (Agendada button, reverse trava, revogar antecipacao + watch
sync popover).
## [2026-05-20 16:00] session | C11 OK (A/B/C/D) + reverse trava + 5 bugs achados
Touched: none (codigo + HANDOFF; memoria project_billing_contracts_no_updated_at)
Detalhes:
CENARIO 11 (Status change pacote saldo) - 4/4 passaram com Andre Green:
- 11A: realizada + markPaid PIX (saldo 0->1, record paid R$ 40)
- 11B: falta + descontar (saldo 1->2, sem multa)
- 11C: falta + multa SEM consumir (saldo stays 2, multa pending R$ 30)
- 11D: cancelado >2h + default_consume_on_miss=true (saldo 2->3, sem multa)
ROOT CAUSE descoberto: billing_contracts NAO tem coluna updated_at.
Passar esse field em UPDATE falhava silently em Promise.allSettled
(ja documentado em memoria). Refatorado pra awaits sequenciais com
error handling explicito.
DIALOG UX (refator): bloco "Cobranca no pacote" antes tinha select
"Como cobrar?" com options "Ja recebi - PIX/Dinheiro" misturadas.
Confuso. Agora tem 2 sub-questions: "Ja recebi?" radio + select
condicional (sem prefixo ambiguo).
REVERSE TRANSITION TRAVA (antecipado pos-C13 pra C11): quando user
clica Agendada em sessao com artefatos (cobranca pending, paid,
ou saldo consumido em pacote), dialog reverse abre mostrando:
- Lista records pending + radio Cancelar/Manter
- Warning textual pra paid (sem auto-estorno)
- Radio devolver saldo se consumido
- Default: cancel + devolver (recovery flow)
Outros fixes acumulados:
- consumeSaldo amarra billing_contract_id (era omissao)
- link universal pre-forward (antes era so em consumeSaldo/generatePackageCharge)
- reverse decrement saldo: refetch FRESH antes do UPDATE (anti-race)
- label pacote saldo state=none: "Aguardando uso do pacote"
- badge $ amber suprimido em pacote saldo state=none
- lock total em sessao encerrada (Editar some, status disabled excepto Agendada)
DOC: addendum no HTML cenarios atualizado anteriormente cobre tudo.
Memorias: project_billing_contracts_no_updated_at (novo gotcha).
PROXIMO: Cenario 12 (antecipar pagamento) ou Cenario 13 (edit
cobrada). Depois replicar em Rail + Clinica.
## [2026-05-20 14:00] session | C10 OK (A/A2/B/C/C2) + lock sessao encerrada + addendum doc
Touched: none (codigo + HANDOFF + addendum HTML; memorias project_agenda_reverse_transitions e project_melissa_popover_snapshot)
Detalhes:
CENARIO 10 (Status change avulsa) - 5/5 sub-testes passaram:
- A: realizado sem markPaid -> record pending preservado (João Almeida)
- A2: realizado + markPaid maquininha -> paid + paid_at + payment_method
(João Almeida; investigado false positive de "stale" - era confusao de
query, sempre passou)
- B: faltou + multa fixed R$ 30 -> original cancelled + nova multa com
description "Multa por falta · sessão dd/mm/aa" (Otto Rank)
- C: cancelado >2h antecedência -> original cancelled sem multa
(Otto/Karen). Hint contextual no dialog explica POR QUE multa veio
desmarcada.
- C2: cancelado tardio <2h full charge -> original cancelled + nova
"Taxa de cancelamento tardio" (Karen Horney)
BUGS DESCOBERTOS + CORRIGIDOS durante bateria (3 commits acumulados):
- Cobranca dupla na multa: _applyStatusDecisions INSERIA multa mas
deixava original pending. Fix: cancelar ctx.pendingRecord com nota
de auditoria em notes.
- _reloadRange not defined: _buildHandlers nao destruturava do deps.
- Badge $ amber em sessao cancelada: gate sessaoEncerrada agora cobre
status=cancelado/faltou em MelissaAgenda.vue.
- paymentLabel usava ev.price pra pending (R$ 150 enquanto multa real
era R$ 30). Fix: paymentAmount tambem em pending.
- Botao "Gerar cobranca" no popover + AgendaEventoFinanceiroPanel
permitia emitir fatura em sessao encerrada. Fix: gated por
isSessaoEncerrada.
- Lock total em cancelado/faltou: Editar sessao some, Realizada/Falta/
Reagendar/Cancelar disabled. So botao "Agendada" (novo, variante
--info cyan) continua funcional pra recuperacao explicita.
- Bug dormente: useAgendaFinanceiro.js comparava 'fixed' em vez de
'fixed_fee' do schema.
UX ADICIONS:
- Botao "Agendada" no popover (pi-calendar, --info cyan)
- Hint contextual sobre min_hours_notice no dialog ("Cancelou 18.5h
antes -> sem multa por padrao")
DOC:
- Addendum C10 no topo de src/docs/agenda-compromisso-financeiro
-cenarios.html capturando todas as divergencias + 3 pendencias.
PENDENCIAS POS-C13 (salvas em memoria):
- Reverse transitions com multa orfa (project_agenda_reverse_transitions)
- Popover Melissa snapshot stale (project_melissa_popover_snapshot)
PROXIMO: Cenario 11 (status change pacote saldo).
## [2026-05-20 06:00] session | C9 OK + rowGroup por paciente + bubble cobranca-atualizada
Touched: none (codigo + HANDOFF)
Detalhes:
CENARIO 9 (per_session):
- Michael Balint 12 sessoes R$ 150 modo "1 por sessao"
- DB conforme esperado: 1 rule, 12 events materializadas, 0 contracts,
12 records pending (R$ 150 cada)
- Visual: 12 badges $ amber, todas pending. Sem linha de pacote no
popover (per_session nao usa contract).
ROWGROUP NO /melissa/financeiro-lancamentos:
- DataTable com rowGroupMode='subheader' + groupRowsBy='patient_id'
- Default todos expandidos (watcher recalcula a cada recordsGrouped)
- Header de grupo: avatar + nome + badge "N lançamento(s)"
- Sort outer por nome de paciente, preserva ordem interna pai→filhos
- Click no chevron contrai/expande
BUBBLE @cobranca-atualizada:
- Bug: card na agenda nao atualizava badge/borda apos marcar como
pago no dialog (so dava refresh ao trocar de view)
- Root cause: AgendaEventoFinanceiroPanel.@cobranca-atualizada
disparava so loadOccFinancialRecord (interno do dialog). O
_paymentStateMap da agenda ficava stale.
- Fix: AgendaEventDialog tem agora _onCobrancaAtualizada que faz
loadOccFinancialRecord + emit('cobranca-atualizada'). MelissaLayout
escuta nos 2 dialogs e chama M.refetch() + refetchEventosHoje().
Card no FC passa pra borda verde imediatamente.
PROXIMO: Cenario 10 (status change avulsa — realizado/faltou/cancelado
+ STATUS_TO_EXCEPTION em financial_exceptions).
## [2026-05-20 03:00] session | C8 OK + Usar/Revogar saldo + UI pacote + ajustes UX
Touched: none (sem nova wiki page; mudancas em codigo + HANDOFF)
Detalhes: noite longa cobrindo C8 (pacote saldo) e principalmente
construindo a UI/UX de pacote saldo do zero — antes nao tinha
indicacao alguma no dialog/popover de que era saldo.
CENARIO 8 (Pacote SALDO):
- Criou Otavio 12 sessoes R$50 saldo
- DB conforme esperado: 1 rule, 0 events, 1 contract (saldo), 0 records
- Visual conforme esperado: 12 virtuais limpas
UI DE PACOTE (saldo + upfront):
- _ruleContractMap em useMelissaAgenda: bulk-load popula contract info
por recurrence_id (query recurrence_rules.patient_id como fonte
autoritativa, cobre saldo sem materializadas)
- Normalize injeta `contract` no evento
- Popover MelissaEventoPanel: linha colorida (violeta saldo, verde
upfront) com "Pacote X · N/M usadas|realizadas" + botão Usar
(verde, paymentState=none) OU Revogar (vermelho, paymentState=pending)
- AgendaEventDialog: info card mt-4 com header+body+hint explicando
modelo, botão "Usar agora"/"Revogar uso" gateado por
occFinancialLoading (spinner durante carga)
HANDLERS USAR/REVOGAR ATOMICOS:
- onUsarSessao: materializa virtual + status=realizado + record per-session
+ sessions_used++ + (se total) contract status=completed
- onRevogarSessao: cancela record + sessions_used-- + reativa contract
+ status=agendado. Bloqueia se record paid (estorno formal precisa)
- Ambos aceitam payload do popover OU do dialog
FIXES NA RODADA:
- Enum status_evento_agenda usa 'realizado' (masculino), nao 'realizada'
- determined_commitment_id backfill no materialize+revogar+update path
(sem isso, dialog mostrava campo "Titulo" indevidamente)
- "Gerar fatura" do popover esconde quando ha contract (evita
duplicacao em saldo)
- Race condition no dialog: spinner enquanto occFinancialLoading,
botoes so renderizam apos carga
RECORRENCIAS APLICADAS — UI:
- Header stats coloridos por status (azul total, verde realizadas,
amber faltaram, cinza canceladas, violeta remarcadas)
- Pills com badge solido por status (em vez de texto cinza)
DECISAO UX antes de codar (3 perguntas):
- Editar servico pago? NAO (cobranca fiscal imutavel)
- Alternar Particular/Convenio/Gratuito em serie cobrada? NAO
- Gerar fatura individual em pacote upfront? NAO (duplicacao)
Tudo isso o lock-edit (Fase 6) cobre.
DECISAO UX "Usar" vs "Confirmacao":
- Recomendei Revogar (undo) em vez de confirmacao toda vez
- Friction baixo no fluxo principal (usuario "Usa" 12x ao longo de 3 meses)
- Reversivel enquanto record pending; paid bloqueia
PROXIMO: Cenario 9 (Michael Balint per_session 12 x R$150).
## [2026-05-19 23:00] session | C7 OK + Fase 6 lock em Melissa + cross-week propagation
Touched: project_cross_week_propagation (nova)
Detalhes: rodada longa cobrindo C7 (pacote upfront, Ana Souza Ferreira 4xR$200=R$800),
ativacao do lock-edit (Fase 6) em Melissa e correcao de bug cross-week
na propagacao de estado de pagamento.
CENARIO 7 (Pacote UPFRONT):
- User criou Ana, pagou os R$800 em dinheiro pelo Financeiro
- Borda verde + popover "Pago R$800" no card materializado funcionou
- 4 pills no dialog da serie, todas com "Cobranca paga R$800 do pacote"
ate as virtuais (via synthesized record em loadOccFinancialRecord)
LOCK-EDIT (Fase 6) ATIVADO EM MELISSA:
- Antes: loadOccFinancialRecord tinha guard occurrenceMode, so ativo
em Rail/Clinica. Em Melissa havia sessionPaymentRecord paralelo so
pro Resumo lateral (sem trigger de lock).
- Agora unificado: removido guard, occFinancialRecord carrega em ambos
modos. Card Sessao/Honorarios ganha Tag em vez de Select billingType
quando ha cobranca. Body mostra Message lock + cadeado.
AgendaEventoFinanceiroPanel so renderiza se record real (nao
sintetizado).
- Antes do codar, alinhei 3 perguntas de UX com user:
1) Editar servico pago? NAO (cobranca fiscal imutavel)
2) Alternar Particular/Convenio/Gratuito em serie cobrada? NAO
3) Gerar fatura individual em upfront? NAO (duplicaria cobranca)
CROSS-WEEK PROPAGATION (descoberto durante C7):
- Bug: virtuais isoladas em semanas futuras nao mostravam paid.
- Root cause: bulk-load tinha "if (realIds.length) { ... propagacao ... }
else { _rulePaymentMap.value = {} }". Quando user navegava pra semana
so com virtuais (sem reais), else zerava o ruleMap.
- Fix: maps inicializados SEMPRE, propagacao roda sempre, atribuicao
final tambem fora do if. Propagacao tambem ficou cross-week — pega
ruleIdsInView de TODOS eventos da view (real+virtual com recurrence_id),
busca records de QUALQUER evento da rule (em qualquer semana). Memoria
durador em project_cross_week_propagation.md.
OUTROS FIXES NA RODADA:
- Atalho "Gerar fatura" no popover (pill amber ao lado de "A cobrar R$ X").
- Info de pacote no header popover ("Sessao · Pacote · N sessoes").
- Botao "Excluir serie inteira" no popover (hard delete, bloqueia se
algum record paid).
- Migration 20260519000001: RPC create_financial_record_for_session
ignora cancelled na idempotencia. Memoria em
project_rpc_idempotency_cancelled.md.
- cancel_session exception some da agenda (era visivel com status
cancelado, doc dizia que sumia).
- recurrence_exceptions cancel agora upsert idempotente (nao quebra
com unique violation em re-cancel).
- onVerLancamentos busca records via siblings da serie pra virtuais de
upfront.
- Visualizacao: virtuais herdadas via propagacao agora mostram borda
verde + linha verde no popover (showPaymentRow e isPaidSession
relaxados pra paymentState !== 'none').
PROXIMO: Cenario 8 (Carl Jung pacote SALDO 4x R$40 = R$160).
Esperado: 0 records iniciais, 4 virtuais limpas (saldo NAO propaga —
cada sessao gera cobranca quando vira realidade).
## [2026-05-19 14:00] session | C5+C6 OK + atalho gerar fatura + RPC idempotencia fix
Touched: project_rpc_idempotency_cancelled (nova)
Detalhes: sessao longa cobrindo C5 e C6 ate green checkmark, com varios
fixes intermediarios:
CENARIO 5 (Sandor + Unimed convenio):
- 2 bugs no save: amount lia 'price' (null em convenio) e payment_method
caia em 'asaas' por fallback. Fix: detecta convenio via insurance_plan_id,
amount=insurance_value, payment_method='convenio'. markPaidNow ignorado
pra convenio (sempre nasce pending).
- 2 bugs na visualizacao: popover so mostrava "Cobranca pendente" sem
valor (lia ev.price) e /financeiro nao mostrava pill convenio.
Fix: normalize expoe insurance_value; popover fallback price ?? insurance_value;
/financeiro ganhou branch pra payment_method='convenio' (pill violeta).
CENARIO 6 (Maria Magali, recorrente sem pacote):
- chargeMode='none' nao materializava 1a (todas viravam virtuais, sem badge).
Fix: adicionado bloco no fluxo de criacao recorrente que materializa 1a
quando chargeMode='none' && paciente_id. Package/per_session ja
materializam nos seus helpers; package saldo intencionalmente NAO.
- Primeira tentativa de fix usou paciente_id (Portuguese) mas
agendaRepository dropa esse campo (legado). Corrigido pra patient_id
(English DB column). Fallback `normalized.patient_id ?? normalized.paciente_id`.
ATALHO "Gerar fatura" no popover:
- Pill amber "Gerar fatura" ao lado de "A cobrar R$ X" no popover.
- Wire em MelissaLayout via emit gerar-cobranca + handler onGerarCobrancaQuick.
- Fecha popover apos sucesso pra impedir click duplicado.
- Tooltip simplificado: "Gerar fatura agora".
BUG RPC IDEMPOTENCIA (gravado em memoria):
- create_financial_record_for_session checava idempotencia por
agenda_evento_id + deleted_at IS NULL, MAS sem filtrar status='cancelled'.
User cancelava cobranca sem querer → todo regenerar retornava cancelado
e nada inseria. Toast verde mentindo.
- Fix: migration 20260519000001 adiciona AND status != 'cancelled'.
- Memoria salva em project_rpc_idempotency_cancelled.md (padrao a aplicar
em toda RPC futura com idempotencia por chave natural).
INFO PACOTE NO POPOVER:
- Header do popover agora mostra "Sessao · Pacote · N sessoes" ou similar
(computed seriesLabel le do _raw). Visual: violeta sem caps lock.
TITULO DIALOG "Sessao do Pacote · Sessao":
- Quando commitment name eh "Sessao" (default), drop pra evitar duplicacao.
Outros nomes (Avaliacao etc) permanecem com forma completa.
CSS:
- .aed-row-50 perdeu margin-bottom (user request).
- .field-card.mb-4 ganhou margin-top: 1rem (scoped via composer wrappers).
OUTROS BUGS RESOLVIDOS NO CAMINHO:
- AgendaEventoFinanceiroPanel.fetchRecord agora filtra cancelled.
- bulk-load do useMelissaAgenda agora filtra cancelled.
- recurrence_exceptions cancel agora usa upsert (idempotente, nao quebra
com unique constraint quando user cancela 2x ou tem exception zumbi).
- "Excluir serie inteira" botao novo no popover (hard delete: rule +
materializadas + financial_records pendentes; bloqueia se paid).
- cancel_session exception agora SOME da agenda (era visivel com status
cancelado, doc dizia "some da agenda" mas codigo mantinha).
- ConfiguracoesConveniosPage ganhou botao "+ Novo convenio" (faltava).
- goToConveniosConfig removida (dead code pos quick-create inline).
- Quick-create inline de procedimento (InsurancePlanServiceQuickCreateDialog).
- Hint contextual abaixo do card Sessao/Honorarios (convenio = "N guia
opcional"; gratuito = "sem cobranca").
PROXIMO: Cenario 7 (Donald Winnicott · pacote UPFRONT · 4 × R$ 200).
## [2026-05-18 23:30] session | UX de convenio refinado (3 fixes) + hint contextual
Touched: none (sem nova wiki page; tudo em codigo + HANDOFF)
Detalhes: tarde inteira consumida em refinar UX de convenio antes do
save real do C5. User bateu em 3 problemas seguidos:
1) Botao "Cadastrar" do procedimento navegava pra /pages/notfound.
Root cause: goToConveniosConfig prefixava com /therapist|/admin mas
/configuracoes/* eh rota raiz sob AppLayout (sibling, nao filho). Em
Melissa, convenios mora via secao=cfg-convenios sem URL propria.
Fix descartado: user nao queria sair da agenda. Criamos quick-create
inline (#2). Removi goToConveniosConfig (dead code).
2) InsurancePlanServiceQuickCreateDialog (novo componente). Mesmo pattern
do InsurancePlanQuickCreateDialog. 2 campos: nome + valor que o
convenio paga. Wiring em useAgendaEventLifecycle: planServiceQuickDlgOpen
+ openPlanServiceQuickCreate + onPlanServiceCreated. Apos criar:
loadInsurancePlans + auto-seleciona SO se nada estava selecionado
antes. UI refatorada: caixa cinza com botao "Cadastrar" SEMPRE
visivel quando convenio selecionado, copy varia por contagem
(0 procedimentos = chamada urgente; 1+ = "se quiser adicionar mais").
3) Botao "+ Novo convenio" faltando em ConfiguracoesConveniosPage.vue.
addingNew=true sem botao pra setar. Empty state mandava clicar em
botao inexistente. Fix: toolbar topo com Button label="Novo convenio"
@click="addingNew = true". Empty state corrigida.
Hint contextual abaixo do card Sessao/Honorarios. User: "Nº da guia
eh obrigatorio?" — consegui salvar sem. Tentativa 1: coloquei em
v-if=occurrenceMode (errado, so Rail/Clinica). Tentativa 2: fluxo
principal Melissa (linha 2305). Copy: convenio = "Nº da guia eh
opcional…", gratuito = "Sessão gratuita…", particular = sem hint.
Label "Nº da Guia" tambem ganhou "(opcional)".
PROXIMO: rodar de fato o save do C5 (Sandor + Unimed + R$ 95). Tudo
preparado, agora eh testar end-to-end.
## [2026-05-18 21:45] session | Linha de cobranca no popover (3 estados) + Resumo do dialog
Touched: none (sem nova wiki page)
Detalhes: extensao do trabalho da sessao anterior (barra verde na agenda).
User pediu pra popover mostrar tambem o estado pago, nao so pendente.
Lembrava que "tinha algo assim mas talvez seja pra outra coisa" —
verifiquei: occFinancialRecord existia mas com guard de occurrenceMode,
servindo Fase 6 (lock-edit) em Rail/Clinica apenas. Decidi NAO unguardar
pra nao ativar lock prematuro em Melissa (isso eh C13).
MelissaEventoPanel.vue: showPaymentRow agora cobre paid tambem; novo
paymentVariant + paymentIcon (pi-check-circle quando pago, pi-dollar
nos outros); paymentLabel inclui "Pago · R$ X,XX"; CSS com 3
modificadores .evento-row--pay-{paid|pending|none} + dark mode.
AgendaEventDialog.vue + useAgendaEventLifecycle.js: novo ref
sessionPaymentRecord (independente do occFinancialRecord). Loader sem
guard, chamado no mesmo lifecycle. Computed paymentSummary cobre 5
estados (paid + verde + paid_at, overdue + vermelho + venceu, pending
+ amber + vence, sem cobranca c/ valor, sem cobranca s/ valor). Nova
linha summary-row entre pi-clock e pi-map-marker em ambas as copias do
Resumo (mobile inline + desktop floating). CSS com 4 classes
.aed-pay-summary-row--{paid|pending|overdue|none}.
@cobranca-atualizada do AgendaEventoFinanceiroPanel agora tambem
dispara loadSessionPaymentRecord pra a linha refrescar quando user
marca pago pelo panel inline.
PROXIMO: cenario 5 (Sandor + Unimed Nacional, R$ 95, convenio).
## [2026-05-18 21:00] session | Cenario 4 OK + barra esquerda verde pra sessao paga
Touched: none (decisao salva em memory/, doc HTML atualizado, sem nova wiki page)
Detalhes: cenario 4 (Joyce R$180 PIX "Ja recebi") testado e passou — toast,
record paid+pix+paid_at, badge $ removido. User pediu sinalizacao visual
pra sessao paga "olhar e saber". Brainstorm de 6 opcoes (check verde
canto, barra esquerda, fundo green-50, $ riscado, so popover, 3 canais
combinados). User escolheu #6 — 3 canais visuais distintos:
- pago: barra verde 4px borda esquerda (emerald-500)
- pendente: badge $ amber canto direito (como antes)
- neutro: nem um nem outro (sem cobranca / virtual)
Implementado em MelissaAgenda.vue (classe ma-evt--paid via classNames,
CSS forca border-left-color !important porque FC seta borderColor inline).
Doc HTML legenda "Indicadores visuais" expandida pros 3 estados (3 mocks
empilhados). Estado-alvo do C4 reescrito. Memoria persistida em
memory/project_agenda_payment_indicators.md (decisao + onde aplicar quando
replicar em Rail/Clinica). HANDOFF atualizado pra apontar C5 como
proximo.
## [2026-05-17 02:30] session | Testes C1-C3 + payment refactor + indicadores visuais + fix modalidade
Touched: agenda-compromisso-fluxo (implicit via HANDOFF.md, sem nova pagina)
Detalhes: rodada de testes manuais dos cenarios do doc viva
src/docs/agenda-compromisso-financeiro-cenarios.html. Cenarios 1, 2 e 3 ok.
CENARIO 1 (bloqueio):
- Fix `bloqueioCobrindo is not defined` em onSelectTime — funcao mora no
escopo de useMelissaAgenda mas onSelectTime esta em _buildHandlers.
Passada via deps, mesmo padrao do _openStatusDialog.
- Soft warn de bloqueio sobre slot agora vai DENTRO do dialog (Message
warn no topo do step 1) em vez de toast atras do overlay. Novo ref
dialogBlockOverlap no composable + nova prop blockOverlapWarning no
AgendaEventDialog. Reset nos outros openers.
- Doc HTML cenario 1 expandido em 1a (criar) + 1b (agendar sobre
bloqueio), com mock visual da Message + comparacao agendador publico.
CENARIO 2 (avulsa sem cobranca):
- Hint chargeMode fonte 0.72rem -> 0.8125rem.
- Card Frequencia avulsa refeito: era empty state convidando configurar,
agora renderiza como "selecionado" com .aed-pay-summary (Tipo: Avulsa
/ Sessao unica, sem repeticao / botao Editar). Visual identico ao
estado configurado de pacote.
CENARIO 3 (avulsa cobrar ao salvar):
- Refactor paymentSettlement -> paymentMethod + markPaidNow. UI antiga
misturava metodo e status num Select unico ("Ja recebi - PIX"). Agora
2 controles: Select forma (sem prefixo "Ja recebi") + SelectButton
status (pendente / ja recebi). SelectButton oculto quando metodo='link'.
Wire em 3 camadas (Dialog -> useAgendaEventActions -> useMelissaAgenda
handler avulsa + _createPackageContract).
- Indicadores visuais de pagamento: bulk-load 1x em _reloadRange etapa 4
(financial_records mapeado por agenda_evento_id -> paid|pending|none).
normalizeForMelissa injeta paymentState + price. Badge $ amber 16px no
canto superior direito do evento da agenda (so sessao+paciente+nao-
virtual+!paid). Linha "A receber" amber abaixo do horario no popover
(MelissaEventoPanel), texto adaptativo.
- BUG FIX pickDbFields whitelist faltando 'modalidade' — todas as sessoes
avulsas criadas no Melissa ate hoje foram salvas como presencial no DB
independente da escolha visual. Adicionado ao allowed[]. Gotcha durador
salvo em memory/project_pickdbfields_whitelist.md.
DOC HTML AMPLAMENTE ATUALIZADO:
- Nova secao topo "★ Indicadores visuais de pagamento" com mocks (badge
$ + linha popover) e link em violeta no TOC.
- Caixa violeta "Indicadores visuais" em cada cenario relevante (C2-C9)
descrevendo o que aparece em cada caso.
- C4 ganhou caixa verde "estado-alvo" (sem badge, sem linha — pago).
- Receitas dos C2-C4 atualizadas pros 3 controles novos.
PROXIMO: cenario 4 (Joyce, "Ja recebi (dar baixa)"). Apos passar, seguir
ate C13. Quando todos passarem, replicar em AgendaTerapeutaPage (Rail) e
AgendaClinicaPage (Clinica). HANDOFF.md reescrito com tudo.
## [2026-05-05 23:45] session | Blueprint tabular Melissa + restore pacientes
Touched: none (sem mudança de wiki — handoff em HANDOFF.md)
Detalhes: criou `blueprints/melissa-table-page-blueprint.md` (~530L, 18 seções);
refatorou MelissaCadastrosRecebidos pro padrão (DataTable + frozen action +
view toggle list/grade); criou MelissaAgendamentosRecebidos nativa (substituindo
embed); MelissaPacientes ganhou subheader, sombras, status pills coloridas,
email/phone colunas próprias, mobile pencil+popover, view toggle, fix scroll
mobile (`min-height: 0` em `.mp-list`), botão Restaurar pra arquivados.
Repository: `restorePatient` novo. PatientsCadastroPage statusOpts: +Arquivado.
A66 V2 — user não gostou design, aguarda feedback específico.
## [2026-05-06 12:00] session | MelissaCompromissos refator blueprint
Touched: none (aplicacao direta do blueprint existente - sem mudanca de wiki)
Detalhes: refator de MelissaCompromissos pro melissa-table-page-blueprint preservando o design do row (color stripe + name+badges + descricao + meta inline). DataTable com 3 colunas (Compromisso flex / Atividade 220px / Acoes frozen 140px com toggle+pencil+trash). Sidebar com 2 grupos de filtros: Status (Ativos verde / Inativos amber) e Tipo (Nativos blue / Meus accent), cada um com Limpar filtro proprio. Grid view com cards (color stripe 28px + toggle topo + footer com edit/trash). Subheader explicativo. View toggle persistido em mc.viewMode.v1. Removeu Popover de actions (drawer mobile cobre). Stats: Total/Ativos/Inativos/Tempo total. ESLint 0 errors. UI nao testada em browser ainda.
## [2026-05-06 14:00] session | Melissa 6 Pages blueprint + WhatsApp drawer + commits
Touched: none (sem nova pagina de wiki - aplicacao do blueprint existente)
Detalhes: Sprint F entregue. Blueprint tabular aplicado em MelissaCompromissos
(row design preservado), MelissaGrupos, MelissaTags, MelissaMedicos,
MelissaConversas, MelissaRecorrencias. Dialogs de criar/editar harmonizados
(FloatLabel + IconField + section dividers espelhando PatientsCadastroPage
Identidade). Dialogs "Pacientes do grupo/tag/medico" com cor primary nos
avatares de letras + X de fechar igual .xx-close. ConversationDrawer redesign
estilo WhatsApp (avatar primary, bg papel de parede, bolhas com tail simulada,
time/status overlay no canto inferior direito, compose pill + send circular
verde #00a884). Bug fix em MelissaPacientes: g.cor->g.color em 20 lugares
(repository devolve camelCase, template lia PT-BR e cores nao apareciam).
5 commits criados: 957e912, 6d9b36d, 269b531, 98f7252, 15103ed. Working tree
limpa. HANDOFF.md atualizado.
## [2026-05-06 17:30] session | Melissa drawers: footer pattern AppMenu
Touched: none
## [2026-05-08 00:00] session | Melissa cfg-* nativas + temas + cronometro DB
Touched: none
## [2026-05-08 21:00] session | MelissaPaciente iteracao pos-Fase 8 + AgendaEventDialog reuse
Touched: none (iteracao de UX, sem novas paginas wiki)
Detalhes: 16 commits adicionais apos Fase 8 cobrindo ajustes de UX e
funcionalidades novas pedidas pelo user em sequencia:
LAYOUT/CHROME
- Full-width (removido right:max) — prontuario tem KPIs+tabelas+timeline,
precisa espaco. Outras Melissa Pages mantem o constraint.
- Sidebar: substituido botao "Configuracoes" por "Voltar para Pacientes"
(prontuario nao pertence a config). X faz history.back; sidebar btn
forca /melissa/pacientes.
- Cards da sidebar com flex-shrink:0 (estavam encolhendo, cortando conteudo).
- .mpa-tab com display:flex+gap:12px (filhos estavam colados).
FUNCIONALIDADES NOVAS
- editPatient abre PatientCadastroDialog INLINE (antes redirecionava pra
MelissaPacientes?edit=).
- openWhatsapp passa string id (era objeto) + detecta store.error pra
toast warn quando paciente sem telefone.
- addFinancial: dialog inline com createRecord mutation no
usePatientFinancial.
- goAgendar: dialog inline com createSession mutation, depois evoluiu
pra usar AgendaEventDialog real via lockType/lockPatient props.
- Botao "Agendar" novo na sidebar Acoes Rapidas (antes so tinha Lancamento).
DIALOG NOVA SESSAO — evolucao em 4 etapas
1. Inline simples (createSession direto)
2. Frequencia integrando useRecurrence (recorrencia semanal)
3. Frequencia estilo AgendaEventDialog (chips Avulsa/Semanal/Quinzenal/
diasEspecificos + qtd sessoes 4/8/12/personalizar)
4. Header custom (icon + Nova sessao + nome paciente)
5. **Decisao final**: trocar tudo por reuso do AgendaEventDialog real.
User pediu pra ver dialog completo da Agenda dentro do prontuario.
Caminho A escolhido: 2 props aditivas (lockType, lockPatient) + slot
#headerLeft no AgendaEventDialog. 301 specs continuam passando — zero
regressao nos 5 callsites legacy.
BLOCO DE RECORRENCIAS NA TAB AGENDA
- 5o KPI "Recorrencias" (count de ativas).
- Lista de cards mostrando regras com label legivel (fmtRecurrenceLabel)
+ meta (duracao/modalidade/fim/desde) + acoes inline (cancelar/reativar).
- Toggle "Ver canceladas".
DEBUGGING DIALOG (etapas finais)
- jornada/billing/freq sumiram: causa = lockType so setava step=2 sem
inicializar form.commitment_id. Fix: watch chama selectCommitment(sessao).
- Resumo lateral sem nome paciente: causa = nao passar paciente_nome/
avatar/status no eventRow. Fix: pre-popular dos computeds.
- Botao Salvar sumido: causa = footer tem v-if step=2; sem
presetCommitmentId prop, lifecycle ia step=1. Fix: passar
:preset-commitment-id no template.
TOTAL: 24 commits no branch. HANDOFF.md reescrito com estado completo +
historico + arquivos novos/modificados + decisoes arquiteturais +
hotspots de drift. Push pendente.
## [2026-05-08 19:30] session | MelissaPaciente Fase 8 — wire-up final (Dialog -> route)
Touched: none
Detalhes: PLANO DE 8 FASES COMPLETO. Os 2 callsites Melissa do
PatientProntuario.vue legacy (3593L Dialog) trocam por router.push pra
/melissa/paciente?id=X. PatientProntuario continua intocado pros 2
callsites legacy (TherapistDashboard, PatientsListPage) quando user nao
esta no layout Melissa.
MELISSAPACIENTE.VUE — wire-up
- useRouter + useConversationDrawerStore.
- close(): emit + router.push('/melissa/pacientes') (volta pra lista).
- editPatient(): emit + router.push('/melissa/pacientes', query: {edit: id})
pra MelissaPacientes detectar e abrir o cadastroFullDialog automaticamente.
- openWhatsapp(): emit + conversationDrawerStore.openForPatient({id, name,
phone, avatar_url}) — drawer global desce sobre Melissa sem fechar.
- addFinancial(): emit + toast "Em breve" (Fase 9 — dialog inline).
MELISSAPACIENTES.VUE — wire-up
- Removeu import PatientProntuario, refs prontuarioOpen/prontuarioPatient,
template PatientProntuario.
- abrirProntuario(p): router.push('/melissa/paciente', query: {id}).
- onMounted: detecta route.query.edit -> abre cadastroFullDialog +
router.replace pra limpar a query. Permite navegacao MelissaPaciente
-> MelissaPacientes?edit=X -> auto-open do cadastro.
- Comentario header atualizado.
MELISSAAGENDA.VUE — wire-up
- Removeu import PatientProntuario, refs prontuarioOpen/prontuarioPatient,
template PatientProntuario.
- abrirProntuarioPorId(id): router.push('/melissa/paciente', query: {id}).
- abrirProntuarioPaciente() / openProntuario(patient) / item kebab
"Prontuario" todos delegam pra abrirProntuarioPorId.
MELISSALAYOUT.VUE
- Render do <MelissaPaciente> simplificado: so passa @close="fecharSecao".
Acoes edit/open-whatsapp/add-financial agora ficam internas no MelissaPaciente.
ESLint: 0 errors da minha mudanca (9 errors pre-existentes nos arquivos
tocados, mesmos de antes do diff — confirmados via git stash baseline).
PLANO COMPLETO. Status final por fase:
1. Foundation (composables + skeleton) — done (Fase 1)
2. Tab Visao Geral (KPIs ricos + timeline + msgs) — done (Fase 2)
3. Tab Perfil (6 sections stacked + anchors) — done (Fase 3)
4. Tab Prontuario MVP (evolucao via observacoes) — done (Fase 4)
5. Tab Agenda (KPIs + filtros + grupos + acoes) — done (Fase 5)
6. Tab Financeiro (KPIs + tabela + mark paid) — done (Fase 6)
7. Tabs Documentos + Conversas (KPIs + embeds) — done (Fase 7)
8. Wire-up final (Dialog -> route) — done (Fase 8)
PatientProntuario.vue (3593L) NAO foi deletado — continua usado pelo
TherapistDashboard.vue (homepage do role therapist) e PatientsListPage.vue
(rota /therapist/patients fora do Melissa). Quando user troca pra Melissa
em /account/profile, ele ve a versao nativa (MelissaPaciente).
## [2026-05-08 18:30] session | MelissaPaciente Fase 7 — Tabs Documentos + Conversas
Touched: none
Detalhes: Duas tabs entregues numa sessao (sao mais leves: KPIs + embed
de componentes existentes ja testados).
EXTENSAO patientFormatters.js:
- fmtSize(bytes): B/KB/MB/GB legivel
- DOC_TYPE_LABEL: atestado/receita/laudo/encaminhamento/termo/etc
- chConvLabel: whatsapp/sms/email -> WhatsApp/SMS/E-mail
EXTENSAO usePatientDocuments.js:
- topType computed: { tipo, count, label } do mais comum (DOC_TYPE_LABEL)
- pendentes computed: count de status_revisao === 'pendente'
- sizeTotalFormatted computed: fmtSize(totalBytes)
- Import patientFormatters dentro do composable.
EXTENSAO usePatientMessages.js:
- primeiraMensagem computed (mais antiga, [length-1])
- canais computed: Set de m.channel unicos
MELISSAPACIENTE.VUE — script
- Imports: DocumentsListPage, PatientConversationsTab, chConvLabel
- Removido kpiDocumentos (nao usado mais — substituido por
documentsHook.total.value direto)
MELISSAPACIENTE.VUE — Tab Documentos (Fase 7)
- Loading state.
- 4 KPIs adaptativos (so renderizam quando ha dados):
- 01 Total + sizeTotalFormatted
- 02 Mais comum (label do tipo + count) — opcional
- 03 Ultimo + relative + dateBR — opcional
- 04 Revisao pendente (laranja) — opcional, so quando > 0
- DocumentsListPage embedded no card Melissa (mpa-embed) — reusa o
componente existente que ja faz upload/preview/listagem completa.
Wrapper ze-ra padding pra ele preencher tudo.
MELISSAPACIENTE.VUE — Tab Conversas (Fase 7)
- Loading state.
- 4 KPIs (so renderizam quando ha mensagens):
- 01 Mensagens total + canais ("via WhatsApp, SMS")
- 02 Recebidas + % do total
- 03 Enviadas + % do total
- 04 Ultima relative + direction + 1ª contato dim
- CTA "Abrir conversa no drawer" estilo WhatsApp (verde #25d366) que
emite open-whatsapp pro parent (futuro: integra com
conversationDrawerStore.openForPatient na Fase 8).
- PatientConversationsTab embedded no mesmo wrapper mpa-embed —
thread completa com filter/scroll/media.
CSS: ~50L novos pros componentes (mpa-conv-cta + mpa-embed wrapper).
Padrao Melissa: CTA WhatsApp circular pill, embed wrapper transparente.
ESLint: 0 errors da minha mudanca.
PROXIMA: Fase 8 (wire-up final) — substituir Dialog do PatientProntuario
por router.push('/melissa/paciente?id=X') nos 4 callsites Melissa
(MelissaPacientes, MelissaAgenda); decidir se TherapistDashboard e
PatientsListPage tambem migram. PatientProntuario.vue pode ficar (legacy
fallback) ou deletar.
## [2026-05-08 17:30] session | MelissaPaciente Fase 6 — Tab Financeiro completa + mark paid mutation
Touched: none
Detalhes: Tab Financeiro espelha o legacy + adiciona mutation que o
legacy NAO tem (mark/unmark pago direto da tabela).
EXTENSAO patientFormatters.js:
- recordStatus(r): pago | vencido | pendente
- RECORD_STATUS_LABEL map.
- fmtPaymentMethod(v): PIX/Cartao/Dinheiro/Boleto/Transferencia/Convenio
cobrindo variantes.
EXTENSAO usePatientFinancial.js:
- ref `busy` + `_lastPatientId` interno.
- recordsOrdenados computed (DESC por due_date com fallback created_at).
- markPaid(recordId): UPDATE financial_records SET paid_at=NOW() + auto-
reload. Retorna {ok, error?}.
- markUnpaid(recordId): UPDATE SET paid_at=NULL + auto-reload (reverte).
MELISSAPACIENTE.VUE — script
- Imports: recordStatus, RECORD_STATUS_LABEL, fmtPaymentMethod.
- markRecordPaid(record) handler: chama markPaid + toast success/error.
- revertRecordPaid(record): chama markUnpaid + toast.
MELISSAPACIENTE.VUE — Tab Financeiro reescrita
- Loading state.
- Empty state com CTA "Novo lancamento" (botao mpa-quick-btn--cta).
- 3 KPIs (Pago / Pendente com proxVenc / Em atraso com cor adaptativa).
- Header "Lancamentos" com badge count + botao "+ Novo" no canto.
- Tabela 6-col: Vencimento (date mono+rel) | Descricao | Forma | Valor
(mono right) | Status pill colorida (pago verde / vencido vermelho /
pendente azul) | Action button.
- Action: pi-check (verde) pra marcar pago, pi-undo (amarelo) pra reverter.
- border-left adaptativa por status (verde pago / vermelho vencido /
azul pendente).
- Mobile: tabela colapsa em cards 2-col 4-row (date|amount / desc /
method|status / action).
CSS: ~190L novos pros componentes (mpa-fin__table/row/date/desc/method/
amount/status/action + responsive). Padrao Melissa: status pills com
color-mix, JetBrains Mono pra valores, header cell uppercase letter-
spacing.
ESLint: 0 errors da minha mudanca.
## [2026-05-08 16:30] session | MelissaPaciente Fase 5 — Tab Agenda completa
Touched: none
Detalhes: Tab Agenda com KPIs, filtros, agrupamento por mes e acoes
rapidas (mark realizada/falta/cancelar). Espelha o legacy.
EXTENSAO patientFormatters.js: +2 helpers
- fmtHourShort (HH:MM 24h pt-br) e fmtDayShort (DOW abbreviado pt-br
sem ponto) — usados na coluna data dos cards.
EXTENSAO usePatientSessions.js: mutation + busy flag
- Novo ref `busy` pra disable de buttons durante mutation.
- _lastPatientId guardado pra auto-reload depois de mutation.
- Nova funcao `updateStatus(sessionId, novoStatus)` que faz
supabase.from('agenda_eventos').update({status}) + auto-reload da
lista. Retorna {ok, error?}.
MELISSAPACIENTE.VUE — script
- agendaFilter ref ('all' default) + AGENDA_FILTERS array com 6 opcoes
(Todas, Proximas, Passadas, Realizadas, Faltas, Canceladas).
- agendaSessoesFiltradas computed: filtra sessoes por future/past/status.
- agendaAgrupadas computed: agrupa por "Mes de YYYY" mantendo ordem DESC.
- updateSessionStatus(ev, status, msg) handler que chama
sessionsHook.updateStatus + toast de sucesso/erro.
- Removido `void toast` (toast usado de verdade agora).
MELISSAPACIENTE.VUE — Tab Agenda reescrita (substitui placeholder Fase 1)
- 4 KPI cards no padrao Visao Geral (numerados 01-04):
- 01 Total + cap "sessoes registradas"
- 02 Realizadas + cap "% do total"
- 03 Faltas + cap "+ N cancel." (cor vermelha quando > 0, cinza quando 0)
- 04 Proxima + relative + datetime
- 6 filter chips redondas (estilo Melissa: cor primary quando active).
- Empty state contextual (sem sessoes vs filtro vazio).
- Grupos por mes com header (label + badge count).
- Cards com 3 colunas: data column (DOW + dia + hora curta) | main
(status tag + chips modalidade/duracao + relative + titulo + note) |
actions (3 buttons: ok/warn/danger com tooltip + cor adaptativa hover).
- Mobile: stack date+main em 2 cols; actions full-width abaixo.
CSS: ~150L novos pros componentes (mpa-ag__group/list/item/date/main/
actions). Padrao visual Melissa: data column estilo calendario, actions
hover muda cor por intent (verde realiz / amarelo falta / vermelho cancel).
ESLint: 0 errors da minha mudanca.
## [2026-05-08 15:30] session | MelissaPaciente Fase 4 — Tab Prontuario MVP
Touched: none
Detalhes: O legacy PatientProntuario.vue tem a aba Prontuario como
PLACEHOLDER ("Em breve"). MVP entregue aqui supera o legacy: usa
agenda_eventos.observacoes como nota evolutiva (pq nao tem schema de
anamnese/clinical_notes ainda).
ESTADO + COMPUTEDS adicionados:
- pronFilter ref ('com-evolucao' default) + PRON_FILTERS array com 5
opcoes (Com evolucao, Todas, Realizadas, Faltas, Cancelamentos).
- pronSessions computed: filtra sessions por status/observacoes presentes.
- sessoesComEvolucao computed: count de sessoes com observacoes nao-vazia.
TEMPLATE Tab Prontuario (substitui placeholder Fase 1):
- Hint banner top: "Prontuario em construcao", explica que usa observacoes
de sessoes como historico evolutivo.
- 4 mini-stats em grid responsivo: com evolucao / realizadas / faltas /
total. Cada uma colorida + icone + value 800.
- 5 filter chips redondas (estilo Melissa): com-evolucao default; troca
pra todas/realiz/falt/cancel.
- Empty state contextual:
- Se nao tem sessoes: "Quando atender este paciente..."
- Se filtro 'com-evolucao' e zero: "Use o campo Observacoes ao editar
sessao..."
- Outro filtro: "Tente outro filtro acima."
- Lista de sessoes (pron-list) com:
- border-left colorida por status (verde realiz / vermelho falta /
amarelo cancel / cinza default)
- head com data + relative + chips status/modalidade/duracao
- titulo opcional (titulo_custom || titulo)
- block "Evolucao" quando tem observacoes (background medium, border-
left primary, label uppercase com icone, texto pre-wrap)
- mensagem "Sem evolucao registrada" italico cinza quando nao tem
- Roadmap card (border-dashed) listando 4 features futuras: anamnese
estruturada / plano terapeutico / evolucao por temas / assinatura
digital + LGPD Art. 18.
CSS: ~200L novos pros componentes (mpa-pron-hint/stats/filters/list/
item/roadmap). Padrao visual Melissa: chips redondas estilo MelissaTags,
border-left adaptativa, monospace inutilizado.
ESLint: 0 errors da minha mudanca.
## [2026-05-08 14:30] session | MelissaPaciente Fase 3 — Tab Perfil (6 sections stacked)
Touched: none
Detalhes: Substituiu o placeholder da aba Perfil por 6 sections stacked
com anchors no MelissaPaciente. Diferente do PatientProntuario legacy que
usava PrimeVue Accordion (1 painel aberto por vez), o Melissa nativo
mostra todos os 6 cards stacked com scroll suave do sidebar sub-nav pra
cada anchor. Mais legivel em desktop, mais rapido pra escanear.
EXTENSAO de patientFormatters.js: +5 formatters
- pickField (ja existia computed local; agora helper compartilhavel)
- onlyDigits, fmtCPF (000.000.000-00), fmtRG (passthrough), fmtPhoneMobile
((XX) 9XXXX-XXXX), fmtGender (Masculino/Feminino/Nao-binario/Outro),
fmtMarital (Solteiro/Casado/Divorciado/Viuvo/Uniao estavel).
MELISSAPACIENTE.VUE — script:
- 30+ field computeds usando pickField (cobre snake_case + camelCase do
schema): birthValue, telefone/Alternativo, email/Alternativo, genero,
estadoCivil, naturalidade, ondeNosConheceu, encaminhadoPor, observacoes,
notasInternas + 8 campos de endereco (cep/pais/cidade/estado/endereco/
numero/bairro/complemento) + 5 dados adicionais (escolaridade/profissao/
nomeParente/grauParentesco/telefoneParente) + 4 responsavel.
- groupNames/groupLabel/groupCountLabel pra Origem.
- scrollToProfileSection(key) que liga sidebar sub-nav -> nextTick ->
scrollIntoView do anchor #mpa-perfil-XXX. Em mobile fecha o drawer.
MELISSAPACIENTE.VUE — template Tab Perfil:
- 1. Informacoes Pessoais: 2-col (Dados de cadastro: nome/data nasc com
idade/genero/estado civil/CPF/RG/naturalidade) + (Contato: tel/tel-alt
com tel: links + e-mail principal/alt com mailto: + Origem: grupos/tags
chips/onde nos conheceu/encaminhado por). Observacoes full-width quando
preenchido.
- 2. Endereco: grid 2-col com 8 fields (CEP/pais/cidade/estado/endereco/
numero/bairro/complemento).
- 3. Dados Adicionais: grid 2-col com escolaridade/profissao/parente/grau/
tel parente.
- 4. Responsavel: 1-col com nome/CPF/tel + observacao block textual.
- 5. Anotacoes Internas: card com hint lock + textblock min-height.
- 6. Sessoes: lista compacta scrollable (max-height 360px) com titulo/
data/duracao/modalidade chips + tag status.
CSS: ~250L novos pros componentes (mpa-fields/field-row/field-grid-2/
field-block/sess/sess-list). Pattern visual Melissa: cards com label
uppercase, separadores horizontais sutis, links com cor primary, monospace
pra CPF/RG/CEP.
ESLint: 0 errors da minha mudanca.
## [2026-05-08 13:00] session | MelissaPaciente Fase 2 — Tab Visao Geral completa
Touched: none
Detalhes: Reescreveu a aba Visao Geral do MelissaPaciente substituindo o
placeholder por uma versao 1:1 do PatientProntuario.vue legado, mas com
estilo Melissa nativo.
NOVO: src/features/patients/utils/patientFormatters.js (~165L)
- Helpers compartilhaveis extraidos do PatientProntuario: parseDateLoose,
fmtDateBR, fmtDateTimeBR, fmtCurrency, fmtRelative, sessionDuration,
calcAge. STATUS_LABEL/SEVERITY pra sessoes. tagStyle com luminance auto
(texto preto/branco baseado em contraste WCAG-ish). Sera usado pelas
Fases 3-7 e finalmente pelo PatientProntuario tambem (Fase 8).
EXTENSAO de composables:
- usePatientSessions ganha computed `ultimasAtendidas` (top 6 sessoes
realizadas/faltadas/canceladas pra Timeline). Refinou totalRealizadas/
Faltas/Canceladas pra usar regex (cobre variantes pt-br).
- usePatientFinancial ganha computed `statusFinanceiro` ({ emDia, proxVenc,
totalPendente, totalPago, vencidos }) pra alimentar o KPI 02 com info
detalhada.
MELISSAPACIENTE.VUE — Visao Geral (Fase 2 done):
- 4 KPI cards ricos (era 4 simples na Fase 1):
- 01 Sessoes: realizadas + total + faltas + cancel.
- 02 Pagamento: emDia/atraso + proxVenc + pendente, com cor adaptativa
(vermelho quando atrasado, primary quando ok).
- 03 Proxima sessao: relative + datetime + modalidade.
- 04 Mensagens: ultimaMensagem relative + direction + count.
- Grid 2-col abaixo: Timeline (1.4fr) + coluna direita (1fr) com
Mensagens recentes + Notas/observacoes.
- Timeline com dot colorido por status (verde/vermelho/amarelo) +
STATUS_LABEL/SEVERITY do utils + chips modalidade/duracao + nota
observacoes inline.
- Mensagens recentes com border-left colorida (verde=in / azul=out) +
meta direction + relative + body 3-line clamp.
- Notas e observacoes com card papel + label uppercase + icone lock
pras internas.
- Removeu kpiEmAberto/Atrasado nao usados (statusFinanceiro encapsula).
ESLint: 0 errors. Working tree limpa antes do commit.
## [2026-05-08 11:30] session | MelissaPaciente Fase 1 (foundation: composables + skeleton + slug)
Touched: none (sem mudanca de wiki)
Detalhes: User escolheu "Full rewrite Melissa nativo" pra portar
PatientProntuario.vue (3593L Dialog) pro Melissa. Plano em 8 fases (2-8 sao
cada tab/wireup, sessao dedicada). Fase 1 entregue:
5 COMPOSABLES NOVOS em src/features/patients/composables/:
- usePatientDetail.js (108L) — patients + groups + tags via 4 queries
(getPatientById, getPatientRelations, getGroupsByIds, getTagsByIds).
Espelha 1:1 a logica de loadDetail() do PatientProntuario L893-953.
- usePatientSessions.js (83L) — agenda_eventos limit 100 ordenado desc +
computeds proximaSessao/ultimaSessao/totalSessoes/totalRealizadas/
totalFaltas/totalCanceladas.
- usePatientFinancial.js (82L) — financial_records (type=receita) limit 100
+ computeds totalRecebido/EmAberto/Atrasado/ultimoPago.
- usePatientMessages.js (64L) — conversation_messages limit 200 + computeds
recentes (top 4)/totalIn/totalOut/ultimaMensagem.
- usePatientDocuments.js (70L) — documents (deleted_at IS NULL) limit 200
+ computeds total/totalBytes/tiposCount/ultimo.
MELISSAPACIENTE.VUE NOVO (1190L) em src/layout/melissa/:
- Prefixo CSS .mpa-* (Melissa PAciente). Chrome glass + drawer mobile +
right: max(...) >=1024px (mesmo padrao MelissaAgendador/Negocio).
- Header: avatar + nome + ageLabel + pronomes + status/convenio Tag +
risco-elevado pill + actions (Conversar / Editar / Close).
- Subheader condicional: banner risco elevado.
- Body 2-col: sidebar 320px (esquerda, drawer no mobile) + main flex 1.
- Sidebar contém 4 cards: Acoes Rapidas (Conversar/Editar/Lancamento) +
Navegacao (7 tabs com icones coloridos) + Sub-nav Perfil (visivel so
quando aba Perfil ativa, 6 secoes) + Vinculos (chips de grupos+tags).
- Main: 7 tabs com placeholders ("Em desenvolvimento — Fase X"). Aba
Visao Geral ja mostra 4 KPIs reais via composables (sessoes totais,
em aberto, mensagens, documentos).
- Props :patient-id; emits close/edit/add-financial/open-whatsapp.
- Watch immediate em props.patientId, dispara loadAll() via Promise.all
dos 5 composables.
MELISSALAYOUT.VUE atualizado:
- Import MelissaPaciente.
- SECOES.paciente entry novo (label/icon/descricao).
- 'paciente' adicionado ao MELISSA_NON_CONFIG_SLUGS.
- Render condicional com :patient-id="String(route.query.id || '')" —
navegacao via /melissa/paciente?id=xxx.
NAO ALTERADO: PatientProntuario.vue continua intocado nos 4 callsites
(TherapistDashboard, MelissaAgenda, MelissaPacientes, PatientsListPage).
Migration acontece nas Fases 2-8. Fase 8 troca os callsites no Melissa.
ESLint: 0 errors da minha mudanca. 2 errors pre-existentes em MelissaLayout
(duplicate key 'financeiro' L242, empty block L1130) — nao toquei aquelas
linhas. PatientProntuario tem 2 outros pre-existentes. Working tree:
MelissaLayout.vue + 6 arquivos novos.
## [2026-05-08 09:30] session | Chrome+preview em 7 paginas Melissa (LinkExterno preview novo)
Touched: none (sem mudanca de wiki - aplicacao do pattern existente)
Detalhes: Aplicou o chrome `right: max(6px, min(50%, calc(100% - 1006px)))`
em 6 paginas tabulares (CadastrosRecebidos .mcr / Recorrencias .mr / Grupos
.mg / Tags .mt / Compromissos .mc / Medicos .mm) - so o tamanho de janela,
sem preview, conforme pedido pelo user. Adicionou novo @media (min-width:
1024px) ao final de cada arquivo (cada um nao tinha esse breakpoint ainda).
MelissaLinkExterno (.ml) ganhou tratamento completo: chrome + sidebar
restruturada (2-col com aside agora a ESQUERDA, antes era a direita) +
mobile drawer pattern (Teleport pro #ml-mobile-drawer-target, transitions,
backdrop, botao Menu mobile-only) + 3-way teleport do preview (mobile=topo
do main / mid-desktop=bottom da sidebar / wide-desktop>=1340=floating glass).
Sidebar agora com Como funciona + Boas praticas (movidos da .ml-side direita)
+ scroll proprio. Sem cfg toggle (nao havia necessidade conceitual).
Componente novo: src/components/cadastro/CadastroExternoPreview.vue (~350L).
Phone-frame 260px estilo AgendadorPreview replicando o CadastroPacienteExterno
publico: nav (logo Psi + chip verificado), hero (avatar 38px + nome split
firstName/lastName em accent + work_description label + clinic name), stepper
4 dots (1 active), card etapa 1 (numero decorativo + tag "Etapa 1 de 4" +
title "Sobre voce" + 3 input bars + CTA "Continuar"), powered by. Recebe
:token prop e busca info do convite via mesma edge function que o publico
(get-intake-invite-info), watch refetcha quando token rotaciona. Sem token
ou sem dados, fallbacks pra "Profissional" + iniciais.
ESLint: 0 errors da minha mudanca. 2 errors pre-existentes em
MelissaRecorrencias.vue (totalDone unused L235, v-for/v-bind:key L584) -
nao toquei aquelas linhas. Working tree: 9 arquivos modificados +
src/components/cadastro/ (untracked). Nao commitado, nao testado em browser.
## [2026-05-08 07:55] session | MelissaAgendador preview celular teleport 3-way
Touched: none (aplicacao do padrao MelissaNegocio - sem mudanca de wiki)
Detalhes: Replicou o padrao floating preview do MelissaNegocio em
MelissaAgendador.vue (+145L). Importou AgendadorPreview (phone-frame ja
existente do legacy ConfiguracoesAgendadorPage). Adicionou ref isWideDesktop
+ matchMedia('(min-width: 1340px)') + computed previewTarget com 3-way
branching: mobile -> #mag-main-preview-target (topo do main, acima de tudo,
DIFERENTE do MelissaNegocio que vai pro drawer); mid-desktop (1024-1339) ->
#mag-sidebar-preview-target (dentro da sidebar apos Status/Resumos);
wide-desktop (>=1340) -> #mag-floating-preview-target (painel flutuante glass
fora do fake dialog, 320px de largura, ancorado a +14px do right edge da
.mag-page). Adicionou regra `right: max(6px, min(50%, calc(100% - 1006px)))`
em .mag-page no @media >=1024px (necessario pra abrir espaco a direita pro
floating). CSS: .mag-floating-preview com glass igual ao fake dialog;
placeholders com display:contents; hide rules por breakpoint. Card de preview
usa mag-w--side e perde fundo/borda no floating (glass do painel ja faz papel).
ESLint 0 errors. Working tree: src/auto-imports.d.ts (auto-gerado) +
MelissaAgendador.vue. Nao commitado, nao testado em browser ainda.
## [2026-05-11 10:50] session | Recorrencia: expandir + materializar + view lista
Touched: [[recorrencia-agenda]]
Detalhes: 6 commits criados e pushed (8b0e633..39cf017).
TIME PICKER do AgendaEventDialog (commit 988a4e5):
- Header dinamico (header-dot + "Nova {commitment.name}" + subtitulo
"Inicio da sessao e duracao"). Inicio + Termino lado a lado (Termino
readonly via fimDateTime). Card destacado de Termino removido.
- Picker virou DataTable (.aed-patient-dt) + Tags Arquivado/Inativo + sort
Ativo>Inativo>Arquivado.
- Cadastro completo INLINE via PatientCadastroDialog (botao pi-id-card)
em vez de redirecionar pra rota nova — nao vaza do layout Melissa.
Usa prop hideViewListButton adicionada antes pra esconder "Salvar e
ver pacientes".
- Mini calendar (.mc-mini) no time picker; chips de duracao rapida
(30/50/60/90m); cards .aed-card; popovers de ajuda.
EXPANSAO DE RECORRENCIA cross-layout (commit 39cf017): 3 composables
compartilhados ganharam loadAndExpand — antes so AgendaTerapeutaPage
e AgendaClinicaPage expandiam, deixando widgets do Melissa com 1 sessao
de uma serie de 4. usePatientSessions.load (range -6mo a +12mo, filtra
por patient_id), useMelissaEventos._fetchRange (range visivel),
useMelissaTodasSessoesPaciente.fetch. normalizeEvent aceita shape de
virtual (paciente_nome/patient_name) alem de joined query.
MATERIALIZACAO em 4 caminhos: UPDATE em id virtual "rec::..." quebrava
com "invalid input syntax for type uuid". Corrigido em
usePatientSessions.updateStatus (aceita row inteira, materializa),
useAgendaEventActions watcher (emit updateSeriesEvent com row),
MelissaLayout.updateEventoStatus (detecta virtual, delega passando
row: ev — sem isso dialogEventRow ficava vazio e criava row orfa sem
patient_id), MelissaPaciente wire-up (@updateSeriesEvent aponta pro
handler certo agora), useMelissaAgenda.onUpdateSeriesEvent (aceita row
do chamador, guard contra rid null, error check no maybeSingle).
VIEW LISTA MelissaAgenda (commit 279b4f7): listWeek -> custom listAll
(duration { years: 2 }, centrada via gotoDate(hoje - 1 ano)). Banner
showRecurrenceHint aparece em day/week/month com botao "Ver na lista".
Sticky day header (.fc-list-day) com z-index 3 + bg opaco — antes
.fc-event passava por cima conforme scroll. View toggle dos botoes
manuais -> PrimeVue SelectButton.
VISUAL EVENTO INATIVO: classNames=['ma-evt--inactive-patient'] em
fcEvents quando paciente_status === Arquivado|Inativo (borda tracejada
+ opacidade 0.58 + italico em list view). useAgendaEventPickerBilling
+ AgendaEventDialogV2: picker mostra TODOS os pacientes ordenados
Ativo>Inativo>Arquivado, nao-Ativos com Tag colorida + disabled +
tooltip. selectPaciente bloqueia non-Ativo (defesa em camadas, 3
specs novas).
OUTROS: services nome unico por owner (case-insensitive); FC touch
defaults centralizados em src/features/agenda/utils/fcDefaults.js
aplicado em 4 calendars; props hideViewListButton em
ComponentCadastroRapido + PatientCadastroDialog pra uso in-flow.
Database backup gerado: backups/2026-05-11/ (138 tabelas, 141 FKs).
Dashboard regenerado.
## [2026-05-11 17:00] session | AgendaEventDialog redesign completo + 2º dialog WIP
Touched: HANDOFF.md (reescrito do zero)
Detalhes: sessao longa de refator visual + UX do AgendaEventDialog.
Headers dos 4 cards (Paciente, Data/Horario, Sessao/Honorarios, Frequencia)
com altura fixa 40px, label so mobile, acoes a direita. Card Paciente
ganhou toggle Presencial/Online com pi-pencil substituindo SelectButton;
mini-links Editar/Limpar no lugar dos botoes redondos. Card Data e
Horario com body em 2 linhas (Data · Duracao / Inicio → Termino). Card
Sessao/Honorarios (renomeado de Pagamento) com Select dropdown default
particular + 3 estados (gratuito/empty/configurado-resumo). Card Extras
renomeado, com botao ? abrindo popover educativo. Layout 50/50 via
.aed-row-50 (Paciente|Data e Sessao|Frequencia).
DIALOGS NOVOS:
- serviceDialogOpen: cada servico vira card individual com preco unit,
total, botoes colapsaveis (Aplicar desconto, Alterar quantidade);
desconto mostra calculo em vermelho; footer fixo com Valor desta
sessao em pill tracejada primary; hint educativo Unidades vs
Recorrencia
- freqDialogOpen: empty/resumo, 4 sub-cards (.aed-freq-section: Tipo,
Dias, Quantidade, Proximas), chips renovados (.freq-tab borda solida
+ variant 2-line com 1 mes/4 sessoes), proximas ocorrencias com
separador por mes + referencia relativa (em 2 semanas/em 1 mes).
"Como interpretar o valor" REMOVIDO.
CONCEITO PACOTE (recorrencia >= 2):
- isPacote computed: criando >=2 OU editando hasSerie
- pacoteTotal = totalFromItems × totalOcorrencias
- Header dialog adapta: "Pacote · 4 Sessoes" / "Sessao do Pacote · Sessao"
/ "Editar Sessao" / "Nova Sessao"
- Resumo: modalidade vira "Presencial · Pacote"; wallet mostra total
pacote; linha extra "4× R$ 40 = R$ 160"
- Status da Sessao escondido em pacote
- pluralCommitment PT-BR (Sessao→Sessoes, Analise→Analises, ão→ões)
MODO EDIÇAO:
- Cadastro Rapido NAO aparece
- Cadastro Completo + toggle Modalidade + Ajustar Horario: disabled
com tooltip explicativo
- time-hero ganha --readonly (sem cursor pointer)
OUTROS: animacao de Dialog + backdrop blur REMOVIDOS (so nativo
PrimeVue); DataTable picker paciente coluna Acao agora frozen
alignFrozen=right; lista Recorrencias Aplicadas com numeracao 1/2/3
em badge primary; badge "atual" → "selecionado".
2º DIALOG EMPILHADO (WIP — BLOQUEIO PRA AMANHA):
- useMelissaAgenda.js: refs novos occDialogOpen/EventRow/StartISO/EndISO
- onEditSeriesOccurrence agora abre 2º dialog (em vez de mutar
dialogEventRow in-place silenciosamente)
- _buildHandlers recebe occDialog* via deps (sem isso dava
ReferenceError em runtime)
- MelissaLayout.vue: 2º AgendaEventDialog mountado paralelo, refs
destruturados como agendaOccDialog* (refs aninhados nao auto-
unwrappam no template — pattern conhecido do projeto)
- Status: ABRE, mas user reportou "nao é essa janela que tem de
abrir" — investigar amanha. Provavelmente precisa de prop pra
esconder Frequencia + Recorrencias Aplicadas no 2º dialog e
ajustar titulo pra "Editar Ocorrencia"
- Pendente replicar em Rail (AgendaTerapeutaPage L1630 + L3080) e
Clinica (AgendaClinicaPage L1119 + L2398) DEPOIS de estabilizar
no Melissa
Mudancas NAO commitadas: 5 arquivos (AgendaEventDialog.vue + dois
QuickCreateDialog + MelissaLayout + useMelissaAgenda). HANDOFF.md
reescrito do zero documentando tudo.
## [2026-05-12 17:55] session | occurrenceMode no 2º dialog da agenda
Touched: recorrencia-agenda
## [2026-05-13 14:00] session | pesquisa fluxo agenda Cliniko SimplePractice TherapyNotes
Touched: none
nTouched: agenda-billing-pesquisa-mercado, index
## [2026-05-13 21:00] session | Pesquisa mercado agenda billing
Touched: agenda-billing-pesquisa-mercado, index
## [2026-05-14 sessao continua] session | AgendaEventDialog testes manuais + correcoes
Touched: none (apenas logs detalhados; sem nova pagina wiki)
Detalhes: User testou fluxo de criacao avulsa (Henrique Lima Souza) e
recorrente (Donald Winnicott, 4×R$40) passo-a-passo. Achados/correcoes:
(1) Bug badge financeiro "Despesa" — campo `type` faltava em BASE_SELECT
de useFinancialRecords.js (caia em else → "Despesa"). Fix: adicionar type
no SELECT. (2) E5 toggle Presencial/Online: removido :disabled="isEdit"
(habilitado em ediçao tambem). (3) E6 Ajustar Horario: trocado por
v-if="!isEdit || !hasSerie" — visivel em criacao E em avulsa em edicao;
escondido em série recorrente (politica "esconder em vez de disabled"
salva na memoria, vale apenas pra agenda). (4) Botao cog + popover sobre
horarios online no time picker — padrao espelhado do Card Extras, linka
pra /melissa/agenda-config (ou /configuracoes/agenda fora do Melissa).
(5) Bug visual: pill --current + --online-cfg perdia destaque selected
porque online-cfg !important ganhava da cascade. Fix: regra combo com
mais especificidade. (6) Time picker vazava dia/hora/duracao pro card
principal quando fechado sem confirmar — snapshot ao abrir + revert no
@hide se _tpCommitted=false (added Cancelar button no footer). (7)
Opção C1 implementada — checkbox bool gerarCobrancaAoSalvar substituido
por SelectButton chargeMode com opcoes dinamicas:
- Avulsa: Não / Gerar cobrança
- Recorrente: Não / Pacote único / 1 por sessão
Handler em useMelissaAgenda agora suporta 3 modos: 'session' (1
financial_record, igual Fase 1 original), 'package' (1 billing_contract
inline em vez de confirm.require pós-save), 'per_session' (materializa N
agenda_eventos + cria N financial_records via RPC, respeitando
recurrence_exceptions). _offerBillingContract removido (codigo morto).
useAgendaEventActions.gerarCobrancaAoSalvar → chargeMode. ESLint: 0
erros novos. Vitest useAgendaEventComposer.spec: 76/76 passed.
## [2026-05-13 22:00] session | Fase 1 — drop agenda_excecoes + render bloqueios cinza
Touched: agenda-compromisso-fluxo
Detalhes: Fase 1 da auditoria fase-a-fase concluida. Auditoria revelou
agenda_excecoes orfa (0 refs em src/, embora policies+trigger+enums
existissem) e bloqueios nunca renderizados no FullCalendar (so impediam
criacao). Aplicado: (1) migration 20260513000001_drop_agenda_excecoes.sql
dropa tabela+enums+trigger; (2) agendaMappers.buildBloqueioBackgroundEvents
renderiza dia-cheio/com-hora/recorrente como background event #6b728033;
(3) composable useAgendaBloqueios reusavel (load aceita owner unico OU
array); (4) wire nos 3 layouts (Melissa via useMelissaAgenda+MelissaAgenda,
Rail via AgendaTerapeutaPage, Clinica via AgendaClinicaPage com multi-owner);
(5) docs/schema_map.md e db.config.json limpos. ESLint 0 novos errors;
agendaMappers.spec 40/40 passed. Pendente: rodar migration no banco local
+ validacao visual nos 3 layouts. Plano de 8 fases salvo em
[[agenda-compromisso-fluxo]]; pesquisa de mercado em [[agenda-billing-pesquisa-mercado]].
## [2026-05-20 evening] session | Fase 0+0.5 sweep de padronização pré-MVP
Touched: none (durable em development/02-auditoria/ + blueprints/ + memory)
Entregue: 3 blueprints (repository, composable, quick-create universal) + AUDIT_BASELINE.md (51 divergências em 6 módulos) + PADRONIZACAO.md (estratégia 4 fases) + DESIGN_BILLING_ORCHESTRATOR.md + 4 migrations + 1 seed do schema clínico (NÃO executadas) + scaffold features/tenantship/ (7 arquivos). Próximo: Fase 1 Módulo 1 (Home/Components).
## [2026-05-20 evening] session | M1 padronização Home/Components concluído
Touched: none (durable em development/02-auditoria/PADRONIZACAO.md + AUDIT_BASELINE.md + memória)
Módulo 1 da Fase 1 fechado: features/medicos/, features/insurance/, ComponentCadastroRapido refatorado (8 callers preservados), TEST_ACCOUNTS extraído, .bak deletado, topbar dev button ganhou switcher de layout + atalhos M1. M1.6 (MelissaLayout 90 imports) deferida pra sessão dedicada. Próximo: M2 Pacientes.
## [2026-05-20 evening] session | M2 Pacientes refatorado em batch
Touched: none (durable em development/02-auditoria/PADRONIZACAO.md + AUDIT_BASELINE.md + memória)
Módulo 2 da Fase 1 fechado sem pausas de teste (estratégia revisada). patientsSelects.js criado com 11 constantes. patientsRepository.js estendido com 15 funções novas. 8 composables refatorados em paralelo (usePatients, usePatientDetail, usePatientFinancial, usePatientSessions, usePatientMessages, usePatientDocuments, usePatientRecurrences, usePatientSupportContacts). Zero supabase.from() em qualquer composable de patients. _lastPatientId DENTRO da function nos 3 composables que tinham. 9 audit items resolvidos. Aguarda teste batch do user antes de seguir M3.
## [2026-05-20 evening] session | M3+M4+M5+M6 foundation em batch único
Touched: none (durable em development/02-auditoria/PADRONIZACAO.md + memória)
Sweep da Fase 1 completa em foundation. M3 (prontuário): 6 files em patients/prontuario/, ativa quando migrations 0.5.B rodarem. M4 (financeiro): 9 files em features/financeiro/, old composables em paralelo, Fase C bloqueada pelas decisoes #2/#3/#6. M5 (tenantship): MembersPage criada, rota TODO. M6 (notificacoes): noticesSelects + conversations foundation, channel factory deferido. Total ~21 files novos nesta sessao. Aguarda teste batch consolidado.
## [2026-05-20 evening] session | M5 quick wins fechados
Touched: none
Rota /admin/members registrada em routes.clinic.js. Migration 20260520000005_accept_tenant_invite_rpc.sql criada (SECURITY DEFINER + lock FOR UPDATE). tenantInvitesRepository.acceptInvite real (nao mais stub). SaasTenantFeaturesPage refatorada via novo tenantFeatureAdminService.js. SetupWizardPage 2648 linhas deferido pra sessao dedicada.
## [2026-05-21 morning] session | Fase 2 hotspots Graphify
Touched: none
convertToPatient de-dup: nova funcao markIntakeConverted no patientsRepository, 2 pages refatoradas. Supabase client triplo: finding defasado, so 1 instancia. 348 nos fracos: graphify update rodou pra refresh apos M1-M6+Fase2. Setup Wizard cohesion: parcial (SaasTenantFeaturesPage feito em M5 quick win); SetupWizardPage 2648 linhas adiado.
## [2026-05-21 morning] session | Fase 3 Asaas Gateway Tier 1 — Fase A foundation
Touched: none
DESIGN_ASAAS_GATEWAY.md completo. 7 arquivos novos: 2 migrations (tables+RLS) + client service + 3 Edge Function stubs. Webhook existente trata WhatsApp credits — extensao pra financial_records eh Fase B. Decisao modelo negocio (A/B/C) pendente. User precisa: conta Asaas, API keys, webhook config, ENV vars no Supabase. Stops bem marcados pra Fase B (implementacao real).
## [2026-05-21 morning] session | Fase 3 — Compliance CFP #5/#8/#9
Touched: none
2 migrations (profiles registration + specialties+joinM:N+RLS) + 1 seed (33 specialties) + 1 service (specialtiesService.js). #8 nome social ja estava integrado. #6 consent forms e #7 assinatura adiados — schemas (document_templates+document_signatures) existem, falta UI workflow.
## [2026-05-21 afternoon] session | Compliance CFP #6 + #7 fechados
Touched: none (durable em development/02-auditoria/PADRONIZACAO.md + memoria padronizacao_sweep)
Fechou Fase 1.2 Compliance basico BR do ROADMAP. 5 commits tematicos.
#6 (consent forms) — biblioteca de templates LGPD-compliant:
- Migration 20260521000005 estende CHECK constraint de document_templates.tipo
com 'termo_lgpd' + 'autorizacao_gravacao'
- Seed seed_060 insere 2 templates globais novos (Consentimento LGPD com
Art. 18 direitos do titular + Autorizacao para Gravacao de Sessao) +
UPDATE no tcle_online amend cláusula LGPD explicita
- Biblioteca completa pos-amend: TCLE, tcle_online (telehealth),
autorizacao_menor (TCLE menores), termo_sigilo, termo_lgpd, autorizacao_
gravacao + 9 outros tipos existentes
#7 (assinatura eletronica no portal) — fluxo end-to-end:
- Migration 20260521000006: 3 RPCs (sign_document_by_signature_id +
sign_document_by_token + get_signable_document_by_token). IP/UA
capturados SERVER-SIDE via inet_client_addr() e current_setting
('request.headers') — anti-spoof. Hash SHA-256 vem do cliente
pra integridade
- Migration 20260521000007: RPC list_my_signatures que cruza auth.uid()
por 3 caminhos (signatario_id, signatario_email, patient.user_id)
- DocumentSignatures.service ganha 4 wrappers: signByPortal,
signByToken, getSignableDocumentByToken, listMySignatures
- useDocumentSignatures composable novo (Tipo A blueprint)
- PortalDocumentos.vue (nova) — lista pendencias do paciente logado
com KPIs + filtro + botao "Assinar agora" que aponta pra share link
- portal.menu.js ganha item "Documentos > Para assinar"
- SharedDocumentPage.vue estendida: painel azul abaixo do preview
com aviso LGPD/CFP + checkbox aceite + selecao multi-signatario
+ botoes Assinar/Recusar com loading + computa SHA-256 do PDF
baixado antes do sign
- DocumentSignatureDialog (terapeuta-side, ja existia) ganha
checkbox "Gerar link publico para assinatura" (default ON) +
select validade (24h/3d/7d/30d) + bloco emerald com URL + copy
Fluxo end-to-end: terapeuta cria signature requests + share_link
no dialog -> copia URL -> envia via WA/email -> paciente abre
/shared/document/:token -> visualiza doc -> aceite -> assinatura
registrada via RPC sign_document_by_token (IP/UA/timestamp/hash
gravados server-side em document_signatures).
Pos-MVP nice-to-have: notificacao automatica do paciente quando
signature criada (depende de Modulo 6 notifications WA/email
channel factory). Por ora, terapeuta envia link manualmente.
PROXIMO: outras 5 secoes do ROADMAP Fase 1 (Asaas Fase B bloqueada,
UX §1.3, Fiscal §1.4, Qualidade §1.5).
## [2026-05-21 evening] session | ROADMAP #14 Recibo profissional PDF
Touched: none (durable em development/02-auditoria/PADRONIZACAO.md + memoria)
Fecha §1.4 Fiscal minimo (parcial — #15 NFS-e fica pra depois).
src/utils/valorExtenso.js — helper pt-BR completo ate 999 milhoes.
"R$ 1.234,56" -> "mil duzentos e trinta e quatro reais e cinquenta
e seis centavos".
DocumentGenerate.service estendido:
- loadTherapistData puxa professional_registration_type/numero/uf
(#5 migration) e auto-formata terapeuta_registro: "CRP 12345/SP".
terapeuta_crp legacy mantido pra compat.
- loadClinicData formata tenants.cpf_cnpj (11 dig CPF, 14 dig CNPJ).
- loadAllVariables aceita extras + computa valor + valor_extenso +
forma_pagamento.
- saveGeneratedDocument ganha templateTipo + mapping
TEMPLATE_TYPE_TO_DOC_TYPE (recibo_pagamento -> 'recibo', laudo ->
'laudo' etc). Antes era hardcoded 'laudo' pra TUDO — bug.
- emitirReciboParaSessao(eventoId, opts) — quick path: busca
template, carrega vars, gera PDF, salva, download. One-call.
Migration 20260521000008 substitui no template recibo_pagamento
"Psicologo(a) - CRP {{terapeuta_crp}}" por "{{terapeuta_registro}}".
Universal pra qualquer conselho (CRP/CRM/CRFa/CREFITO/CRESS/CRN).
DocumentTemplates.service.TEMPLATE_VARIABLES ganha 4 entries de
registro profissional. useDocumentGenerate passa templateTipo.
AgendaEventoFinanceiroPanel ganha botao "Emitir recibo" outlined
quando record.status === 'paid'. Toast + loading state.
PROXIMO: UX §1.3 (busca global + recently viewed + papel timbrado
+ relatorios export) OU sweep residual (M4 cutover billing decisoes
#2/#3/#6).
## [2026-05-21 evening] session | ROADMAP §1.3 UX 3/4 (#10/#11/#13)
Touched: none
3 commits fechando 3 dos 4 itens da Fase 1.3 UX:
#10 Busca global topbar — GlobalSearch.vue ja estava feito no Rail/
classic. **MelissaBusca promovida** de preview client-side pra RPC
search_global com debounce 200ms + searchSeq pra ignorar respostas
obsoletas. 3 grupos novos exibidos quando RPC retorna: sessoes,
documentos, cadastros recebidos. @paciente no MelissaLayout
corrigido (antes ignorava payload — bug). Emits novos: documento,
intake.
#11 Recently viewed — composables/useRecentPatients.js (localStorage
por user_id, max 5, dedup, eventos CustomEvent + 'storage' pra sync
entre instancias no mesmo browser). registerPatientVisit chamado
em MelissaPaciente.loadAll e PatientProntuario.loadDetail. Grupo
"Acessados recentemente" no GlobalSearch.vue + MelissaBusca.vue
quando query vazia. Decisao: localStorage > tabela user_recent_access
por simplicidade + zero round-trip por visita.
#13 Relatorios export PDF/Excel — services/reportExport.service.js
com exportSessionsToPDF (pdf.service HTML→PDF + KPIs + tabela A4),
exportSessionsToXLSX (exceljs com import dinamico, frozen header,
alternating rows, branded), exportSessionsToCSV (vanilla, BOM UTF-8,
separador ';'). 3 botoes pi-file-pdf/pi-file-excel/pi-table em
RelatoriosPage.vue (therapist) + MelissaRelatorios.vue. Respeita
filtro de status da tabela.
#12 Papel timbrado — BLOQUEADO: codigo no UniaoApp. Quando user
importar, plugar como cabecalho_html/rodape_html global em
document_templates ou setting tenants.letterhead_html.
PROXIMO: NFS-e (#15, esforco L), §1.5 Sentry (#18 nao-teste),
sweep residual (M4 cutover billing — bloqueado decisoes #2/#3/#6),
ou agenda Fase 4 residual.
## [2026-05-21 night] session | agenda Fase 4: C12 UX iter + utils extract
Touched: none (durable em memoria project_c12_antecipar_iterar atualizada)
Iniciou agenda Fase 4 residual. Auditoria revelou: popover snapshot
e reverse transition trava JA estavam done de fato (commits f83315b
+ 5684297 durante C11). Pendentes reais: C12 UX, replicacao Rail/
Clinica, doc ajuda.
3 commits:
1) agenda C12 UX: "Trocar metodo" em vez de Revogar+Antecipar
MelissaEventoPanel ganha 2 botoes quando isAntecipacaoAtiva
(antes era so "Revogar"). MelissaLayout: anteciparMode ref +
onTrocarMetodoAntecipacao pre-seleciona metodo atual. confirm
Antecipar Pagamento ramifica: mode='update' faz UPDATE no paid
existente (sem cancel cycle). Result: trocar metodo gera 0
records cancelled.
2) agenda C12 UX: filtrar cancelled do dialog Lancamentos
lancamentosShowHistory ref (default false) + lancamentosFiltered
computed. UI: badge "{N} cancelado(s) ocultos" + toggle
Mostrar/Ocultar historico. Cards cancelled atenuados (opacity
0.55, border-dashed, line-through na desc) quando expandidos.
Combina com Trocar metodo — caso 99% so ve ativos.
3) agenda Fase A: extrai utils puros pra features/agenda/utils
Decomposicao em prep pra Rail/Clinica adotarem. 4 arquivos novos:
eventoTipo.js + dbFields.js + timeHelpers.js + colors.js.
useMelissaAgenda.js: 2863L -> 2792L (-71L), imports via aliases
pra nao mexer em 70+ callsites internos. Zero impacto comportamental.
C12 UX iter 3 (validar antecipar->Realizada nao duplica record) JA
estava implementado em commits 00c4168 + f83315b — comentario no
codigo de _loadStatusChangeContext confirma "ctx.existingPaidRecord"
pra evitar oferecer "Gerar cobranca nova".
PENDENTE replicacao Rail/Clinica:
- Fase B (service de billing): extrair _loadStatusChangeContext,
_applyStatusDecisions, _createPackageContract, _materializeAndCharge
PerSession num service reusavel. ~2-3h, risco medio (precisa nao
quebrar 7 ciclos da agenda C7-C13).
- Fase C/D: adapter em AgendaTerapeutaPage/AgendaClinicaPage.
ATUAL: decidir entre Fase B agora ou pausar replicacao + atacar
outro residual (NFS-e, sweep, etc).
## [2026-05-21 late night] session | agenda Fase B (B1+B2) — agendaBilling.service
Touched: none
Continua decomposicao da agenda pra Rail/Clinica. 2 commits cobrindo
Fase B inteira (read-only + mutations):
Fase B1 (e7e3d1b): agendaBilling.service nasce com
- computeSeriePrice (puro)
- generateOccurrenceDates (puro)
- needsStatusConfirmDialog (puro)
- loadStatusChangeContext (read-only, 5 deps)
useMelissaAgenda: 2792L -> 2593L (-199L)
Fase B2 (049dd91): adiciona mutations
- applyStatusDecisions (~330L — todas as decisoes do dialog)
- createPackageContract (~140L — upfront/saldo)
- materializeAndChargePerSession (~90L — per_session)
useMelissaAgenda: 2593L -> 2042L (-551L)
TOTAL fases A+B1+B2: 3033L -> 2042L (-991L extraidas, ~33% reducao).
3 pages (Melissa/Rail/Clinica) agora podem reusar mesmo billing
core. Comportamento Melissa identico — codigo movido linha-a-linha,
so refactor de signature pra receber deps explicitas em vez de
closure.
Pendente: Fase C (adapter Rail) + Fase D (adapter Clinica) +
doc ajuda.
## [2026-05-21 dawn] session | migrations + seeds aplicados no banco local
Touched: none
Aplicou todas as 13 migrations pendentes do dia (clinical_notes
tables/rls/versioning + documents link + accept_invite RPC + asaas
tables/rls + profiles registration + specialties + document_templates
consent types + sign_document RPCs + list_my_signatures + recibo
amend) + 3 seeds novos (seed_040 clinical_note_templates 6 entries +
seed_050 specialties 34 entries + seed_060 consent forms 2 templates
LGPD/Gravacao + amend tcle_online).
Gotcha re-validado (memoria atualizada): migration 20260521000005
estendendo CHECK dt_tipo_check foi marcada aplicada pelo db.cjs mas
silenciosamente ROLLBACK (postgres nao e owner de document_templates).
Detectado quando seed_060 falhou com violates check constraint.
Re-rodada via `docker exec -i ... sh -c 'psql -U supabase_admin -h
127.0.0.1 -d postgres'` (trust pra 127.0.0.1/32 em pg_hba.conf).
db.config.json estendido com os 3 seeds novos (system group, ordem
seed_040 -> seed_050 -> seed_060) pra setup do zero rodar tudo.
Sanity check pos-aplicacao:
- 5 RPCs novas (accept_tenant_invite + 3 sign + list_my_signatures)
- 8 tabelas novas (clinical_notes + versions + templates + asaas
customers/payments/webhook + profile_specialties + specialties)
- 17 document_templates global (15 existentes + 2 LGPD/Gravacao)
- 34 specialties seedadas
- 6 clinical_note_templates seedados
- 3 colunas professional_registration_* em profiles
- Backup automatico criado em backups/2026-05-21/
## [2026-05-21 deep night] session | agenda Fases C + D — Rail+Clinica adotam billing core
Touched: none
Replicacao Rail/Clinica fechada via composable reusavel
useAgendaStatusChange (Tipo A wrapper sobre agendaBilling.service).
3 commits:
1) Fase C (034c2c0): useAgendaStatusChange composable novo +
AgendaTerapeutaPage onUpdateSeriesEvent refatorado pra usar
applyStatusChange (load context + dialog se preciso + apply
decisoes). AgendaStatusChangeConfirmDialog plugado no template.
Antes: Rail fazia so update(id, { status }) cru. Zero das
features C7-C13.
Depois: Rail tem feature parity com Melissa pra status change.
Multa por falta, taxa cancelamento tardio, consumir saldo,
gerar cobranca pacote saldo, reverse transition trava.
2) Fase D (6807b44): AgendaClinicaPage espelha Fase C usando o
mesmo composable. Diferencas adaptadas (updateClinic + createClinic
recebem tenantId arg explicito).
3) Pendente residual:
- Indicadores visuais (3 canais: barra esquerda verde / badge $
amber / neutro) ainda nao replicados no Rail/Clinica — sao
custom event classNames do FullCalendar, requerem _payment
StateMap.
- Antecipar/Revogar/Trocar metodo no popover do Rail — Rail
nao tem popover separado, usa AgendaEventDialog direto;
precisa refactor maior pra acomodar.
- Doc ajuda completa.
ESTADO: agenda Fase 4 residual 70% fechada. C7-C13 core flow
(status change com billing) agora cobre os 3 layouts. UI fina
(popover antecipar, indicadores visuais) fica pra iter incremental
sob demanda.
TOTAL DA SESSAO (24/05 - 25/05, ~24 commits):
- CFP #6/#7 (Compliance Fase 1.2 ✅)
- #14 Recibo profissional PDF
- §1.3 UX 3/4 (#10 #11 #13)
- C12 UX iter (Trocar metodo + filtro cancelled)
- Agenda decomposicao A+B1+B2: -991L em useMelissaAgenda (~33%)
- Agenda Fases C+D: Rail+Clinica adotam billing core
- useAgendaStatusChange composable novo
## [2026-05-21 23:00] session | Melissa Fase 2 UX iter + bug isFinite(null)
Touched: feedback_isfinite_strict, feedback_teleport_body_styles
Detalhes:
Sessao de testes manuais Fase 2 (templates + paciente.documentos).
4 ajustes UX + 1 bug funcional resolvido. 5 commits, 0 push (SSL
self-signed Gitea — user faz manual amanha).
1) MelissaPatientDocuments (4e1ebeb, 6c39c58):
Aba Documentos no /melissa/paciente?id=X foi convertida de embed
<DocumentsListPage> pra pagina nativa 2-col Melissa. Drawer mobile
bugava (transform/filter em ancestrais trapando position:fixed).
Fix:
- <Teleport to="body"> no drawer + backdrop pra escapar stacking
- styles do drawer movidos pra <style> nao-scoped (teleport perde
data-v attrs do scoped)
- wrapper teleportado recebe class "win11-root" pra herdar vars
--m-* (definidas nesse escopo no MelissaLayout)
- cascata --mpd-bg/border/text: --m-* -> --p-* -> hardcoded
2) DocumentGenerateDialog (61bb0d9, 512bcc9):
Inputs trocados pra FloatLabel variant="on". Adicionado map de
ORIGEM dos campos (TEMPLATE_VARIABLES.source) — hint embaixo de
cada campo vazio explica onde cadastrar (ex: "Perfil -> Registro
Profissional"). Banner verde/amber no topo conta preenchidos.
3) Bug critico (4f05c2c) — RAIZ do "campos vem vazio mesmo com
profile preenchido":
loadAllVariables crashava com TypeError "Cannot read properties
of null (reading toFixed)" quando NAO havia sessao vinculada
(agendaEventoId=null) E sem extras.valor. Toda a Promise
estourava, variables zerava.
Causa: isFinite(null) global retorna TRUE (Number(null)===0),
entrava no branch valorNum.toFixed e crashava.
Fix: trocar por Number.isFinite (strict, nao coerce).
Salvo como memoria feedback_isfinite_strict.
PROXIMA SESSAO (retomar amanha 22/05):
- Continuar Fase 2: 2.7-2.9 (gerar PDF dentro da aba Documentos
do paciente, conferir vars CRP/UF preenchem, doc aparece como
tipo_documento='outro')
- Gerar JSON docs Fase 2 (#6 + templates page)
- Fase 3: Portal assinatura #7
- Fase 4: Recibo profissional #14 testes
- Fase 5: Relatorios export #13
- Fase 6: C12 UX iter (deferred 20/05)
- Fase 7: Regressao Agenda C7-C13
PUSH PENDENTE: 35 commits ahead of origin/main; SSL self-signed
do Gitea exige `git -c http.sslVerify=false push origin main`
+ credenciais (user faz manual).