86311ef305
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>
645 lines
30 KiB
Markdown
645 lines
30 KiB
Markdown
# 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`) → 08–18h 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 08–18) 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 07–20h (preserva range visual original do Dashboard, em vez
|
||
do 08–18 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.
|
||
|