Files
agenciapsilmno/Obsidian/Brain/log.md
T
Leonardo 1feb7112ff agenda: C7 OK + Fase 6 lock-edit ativada em Melissa + cross-week payment propagation
Cenário 7 (Pacote UPFRONT — Ana Souza Ferreira 4×R$ 200 = R$ 800)
- Testado e passou. User criou Ana, pagou os R$ 800 em dinheiro pelo
  Financeiro. Borda verde + popover "Pago R$ 800" funcionando.

Fase 6 (lock-edit cobrada) ativada em Melissa
- Removido guard `if (!props.occurrenceMode) return;` em
  loadOccFinancialRecord (useAgendaEventLifecycle.js:217+). Agora ele
  carrega em ambos modos (Rail/Clínica E Melissa)
- loadOccFinancialRecord SINTETIZA record paid/pending pra siblings de
  contrato upfront ativo — assim TODAS as ocorrências da série mostram
  "Cobrança paga R$ 800 do pacote" no AgendaEventDialog
- AgendaEventDialog card Sessão/Honorários (flow Melissa) ganhou lock
  template: Tag em vez de Select billingType quando occFinancialRecord
  existe; Message com cadeado "Cobrança de R$ X já emitida"
- AgendaEventoFinanceiroPanel só renderiza dentro do lock quando record
  é REAL (não sintetizado) — evita "Gerar cobrança" indevido em sibling
- paymentSummary do Resumo lateral unificado pra usar occFinancialRecord
  (em vez do sessionPaymentRecord paralelo de antes)

Cross-week propagation de pacote upfront
- BUG: ao navegar pra semana só com virtuais (sem reais), bulk-load
  caía no else `_rulePaymentMap.value = {}` — virtuais perdiam estado
  paid herdado
- FIX em useMelissaAgenda._reloadRange:
  * Maps (payment/amount/rule) inicializados SEMPRE no início
  * Propagação roda independente de realIds.length (depende só de
    ruleIdsInView.size>0, considera reais E virtuais com recurrence_id)
  * Query cross-week: pra cada rule em view, busca QUALQUER evento
    sibling em qualquer semana + seus records pra determinar estado do
    contrato. Encontra o record do pacote mesmo em outra semana
- Saldo NÃO propaga (filter: charging_style='upfront' || NULL); cada
  sessão de saldo gera cobrança individual ao realizar
- Memória durável: memory/project_cross_week_propagation.md

Visualização de virtuais cobertas
- MelissaEventoPanel.showPaymentRow: virtuais só escondem quando state
  ='none'. Com paid/pending herdado, exibem linha colorida
- MelissaAgenda fcEvents: isPaidSession e badge $ pendente removeram
  exigência de !is_occurrence. Virtuais herdadas via propagação mostram
  borda verde / badge amber

Atalho "Gerar fatura" no popover
- Pill amber pequeno ao lado de "A cobrar R$ X" quando paymentVariant
  ='none' && !is_occurrence. Click → gerarCobrancaManual direto, fecha
  popover pra impedir double-click. Tooltip: "Gerar fatura agora"
- Wire em MelissaLayout via novo emit gerar-cobranca + handler
  onGerarCobrancaQuick

Info de pacote no popover
- Header agora mostra "Sessão · Pacote · N sessões" (computed
  seriesLabel lê de _raw do rule)

Botão "Excluir série inteira"
- Novo emit delete-series em MelissaEventoPanel + botão ao lado de
  "Excluir sessão" quando evento tem recurrence_id
- Handler onDeleteSeries em MelissaLayout: hard delete em 3 etapas
  (financial_records pendentes → agenda_eventos materializados →
  recurrence_rules CASCADE leva exceptions). Bloqueia se algum record
  paid (estorno via Financeiro primeiro)

cancel_session some da agenda
- useRecurrence.expandRules agora pula occurrence com exception.type=
  'cancel_session' (era visível com status cancelado; doc dizia que
  some). patient_missed/therapist_canceled/holiday_block permanecem
  como histórico

recurrence_exceptions cancel idempotente
- MelissaLayout onDeleteEvento usa upsert com onConflict pra exception
  cancel — não quebra mais com unique violation em re-cancel

billing_contract_id na 1ª materializada
- _createPackageContract agora .select() o contrato após insert e seta
  billing_contract_id no insert da 1ª agenda_eventos materializada

onVerLancamentos cobre virtual de upfront
- Antes virtual sempre toast "Sem lançamentos". Agora busca records via
  siblings da série pra encontrar o do pacote. Saldo/sem pacote continua
  com toast

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

990 lines
52 KiB
Markdown
Raw 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-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]].