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

@ -0,0 +1,151 @@
import * as React from "react"
import { Button, Heading, Hr, Section, Text } from "@react-email/components"
import { RavenEmailLayout } from "./_components/layout"
import { EMAIL_COLORS } from "./_components/tokens"
export type SlaBreachedEmailProps = {
ticketNumber: string
ticketTitle: string
breachedAt: string
ticketUrl: string
}
function formatDate(dateStr: string): string {
try {
const date = new Date(dateStr)
return new Intl.DateTimeFormat("pt-BR", {
dateStyle: "long",
timeStyle: "short",
}).format(date)
} catch {
return dateStr
}
}
export default function SlaBreachedEmail(props: SlaBreachedEmailProps) {
const { ticketNumber, ticketTitle, breachedAt, ticketUrl } = props
return (
<RavenEmailLayout title="SLA estourado" preview={`Chamado #${ticketNumber} estourou o SLA`}>
<Section style={{ textAlign: "center", margin: "24px 0" }}>
<div
style={{
display: "inline-block",
width: "64px",
height: "64px",
backgroundColor: "#fee2e2",
borderRadius: "50%",
lineHeight: "64px",
fontSize: "28px",
border: "1px solid #ef4444",
}}
>
&#128680;
</div>
</Section>
<Heading style={{ margin: "0 0 12px 0", fontSize: "26px", fontWeight: 700, color: EMAIL_COLORS.textPrimary, textAlign: "center" }}>
SLA estourado
</Heading>
<Text style={{ margin: "0 0 24px 0", fontSize: "15px", lineHeight: "1.7", color: EMAIL_COLORS.textSecondary, textAlign: "center" }}>
O chamado abaixo excedeu o tempo de atendimento acordado e requer atencao imediata.
</Text>
<Section
style={{
backgroundColor: "#fef2f2",
borderRadius: "12px",
border: "1px solid #fca5a5",
margin: "24px 0",
}}
>
<table cellPadding="0" cellSpacing="0" role="presentation" style={{ width: "100%" }}>
<tbody>
<tr>
<td style={{ padding: "16px 20px", borderBottom: "1px solid #fecaca" }}>
<table cellPadding="0" cellSpacing="0" role="presentation" style={{ width: "100%" }}>
<tbody>
<tr>
<td style={{ color: "#991b1b", fontSize: "13px", fontWeight: 500, width: "120px" }}>
Chamado
</td>
<td style={{ color: "#7f1d1d", fontSize: "14px", fontWeight: 600 }}>
#{ticketNumber}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td style={{ padding: "16px 20px", borderBottom: "1px solid #fecaca" }}>
<table cellPadding="0" cellSpacing="0" role="presentation" style={{ width: "100%" }}>
<tbody>
<tr>
<td style={{ color: "#991b1b", fontSize: "13px", fontWeight: 500, width: "120px" }}>
Titulo
</td>
<td style={{ color: "#7f1d1d", fontSize: "14px" }}>
{ticketTitle}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td style={{ padding: "16px 20px" }}>
<table cellPadding="0" cellSpacing="0" role="presentation" style={{ width: "100%" }}>
<tbody>
<tr>
<td style={{ color: "#991b1b", fontSize: "13px", fontWeight: 500, width: "120px" }}>
Estourado em
</td>
<td style={{ color: "#dc2626", fontSize: "14px", fontWeight: 700 }}>
{formatDate(breachedAt)}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</Section>
<Section style={{ textAlign: "center", margin: "32px 0" }}>
<Button
href={ticketUrl}
style={{
display: "inline-block",
backgroundColor: "#dc2626",
color: "#ffffff",
textDecoration: "none",
borderRadius: "12px",
padding: "14px 24px",
fontWeight: 800,
fontSize: "14px",
border: "1px solid #b91c1c",
}}
>
Atender agora
</Button>
</Section>
<Hr style={{ borderColor: EMAIL_COLORS.border, margin: "24px 0" }} />
<Text style={{ margin: 0, fontSize: "12px", color: EMAIL_COLORS.textMuted, textAlign: "center" }}>
Este chamado deve ser tratado com prioridade maxima.
</Text>
</RavenEmailLayout>
)
}
SlaBreachedEmail.PreviewProps = {
ticketNumber: "41025",
ticketTitle: "Computador nao liga apos atualizacao",
breachedAt: new Date().toISOString(),
ticketUrl: "https://raven.rever.com.br/tickets/abc123",
} satisfies SlaBreachedEmailProps