Files
agenciapsilmno/HANDOFF.md
T
Leonardo 86311ef305 Melissa: hub Configuracoes + Embed + 9 Pages novas + dialog blueprint dark
Sprints 04-29 + 04-30 acumuladas.

- MelissaConfiguracoes: hub 2-col com 6 grupos (Layout/Conta/Agenda/
  Financeiro/WhatsApp/Sistema), tudo embedado via MelissaEmbed.
- MelissaEmbed: wrapper generico que injeta layout-variant=melissa
  e remove cromos pra reaproveitar Pages tradicionais.
- 9 Melissa Pages novas: CadastrosRecebidos, Compromissos, Configuracoes,
  Conversas, Embed, Grupos, Medicos, Recorrencias, Tags.
- Dialog blueprint atualizado: bg-gray-100 (hardcoded light) ->
  bg-[var(--surface-ground)] (tema-aware). 22 dialogs migrados em
  9 arquivos. Anti-pattern documentado.
- PatientsCadastroPage: bug fix dropdown Grupo (optionLabel nome->name),
  toggle vertical/abas com persist localStorage, sticky margin-top.
- Surface picker no popover do MelissaLayout (8 swatches).
- useTopbarPlanMenu, useMelissaWhatsapp, useMelissaPacientesAside novos.
- Migration: status agenda remarcado/confirmado.

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

645 lines
30 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.
# HANDOFF — 2026-04-30 (quinta, sprint MelissaConfiguracoes + MelissaEmbed + dialog blueprint dark)
Documento de continuidade. **Quando voltar, comece lendo esta página.**
Sessão grande — criação do hub de configs Melissa (com tudo embedado),
wrapper genérico pra pages tradicionais, polimento do cadastro de paciente,
migração de 22 ocorrências de `bg-gray-100` em dialogs pra tema-aware.
Working tree **NÃO commitado** ainda.
A sessão anterior (2026-04-29) deixou 7 Melissa Pages novas também não
commitadas — estão acumuladas com esta. Decidir junto: 1 commit grande
ou chunks lógicos.
---
## 🚦 STATUS — Working tree
**Modificados (acumulado das 2 sprints):**
```
M HANDOFF.md
M blueprints/dialog-blueprint.md
M src/assets/layout/_menu.scss
M src/components/CadastroRapidoConvenio.vue
M src/components/CadastroRapidoMedico.vue
M src/components/agenda/AgendaQuickAddDialog.vue
M src/components/ui/PatientCadastroDialog.vue
M src/features/patients/cadastro/PatientsCadastroPage.vue
M src/features/patients/medicos/MedicosPage.vue
M src/layout/AppMenu.vue
M src/layout/AppRail.vue
M src/layout/AppRailPanel.vue
M src/layout/AppRailSidebar.vue
M src/layout/composables/layout.js
M src/layout/configuracoes/ConfiguracoesAgendaPage.vue
M src/layout/configuracoes/ConfiguracoesRecursosExtrasPage.vue
M src/layout/configuracoes/ConfiguracoesWhatsappPage.vue
M src/layout/melissa/MelissaAgenda.vue
M src/layout/melissa/MelissaLayout.vue
M src/layout/melissa/MelissaMenu.vue
M src/layout/melissa/MelissaPacientes.vue
M src/layout/melissa/composables/useMelissaAgenda.js
M src/router/routes.clinic.js
M src/router/routes.therapist.js
M src/views/pages/account/ProfilePage.vue
M src/views/pages/saas/SaasAddonsPage.vue
M src/views/pages/saas/SaasNotificationTemplatesPage.vue
```
**Novos (acumulado):**
```
?? blueprints/melissa-page-blueprint.md
?? src/layout/melissa/MelissaCadastrosRecebidos.vue
?? src/layout/melissa/MelissaCompromissos.vue
?? src/layout/melissa/MelissaConfiguracoes.vue
?? src/layout/melissa/MelissaConversas.vue
?? src/layout/melissa/MelissaEmbed.vue
?? src/layout/melissa/MelissaGrupos.vue
?? src/layout/melissa/MelissaMedicos.vue
?? src/layout/melissa/MelissaRecorrencias.vue
?? src/layout/melissa/MelissaTags.vue
?? src/layout/melissa/composables/useMelissaPacientesAside.js
```
---
## ✅ FEITO HOJE (2026-04-30)
### PatientsCadastroPage — polimento
1. **Bug fix dropdown Grupo vazio**`optionLabel="nome"``"name"` (`PatientsCadastroPage.vue:1542`). Repo `listGroups` retorna `{name,color}` mas template buscava `nome`. Tags já estavam OK.
2. **Toggle Vertical/Abas** — botão segmented na sidebar (entre avatar e nav). Em "Abas", esconde nav vertical da sidebar + mostra tab list em cima do main + esconde headers do Accordion (via `.pcd-horizontal :deep(.p-accordionheader)`). Persiste em `localStorage` (chave `pcd.viewMode.v1`).
3. **Sticky + margin-top fantasma** — adicionado `xl:items-start` no grid container (era stretch por default). Sticky da esquerda mantido como estava. Margin-top fantasma resolveu.
### Dialog blueprint — dark/light aware
4. **`blueprints/dialog-blueprint.md`** atualizado: trocado `bg-gray-100` (hardcoded light) por `bg-[var(--surface-ground)]` (tema-aware: `--p-surface-100` light / `--p-surface-950` dark). Removido o hack `shadow-[0_1px_0_0_rgba(255,255,255,0.06)]`. Adicionada seção Anti-pattern explícita.
5. **22 ocorrências em 9 arquivos migradas** pro novo padrão:
- `MedicosPage.vue` (1 dialog)
- `SaasNotificationTemplatesPage.vue` (1)
- `SaasAddonsPage.vue` (3 dialogs)
- `PatientsCadastroPage.vue` (2 dialogs internos: criar grupo, criar tag)
- `ConfiguracoesWhatsappPage.vue` (1)
- `CadastroRapidoMedico.vue` (1)
- `CadastroRapidoConvenio.vue` (1)
- `ConfiguracoesRecursosExtrasPage.vue` (1)
- `AgendaQuickAddDialog.vue` (1)
### Surface picker no popover do canto superior direito
6. **`MelissaLayout.vue`** — importado `surfaces` de `theme.options`, criado `setSurface()` análogo a `setPrimary()`, computed `activeSurface` com fallback (`zinc` no dark, `slate` no light). Popover do canto sup. dir. agora mostra **Surface** (8 swatches) abaixo de **Cor primária**.
### MelissaConfiguracoes — hub de configurações
7. **Novo arquivo: `src/layout/melissa/MelissaConfiguracoes.vue`**
- Layout 2-col (estilo MelissaAgenda): aside ~320px com Accordion de grupos + main com conteúdo da seção ativa
- **6 grupos** (espelham `/configuracoes/` + extensões):
- **Layout Melissa**: Aparência, Plano de fundo, Relógio, Cronômetro (4 inlines com controles definidos no próprio arquivo)
- **Conta** (NOVO): Meu Perfil, Meu Plano, Meu Negócio, Segurança
- **Agenda**: 3 sub-itens
- **Financeiro**: 5 sub-itens
- **WhatsApp & Conversas**: 9 sub-itens
- **Comunicação**: 2 sub-itens
- **Empresa & Plataforma**: 3 sub-itens
- **Total: 30 sub-itens** — 4 inlines + 26 embedados via `defineAsyncComponent` + `<Suspense>`
- **`COMPONENT_MAP`** mapeia keys pra `defineAsyncComponent(() => import(...))`
- **`mcfg-embed-hero`** sticky no topo (`z-index: 11`) com ícone+label+desc+slot `#cfg-page-actions` pros Teleports das pages tradicionais
- **`mcfg-embed-wrap`** dá padding equivalente ao `px-3 md:px-4 pb-5` da `ConfiguracoesPage`
- Aceita prop `secaoRota` que mapeia rota → `secaoAtiva` (`ROUTE_TO_SECAO`): permite deep-link tipo `/melissa/perfil` abrir direto na seção certa
8. **`MelissaLayout.vue`** — adicionou ao `SECOES`:
- `aparencia` (default do MelissaConfiguracoes)
- `perfil`, `plano`, `negocio`, `seguranca` (atalhos de Conta — montam MelissaConfiguracoes pré-selecionado)
- **`provide('melissaSettings', {...})`** após `testarToque` (ordem importa pra ter todas as refs definidas) — expõe pro MelissaConfiguracoes
### MelissaEmbed — wrapper genérico (Onda 1)
9. **Novo arquivo: `src/layout/melissa/MelissaEmbed.vue`**
- 1-coluna (sem aside) — mais leve que MelissaConfiguracoes
- Hero glass sticky (z-index 11) + `<Suspense>` + `<component :is>` lazy
- **9 pages embedadas** (`EMBED_MAP`):
- Financeiro Visão geral + Lançamentos
- Documents List + Templates
- Agendamentos Recebidos
- Online Scheduling
- Relatórios
- Notifications History
- Patients External Link
- Reusa Teleport target `#cfg-page-actions` (compartilhado com ConfiguracoesPage tradicional)
10. **`MelissaLayout.vue`** — `MELISSA_EMBED_KEYS` array + render condicional + filtro do placeholder atualizado
### MelissaMenu — handlers internos + Onda 1
11. **`MelissaMenu.vue`** — várias mudanças:
- **Footer**: `goPerfil/goPlano/goSeguranca` trocados de `navAndClose(rota_externa)` pra `emit('select', '...')` interno. Adicionado `goNegocio` + botão "Meu Negócio".
- **Backdrop blur** no `.mm-layer`: `background: rgba(0,0,0,0.25)` + `backdrop-filter: blur(2px)` (equivalente ao `backdrop-blur-xs` do PrimeVue Dialog)
- **Categoria Configurações > Layout Melissa** > "Aparência e cronômetro"
- **Onda 1 entries**:
- Agenda e Pacientes > Principais: + Agendamentos recebidos
- Agenda e Pacientes > Outros: + Agendador online, Link externo de cadastro
- Prontuários: novo grupo "Documentos" (Documentos, Templates)
- Financeiro: convertido `fin-overview/fin-lancamentos` (route externo) → `financeiro/financeiro-lancamentos` (internos), + grupo "Análise" com Relatórios
- WhatsApp > Atendimento: + Notificações enviadas
---
## 📊 Estado da migração Melissa
**Promovidas (10 nativas)**: Agenda, Pacientes, Compromissos, Recorrências, Conversas, Tags, Grupos, CadastrosRecebidos, Médicos, Configurações
**Embedadas via MelissaConfiguracoes (26)**: 22 configs + 4 conta
**Embedadas via MelissaEmbed (9)**: Financeiro+Lançamentos, Documents+Templates, Agendamentos Recebidos, Online Scheduling, Relatórios, Notificações, Link Externo
**Faltam (🟢 baixa prioridade)**: Dashboards (Therapist/Clinic — paradigma diferente, resumo já cobre), Setup Wizard, Upgrade pages, Clinic admin (Features/Professionals)
🚫 **Fora de escopo**: routes.saas.js (admin SaaS), Auth pages
---
## 🧪 ROTEIRO DE TESTE — passo a passo (7 fases, ~35 min)
### Setup (1 min)
```powershell
Remove-Item -Recurse -Force node_modules\.vite -ErrorAction SilentlyContinue
npm run dev
```
- Abre `http://localhost:5173` → faz login
- `/account/profile` → terceiro card **"Layout"** → confirma `Melissa` selecionado
- **DevTools console aberto** durante TODOS os testes (F12)
❌ Se ver `Cannot read properties of null` → mata vite, limpa cache (`Remove-Item -Recurse -Force node_modules\.vite`), reinicia.
---
### Fase 1 — Smoke (3 min)
| # | Passo | Esperado |
|---|---|---|
| 1.1 | Acessa `/melissa` | Resumo carrega: relógio gigante + saudação + cards. Console limpo. |
| 1.2 | Click no **ψ** (canto inf. esq.) | Menu Win11 abre. **Fundo escurece com blur sutil** (mudança nova) |
| 1.3 | Click fora do menu | Menu fecha |
---
### Fase 2 — Cadastro de paciente (5 min)
1. `/melissa/pacientes` → click **"+ Novo paciente"**
2. **Toggle Vertical/Abas** (topo da sidebar do dialog):
- Click **"Abas"** → tabs aparecem em cima do form (6 com cores) + nav vertical da sidebar some
- Painel ativo continua sendo mostrado
- Click **"Vertical"** → volta ao Accordion
3. **Painel "Clínico & origem"** (seção 2):
- Dropdown **Grupo** mostra nomes (era vazio antes)
- Multiselect **Tags** funciona
- Botão **+** ao lado de Grupo → abre dialog "Novo grupo"
- Botão **+** ao lado de Tag → abre dialog "Nova tag"
4. **Sticky / margin-top fantasma**:
- Expande painel grande, scroll pra baixo
- Coluna esquerda acompanha sticky
- **Sem espaço fantasma** entre topo e sidebar
5. **Refresh hard** (Ctrl+Shift+R) → reabre dialog → toggle Vertical/Abas **persiste**
---
### Fase 3 — Dialogs dark/light (3 min)
1. `/account/profile` → tema **claro**
2. `/melissa/pacientes` → abre dialog (criar tag pelo + na sidebar)
- Header e footer com **cor levemente cinza** (var `--surface-ground`)
3. Troca pra **escuro** → reabre dialog
- Header e footer com **cor levemente preta** (mais escuro que body)
4. Repete em outros dialogs:
- Cadastro paciente
- Médicos (`/melissa/medicos` → editar)
- Convênio (cadastro rápido)
- Agenda quick add (`/melissa/agenda` → click numa célula vazia)
---
### Fase 4 — MelissaConfiguracoes (10 min) — **mais densa**
Acessa `/melissa/aparencia`
**Sidebar — confirma 6 grupos no Accordion:**
- Layout Melissa (aberto por default)
- Conta, Agenda, Financeiro, WhatsApp & Conversas, Comunicação, Empresa & Plataforma
**Grupo "Layout Melissa" — 4 inlines:**
| Sub-item | O que confere |
|---|---|
| Aparência | Segmented Tema, swatches Primary, swatches Surface, botão "Padrão" |
| Plano de fundo | Preview, upload de imagem, sliders |
| Relógio | Segmented 24h/12h |
| Cronômetro | Select de toque + botão "Testar" |
**Grupo "Conta" — 4 embedados:**
- Meu Perfil → ProfilePage com hero "Meu Perfil" no topo
- Meu Plano → TherapistMeuPlanoPage
- Meu Negócio → NegocioPage
- Segurança → SecurityPage
**Grupo "Agenda" — 3 embedados:** Agenda, Bloqueios, Agendador Online
**Grupo "Financeiro" — 5 embedados:** Pagamento, Precificação, Descontos, Exceções, Convênios
**Grupo "WhatsApp" — 9 embedados:** testa pelo menos 2-3 (ex: Templates, Créditos, Histórico)
**Grupo "Plataforma" — 3 embedados:** Empresa, Recursos Extras, Auditoria
**Em TODAS as embedadas, conferir:**
- **Hero contextual** sticky no topo do main, z-index acima de qq sticky interno
- Ícone + título + descrição corretos por seção
- **Padding adequado** — conteúdo não cola na borda
---
### Fase 5 — Atalhos MelissaMenu (5 min)
Click no **ψ** pra abrir menu:
**Footer (5 botões):**
| Botão | Esperado |
|---|---|
| Meu Perfil | Fecha menu, abre `/melissa/perfil` (embedado, **não** navega externo) |
| Meus Planos | `/melissa/plano` |
| **Meu Negócio** | `/melissa/negocio` (botão NOVO desta sprint) |
| Segurança | `/melissa/seguranca` |
| Modo escuro | Toggle dark/light |
**Categoria Configurações:**
- Configurações → grupo **"Layout Melissa"** → "Aparência e cronômetro" → vai pra `/melissa/aparencia`
**Backdrop:**
- Ao abrir menu, fundo escurece (rgba 0.25) + blur 2px
---
### Fase 6 — Onda 1 embedadas (8 min)
Pra cada URL: **hero contextual + conteúdo renderiza + botão X fecha + console limpo**
| URL | Como chegar pelo menu |
|---|---|
| `/melissa/financeiro` | ψ → Financeiro → Visão geral |
| `/melissa/financeiro-lancamentos` | ψ → Financeiro → Lançamentos |
| `/melissa/documentos` | ψ → Prontuários → Documentos |
| `/melissa/documentos-templates` | ψ → Prontuários → Templates de documentos |
| `/melissa/agendamentos-recebidos` | ψ → Agenda e Pacientes → Agendamentos recebidos |
| `/melissa/online-scheduling` | ψ → Agenda e Pacientes → Agendador online |
| `/melissa/relatorios` | ψ → Financeiro → Relatórios |
| `/melissa/notificacoes` | ψ → WhatsApp → Notificações enviadas |
| `/melissa/link-externo` | ψ → Agenda e Pacientes → Link externo de cadastro |
---
### Fase 7 — Surface picker (1 min)
1. `/melissa` → click **engrenagem** (canto sup. dir.)
2. Aparece **Cor primária** + **Surface** abaixo (8 swatches)
3. Click em diferentes surfaces → fundo de cards/dialogs muda
---
### Como reportar bugs (pra cada problema)
- **Fase + step** (ex: "Fase 4, Conta > Meu Plano")
- **O que aconteceu** (frase curta)
- **Console error** (stack se tiver)
- **Screenshot** se for visual
**Prioridade pra arrumar:**
1. 🔴 Crashes (página em branco, erro vermelho)
2. 🟠 Funcionalidade quebrada
3. 🟡 Polish visual
---
## ⏭️ PRÓXIMOS PASSOS (após testes)
**1. Bugs encontrados → arrumar pontual**
**2. Bug aberto pendente — A#37**
- "Erros ao salvar paciente + dialog não fecha"
- Botão maximizar já corrigido (sessão anterior)
- Falta erro específico do Leonardo (console + toast + Network)
- Hipóteses: RLS, NOT NULL constraint, validação silenciosa
**3. Commits**
- Decidir: 1 mega-commit ou chunks lógicos. Acumulado = 27 modificados + 11 novos.
- Sugestão de chunks (em ordem):
1. Sprint anterior (HANDOFF 2026-04-29) — 7 Melissa Pages + bugfixes Teleport
2. PatientsCadastroPage polish (toggle + bug Grupo + sticky)
3. Dialog blueprint dark/light (blueprint + 9 arquivos migrados)
4. Surface picker + provide melissaSettings
5. MelissaConfiguracoes (hub completo)
6. MelissaEmbed (Onda 1)
7. MelissaMenu (handlers internos + Onda 1 entries + blur)
**4. Onda 2/3 — decisão pendente**
- Onda 2: MelissaDocumentos nativa (~700 linhas glass card 2-col)
- Onda 3: MelissaFinanceiro nativa (~1000 linhas, dashboard cards Win11)
- Critério: se usar muito → vale nativa. Se ocasional → embedado tá bom.
- Decidir DEPOIS de testar a Onda 1 atual.
**5. Itens 🟢 baixa prioridade (talvez nunca)**
- Dashboards tradicionais (resumo já cobre)
- Setup Wizard (fluxo pontual)
- Upgrade pages
- Clinic admin specific (Features/Professionals — admin só)
---
## 📚 Tracking persistente
- **A#32** — Fase 5 router wire-up (ainda pendente, sessão dedicada)
- **A#33-A#36** — bugs resolvidos sessões anteriores (memória project_layout_melissa.md)
- **A#37** — Cadastro paciente erro ao salvar: ⚠️ INVESTIGAR (preciso erro específico)
- Memória atualizada: `project_layout_melissa.md` (sprint 2026-04-29 completa)
- Blueprints: `dialog-blueprint.md` (atualizado dark/light), `melissa-page-blueprint.md` (referência)
---
## 📦 Setup pra retomar
```bash
# Terminal 1 — Functions
supabase functions serve --no-verify-jwt --env-file supabase/functions/.env
# Terminal 2 — Vite
rm -rf node_modules/.vite # se cache estiver bagunçado
npm run dev
# Browser
http://localhost:5173/melissa
```
---
# HANDOFF — 2026-05-03 (sábado, sprint Melissa polishing + topbar parity + notif redesign)
Sessão longa. Working tree continua não-commitado (acumula com as duas anteriores
de 04-29 e 04-30). Dados de demo no DB (9 eventos hoje com price/billed) — limpar
antes de qualquer push pra outro ambiente.
## ✅ FEITO HOJE
### Melissa: timeline do resumo com paridade FullCalendar
- **Range derivado de `agenda_regras_semanais`** (regra do dia atual) com fallback
pra `agenda_configuracoes` (`agenda_custom_start/end`) → 0818h hardcoded.
Substitui as constantes `HORA_INICIO=8` / `HORA_FIM=20`.
- **Range expande pra fora do expediente** — sessões agendadas fora da jornada
(ex: 22h num dia 0818) ainda aparecem; a timeline cresce pra acomodar.
- **Badge "Folga" / "Feriado: <nome>"** no header — `isFolga` checa ausência de
rule pro `dia_semana`; `todayFeriado` busca em `agendaFeriados` (já exposto via
`useMelissaAgenda`). Não bloqueia, só sinaliza.
- **Scroll horizontal** com `min-width` por slot via CSS var `--m-tl-slot-w`
(default 80px); `--m-tl-cols` setada inline. Wrapper `.tl-h-scroll` com
scrollbar fina theme-aware.
- **Auto-scroll inicial pra "agora"** registrado dentro de `onMounted` (TDZ-safe);
watch `[HORA_INICIO, HORA_FIM]` com `_tlAutoScrolled` flag pra disparar uma
vez só. ResizeObserver mantém viewW/innerW frescos.
- **Eco lateral** — minimap pulsante de cores nas bordas. Faixa 8px com tracinhos
coloridos (cor do status) posicionados por tempo dentro da janela invisível.
Click anima scroll até o evento. Pulse 2.4s só quando há off-screen. Hover
expande tracinho `scaleX(2.2)` pra fora da faixa.
### Cards do resumo Melissa (todos funcionais)
- **Próximo paciente** — computed de `eventosHojeReais`, filtra sessao pendente,
ordem por startH, primeiro. "Em curso" pulsa avatar quando `hNow ∈ [start, end]`.
- **Recebíveis hoje** — `price + billed` do agenda_eventos. 3 estados: com valores
(barra de progresso), sem preço, sem sessões. `billed=true` é proxy pra "pago"
(fonte real seria `financial_records.status='paid'` — refinamento futuro).
- **WhatsApp** — novo composable `useMelissaWhatsapp` lendo `conversation_threads`
filtrando channel=whatsapp + unread_count>0. Limit 50, agregação local.
Fallback pra contact_number quando patient_name vazio.
- **Copilot** — virou `implementado: false` no catálogo; cai no placeholder
"Em breve" honesto (sem mock). Backend de IA não existe.
### Dock pinned (Agenda + WhatsApp)
- Adicionados ao `.melissa-dock` (que estava vazio, esperando uso). Ícones
rounded-square 44px (vs ψ full-circle 56px) — hierarquia auto-resolve.
- Active state primary-tinted quando seção correspondente aberta. Badge vermelho
no WhatsApp com `whatsappPendente.count` (99+ se passar).
- Hover: lift `-3px` + sombra crescendo (Win11 dock peek).
### Topbar Melissa (paridade com Rail)
- 3 botões trazidos do AppTopbar pro Melissa (canto sup. dir., flex row): plan
switcher DEV (DEV-only), notificações (com badge), ajuda. Cog continua o
rightmost.
- **Composable extraído**: `src/composables/useTopbarPlanMenu.js` encapsula
~250 linhas de plan-menu logic (resolveActiveSubscriptionContext, listPlans,
changePlanTo, etc). Reusável. AppTopbar inline NÃO foi refatorado (evita
risco de regressão — refactor opcional).
- `<NotificationDrawer />` montado em MelissaLayout (idem `<Toast />`).
- `<AjudaDrawer />` já é global em App.vue, só importei o toggle.
### Toast funcionando no Melissa
- Bug: rota `/melissa/:secao?` está em `routes.misc.js` fora do `AppLayout`
(que monta `<Toast />`). Resultado: toast.add() era silenciado em qualquer
page embedada.
- Fix: `<Toast />` adicionado no fim do template do MelissaLayout (PrimeVue
auto-import via PrimeVueResolver).
### Refresh da timeline ao salvar jornada
- Bug: `useMelissaAgenda.loadSettings()` rodava só no mount. Salvar jornada em
`/melissa/configuracoes/agenda` atualizava DB mas Melissa ficava com workRules
antigas até reload.
- Fix: `ConfiguracoesAgendaPage.saveJornada()` dispara
`window.dispatchEvent(new CustomEvent('agenda:settings-saved'))` após sucesso.
`useMelissaAgenda` registra listener em window, chama `loadSettings()` quando
ouve. Cleanup em `onBeforeUnmount`. Pattern espelha `app:session-refreshed`
já em uso (`main.js:134`).
### Profile: redirect ao trocar Melissa→Rail/Classic
- Bug: `saveAll()` em ProfilePage persistia `layout_variant` mas não navegava.
Usuário ficava preso em `/melissa` mesmo com flag mudado.
- Fix: depois do save bem-sucedido, se estamos em `/melissa` E variant ≠ melissa
→ toast "Aplicando layout" + `setTimeout(700ms, window.location.assign('/'))`.
Hard reload pra remontar a árvore com AppLayout. Caminho inverso (qualquer→melissa)
já era tratado em selectMelissa.
### Tratamento visual por status nas pílulas (Melissa)
- Helpers no MelissaLayout: `statusKey(ev)`, `statusIcon(ev)`, `isEvEmCurso(ev)`,
`pillStatusClass(ev)`. Aplicados na pílula horizontal e no `.vt-event` vertical.
- Tratamentos:
- **realizado** ✓ → glow verde sutil
- **faltou** ✗ → opacidade 0.78 + label tachado
- **cancelado** ⊘ → opacidade 0.6 + diagonal hatching 135° + label tachado
- **remarcar** 🔄 → ring âmbar 2px + glow âmbar
- **em-curso** → pulse 2.2s usando `--ev-color` (color-mix) — herda hue do bg
- `eventStyle()` agora também injeta `--ev-color` inline pra o pulse usar.
### Status updates: refetch fix
- Bug: status mudava no DB mas timeline visual não atualizava. `M.refetch()`
só refresh a Agenda (composable separado).
- Fix: capturei `refetch` do `useMelissaEventosHoje` no destructure e chamo
junto com `M.refetch()` em `updateEventoStatus`.
### Dialog do evento (MelissaEventoPanel) — botões
- **Blur XS** — `.evento-layer` baixou `blur(20px)` pra `blur(4px)` + saturate
110%. Overlay opacidade 0.5→0.32 (dark) / 0.18 (light). Resumo atrás continua
legível, só com leve "tilt-shift".
- **Editar** funciona — antes precisava de `_raw` que `useMelissaEventosHoje`
não inclui (select limitado). Agora busca `select('*')` do row antes de chamar
`M.onEditEvento(data)`. Toast de erro com detalhe se falhar.
- **Prontuário e Histórico** funcionam mesmo sem Agenda montada — novo helper
`_callOnAgenda(action)`: se `melissaAgendaRef.value` existe executa imediato,
senão enfileira em `_pendingAgendaAction` ref e abre seção Agenda. Watch em
`melissaAgendaRef` drena a queue quando o ref aparece.
### Notification drawer redesign
- **NotificationItem.vue** — repensado como card-item:
- `--type-rgb` injetado inline; uma var pinta ícone, spine, chips e actions
via color-mix em várias intensidades.
- Avatar 40px circular (iniciais OU ícone do tipo) com pulse dot 9px no
canto sup-direito quando não-lida.
- Spine vertical 3px à esquerda na cor do tipo (cresce no hover de 80% pra 100%).
- Card border-radius 10px + margin lateral; hover lifta 1px com shadow tinted.
- Header com type label uppercase + horário relativo. Title 2-line clamp,
detail 2-line clamp.
- Quick actions: chips type-colored, primária filled (deeplink), outline
(Conversa). Actions secundárias revelam no hover deslizando da direita.
- **NotificationDrawer.vue** — toolbar limpa + grupos por data:
- Width 380→420px. Header: título + count-pill ("3 não lidas").
- Browser-notif vira icon-btn com active state primary-tinted.
- Body com bg ground sutil. Toolbar sticky. Tabs em segmented control.
- Mark-all virou ghost button compacto.
- **Grupos por data**: Hoje / Ontem / Esta semana / Mais antigas (date-fns
`isToday`/`isYesterday`/`differenceInDays`). Cada grupo tem header
label-uppercase + linha + count.
- Empty state: círculo 72px primary-tinted com check-circle, copy refinada,
link "Ver tudo" se filtro=unread mas há itens.
- Footer: pílula com border (em vez de link plain), arrow scoot 2px no hover.
### TherapistDashboard (rail layout) — timeline parity
- Mesmas features do Melissa aplicadas inline no `TherapistDashboard.vue`
(cópia consciente, não extração — risco de regressão).
- `useAgendaSettings` + `useFeriados` importados; `loadFeriadosBase(tid)`
chamado em `load()` após resolver tid.
- `TL_START`/`TL_END` viraram computeds (eram constantes 7/20). Default
fallback 0720h (preserva range visual original do Dashboard, em vez
do 0818 do Melissa).
- Novo `timelineEventsRaw` evita dep circular: TL_START depende de
`timelineEventsRaw` (que NÃO depende de TL_START). `timelineEvents`
então adiciona positioning baseado em TL_START.
- Folga/feriado badge inline no header.
- Wrapper `.dash-tl-frame > .dash-tl-scroll > .dash-tl-inner`. Eco lateral
com `.dash-tl-eco`. CSS scoped ao componente — duplicação consciente do
Melissa até eventual extração pra `<DailyTimelineStrip />` compartilhado.
### Plan menu popover — ancoragem
- Bug: ao clicar no botão Plan-DEV no Melissa, popover abria no top-left
(sem âncora). Causas:
1. `planBtn.value?.$el` é a forma correta pra PrimeVue Button mas Melissa
usa `<button>` HTML cru, onde planBtn.value já É o DOM (sem `$el`).
2. `event.currentTarget` é null DEPOIS do `await loadPlanMenuData()` — DOM
event spec normal: após a microtask, ciclo de propagação acabou.
- Fix em `useTopbarPlanMenu.js`: captura âncora ANTES do await, com fallback
ampliado: `planBtn.value?.$el || planBtn.value || event?.currentTarget || event?.target`.
Suporta os dois tipos de trigger sem branch.
### Migration aplicada: status_evento_agenda + remarcado + confirmado
- Enum tinha só `{agendado, realizado, faltou, cancelado, remarcar}` mas o
código (`AgendaTerapeutaPage.vue:1339` — bloqueio por feriado) e o trigger
`fn_notify_agenda_status_change` (migration `20260423000009`) referenciam
`'remarcado'` e `'confirmado'`. Tentativas de save falhavam com
`invalid input value for enum status_evento_agenda`.
- Migration: `database-novo/migrations/20260503000001_status_evento_agenda_remarcado_confirmado.sql`.
Idempotente (ADD VALUE IF NOT EXISTS). Aplicada local.
- `NOTIFY pgrst, 'reload schema'` + restart do container `supabase_rest_*`
pra dropar cache do PostgREST.
- Distinção semântica preservada: `remarcar` (verbo, action label) ≠ `remarcado`
(state final, sessão remarcada efetivamente). `confirmado` = paciente
confirmou presença antes da sessão.
## 🗄️ DEMO DATA NO DB (LOCAL)
9 atendimentos populados em `agenda_eventos` pra hoje (2026-05-03), owner
`aaaaaaaa-...02`, tenant `bbbbbbbb-...02`. Mix de status (realizado/faltou/
cancelado/agendado), price R$ 200-280, billed em 3 (R$ 780 / R$ 1.680 = 46%).
Sessão demo "em curso" às 00:12 (John Bowlby) realinhada pra `NOW()±window`
pra preservar pulse.
**Ao virar o dia**, shift +1d com:
```sql
UPDATE agenda_eventos
SET inicio_em = inicio_em + interval '1 day',
fim_em = fim_em + interval '1 day'
WHERE owner_id = 'aaaaaaaa-0002-0002-0002-000000000002'
AND inicio_em >= (CURRENT_DATE - 1)::timestamp AT TIME ZONE 'America/Sao_Paulo'
AND inicio_em < (CURRENT_DATE)::timestamp AT TIME ZONE 'America/Sao_Paulo';
```
**Limpar tudo (antes de qualquer push)**:
```sql
DELETE FROM agenda_eventos
WHERE owner_id = 'aaaaaaaa-0002-0002-0002-000000000002'
AND id IN (
'6b3ed093-fe1c-48de-a0ad-9bb4ea4d4c00',
'136c2dcc-9da6-4fe8-bf24-3ca72d36a9e7',
'8a6386b1-53d6-4043-a80d-90b4d146446b',
'7002e899-f97e-4ca8-b3f2-826fc71c6e84',
'3c7f5a11-8684-4adf-9fa0-76906dd5cc3c',
'8f9f9ee1-3227-408c-9a97-91635a62078a',
'71623e8b-38a9-4b62-8743-1e66eea2ab73',
'b673d2db-335a-4c38-a939-9db1f9e400c6',
'5142ad19-0224-456f-9c41-18c19fafd067'
);
```
## 📂 ARQUIVOS MEXIDOS (SESSÃO 05-03)
**Modificados:**
```
M HANDOFF.md
M src/layout/melissa/MelissaLayout.vue ← massivo
M src/layout/melissa/MelissaEventoPanel.vue (blur XS)
M src/layout/melissa/composables/useMelissaEventos.js (price/billed/select)
M src/layout/melissa/composables/useMelissaAgenda.js (listener settings-saved)
M src/components/notifications/NotificationDrawer.vue (redesign)
M src/components/notifications/NotificationItem.vue (redesign)
M src/views/pages/therapist/TherapistDashboard.vue (timeline parity)
M src/layout/configuracoes/ConfiguracoesAgendaPage.vue (dispatch event)
M src/views/pages/account/ProfilePage.vue (post-save redirect)
```
**Novos:**
```
?? src/layout/melissa/composables/useMelissaWhatsapp.js
?? src/composables/useTopbarPlanMenu.js
?? database-novo/migrations/20260503000001_status_evento_agenda_remarcado_confirmado.sql
```
## ⚠️ EM ABERTO
- **Erro de enum persistente** — usuário relatou que erro de enum persiste
depois da migration + reload do schema. Não recebi o **valor literal**
rejeitado (devtools → network → resposta da API). Suspeitos: `tipo_evento_agenda`
(só tem `sessao`/`bloqueio`, mas código fala em `supervisao`/`reuniao`),
ou outro enum. **Próximo passo amanhã**: capturar o erro literal e decidir
fix (migration nova ou correção de código).
- **WhatsApp realtime no card** — MVP só faz fetch on mount. Pluggar
`useConversations` realtime channel (`conv_msg_tenant_<tid>` em
`conversation_messages` INSERT) pra atualizar count instantâneo.
- **Recebíveis usa proxy `billed`** — ideal seria query em `financial_records`
com `status='paid'` filtrado por reference_date hoje. Refinamento futuro.
- **`<DailyTimelineStrip />` extração** — Dashboard duplicou inline em vez
de extrair componente compartilhado. Quando aparecer 3º caller (admin
dashboard?), vale a refatoração.
- **AppTopbar plan logic ainda inline** — composable `useTopbarPlanMenu`
existe mas AppTopbar não foi refatorado (evita risco). Quando tocar nele
por outro motivo, dedupe.
- **Cleanup do demo data** — 9 eventos populados local. Não comitar nem
pushar antes de DELETE.
## 🎯 PRÓXIMOS PASSOS (sugestão)
1. Capturar erro literal de enum + corrigir.
2. Decidir commits acumulados (3 sprints sem commitar).
3. WhatsApp realtime (rápido — só pluggar o channel).
4. Avaliar extração `<DailyTimelineStrip />` se for tocar Dashboard de novo.