Commit Graph

283 Commits

Author SHA1 Message Date
Leonardo e7c0f6c4f5 MelissaPaciente Fase 6: Tab Financeiro completa + mark paid (mutation que legacy nao tem)
EXTENSAO src/features/patients/utils/patientFormatters.js
- recordStatus(r): pago / vencido (paid_at NULL && due_date < hoje) / pendente
- RECORD_STATUS_LABEL map
- fmtPaymentMethod(v): PIX/Cartao/Dinheiro/Boleto/Transferencia/Convenio
  cobrindo variantes pt-br + camelCase

EXTENSAO src/features/patients/composables/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 via _lastPatientId. Retorna {ok, error?}
- markUnpaid(recordId): reverte (paid_at=NULL) + auto-reload

MELISSAPACIENTE.VUE — script
- Imports: recordStatus, RECORD_STATUS_LABEL, fmtPaymentMethod
- markRecordPaid(r): chama financialHook.markPaid + toast success/error
- revertRecordPaid(r): chama markUnpaid + toast

MELISSAPACIENTE.VUE — Tab Financeiro reescrita (substitui placeholder Fase 1)
- Loading state
- Empty state com CTA "Novo lancamento" (mpa-quick-btn--cta)
- 3 KPIs: Pago / Pendente com proxVenc / Em atraso (cor adaptativa
  vermelho quando > 0, cinza quando 0)
- Header "Lancamentos" com badge count + botao "+ Novo" no canto
- Tabela 6-col responsiva:
  - Vencimento (date mono + relative)
  - Descricao
  - Forma (PIX/Cartao/etc)
  - Valor (mono right-aligned)
  - Status pill colorida (verde pago / vermelho vencido / azul pendente)
  - Action button (pi-check verde marca pago / pi-undo amarelo reverte)
- border-left adaptativa por status
- Mobile: tabela colapsa em cards 2-col 4-row

DIFERENCA DO LEGACY: o PatientProntuario.vue exibe a tabela mas NAO
permite marcar pago/reverter direto dela. MelissaPaciente adiciona essa
acao inline (mutation auto-reload).

CSS: ~190L novos. Padrao Melissa: status pills com color-mix, JetBrains
Mono pra valores, header cell uppercase letter-spacing.

ESLint: 0 errors da minha mudanca.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:57:42 -03:00
Leonardo 8a8d2e05bd MelissaPaciente Fase 5: Tab Agenda completa (KPIs + filtros + grupos por mes + acoes)
EXTENSAO src/features/patients/utils/patientFormatters.js: +2 helpers
- fmtHourShort (HH:MM 24h pt-br) — usado na coluna data dos cards
- fmtDayShort (DOW abreviado pt-br sem ponto) — usado na coluna data

EXTENSAO src/features/patients/composables/usePatientSessions.js
- Novo ref `busy` pra disable de buttons durante mutation
- _lastPatientId guardado internamente pra auto-reload
- Nova funcao `updateStatus(sessionId, novoStatus)` que faz
  supabase.from('agenda_eventos').update({status}) + auto-reload da
  lista de sessoes. 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 por future/past/status (regex)
- agendaAgrupadas computed: agrupa por "Mes de YYYY" DESC
- updateSessionStatus(ev, status, msg): 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):
  Total / Realizadas (% do total) / Faltas (cor adaptativa) / Proxima
- 6 filter chips redondas (cor primary quando active)
- Empty state contextual (sem sessoes vs filtro vazio)
- Grupos por mes com header (label + badge count)
- Cards 3-col: data column (DOW + dia + hora) | main (status tag + chips
  modalidade/duracao + relative + titulo + note 2-line clamp) | actions
  (3 buttons: ok/warn/danger com tooltip + cor adaptativa no hover)
- Mobile: stack date+main em 2 cols; actions full-width abaixo

CSS: ~150L novos. Padrao visual Melissa: data column estilo calendario,
actions hover muda cor por intent (verde realiz / amarelo falta / vermelho
cancel), border-left por status.

ESLint: 0 errors da minha mudanca.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:53:59 -03:00
Leonardo 1278e93b01 MelissaPaciente Fase 4: Tab Prontuario MVP (evolucao via session.observacoes)
O legacy PatientProntuario.vue tem a aba Prontuario como PLACEHOLDER
("Em breve" rich empty state). O MVP entregue aqui SUPERA o legacy: usa
agenda_eventos.observacoes como nota evolutiva — funcional ja hoje sem
precisar de schema novo.

ESTADO + COMPUTEDS adicionados ao MelissaPaciente.vue:
- pronFilter ref ('com-evolucao' default) + PRON_FILTERS com 5 opcoes
  (Com evolucao / Todas / Realizadas / Faltas / Cancelamentos)
- pronSessions computed: filtra sessoes por status/presenca de observacoes
- sessoesComEvolucao computed: count de sessoes com observacoes nao-vazia

TEMPLATE Tab Prontuario (substitui placeholder Fase 1):
- Hint banner explicativo no topo (icon info + "Prontuario em construcao")
- 4 mini-stats em grid: com evolucao / realizadas / faltas / total
- 5 filter chips redondas — selecao default 'com-evolucao' filtra so
  sessoes que tem nota
- Empty states contextuais (sem sessoes / sem evolucao / filtro vazio)
- Lista de sessoes:
  - border-left colorida por status (verde/vermelho/amarelo/cinza)
  - head com data + relative + chips status/modalidade/duracao
  - block "Evolucao" destacado quando tem observacoes (bg medium + border
    primary + label uppercase + texto pre-wrap)
  - "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. Padrao Melissa (chips estilo MelissaTags, border-left
adaptativa, label uppercase nos blocks de evolucao).

ESLint: 0 errors da minha mudanca.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:46:58 -03:00
Leonardo 4fc0e3a02b MelissaPaciente Fase 3: Tab Perfil completa (6 sections stacked + anchors)
EXTENSAO: src/features/patients/utils/patientFormatters.js
- +5 formatters: pickField (compartilhado), 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):
  birthValue, telefone/Alternativo, email/Alternativo, genero, estadoCivil,
  naturalidade, ondeNosConheceu, encaminhadoPor, observacoes, notasInternas
  + 8 campos de endereco + 5 dados adicionais + 4 responsavel.
- groupNames/groupLabel/groupCountLabel pra bloco Origem.
- scrollToProfileSection(key): liga sidebar sub-nav -> scrollIntoView do
  anchor #mpa-perfil-XXX. Em mobile fecha o drawer.

MELISSAPACIENTE.VUE — Tab Perfil reescrita
Diferente do PatientProntuario legacy que usa PrimeVue Accordion (1 painel
aberto por vez), o Melissa nativo mostra os 6 cards stacked com scroll
suave do sidebar sub-nav. Mais legivel em desktop, mais rapido de escanear.

- 1. Informacoes Pessoais: 2-col com Dados de cadastro (nome/data nasc
  com idade inline/genero/estado civil/CPF/RG/naturalidade) + Contato +
  Origem (grupos/tags chips/onde nos conheceu/encaminhado por). tel: e
  mailto: links onde ha valor. Observacoes full-width quando preenchido.
- 2. Endereco: grid 2-col com 8 fields.
- 3. Dados Adicionais: grid 2-col com escolaridade/profissao/parente/grau/
  tel parente.
- 4. Responsavel: 1-col com nome/CPF/tel + observacao block textual.
- 5. Anotacoes Internas: card com hint lock + textblock min-height.
- 6. Sessoes: lista compacta scrollable (max-height 360px) com titulo/
  data/duracao/modalidade chips + tag status.

CSS: ~250L novos pros componentes (mpa-fields/field-row/field-grid-2/
field-block/sess/sess-list). Pattern visual Melissa: cards com label
uppercase, separadores horizontais sutis, links primary, monospace pra
CPF/RG/CEP.

ESLint: 0 errors da minha mudanca.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:43:03 -03:00
Leonardo ab7526b8d7 MelissaPaciente Fase 2: Tab Visao Geral completa (4 KPIs + timeline + msgs + notas)
Reescreveu o placeholder da aba Visao Geral por uma versao 1:1 do
PatientProntuario.vue legado, com estilo Melissa nativo e dados
alimentados pelos composables criados na Fase 1.

NOVO: src/features/patients/utils/patientFormatters.js (~165L)
- Helpers compartilhaveis extraidos do PatientProntuario:
  parseDateLoose, fmtDateBR, fmtDateTimeBR, fmtCurrency, fmtRelative
  (pt-br: "agora"/"ha 5 min"/"em 2 dias"/"ha 3 sem"), sessionDuration,
  calcAge.
- STATUS_LABEL e STATUS_SEVERITY pra mapear status de sessao (cobre
  variantes: realizado/realizada, falta/faltou, cancelado/cancelada).
- tagStyle com contraste auto (luminance WCAG-ish: bg colorido +
  texto preto/branco baseado em luminance < 0.45).
- Sera reutilizado pelas Fases 3-7 e na Fase 8 substitui as funcoes
  duplicadas do PatientProntuario.

EXTENSAO de composables (Fase 1):
- usePatientSessions: novo computed `ultimasAtendidas` (top 6 sessoes
  com status realiz/falt/cancel/remarc pra Timeline). totalRealizadas/
  Faltas/Canceladas refinados pra usar regex (cobre variantes pt-br).
- usePatientFinancial: novo computed `statusFinanceiro` que retorna
  { emDia: bool, proxVenc: record, totalPendente, totalPago, vencidos }
  pra alimentar KPI 02 com info detalhada de status financeiro.

MELISSAPACIENTE.VUE — Visao Geral reescrita:
- 4 KPI cards ricos (substituem os simples da Fase 1):
  - 01 Sessoes: realizadas / total + faltas + canceladas
  - 02 Pagamento: status (Em dia/atraso) + prox venc + cor adaptativa
    (vermelho atrasado / primary ok)
  - 03 Proxima sessao: relative + datetime + modalidade
  - 04 Mensagens: ultima relative + direction + count
- Grid 2-col abaixo (1.4fr / 1fr em >=900px):
  - Timeline coluna esquerda: dots coloridos por status, tags severity,
    chips modalidade + duracao, nota observacoes inline.
  - Coluna direita: Mensagens recentes (4) com border-left in/out +
    meta direction/relative + body 3-line clamp; Notas e observacoes
    em card papel com label uppercase e icone lock.
- Removeu kpiEmAberto/Atrasado nao usados (statusFinanceiro encapsula).

CSS: ~280L novos pros componentes (KPIs ricos, panel base, empty rich,
timeline, mensagens, notas). Mantem o pattern visual Melissa.

ESLint: 0 errors da minha mudanca.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:31:36 -03:00
Leonardo df61cc4d99 MelissaPaciente Fase 1: foundation (5 composables + skeleton 7 tabs + slug paciente)
Inicio do port do PatientProntuario.vue (3593L Dialog) pra Melissa nativo.
Plano em 8 fases — esta entrega cobre apenas a Fase 1 (foundation).
PatientProntuario continua intocado nos 4 callsites (TherapistDashboard,
MelissaAgenda, MelissaPacientes, PatientsListPage); migration acontece
nas fases 2-8.

5 COMPOSABLES NOVOS em src/features/patients/composables/
- usePatientDetail.js (108L): patients + groups + tags
- usePatientSessions.js (83L): agenda_eventos + computeds proxima/ultima/totais
- usePatientFinancial.js (82L): financial_records + computeds totalRecebido/Aberto/Atrasado
- usePatientMessages.js (64L): conversation_messages + computeds recentes/totalIn/Out
- usePatientDocuments.js (70L): documents + computeds total/Bytes/tiposCount

Cada composable encapsula a query original do PatientProntuario.vue +
adiciona computeds derivados. Reutilizaveis em outros lugares no futuro
(dashboards, relatorios, etc).

MELISSAPACIENTE.VUE NOVO (1190L) em src/layout/melissa/
- Prefixo CSS .mpa-*. Chrome glass + drawer mobile + right: max(...) >=1024px
  (mesmo padrao MelissaAgendador/Negocio).
- Header: avatar + nome + ageLabel + pronomes + Tag status/convenio +
  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 com 4 cards: Acoes Rapidas / Navegacao 7 tabs / Sub-nav Perfil /
  Vinculos (chips grupos+tags).
- Main: 7 tabs (Visao Geral / Perfil / Prontuario / Agenda / Financeiro /
  Documentos / Conversas). Visao Geral ja mostra 4 KPIs reais via composables.
  Outras 6 abas com placeholders "Em desenvolvimento — Fase X".

MELISSALAYOUT.VUE
- Import MelissaPaciente.
- SECOES.paciente entry novo.
- 'paciente' adicionado ao MELISSA_NON_CONFIG_SLUGS.
- Render condicional com :patient-id="String(route.query.id || '')"
  — navegacao via /melissa/paciente?id=xxx.

ESLint: 0 errors da mudanca. 2 errors pre-existentes em MelissaLayout
(duplicate key 'financeiro' L242, empty block L1130) — nao toquei essas
linhas. PatientProntuario tem outros pre-existentes nao tocados.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:23:48 -03:00
Leonardo f3f0d831d2 Melissa: preview teleport 3-way no Agendador/LinkExterno + chrome 6 paginas
PADRAO PREVIEW 3-WAY (mobile/sidebar/floating)
- Replica o pattern do MelissaNegocio em MelissaAgendador e MelissaLinkExterno.
- Mobile: preview teleporta pro topo do main, acima de tudo (diferente do
  Negocio que vai pro drawer).
- Mid-desktop (1024-1339): teleporta pro fim da sidebar inline.
- Wide-desktop (>=1340): painel flutuante glass fora do fake dialog,
  ancorado a +14px do right edge da .X-page com width 320px.

MELISSAAGENDADOR (.mag-page)
- Importa AgendadorPreview (componente legacy do ConfiguracoesAgendadorPage).
- isWideDesktop ref + matchMedia('(min-width: 1340px)') + previewTarget computed.
- 3 placeholders + Teleport com card mag-w--side mag-w--preview.
- Adiciona right: max(6px, min(50%, calc(100% - 1006px))) em .mag-page no
  @media >=1024px (necessario pra abrir espaco pro floating).

MELISSALINKEXTERNO (.ml-page)
- Restruturacao: sidebar (Como funciona / Boas praticas) movida da DIREITA
  pra ESQUERDA + mobile drawer pattern (botao Menu, Teleport, transitions,
  backdrop) espelhando MelissaAgendador.
- 3-way teleport do preview com placeholders nos 3 alvos.
- ml-side ganha width 320px + scroll proprio.
- Right rule + floating preview CSS.

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 e busca info via mesma edge function que o publico
  (get-intake-invite-info), watch refetcha quando token rotaciona.
- Sem token ou sem dados, fallback gracioso pra placeholders ("Profissional"
  + iniciais).

CHROME EM 6 PAGINAS TABULARES (sem preview)
- Apenas o right: max(6px, min(50%, calc(100% - 1006px))) no @media >=1024px,
  fazendo a janela ficar do mesmo tamanho do MelissaAgendador.
- MelissaCadastrosRecebidos (.mcr), MelissaRecorrencias (.mr), MelissaGrupos
  (.mg), MelissaTags (.mt), MelissaCompromissos (.mc), MelissaMedicos (.mm).
- +9 a 12 linhas por arquivo. Cada um nao tinha @media >=1024px ainda.

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.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:08:56 -03:00
Leonardo 558922d1a5 log: sessao Melissa cfg-* nativas + temas + cronometro DB
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 00:00:24 -03:00
Leonardo 9966b5f175 Melissa: paginas nativas cfg-* + temas + textos com fundo + drawer WA
CHROME COMPARTILHADO + 18 PAGINAS NATIVAS
- MelissaConfigPage: chrome unico (header, drawer mobile, sidebar com Configuracoes
  + FAQ slot, main com Suspense). Replica fake-dialog right rule e fica flush
  com o config-aside global.
- 18 wrappers finos (~25 linhas cada): cfg-precificacao, cfg-descontos,
  cfg-excecoes, cfg-convenios, cfg-wa, cfg-wa-pessoal, cfg-wa-oficial,
  cfg-wa-templates, cfg-conversas-tags/autoreply/optouts/sla/bots,
  cfg-lembretes, cfg-creditos-wa, cfg-sms, cfg-email-templates,
  cfg-recursos-extras, cfg-recursos-extras-extrato, cfg-auditoria.
- Cada wrapper usa defineAsyncComponent + Suspense pra evitar race com
  tenantStore no boot (loading travado em alguns chooser-style pages).
- MelissaLayout: imports + SECOES + MELISSA_NON_CONFIG_SLUGS + render
  conditions atualizados pra cobrir os 18 slugs.

PAGINAS LEGADAS DETECTAM CONTEXTO MELISSA
- ConfiguracoesWhatsappChooserPage, WhatsappPage, TwilioWhatsappPage,
  SmsPage, RecursosExtrasPage, EmailTemplatesPage, AddonsExtratoPage,
  AgendadorPage, ConversasAutoreplyPage: route.startsWith('/melissa')
  decide se router.push vai pro slug Melissa ou /configuracoes legado.
- Anchors <a href="/configuracoes/..."> (que recarregavam pagina e
  vazavam o usuario do Melissa) trocados por RouterLink context-aware.
- MelissaAgenda.goSettings agora vai pra /melissa/agenda-config.

PERSONALIZAR > TEMAS
- melissaThemes.js: catalogo Freud/Klein/Jung (wallpaper + cor primaria
  + preset Lara/Nora + surface).
- Toggle de tema aplica tudo de uma vez; persistido em melissa_prefs.themeName.
- Boot resolve themeName -> imagem via fetch + data URL (sem guardar
  data URL gigante no DB).
- onCustomFileChange/onClearBg invalidam themeName quando user mexe no bg.

PERSONALIZAR > FUNDO NOS TEXTOS
- Pref textBgEnabled em melissa_prefs.
- MelissaHeroClock: prop textBg envolve relogio/data/saudacao/resumo
  em <span class="hero-text"> que ganha bg branco/preto 60% + borda
  + padding + radius quando o toggle esta on.
- Vars --m-hero-text-bg / --m-hero-text-border flipam com light/dark.

TOP + DOCK COM GRADIENT HORIZONTAL
- Var --m-band: preto 80% (dark) / branco 80% (light).
- .melissa-topbar-band: gradiente cor->transparente (right->left) atras
  dos botoes do topo.
- .melissa-dock: gradiente cor->transparente (left->right) atras dos pins.

MELISSANEGOCIO ABSORVE MINHA EMPRESA
- Adiciona logo upload + preview "cartao de visita" (computeds
  enderecoLinhas/redesValidas/temDados/logoDisplay + redeIcon helper).
- Normaliza dados legados do cfg-empresa: redes_sociais.{rede} virou {name}.
- Preview teleporta entre 3 destinos baseado no viewport:
  mobile -> drawer; mid-desktop -> sidebar; wide-desktop (>=1340px) ->
  painel flutuante FORA do fake dialog (ancora no right edge + 14px gap,
  altura segue conteudo, header alinhado com header do dialog).
- Remove cfg-empresa de melissaConfigGrupos.js + COMPONENT_MAP do
  MelissaConfiguracoes; grupo "Empresa & Plataforma" -> "Plataforma".

CRONOMETRO -> SESSAO AGENDADA
- MelissaCronometro emite session-end ao parar com paciente selecionado
  (threshold 5s pra ignorar start/stop acidental).
- MelissaLayout.onCronometroSessionEnd busca agenda_eventos do paciente
  no dia (tipo='sessao'), pega o mais recente e grava em
  extra_fields.cronometro_duracao_seg + cronometro_parado_em.
- Toast: sucesso ("X min salvos") ou warn ("sessao nao encontrada").

CONVERSATIONDRAWER WHATSAPP-LIKE
- Nova imagem whatsapp-bg.jpg (renomeada de hash random) usada como
  tile (380px) no .cd-msgs.
- Light: bege #efeae2 + multiply blend.
- Dark: #0b141a + camada 78% sobre o doodle.
- Bubbles WA-style (verde out / branco-dark in com tails) ja existiam.

EXTRATO RECURSOS EXTRAS
- Filtros 2-por-linha em Melissa (vs 1/4 no /configuracoes).
- Cards de Resumo teleportam pro #cfg-page-side em Melissa
  (1-col empilhado no drawer; 4-col inline no /configuracoes).
- Botoes de exportar com flex-1 distribuidos em uma unica linha em
  desktop, wrap no mobile.
- DataTable scrollable em ambos os layouts.

OUTROS AJUSTES MENORES
- Cfg-conversas-autoreply: dias semana 4-cols em Melissa (vs 7-cols
  no /configuracoes).
- Cfg-creditos-wa: 1/2 por linha (vs 1/2/4) em Melissa.
- Cfg-recursos-extras: pacotes 1/2 (vs 1/2/4); "Em breve" 1-col.
- WhatsAppPage aba Templates: guia de formatacao teleporta pro side
  drawer em Melissa, deixando textareas full-width.
- ConfigPage chrome agora tem #cfg-page-actions target pros Teleport
  de acoes (refresh button etc).
- Imagens renomeadas em src/assets/themes/ (freudwebp/melainewebp/
  jungwebp.webp) e src/assets/whatsapp-bg.jpg.
- JoditTextEditor.vue novo (wrapper Jodit generico, sem features de email).
- MelissaConfigList.vue novo (lista compartilhada de configs pro drawer).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 23:48:18 -03:00
Leonardo cc7841bd1f MelissaConversas: a11y + perf tagsForThread + DRY (channelMeta + KANBAN_COLUMNS shared)
A11y no parent:
- aria-label em botoes icon-only do header (Recarregar dinamico, Buscar
  compact, Close); tooltip vira title que SR ignora
- aria-hidden=true em icones decorativos (header title, search input,
  subheader info-circle, kanban col head, empty state, button icons)
- aria-busy reativo no mw-col__body durante loading
- aria-label dinamico no count do kanban ("3 conversas em Urgente")
- aria-expanded + aria-controls no menu mobile button
- aria-label no input de busca
- role=note no subheader explicativo
- :inert="(drawerOpen && isMobile) || null" no <section class="mw-page">
  — focus trap real: drawer aberto torna conteudo de fundo inerte
  (boolean attr via || null pra Vue 3.4 serializar correto)

A11y no Sidebar:
- aria-hidden=true em todos icones decorativos restantes (filter title
  icons, list/bell/user/user-minus, channel icons, filter-slash, etc)

Perf — tagsForThread cacheado:
- Antes era chamado in-template (2x por card, recriava array a cada
  render). Agora tagsByThreadKey computed Map: lookup O(1) por card,
  recompute so quando threadTagsMap ou tagById muda. EMPTY_TAGS frozen
  evita criar arrays novos pra threads sem tags.

DRY — channelMeta + KANBAN_COLUMNS shared:
- src/utils/channelMeta.js (novo): CHANNEL_OPTIONS frozen + channelIcon
  + channelLabel. Antes channelIcon estava em 3 lugares (parent, Sidebar,
  Card); CHANNEL_OPTIONS em 2 (parent, Sidebar). Agora 1.
- useConversations.js: exporta KANBAN_COLUMNS frozen (metadata canonica:
  key + label + icon + color). Antes parent+Sidebar tinham copias locais
  de 8 linhas cada + composable tinha KANBAN_ORDER separado. Agora
  KANBAN_ORDER deriva de KANBAN_COLUMNS.

Drift eliminado: 3 fontes -> 1 pra channelIcon, 2 -> 1 pra
CHANNEL_OPTIONS, 2 -> 1 pra KANBAN_COLUMNS (KANBAN_ORDER ainda interno
ao composable mas derivado).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:37:46 -03:00
Leonardo 250e946084 MelissaConversas: refator + extracoes + migracao Tailwind
useConversations: debounce 300ms no realtime load (sem isso, clinica
ativa fazia SELECT 500 por mensagem); expose currentUserId no return
(antes SFC + composable faziam 2 round-trips a auth.getUser); cleanup
do timer no unsubscribeRealtime.

MelissaConversas: bug fixes de loading
- reloadThreadTags lê de threads.value (universal, nao filtered) — antes
  tags piscavam a cada flick de filtro
- watch(threads) com debounce 200ms substitui watch(filteredThreads.length)
  — antes recarregava todas as tags em cada char digitado
- Promise.all no mount sem race com currentUserId (reloadThreadTags
  removido daqui — vem via watch automatic)
- watch drawer.isOpen: await load() antes (antes load+reload em paralelo
  liam threads velhas)
- watch tenantStore com token monotonico (race A→B→A)
- supabase.auth.getUser local removido (usa currentUserId do composable)

Extracoes:
- MelissaConversasSidebar.vue: aside col-1 (alerta unlinked + 4 grupos
  de filtros + footer "Limpar filtros" com Vue Transition). filters
  passado como prop e mutado direto. KANBAN_COLUMNS/CHANNEL_OPTIONS/
  channelIcon/hasActiveFilters/clearAllFilters movidos pra dentro.
  Tailwind nas bases; state modifiers .is-active/.is-warn/.is-danger/
  .is-{red,amber,blue,emerald} ficam scoped (cores fixas por status).
- MelissaConversasCard.vue: card do kanban (head/msg/tags/foot).
  channelIcon/truncate/contactLabel/fmtRelative/assigneeLabel movidos.
  aria-label, aria-pressed, aria-hidden em icones decorativos.
  Tailwind no template; .is-mine do assignee fica scoped.

Tailwind no resto do parent: containers (.mw-page + animation), header
(.mw-page__head/title/count/unread/actions), search (.mw-search* +
--xl-only via max-[1279px]:hidden), close/head-btn/menu-btn (incluindo
--compact-only e --mobile-only via hidden + max-[XXX]:grid/inline-flex),
subheader, body/main/kanban/col/col__head/title/count/body/empty,
mobile drawer + backdrop. 2 media queries inteiras eliminadas
(@media max-width 1279/1023). State modifiers de kanban color
(.mw-col.is-{color}) ficam scoped — 12 regras com cores fixas RGB
seriam ruidosas inline. Cross-teleport :deep(.mw-side*) preservado.

MelissaConversas: 1293 -> 465 linhas (-828, -64%)
  script: 198 -> 195 (logica essencial preservada)
  template: 278 -> 143 (49% reducao via componentizacao)
  style: 761 -> 99 (87% reducao — so keyframes, kanban color states,
                     scrollbars, cross-teleport :deep, Vue Transitions)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:51:05 -03:00
Leonardo ef3e160b36 MelissaAgenda: migra CSS pra Tailwind + extrai SearchPopover/ActionsPopover + fixes de smell
CSS migration (Tailwind v4 com max-[1023px]:/max-[1279px]: arbitrarios pra preservar pixel-perfect):
- Containers/layout: ma-page, ma-page__head/__title/__actions, ma-close, ma-head-btn, ma-body, ma-menu-btn, ma-mobile-drawer*
- Mini-calendar: weekdays/grid/day/dots/dot bases (state modifiers .is-feriado--* ficam em CSS por usarem color-mix por tipo)
- Aside: ma-side, ma-search*, ma-pat* (avatar/info/name/sub/novo/kebab), ma-act-btn*, paginator
- Toolbar: ma-cal*, ma-cal__nav*, ma-cal__btn (versao ghost + bug pre-existente da definicao duplicada preservado), ma-cal__icon, ma-cal__view*
- Stats/Sessions/Filter chip/Loading/Dock actions: bases full-Tailwind, state modifiers ficam em CSS
- Patient banner + All sessions: bases + grid responsivo via max-[640px]:[grid-column:N] arbitrarios

Extracoes:
- MelissaAgendaSearchPopover.vue: Cmd+K busca de toolbar (datas + paciente). Token monotonico + invalidacao em early returns + cleanup no @hide do Popover.
- MelissaAgendaActionsPopover.vue: popover Acoes mobile (<xl) com SelectButtons + 4 botoes de bloqueio. v-model:calendar-view/only-sessions/time-mode + emit bloqueio.

Fixes acionaveis (smells previamente listados):
- #2 null-safety em M.feriados/workRules (fallbacks pra modo standalone)
- #3 race em searchEventosByText (token monotonico contra out-of-order resolution)
- #5 cleanup _patClickTimer em onBeforeUnmount
- onHistoricoOpen valida inicio_em/fim_em antes de construir startH/endH (evita NaN propagation)
- onPacientesPageChange ignora clicks durante loading (evita resolucao fora de ordem)
- ESC no search popover limpa state via @hide handler centralizado
- fcEvents em 1 passada (for loop) em vez de filter().filter().filter().map() — 4x mais rapido em listView mensal
- pacientesIndex Map O(1) substitui 2 .find() sequenciais + cache extra pra fetch on-demand de patient (resolve dock/banner sumindo silenciosamente em clinicas >1k)
- Bloqueio buttons :disabled quando M=null (standalone)
- Teleport to=.melissa-dock guard com v-if M (evita warn em standalone)
- Dedup em flight de getSessionCounts (Set _sessionFetchInflight)

MelissaAgenda: 4181 -> 2851 linhas (-1330, -32%)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:37:59 -03:00
Leonardo 95b2535d3d MelissaLayout: extrai Settings/Hero/Timeline + composables wallpaper/toques + push-back veil perf
- MelissaSettingsPanel.vue: painel Personalizar (Plano de Fundo, Relogio & Som, Tema com preset Lara/Nora)
- MelissaHeroClock.vue: relogio gigante + saudacao + cronometro + resumo do dia
- MelissaTimelineHoje.vue: timeline horizontal (lg+) e vertical (mobile) com eco/cursor agora
- useMelissaWallpaper(): bgUrl/overlayOpacity/bgImageOpacity + onFileChange/clearBg + photoStyle/defaultBgStyle
- useMelissaToques(): toqueTermino + testarToque (preferencia, nao instance state do cronometro)
- Push-back perf: filter:blur animado no .win11-summary substituido por veil unico com backdrop-filter
  (1 backdrop pass por frame em vez de N glass-panels re-blurados; will-change + contain:strict +
  transform/opacity GPU-friendly; 60fps em mobile)

MelissaLayout: 4114 -> 2861 linhas (-1253, -30%)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:37:24 -03:00
Leonardo 63340d1226 MelissaMenu: label Conta + remove modo escuro + preset migra pra Personalizar
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:37:05 -03:00
Leonardo 27b5bbed6f MelissaPerfil mobile: drawer "Menu Perfil" ganha o menu de configs no topo
Refator (entendi corretamente agora): o drawer da pagina deve
PERSISTIR em mobile (botao "Menu Perfil" abre um slide-in da
esquerda com a info contextual). O que muda e que dentro do drawer,
no topo, tambem aparece o MENU GLOBAL DE CONFIGURACOES — em vez
de ficar fixado na lateral em desktop e desaparecer em mobile.

MelissaLayout:
- @media (max-width: 1023px) esconde .melissa-config-aside-host
- Reseta --m-config-aside-left pra 6px em mobile (pagina vira full-width)

MelissaPerfil:
- Restaura o drawer slide-in (drawerOpen + toggle/fechar)
- Restaura botao "Menu Perfil" no header mobile
- Drawer scroll wrapper agora tem dois filhos:
  1. .mpr-mobile-drawer__configs com `<MelissaConfigSidebar>`
  2. .mpr-mobile-drawer__contextual com Teleport target da
     sidebar contextual (Sua evolucao + Avatar + Sair)
- Removido o trecho de menu inline no body (que era o approach errado)

Em desktop nada muda — a sidebar global do MelissaLayout continua
fixa na esquerda (296px de left no inset das paginas).

Pendente: aplicar o mesmo pattern (Teleport do MelissaConfigSidebar
pro drawer da pagina, acima do contextual) nas outras 8 paginas.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:07:25 -03:00
Leonardo d1dced242f MelissaPerfil mobile: menu de configs inline no topo (sem drawer)
Refator do menu mobile so no Perfil (validacao do padrao):
- Remove o drawer slide-in da esquerda + backdrop + botao "Menu"/
  "Configuracoes" no header
- Renderiza <MelissaConfigSidebar> INLINE no topo do .mpr-body em
  mobile (.mpr-mobile-config-menu)
- A sidebar contextual (Sua evolucao + Avatar) tambem renderiza
  inline em sequencia, abaixo do menu global
- O main com o form fica abaixo de tudo
- Body em mobile vira flex column + overflow-y: auto (scroll externo
  unico pra toda a pagina)

Drawer state (drawerOpen/toggle/fechar) e Teleport removidos do
JS+template. Em desktop nada muda — MelissaLayout segue renderizando
a sidebar global fixa na esquerda.

Pendente: aplicar o mesmo pattern nas outras 8 paginas de config se
o usuario validar este formato.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:01:34 -03:00
Leonardo 989c5330f8 MelissaLayout: sidebar global de configs em qualquer rota de config
Antes cada pagina nativa de config tinha seu proprio chrome 2-col, e
quando o usuario navegava entre Perfil/Plano/Negocio/Seguranca/Agenda
Config/Bloqueios/Agendador/Pagamento, perdia o contexto do menu.

Agora:
- Catalogo unico em composables/melissaConfigGrupos.js (MELISSA_CONFIG_
  GRUPOS + isMelissaConfigSlug helper)
- MelissaConfigSidebar.vue componente standalone com accordion +
  navegacao via router.push + destaque do item ativo
- MelissaLayout renderiza `<MelissaConfigSidebar>` em qualquer slug
  que esteja em MELISSA_CONFIG_GRUPOS (computed showConfigSidebar)
- CSS var --m-config-aside-left no .win11-root: 296px quando sidebar
  visivel, 6px caso contrario
- Todas as 9 paginas nativas (Perfil, Plano, AlterarPlano, Negocio,
  Seguranca, Bloqueios, AgendaConfig, Agendador, Pagamento) +
  MelissaConfiguracoes ajustam left do inset usando a var

Sidebar tem entrada animada (lift + slide) e usa o pattern do .mcfg-
accordion (head com icone primary + label + desc 2-linhas + badge;
items com hover/active color-mix primary 12-16%).

Proximo passo: limpar o aside redundante interno do MelissaConfiguracoes
+ ajustar MelissaSeguranca pra considerar o aside no min-width 1000.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:50:03 -03:00
Leonardo 7d2307dcf0 MelissaPagamento: pagina nativa 2-col com 6 cards de metodos
Tira "Pagamento" do MelissaConfiguracoes (era embed cfg-pagamento ->
ConfiguracoesPagamentoPage.vue, 580 linhas). Cria a /melissa/pagamento
nativa Melissa.

Sidebar (mpg-side):
- Card "Resumo" — 5 mini stats coloridos por metodo (Pix verde,
  Deposito azul, Dinheiro amarelo, Cartao roxo, Convenio teal),
  com label "Ativo" ou "Inativo" + cor da borda quando ativo
- Card "Como funciona" — FAQ (Agendador / Cobranca WhatsApp / Obs)

Main (1-col, sem grid pq cards expandem dinamicamente quando ativos):
- Pix: tipo de chave (Select 5 opcoes) + chave + nome titular
- Deposito/TED: banco (Select 16 bancos BR) + tipo conta + agencia
  + conta + titular + CPF/CNPJ
- Dinheiro: toggle simples
- Cartao: toggle + instrucao opcional
- Convenio: toggle + lista de convenios (Textarea)
- Observacoes: Textarea livre

Cada card com toggle no head + body que expande quando ativo +
botao "Salvar" proprio (saveCard build payload do subset). Quando
inativo, mostra so "Salvar como inativo" pra persistir o desligar.
flex-shrink: 0 nos cards (mesmo padrao do AgendaConfig — conteudo
varia muito).

Logica espelhada do ConfiguracoesPagamentoPage (tabela payment_settings).
Compativel com /configuracoes/pagamento.

Wire-up:
- MelissaLayout: import + render `<MelissaPagamento>` quando
  secaoAberta === 'pagamento'
- 'pagamento' adicionado em SECOES + MELISSA_NON_CONFIG_SLUGS
- MelissaConfiguracoes: cfg-pagamento removido de COMPONENT_MAP +
  item do grupo Financeiro re-rotulado pra slug 'pagamento' (atalho
  pra pagina nativa)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:31:28 -03:00
Leonardo 6cc094d252 MelissaAgendaConfig: cards com flex-shrink: 0 (altura por conteudo)
Os cards estavam comprimindo (ficando "pequenos") quando o total
ultrapassava a altura do .mac-main. Causa: flex-shrink: 1 (default)
deixa o flex column comprimir antes de engatar overflow-y: auto.

Fix: flex-shrink: 0 nos .mac-w (main e sidebar). Agora cada card
mantem a altura natural do seu conteudo e o .mac-main scrolla
externamente quando o total passa da viewport.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:53:12 -03:00
Leonardo 11201e1e5d MelissaAgendaConfig: cards crescem com conteudo, sem scroll interno
Remove min-height/max-height/overflow-y das cards (sidebar e main)
em desktop. Agora cada card cresce naturalmente conforme o conteudo
muda (alternar "Diferente por dia" na Jornada, expandir slots no
Online, etc). O scroll externo do .mac-main/.mac-side__scroll cuida
da pagina inteira.

Decisao especifica desta tela — Perfil/Negocio/Plano/AlterarPlano/
Bloqueios/Agendador continuam com cap 300+scroll porque o conteudo
deles e mais homogeneo. Aqui o conteudo da Jornada varia bastante.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:51:36 -03:00
Leonardo d49248979a MelissaAgendaConfig: cards do main com altura por conteudo + scroll interno
Aplica o mesmo pattern dos outros (Perfil/Negocio/Plano):
- Em desktop, cada .mac-main > .mac-w ganha min-height: 300px +
  max-height: 100% (do .mac-main).
- Body com flex: 1 + min-height: 0 + overflow-y: auto.

Quando o usuario alterna pra "Diferente por dia" (Jornada), pra
"Personalizar" (Ritmo) ou expande slots (Online), o card cresce ate
o teto do main e depois passa a scrollar internamente em vez de
empurrar os cards seguintes pra fora.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:50:04 -03:00
Leonardo 48a9700aea MelissaConfiguracoes: restaura grupos Conta + Agenda como atalhos pras paginas nativas
Remover os grupos inteiros tirava o caminho de descoberta via sidebar
de Configuracoes. Agora os items continuam listados, mas as keys
apontam pros slugs nativos (perfil/plano/negocio/seguranca + agenda-
config/bloqueios/online-scheduling).

Quando o user clica, selecionar() empurra a rota /melissa/<slug> e o
MelissaLayout troca pra renderizar a pagina nativa correspondente —
MelissaConfiguracoes desmonta porque isMelissaConfigRoute(slug) retorna
false (slug esta em MELISSA_NON_CONFIG_SLUGS).

Resultado: o user encontra os items no Configuracoes (descoberta) e
ao clicar abre a pagina nativa (UX melhor que embed antigo).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:47:36 -03:00
Leonardo cf1fa7e361 MelissaAgendaConfig: pagina nativa 2-col com Jornada + Ritmo + Online
Tira "Agenda" do MelissaConfiguracoes (era embed cfg-agenda ->
ConfiguracoesAgendaPage.vue, 1714 linhas). Cria a /melissa/agenda-config
nativa Melissa.

Sidebar (mac-side):
- Card "Status do setup" — 3 status items clicaveis (Jornada/Ritmo/
  Online) com icone verde se OK ou amber se pendente + resumo
  dinamico + chevron pra ancora
- Card "Como funciona" — FAQ 3-passos (1/2/3) explicando o fluxo

Main (1-col stacked, denso demais pra 50/50):
- Jornada: fuso (timezone Select) + dias da semana (chips toggleaveis)
  + modo igual/diferente (toggle bonito) + horarios (DatePickers timeOnly,
  weekdays + sab + dom separados em modo igual; por dia em modo
  diferente) + pausas (PausasChipsEditor reaproveitado, globais ou
  por dia)
- Ritmo: 5 presets de duracao (30/45/50/60/90 min com gap) + custom
  collapse com 2 DatePickers (duracao + intervalo)
- Online: aviso de slots orfaos (dias com slots mas sem jornada) +
  toggle ativo + tabs de dia + periodos quick actions (Manha/Tarde/
  Noite/Todos/Limpar) + slot chips individuais + info contagem

Cada card com Salvar proprio (saveJornada/saveRitmo/saveOnline). DB:
agenda_configuracoes + agenda_regras_semanais + agenda_online_slots.
Logica de igual/diferente com snapshot preservation, geracao de slots
respeitando jornada+pausas, limpeza automatica de slots orfaos ao
salvar jornada — tudo espelhado do original.

SKIPPED: FullCalendar preview (visite /melissa/agenda real).

Wire-up:
- MelissaLayout: import + render `<MelissaAgendaConfig>` quando
  secaoAberta === 'agenda-config'
- 'agenda-config' adicionado em SECOES + MELISSA_NON_CONFIG_SLUGS
- MelissaConfiguracoes: cfg-agenda removido de COMPONENT_MAP +
  grupo Agenda inteiro removido (Agenda/Bloqueios/Agendador todos
  viraram nativos agora)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:41:26 -03:00
Leonardo 85ebbf334d MelissaAgendador: pagina nativa 2-col com 6 secoes de config
Tira "Agendador Online" do MelissaConfiguracoes (era embed
cfg-agendador -> ConfiguracoesAgendadorPage.vue) e tambem do
MelissaEmbed (era 'online-scheduling' em MELISSA_EMBED_KEYS).
Cria a /melissa/online-scheduling como pagina nativa Melissa.

Sidebar (mag-side):
- Card "Status" — toggle ativo + tag PRO + link publico (com input
  selecionavel + copy + open) + slug personalizado (se entitlement)
  ou upgrade hint
- Card "Configuracoes" — 6 atalhos clicaveis com icones coloridos
  + resumo dinamico de cada secao (scroll suave pra ancora)

Main (50/50 desktop, Textos full-width):
- Identidade Visual: nome + cor (ColorPicker) + 3 uploads
  (logomarca/header/fundo) com auto-save apos upload
- Perfil Publico: endereco + botao "Como chegar" toggle + maps_url
- Fluxo: modo aprovacao (radio cards) + prazo resposta + modalidade
  (SelectButton) + tipos (chips) + duracao + antecedencia
- Pagamento: 3 modos (radio) + metodos visiveis (com payment_settings
  sync) + Pix config + reserva
- Triagem & LGPD: 4 toggles (motivo + origem + verificacao email + lgpd)
- Textos: 3 Editors PrimeVue (boas-vindas + como_se_preparar +
  termos_lgpd condicional) — em row full-width pq sao mais altos

Cada card tem botao "Salvar" proprio (saveCard build payload do
respectivo subset). Aplicam o pattern: min-h 300, max-h 100%, body
overflow-y: auto.

Logica espelhada do ConfiguracoesAgendadorPage (agendador_configuracoes
+ bucket agendador + entitlements). Compativel com /configuracoes/agendador.

Wire-up:
- MelissaLayout: import + render `<MelissaAgendador>` quando
  secaoAberta === 'online-scheduling'
- MELISSA_EMBED_KEYS agora vazio (Melissa nao tem mais embeds)
- 'online-scheduling' adicionado explicitamente em
  MELISSA_NON_CONFIG_SLUGS
- SECOES['online-scheduling'].descricao atualizada
- MelissaConfiguracoes: cfg-agendador removido de COMPONENT_MAP e
  do grupo Agenda (resta so cfg-agenda)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:31:29 -03:00
Leonardo 25444c1f5f MelissaBloqueios: pagina nativa 2-col com nacionais + municipais + bloqueios
Tira "Bloqueios" do MelissaConfiguracoes (era embed cfg-bloqueios ->
BloqueiosPage.vue) e cria a /melissa/bloqueios nativa Melissa.

Sidebar (mbq-side):
- Card "Resumo" — 3 mini-stats coloridos (Nacionais blue, Municipais
  orange, Bloqueios red) + nav de ano (chevron < ANO > )
- Card "Adicionar" — 2 CTAs (Feriado municipal secundario + Novo
  bloqueio primary)
- Card "Como funciona" — FAQ 3-bullets explicando os tipos

Main (50/50 desktop, com Bloqueios full-row abaixo):
- Card Nacionais — read-only (gerado automaticamente), tags Movel
- Card Municipais — CRUD via dialog (nome + data + observacao)
- Card Bloqueios — CRUD via dialog (titulo + datas + horas + obs +
  recorrente). Border-left colorido por tipo (azul/laranja/vermelho).
- Items com data + titulo + observacao inline + acoes (edit/trash)

Cards aplicam o pattern dos anteriores: min-h 300, max-h 100%, body
overflow-y: auto. Bloqueios spans 2-col com .mbq-w--full.

Logica espelhada do BloqueiosPage (composable useFeriados +
agenda_bloqueios). Compativel com /configuracoes/bloqueios legacy.

Wire-up:
- MelissaLayout: import + render `<MelissaBloqueios>` quando
  secaoAberta === 'bloqueios'
- 'bloqueios' sai de MELISSA_CONFIG_ALIASES, entra em
  MELISSA_NON_CONFIG_SLUGS
- SECOES.bloqueios adicionado (icone pi-ban)
- MelissaConfiguracoes: cfg-bloqueios removido de COMPONENT_MAP,
  ROUTE_ALIASES e do grupo Agenda (resta cfg-agenda + cfg-agendador)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:21:44 -03:00
Leonardo 33370018b5 MelissaSeguranca: breakpoint mobile <768px (era <1024px)
Como a pagina e enxuta (so 1 form pequeno + sidebar com info), cabe
bem em tablet portrait. Reduzi o breakpoint mobile pra 768px e
adaptei a formula da largura:

- 768-1012px : full-width (right: 6px)
- 1012-2012px: width fixo 1000px
- >= 2012px  : ~50% do viewport (right: 50%)

Formula: right = max(6px, min(50%, calc(100% - 1006px)))

JS _mqMobile tambem atualizado pra (max-width: 767px).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:10:03 -03:00
Leonardo 3549a977cc MelissaSeguranca: pagina min 1000px de largura no desktop
Antes era right: 50% fixo, o que dava ~512px em viewports 1024-1100
(cramped p/ um form de senha + sidebar 320px).

Agora right = min(50%, calc(100% - 1006px)):
- viewport <  2012: page fixa em 1000px (nao shrink)
- viewport >= 2012: page = 50% (sobra mais espaco no lado direito)

Mobile (<1024px) continua full-width via media query existente.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:07:03 -03:00
Leonardo df7ab9c5a8 MelissaSeguranca: pagina 50% alinhada a esquerda
Troca a centralizacao (left: 25% + right: 25%) por alinhamento a
esquerda: left fica em 6px (do inset base) e right: 50% (push do
edge direito pro meio). Pagina passa a ocupar a metade esquerda
do viewport, encostada na borda esquerda.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:04:10 -03:00
Leonardo a89745f668 MelissaSeguranca: pagina 50% de largura em desktop
Em desktop a pagina ocupa apenas 50% da largura util (left: 25% +
right: 25%), centralizada. Como Seguranca so tem 1 form pequeno
(Trocar senha + sidebar de info), nao precisa de toda a largura
do viewport. Em mobile mantem 100% (override so na media query
>= 1024px).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:03:25 -03:00
Leonardo c605a4f1a2 MelissaSeguranca: card Trocar senha altura por conteudo + scroll y auto
Em desktop o card .mse-w do main (Trocar senha) ganha:
- max-height: 100% (do .mse-main) — nao passa do viewport
- SEM min-height — altura natural por conteudo
- body com flex: 1 + min-height: 0 + overflow-y: auto pra scroll
  interno quando o conteudo (3 inputs + barra de forca + match +
  warning + 2 botoes) precisar de mais espaco que o disponivel.

Diferente da sidebar (que mantem min-h 300 pq pode haver pouca info).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:59:26 -03:00
Leonardo 2ca9cde2ea MelissaSeguranca: pagina nativa 2-col + grupo "Conta" sai inteiro de Configuracoes
Tira "Seguranca" do MelissaConfiguracoes (era embed cfg-seguranca ->
SecurityPage.vue) e cria a /melissa/seguranca nativa Melissa.

Sidebar (mse-side):
- Card "Estado da conta" — email (mono) + tag "Sessão Ativa" pulsando
  + warning amber sobre desconectar todos dispositivos
- Card "Boas praticas" — 4 dicas com bullet colorido (8+ chars,
  evite obvio, encerre sessao publica, nao reuse senhas)

Main:
- Card "Trocar senha" — 3 Password inputs (atual + nova + confirmar)
  + barra de forca 4-segmentos (Muito fraca/Fraca/Boa/Forte) +
  match indicator (check verde / x amber) + warning + 2 botoes:
  "Enviar link por e-mail" (reset por email) + primary "Trocar senha"
- Estado "concluido" com check verde + redirect pro login

Logica espelhada do SecurityPage:
- changePassword: signInWithPassword pra reautenticar + updateUser +
  hardLogout (signOut global + clear sb-* tokens) apos 2.6s
- sendResetEmail: resetPasswordForEmail com redirectTo /auth/reset-password

Wire-up:
- MelissaLayout: import + render `<MelissaSeguranca v-if=secaoAberta=='seguranca'>`
- 'seguranca' sai de MELISSA_CONFIG_ALIASES, entra em MELISSA_NON_CONFIG_SLUGS
- SECOES.seguranca atualizado (label + descricao + duplicado removido)
- MelissaConfiguracoes: cfg-seguranca removido de COMPONENT_MAP +
  ROUTE_ALIASES; grupo "Conta" inteiro removido (Perfil/Plano/Negocio/
  Seguranca todos viraram nativos agora)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:57:27 -03:00
Leonardo 7c0c1b3528 MelissaPlano/AlterarPlano desktop: cards min-h 300 + body scroll
Aplica o mesmo fix do MelissaPerfil/Negocio:
- align-items: start no grid (cells nao stretch p/ row height)
- Cards min-height 300px + max-height 100% (do container)
- .mpl-w__body / .map-w__body com flex: 1 + min-height: 0 +
  overflow-y: auto (scrollbar fina)

MelissaPlano: vale pros 2 cards do main (Recursos / Historico) e
pros 2 cards da sidebar (Plano atual / Resumo) — quando o user
tem features longas ou muitos eventos, scroll interno engata.

MelissaAlterarPlano: aplicado SO na sidebar (Plano atual / Filtros).
Os plan cards do main (.map-plan) ficam fora — sao product cards
com layout proprio (preco grande + 3 CTAs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:51:47 -03:00
Leonardo 5db6000c2c MelissaPerfil/Negocio desktop: cards min-h 300, max-h 100%, body scroll
Em desktop os cards ficavam com altura natural do conteudo, e o
.mpr-main / .mng-main scrollava externamente. Quando o usuario
adicionava redes sociais (ou customs), o card crescia, empurrava a
row do grid e o conteudo novo ficava fora do viewport sem feedback
de scroll claro.

Fix:
- align-items: start no grid (cells nao stretch p/ row height)
- Cada card min-height: 300px + max-height: 100% (do container)
- .mpr-w__body / .mng-w__body com flex: 1 + min-height: 0 +
  overflow-y: auto (scrollbar fina)
- Vale tanto pros cards do main (Identidade/Contato/Bio/Redes etc)
  quanto pros da sidebar (Sua evolucao/presenca + Avatar/Logomarca)
  que tinham o mesmo problema com badges/dicas

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:49:30 -03:00
Leonardo 5a2d24dd99 MelissaAlterarPlano: pagina nativa pra escolha de plano
Substitui o redirect pra /therapist/upgrade (que sai do overlay
Melissa) por uma pagina nativa em /melissa/alterar-plano com o
mesmo chrome 2-col das outras.

Sidebar (map-side):
- Card "Plano atual" — nome destacado em primary box + key + valor
  + status; ou empty state se nao tem plano pessoal
- Card "Filtros" — busca por nome/key/desc + chips Mensal/Anual
- Footer: botao "Voltar pro Meu Plano"

Main:
- Grid responsivo 1/2/3 cols (mobile/md/xl) de plan cards
- Cada card: nome + key (mono) + tag "Atual" se for o plano atual,
  descricao, preco grande (do interval selecionado), CTA primario
  "Escolher mensal/anual" + 2 botoes secundarios (Mensal | Anual)
  cada um mostrando seu preco abaixo do label
- Card destacado com border primary se for o plano atual
- Empty state: filtro vazio com botao "Limpar busca"

Logica:
- preflight: valida sessao + plano + interval + preco ativo + nao ja
  estar nesse plano/intervalo
- choosePlan: se ja tem subscription -> RPC change_subscription_plan
  + update do interval; se nao tem -> insert manual em subscriptions.
  Apos sucesso, emit('goto', 'plano') volta pro MelissaPlano com
  estado fresh.

Wire-up:
- MelissaLayout: import + render `<MelissaAlterarPlano>` com
  @goto="abrirSecao"
- 'alterar-plano' adicionado em SECOES + MELISSA_NON_CONFIG_SLUGS
- MelissaPlano.goUpgrade() agora router.push pra Melissa(secao=alterar-plano)
  em vez de /therapist/upgrade

Espelha o TherapistUpgradePage.vue (subscriptions + plans target=therapist
+ plan_prices + RPC change_subscription_plan), compativel com fluxo legacy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:42:45 -03:00
Leonardo 0c88cc2e72 MelissaNegocio: pagina nativa 2-col com gamificacao + logomarca
Tira "Meu Negocio" do MelissaConfiguracoes (era embed cfg-negocio
-> Negociopage.vue) e cria a /melissa/negocio nativa Melissa.

Sidebar (mng-side):
- Card "Sua presenca" — gamificacao 7 niveis (Cadastro Basico ->
  Excelencia) + barra de progresso + 7 badges (Nomeado, Categorizado,
  Regularizado, Localizado, Acessivel, Identificado, Online) +
  dicas do que falta. Badges/dicas com ancora pra sessao.
- Card "Logomarca" — preview 96x96 (object-fit: contain) + upload/
  remover (bucket 'logos', max 2MB, PNG/SVG/JPG/WebP)

Main (50/50 desktop):
- Identidade: nome_fantasia* + razao_social + tipo_empresa* (Select 8 opcoes)
- Dados Fiscais: cnpj (mask 99.999.999/9999-99) + IE + IM
- Endereco: cep (mask + ViaCEP autofill onBlur) + logradouro + numero
  + complemento + bairro + cidade + estado (Select UFs BR)
- Contato: telefone (mask) + email (placeholder=" ") + site
- Redes Sociais: array com add/remove (name + url)

Validacao: nome_fantasia + tipo_empresa obrigatorios.
URL: /melissa/negocio. Compativel com /account/negocio (mesma tabela
company_profiles + bucket logos).

Wire-up:
- MelissaLayout: import + render
- 'negocio' sai de MELISSA_CONFIG_ALIASES, entra em MELISSA_NON_CONFIG_SLUGS
- SECOES.negocio descricao atualizada
- MelissaConfiguracoes: cfg-negocio removido de COMPONENT_MAP,
  ROUTE_ALIASES e do grupo "Conta" (so resta Seguranca agora)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:38:48 -03:00
Leonardo 6395c4c0b6 MelissaPlano: pagina nativa 2-col com assinatura + recursos + historico
Tira "Meu Plano" do MelissaConfiguracoes (era embed cfg-plano ->
TherapistMeuPlanoPage.vue) e cria a /melissa/plano como pagina
nativa Melissa no padrao das outras 2-col.

Sidebar (mpl-side):
- Card "Plano atual" — nome destacado + valor + status + ciclo
  + proxima renovacao (com badge cancelamento agendado vs auto) +
  descricao do plano
- Card "Resumo" — mini-stats: Recursos / Eventos / Renova-Encerra +
  ID da assinatura
- Footer: botao "Alterar plano" (router.push /therapist/upgrade)

Main:
- Card "Seu plano inclui" — features agrupadas por modulo (a partir
  do prefix antes do . ou _ na key), cada item com check verde +
  key + descricao em 1 linha (ellipsis), grid 1-2 cols
- Card "Historico" — subscription_events com tag de tipo + before
  -> after dos plan_ids + autor (profiles join) + reason + metadata
  (max 50 eventos)

Estados:
- Loading: skeletons na sidebar + main
- Sem assinatura: empty state grande no main com CTA "Ver planos",
  empty compacto na sidebar
- Erro: toast (mesma logica do TherapistMeuPlanoPage)

Wire-up:
- MelissaLayout: import + render `<MelissaPlano v-if=secaoAberta=='plano'>`
- 'plano' sai de MELISSA_CONFIG_ALIASES, entra em MELISSA_NON_CONFIG_SLUGS
- SECOES.plano descricao atualizada (Assinatura, recursos, historico)
- MelissaConfiguracoes: cfg-plano removido de COMPONENT_MAP,
  ROUTE_ALIASES e do grupo "Conta" (continua com Negocio + Seguranca)

Logica de fetch espelhada do TherapistMeuPlanoPage (subscriptions +
plans + plan_prices + plan_features + features + subscription_events
+ profiles), compativel com a /therapist/meu-plano legacy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:31:50 -03:00
Leonardo 56d30b4285 MelissaPerfil: cards Sua evolucao e Avatar com bg --m-bg-medium
Espelha o pattern do MelissaPacientes (.mp-w dentro de .mp-side):
sidebar tem bg --m-bg-soft e os cards .mpr-w--side ganham bg
--m-bg-medium pra destacar com contraste sutil. Antes ambos eram
soft e os cards sumiam contra o fundo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:26:05 -03:00
Leonardo dc57caf534 MelissaPerfil: botao Salvar mostra o texto em mobile
Remove o display: none do span do .mpr-act-btn--primary em mobile.
Salvar e acao primaria importante o suficiente pra ocupar espaco
do label + icone no header.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:24:52 -03:00
Leonardo 9e4421b7ff MelissaPerfil: cards mobile com altura por conteudo
Em mobile cada .mpr-w no main vira flex: 0 0 auto + height: auto +
align-self: stretch. Garante que cada card ocupa exatamente a
altura do seu conteudo sem ser comprimido nem esticado pelo flex
column do .mpr-main.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:24:33 -03:00
Leonardo dad1fd72c2 MelissaPerfil: cards com chrome estilo financeiro (icon-box + sub + body)
Cada card .mpr-w agora segue o mesmo padrao visual do MelissaFinanceiro:
- Head: icon-box 36x36 com bg primary-tint + titulo + subtitulo
- Border-bottom separando head do body
- Body wrappado em .mpr-w__body com padding 14px e gap 12px
- Box-shadow elevando o card sobre o bg da sidebar/main

Subtitulos novos por card:
- Sua evolucao  : Nivel, conquistas e pendencias
- Avatar        : Foto exibida no menu e cabecalho
- Identidade    : Nome, apelido e descricao profissional
- Contato       : WhatsApp e e-mail de login
- Bio           : Apresentacao curta para o seu perfil publico
- Sites e Redes : Site, redes sociais e links customizados

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:22:22 -03:00
Leonardo f2fd2e4722 MelissaPerfil: scroll mobile + ancoras nos badges + email placeholder + 50/50 desktop
1. Mobile scroll fix: .mpr-main ganha min-height: 0 (faltava pra
   permitir shrink dentro do flex column do .mpr-body em mobile, sem
   isso o overflow-y: auto nao engatava).

2. Badges e dicas viraram <button> com @click que rola pra sessao
   correspondente do form (Identidade / Avatar / Bio / Contato /
   Redes). Em mobile o drawer fecha antes do scroll (exceto Avatar,
   que vive na propria sidebar). Cada card .mpr-w ganhou id pra
   ancora (mpr-sec-*).

3. Email readonly recebe placeholder=" " (espaco) — sem ele o
   FloatLabel variant=on ficava em cima do email enquanto o user
   nao tinha foco, pq :placeholder-shown nao aplica.

4. Desktop (>=1024px): .mpr-main vira grid 2 colunas (50/50). Os 4
   cards (Identidade, Contato, Bio, Redes) ficam lado a lado em
   pares. Internal .mpr-grid colapsa pra 1 col nesse modo, e
   .mpr-field--half passa a span 1/-1 — evita ficar cramped em
   metade da largura.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:14:49 -03:00
Leonardo abd4f8f34c MelissaPerfil: pagina nativa 2-col com gamificacao no aside
Tira "Meu Perfil" do MelissaConfiguracoes (era embed cfg-perfil ->
ProfilePage.vue) e cria a /melissa/perfil como pagina nativa Melissa
no padrao das outras 2-col (sidebar + main).

Sidebar (mpr-side):
- Card "Sua evolucao" — gamificacao: nivel atual + barra de progresso
  + XP-to-next + 7 badges (earned/locked) + dicas do que falta
- Card "Avatar" — preview + upload (5MB max) + remover
- Footer: botao "Sair da conta" (com Confirm dialog)

Main:
- Card Identidade: full_name + nickname + work_description (+ outro)
- Card Contato: phone (mask BR) + email read-only
- Card Bio: textarea
- Card Sites e Redes: site/IG/YT/FB/X + customSocials (add/remove)

O que ficou de fora (vs ProfilePage.vue):
- Aparencia (tema/cores) — vive no MelissaConfiguracoes Layout Melissa
- Layout Variant (Rail/Classic/Melissa) — irrelevante dentro do Melissa
- Trocar senha — empurrado pro cfg-seguranca
- Preferencias (idioma/timezone/notifs) — fora de escopo do MVP

Wire-up:
- MelissaLayout: import + render `<MelissaPerfil v-if=secaoAberta=='perfil'>`
- 'perfil' sai de MELISSA_CONFIG_ALIASES, entra em MELISSA_NON_CONFIG_SLUGS
- SECOES.perfil descricao atualizada
- MelissaConfiguracoes: cfg-perfil removido de COMPONENT_MAP, ROUTE_ALIASES
  e do grupo "Conta" (continua com Plano + Negocio + Seguranca)

Logica de load/save espelhada do ProfilePage (auth.user_metadata +
profiles + storage avatars), compativel com a /account/perfil legacy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:06:22 -03:00
Leonardo 44135a961f MelissaConfiguracoes: gap entre os panels do accordion
Adiciona display: flex + flex-direction: column + gap: 8px no
.p-accordion pra os AccordionPanels nao colarem um no outro
quando todos estao fechados.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:53:56 -03:00
Leonardo ac8308f45b MelissaConfiguracoes: desc pode quebrar em ate 2 linhas
Volta -webkit-line-clamp: 2 no .mcfg-grp-desc e
.mcfg-nav-item__desc — descricao quebra em 2 linhas se precisar
ao inves de cortar com ellipsis em 1 linha.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:53:16 -03:00
Leonardo 1b5214c90b MelissaConfiguracoes: titulo + subtitulo de volta no accordion
Restaura label + desc tanto no header do grupo quanto no sub-item,
com altura confortavel (min-height 44px no item). Optimizacoes
mantidas pra evitar lag:

- Sem -webkit-line-clamp (custoso com o backdrop-filter do parent);
  desc 1 linha com text-overflow: ellipsis
- Icone inline (16-18px, sem caixa 32x32 + box-shadow transition)
- Sem transition de color-mix em hover

Hover/active continuam com cor primary (12-16%). Desc no hover/active
ganha tom misturado primary 70% pra ficar legivel sem competir com
o label.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:52:46 -03:00
Leonardo a0948919ef MelissaConfiguracoes: accordion enxuto pra tirar o lag
Continua usando o <Accordion> do PrimeVue, mas DOM/CSS bem mais leves:

- Header: icone inline + label + badge (era icone 36x36 caixa
  centralizada + label + desc 2-linhas + badge)
- Sub-itens: botao denso 1-linha (icone + label, desc vai pro
  title="" como tooltip nativo)
- Removidas transitions de box-shadow e color-mix nos hovers
  (eram custosas com o backdrop-filter blur do parent)
- Removidas as line-clamp 2-linhas em cada item (~30 itens
  abertos = ~30 layouts caros)
- Hover/active dos sub-itens com color-mix(--p-primary-color),
  alinhado com o padrao do MelissaMenu (.mm-foot-item)
- Padding compactado, gap entre items 1px (era 6px)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:49:38 -03:00
Leonardo e912558769 MelissaConfiguracoes: Layout Melissa unificado em 1 pagina
Antes a sidebar tinha 4 items (Aparencia / Plano de fundo / Relogio /
Cronometro), cada um abria uma sessao separada. Agora vira 1 unico
item "Layout Melissa" com os 4 cards stackeados em uma tela so.

- grupos[0].items reduzido pra 1 entrada (key: aparencia, label:
  Layout Melissa)
- INLINE_KEYS so tem 'aparencia' agora
- DEPRECATED_ALIASES adicionado: /melissa/fundo, /melissa/relogio,
  /melissa/cronometro -> 'aparencia' (URLs antigas continuam abrindo
  a tela unificada)
- Template: 4 v-if/v-else-if -> 1 <template v-if> com os 4 .mcfg-w
  como siblings
- MelissaLayout SECOES.aparencia label: "Configuracoes do Melissa"
  -> "Layout Melissa" (icon palette)
- MelissaMenu CATEGORIAS aparencia label idem

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:44:24 -03:00
Leonardo 66441c1744 MelissaMenu: busca tambem casa pelo nome da categoria
Se o termo bate com o label da categoria (ex: "financeiro"),
inclui todos os sub-itens dessa categoria nos resultados. Antes
so casava por label do sub-item.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:38:05 -03:00
Leonardo 9c6d77ec56 MelissaMenu: busca no topo do mm-side (estilo rail)
Input com pi-search a esquerda + botao limpar a direita. Quando
query tem texto, substitui a lista de categorias por uma lista
flat de sub-itens que casam (com nome da categoria a direita
como breadcrumb). Click no resultado dispara clicarSubItem (mesma
logica de navegacao) e limpa o termo. Empty state pra "nenhum
resultado".

Visual segue mm-aside: bg --m-bg-soft, border --m-border, focus
border --p-primary-color. Hover dos resultados usa color-mix
primary 12% (mesmo pattern do .mm-foot-item).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:33:58 -03:00
Leonardo 0dd070c6a5 Revert: divisor degrade entre .mm-cat
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:32:09 -03:00