feat(email): adiciona templates React Email e melhora UI admin
Some checks failed
CI/CD Web + Desktop / Detect changes (push) Successful in 7s
CI/CD Web + Desktop / Deploy (VPS Linux) (push) Successful in 3m33s
Quality Checks / Lint, Test and Build (push) Successful in 3m41s
CI/CD Web + Desktop / Deploy Convex functions (push) Has been cancelled

- Cria 10 novos templates React Email (invite, password-reset, new-login,
  sla-warning, sla-breached, ticket-created, ticket-resolved,
  ticket-assigned, ticket-status, ticket-comment)
- Adiciona envio de email ao criar convite de usuario
- Adiciona security_invite em COLLABORATOR_VISIBLE_TYPES
- Melhora tabela de equipe com badges de papel e colunas fixas
- Atualiza TicketCard com nova interface de props
- Remove botao de limpeza de dados antigos do admin

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rever-tecnologia 2025-12-17 11:46:02 -03:00
parent 8546a1feb1
commit 498b9789b5
17 changed files with 1422 additions and 190 deletions

View file

@ -10,7 +10,8 @@ import { DEFAULT_TENANT_ID } from "@/lib/constants"
import { ROLE_OPTIONS, type RoleOption, isAdmin } from "@/lib/authz"
import { env } from "@/lib/env"
import { prisma } from "@/lib/prisma"
import { computeInviteStatus, normalizeInvite, type InviteWithEvents, type NormalizedInvite } from "@/server/invite-utils"
import { buildInviteUrl, computeInviteStatus, normalizeInvite, type InviteWithEvents, type NormalizedInvite } from "@/server/invite-utils"
import { notifyUserInvite } from "@/server/notification/notification-service"
const DEFAULT_EXPIRATION_DAYS = 7
const JSON_NULL = Prisma.JsonNull as Prisma.NullableJsonNullValueInput
@ -27,6 +28,17 @@ function normalizeRole(input: string | null | undefined): RoleOption {
return (ROLE_OPTIONS as readonly string[]).includes(role) ? role : "agent"
}
const ROLE_LABELS: Record<string, string> = {
admin: "Administrador",
manager: "Gestor",
agent: "Agente",
collaborator: "Colaborador",
}
function formatRoleName(role: string): string {
return ROLE_LABELS[role.toLowerCase()] ?? role
}
function generateToken() {
return randomBytes(32).toString("hex")
}
@ -213,5 +225,24 @@ export async function POST(request: Request) {
const normalized = buildInvitePayload(inviteWithEvents, now)
await syncInviteWithConvex(normalized)
// Envia email de convite
const inviteUrl = buildInviteUrl(token)
const inviterName = session.user.name ?? session.user.email
const roleName = formatRoleName(role)
try {
await notifyUserInvite(
email,
name ?? null,
inviterName,
roleName,
null, // companyName - não temos essa informação no convite
inviteUrl
)
} catch (error) {
// Log do erro mas não falha a criação do convite
console.error("[invites] Falha ao enviar email de convite:", error)
}
return NextResponse.json({ invite: normalized })
}