feat: enhance vacation management system with new employee association functionality, improved email notification handling, and comprehensive documentation; update dependencies and UI components for better user experience
This commit is contained in:
@@ -98,6 +98,7 @@ export const listarFilaEmails = query({
|
||||
)),
|
||||
limite: v.optional(v.number()),
|
||||
},
|
||||
returns: v.array(v.any()),
|
||||
handler: async (ctx, args) => {
|
||||
let query = ctx.db.query("notificacoesEmail");
|
||||
|
||||
@@ -140,9 +141,7 @@ export const reenviarEmail = mutation({
|
||||
});
|
||||
|
||||
/**
|
||||
* Action para enviar email (será implementado com nodemailer)
|
||||
*
|
||||
* NOTA: Este é um placeholder. Implementação real requer nodemailer.
|
||||
* Action para enviar email REAL usando nodemailer
|
||||
*/
|
||||
export const enviarEmailAction = action({
|
||||
args: {
|
||||
@@ -150,7 +149,9 @@ export const enviarEmailAction = action({
|
||||
},
|
||||
returns: v.object({ sucesso: v.boolean(), erro: v.optional(v.string()) }),
|
||||
handler: async (ctx, args) => {
|
||||
// TODO: Implementar com nodemailer quando instalado
|
||||
"use node";
|
||||
|
||||
const nodemailer = require("nodemailer");
|
||||
|
||||
try {
|
||||
// Buscar email da fila
|
||||
@@ -171,7 +172,11 @@ export const enviarEmailAction = action({
|
||||
});
|
||||
|
||||
if (!config) {
|
||||
return { sucesso: false, erro: "Configuração de email não encontrada" };
|
||||
return { sucesso: false, erro: "Configuração de email não encontrada ou inativa" };
|
||||
}
|
||||
|
||||
if (!config.testado) {
|
||||
return { sucesso: false, erro: "Configuração SMTP não foi testada. Teste a conexão primeiro!" };
|
||||
}
|
||||
|
||||
// Marcar como enviando
|
||||
@@ -183,13 +188,33 @@ export const enviarEmailAction = action({
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Enviar email real com nodemailer aqui
|
||||
console.log("⚠️ AVISO: Envio de email simulado (nodemailer não instalado)");
|
||||
// Criar transporter do nodemailer
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: config.smtpHost,
|
||||
port: config.smtpPort,
|
||||
secure: config.smtpSecure, // true para 465, false para outros
|
||||
auth: {
|
||||
user: config.smtpUser,
|
||||
pass: config.smtpPassword,
|
||||
},
|
||||
tls: {
|
||||
// Não rejeitar certificados não autorizados (útil para testes)
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
});
|
||||
|
||||
// Enviar email REAL
|
||||
const info = await transporter.sendMail({
|
||||
from: `"${config.remetenteNome}" <${config.remetenteEmail}>`,
|
||||
to: email.destinatario,
|
||||
subject: email.assunto,
|
||||
html: email.corpo,
|
||||
});
|
||||
|
||||
console.log("✅ Email enviado com sucesso!");
|
||||
console.log(" Para:", email.destinatario);
|
||||
console.log(" Assunto:", email.assunto);
|
||||
|
||||
// Simular delay de envio
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
console.log(" Message ID:", info.messageId);
|
||||
|
||||
// Marcar como enviado
|
||||
await ctx.runMutation(async (ctx) => {
|
||||
@@ -201,6 +226,8 @@ export const enviarEmailAction = action({
|
||||
|
||||
return { sucesso: true };
|
||||
} catch (error: any) {
|
||||
console.error("❌ Erro ao enviar email:", error.message);
|
||||
|
||||
// Marcar como falha
|
||||
await ctx.runMutation(async (ctx) => {
|
||||
const email = await ctx.db.get(args.emailId);
|
||||
@@ -221,6 +248,7 @@ export const enviarEmailAction = action({
|
||||
*/
|
||||
export const processarFilaEmails = internalMutation({
|
||||
args: {},
|
||||
returns: v.object({ processados: v.number() }),
|
||||
handler: async (ctx) => {
|
||||
// Buscar emails pendentes (max 10 por execução)
|
||||
const emailsPendentes = await ctx.db
|
||||
@@ -240,17 +268,17 @@ export const processarFilaEmails = internalMutation({
|
||||
continue;
|
||||
}
|
||||
|
||||
// Agendar envio (será feito por uma action separada)
|
||||
// Por enquanto, apenas marca como enviado para não bloquear
|
||||
await ctx.db.patch(email._id, {
|
||||
status: "enviado",
|
||||
enviadoEm: Date.now(),
|
||||
// Agendar envio via action
|
||||
// IMPORTANTE: Não podemos chamar action diretamente de mutation
|
||||
// Por isso, usaremos o scheduler
|
||||
await ctx.scheduler.runAfter(0, "email:enviarEmailAction" as any, {
|
||||
emailId: email._id,
|
||||
});
|
||||
|
||||
processados++;
|
||||
}
|
||||
|
||||
console.log(`📧 Fila de emails processada: ${processados} emails`);
|
||||
console.log(`📧 Fila de emails processada: ${processados} emails agendados para envio`);
|
||||
|
||||
return { processados };
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user