feat: adiciona fluxo de redefinição de senha e melhora página de configurações
- Adiciona página /recuperar para solicitar redefinição de senha - Adiciona página /redefinir-senha para definir nova senha com token - Cria APIs /api/auth/forgot-password e /api/auth/reset-password - Adiciona notificação por e-mail quando ticket é criado - Repagina página de configurações removendo informações técnicas - Adiciona script de teste para todos os tipos de e-mail - Corrige acentuações em templates de e-mail 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
300179279a
commit
1bc08d3a5f
10 changed files with 1258 additions and 166 deletions
|
|
@ -281,6 +281,43 @@ async function sendSmtpMail(cfg: SmtpConfig, to: string, subject: string, html:
|
|||
}
|
||||
}
|
||||
|
||||
export const sendTicketCreatedEmail = action({
|
||||
args: {
|
||||
to: v.string(),
|
||||
ticketId: v.string(),
|
||||
reference: v.number(),
|
||||
subject: v.string(),
|
||||
priority: v.string(),
|
||||
},
|
||||
handler: async (_ctx, { to, ticketId, reference, subject, priority }) => {
|
||||
const smtp = buildSmtpConfig()
|
||||
if (!smtp) {
|
||||
console.warn("SMTP not configured; skipping ticket created email")
|
||||
return { skipped: true }
|
||||
}
|
||||
const baseUrl = buildBaseUrl()
|
||||
const url = `${baseUrl}/portal/tickets/${ticketId}`
|
||||
|
||||
const priorityLabels: Record<string, string> = {
|
||||
LOW: "Baixa",
|
||||
MEDIUM: "Média",
|
||||
HIGH: "Alta",
|
||||
URGENT: "Urgente",
|
||||
}
|
||||
const priorityLabel = priorityLabels[priority] ?? priority
|
||||
|
||||
const mailSubject = `Novo chamado #${reference} aberto`
|
||||
const html = await renderSimpleNotificationEmailHtml({
|
||||
title: `Novo chamado #${reference} aberto`,
|
||||
message: `Seu chamado foi registrado com sucesso. Nossa equipe irá analisá-lo em breve.\n\nAssunto: ${subject}\nPrioridade: ${priorityLabel}\nStatus: Pendente`,
|
||||
ctaLabel: "Ver chamado",
|
||||
ctaUrl: url,
|
||||
})
|
||||
await sendSmtpMail(smtp, to, mailSubject, html)
|
||||
return { ok: true }
|
||||
},
|
||||
})
|
||||
|
||||
export const sendPublicCommentEmail = action({
|
||||
args: {
|
||||
to: v.string(),
|
||||
|
|
|
|||
|
|
@ -2456,6 +2456,25 @@ export const create = mutation({
|
|||
createdAt: now,
|
||||
});
|
||||
|
||||
// Notificação por e-mail: ticket criado para o solicitante
|
||||
try {
|
||||
const requesterEmail = requester?.email
|
||||
if (requesterEmail) {
|
||||
const schedulerRunAfter = ctx.scheduler?.runAfter
|
||||
if (typeof schedulerRunAfter === "function") {
|
||||
await schedulerRunAfter(0, api.ticketNotifications.sendTicketCreatedEmail, {
|
||||
to: requesterEmail,
|
||||
ticketId: String(id),
|
||||
reference: nextRef,
|
||||
subject,
|
||||
priority: args.priority,
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("[tickets] Falha ao agendar e-mail de ticket criado", e)
|
||||
}
|
||||
|
||||
if (initialAssigneeId && initialAssignee) {
|
||||
await ctx.db.insert("ticketEvents", {
|
||||
ticketId: id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue