feat(c6): notificações e push — Web Push VAPID, badge dinâmico, Share API

FR-6.1/6.2: Sandra recebe push quando pedido entra em pending_approval;
Rafael recebe quando pedido é aprovado ou recusado. Service worker registrado
em background (PWA-ready via public/sw.js).

FR-6.3: Badge na Topbar busca GET /notifications/pending-count (supervisores
veem count de pending_approval; reps veem 0). Intervalo de 30s.

FR-6.4: Botão Compartilhar no OrderDetailPage para pedidos approved/invoiced
(apenas reps). Usa navigator.share() com texto formatado para WhatsApp.

Infra: modelo PushSubscription (Prisma), NotificationsModule (subscribe/
unsubscribe/pending-count + PushService VAPID), VAPID keys em .env,
integração no OrdersService (create → supervisores, approve/reject → repId).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-28 12:31:13 +00:00
parent e3587e680a
commit a1a852c44d
22 changed files with 522 additions and 18 deletions

View File

@@ -45,6 +45,14 @@ OTEL_TRACES_SAMPLER=parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARG=1.0
SENTRY_DSN=
# Web Push VAPID (C6) — gerar com: node -e "const wp=require('web-push'); const k=wp.generateVAPIDKeys(); console.log(k)"
# Em prod: Vault injeta. Em dev: opcional — push fica desabilitado se vazio.
VAPID_PUBLIC_KEY=
VAPID_PRIVATE_KEY=
VAPID_CONTACT=mailto:noreply@sar.dev
# Chave pública VAPID para o front-end (mesmo valor de VAPID_PUBLIC_KEY)
VITE_VAPID_PUBLIC_KEY=
# Feature flags (DEV: bypass. Prod: GrowthBook self-host)
GROWTHBOOK_API_HOST=http://localhost:3100
GROWTHBOOK_CLIENT_KEY=