Files
agenciapsilmno/Obsidian/Brain/log.md
T
Leonardo 4da0bc2e11 HANDOFF + log: C12 deferred (UX iterar) · testando C13
C12 fluxo critico OK no DB (antecipar/revogar/re-antecipar/realizada
detecta paid). 5 bugs corrigidos no caminho: re-antecipar nao reusa
cancelled, popover watch sync com lookup virtual->materializada,
normalizeForMelissa expoe owner_id, etc.

User adiou C12 pra iterar UX depois (pos-Rail/Clinica). Salvo em
memoria project_c12_antecipar_iterar.

C13 prep: lock "edit cobrada" ja implementado na Fase 6 (commit
1feb711). User vai validar visualmente com Joao Almeida ou Andre.

14 commits no dia. Pendencias documentadas. Working tree limpo
exceto HANDOFF/log (este commit).

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

62 KiB
Raw Blame History

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-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.

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 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.
    1. Endereco: grid 2-col com 8 fields (CEP/pais/cidade/estado/endereco/ numero/bairro/complemento).
    1. Dados Adicionais: grid 2-col com escolaridade/profissao/parente/grau/ tel parente.
    1. Responsavel: 1-col com nome/CPF/tel + observacao block textual.
    1. Anotacoes Internas: card com hint lock + textblock min-height.
    1. 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