Commit Graph

7 Commits

Author SHA1 Message Date
Leonardo 4441661f62 Toast system_alert: agregar no catch-up pra não empilhar enxurrada
Bug: acumulando N system_alert não-lidas, o refreshAndMaybeAlert
(mount / visibilitychange / polling 60s) disparava N toasts de uma vez.
Comum após recarregar a página com alertas pendentes do último teste.

Fix: no catch-up, mostra só a notif mais recente, com sufixo "+N
outros alertas no sino" no detail se houver múltiplas. As demais são
marcadas no alertedIds pra não redisparar — continuam visíveis no
sininho/drawer com badge.

Eventos novos via Realtime seguem aparecendo individualmente (fluxo
normal — o usuário está online vendo chegar).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:03:24 -03:00
Leonardo 6db06abfc2 Toast system_alert ganha botão de ação com deeplink
Novo <Toast group="system-alerts"> no AppLayout com template custom
(vive no bloco global — persiste em qualquer layout/rota). Renderiza:
- Ícone de alerta + título em bold
- Detail em texto menor com opacity
- Botão com deeplink quando payload.deeplink existe, severity danger

Label do botão inferido do deeplink:
- /configuracoes/creditos-whatsapp → "Ir pra loja"
- /configuracoes/whatsapp-pessoal  → "Ver conexão"
- /configuracoes/whatsapp-oficial  → "Ver canal oficial"
- outros → "Abrir" (ou payload.actionLabel se vier explícito)

Clique navega via router.push se é path interno, senão
window.location.href. Toast continua sticky (24h) + closable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:00:18 -03:00
Leonardo 5c50db6704 Notifications: fallback de polling + catch-up ao focar a aba
Realtime em ambiente self-hosted às vezes perde eventos (WebSocket
desconecta silenciosamente, JWT expira, sleep do SO, etc). Sem fallback,
system_alert chega no DB mas toast nunca dispara — usuário só vê ao
relogar ou recarregar.

Três caminhos complementares agora:
1. Realtime (instantâneo, quando funciona)
2. visibilitychange — ao voltar pro foco da aba, recarrega notificações
   e dispara toast pras system_alert não-lidas ainda não exibidas
3. Polling a cada 60s como redundância

Set alertedIds (in-memory por sessão) evita toast duplicado quando dois
caminhos entregam a mesma notif. Seed inicial marca notifs já lidas/
arquivadas no mount pra não disparar retroativamente.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 09:54:48 -03:00
Leonardo 881fa16c27 Fluxo de reativação de canal WhatsApp + alerta toast sticky + notify owner
Cadeia de fixes descoberta ao testar o heartbeat 6.1 num tenant que migrou
de Evolution → Twilio e precisava voltar pro Evolution.

1. RLS notification_channels (migration 20260423000003)
   - Policy antiga tinha `deleted_at IS NULL` como primeira condição AND,
     bloqueando leitura de soft-deleted até pro próprio owner/saas_admin.
   - Isso fazia o chooser nunca detectar "canal antigo pra reativar".
   - Relaxada: owner/membro/saas_admin leem inclusive soft-deleted.
   - Filtro de deleted_at fica no código aplicativo (todos os queries já
     filtram explicitamente quando querem apenas ativos).

2. Edge function reactivate-notification-channel (nova)
   - Espelho da deactivate existente; service_role bypass RLS.
   - Aceita {channel_id} OU {tenant_id + provider}.
   - Autoriza saas_admin OU membro ativo do tenant.
   - Garante exclusividade: soft-deleta qualquer OUTRO canal ativo do
     mesmo tenant+channel.
   - Reseta metadata.first_unhealthy_at + connection_status=disconnected
     (heartbeat começa do zero).

3. SaasWhatsappPage (/saas/whatsapp)
   - loadChannel busca soft-deleted como fallback quando não tem ativo.
   - saveCredentials detecta soft-deleted e chama reactivate edge,
     depois atualiza credentials+display_name.
   - Banner âmbar "Canal configurado anteriormente" + botão vira
     "Reativar e salvar".

4. ConfiguracoesWhatsappPage tenant (/configuracoes/whatsapp-pessoal)
   - loadCredentials busca soft-deleted como fallback.
   - Card âmbar "WhatsApp Pessoal foi usado anteriormente" com botão
     "Reativar WhatsApp Pessoal" em vez de mostrar apenas "chame o suporte".

5. ChooserPage (/configuracoes/whatsapp)
   - Fix bug lateral: comparava activeProvider === 'evolution' (template)
     com 'evolution_api' (DB) — card nunca mostrava estado ativo. Agora
     normaliza via computed activeProviderKey.
   - softDeletedByProvider map carregado no mount; cards que têm row
     soft-deleted mostram "Reativar" em vez de "Ativar".
   - handleChoose chama reactivate edge antes de goSetup se detecta
     soft-deleted do provider escolhido.

6. whatsapp-heartbeat-check: notifica owner do channel + admins
   - notifyChannelStakeholders substitui notifyTenantAdmins.
   - Set dedupa o owner_id do channel + clinic_admin + tenant_admin.
   - Em tenant solo: 1 notificação; em clínica com canal de terapeuta
     específico: terapeuta (owner) + admin recebem; em clínica com canal
     do próprio admin: 1 (owner=admin).

7. Toast frontend para system_alert
   - notificationStore.subscribeRealtime aceita callback onInsert.
   - useNotifications registra callback que dispara toast PrimeVue
     (severity error, life 24h, closable) para type='system_alert'.
   - Usuário precisa fechar manualmente — alerta crítico de infra
     não pode sumir sozinho.

Cron heartbeat ativado em runtime local via cron.schedule()
(não vai neste commit — é config de ambiente, não migration).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 09:21:29 -03:00
Leonardo 53a4980396 Correcao Sidebar Classico e Rail, Correcao Layout, Ajuste de Breakpoint para Tailwind, Ajuste AppTopbar, Ajuste Menu PopOver, Recriado Paleta de Cores, Inserido algumas animações leves, Reajuste Cor items NOVOS da tabela, Drawer Ajuda Corrigido no Logout, Whatsapp, sms, email, recursos extras 2026-03-24 21:26:58 -03:00
Leonardo a89d1f5560 Copyright, Financeiro, Lançamentos, aprimoramentos de ui 2026-03-21 08:05:40 -03:00
Leonardo 66f67cd40f Layout 100%, Notificações, SetupWizard 2026-03-17 21:08:14 -03:00