refactor: enhance role management UI and integrate profile management features

- Introduced a modal for managing user profiles, allowing for the creation and editing of profiles with improved state management.
- Updated the role filtering logic to enhance type safety and readability.
- Refactored UI components for better user experience, including improved button states and loading indicators.
- Removed outdated code related to permissions and streamlined the overall structure for maintainability.
This commit is contained in:
2025-11-03 15:14:33 -03:00
parent c1d9958c9f
commit 0d011b8f42
38 changed files with 2664 additions and 4919 deletions

View File

@@ -46,6 +46,11 @@ export const enfileirarEmail = mutation({
criadoEm: Date.now(),
});
// Agendar envio imediato via action
await ctx.scheduler.runAfter(0, api.actions.email.enviar, {
emailId,
});
return { sucesso: true, emailId };
},
});
@@ -94,6 +99,11 @@ export const enviarEmailComTemplate = mutation({
criadoEm: Date.now(),
});
// Agendar envio imediato via action
await ctx.scheduler.runAfter(0, api.actions.email.enviar, {
emailId,
});
return { sucesso: true, emailId };
},
});
@@ -225,99 +235,7 @@ export const markEmailFalha = internalMutation({
},
});
export const enviarEmailAction = action({
args: {
emailId: v.id("notificacoesEmail"),
},
returns: v.object({ sucesso: v.boolean(), erro: v.optional(v.string()) }),
handler: async (ctx, args) => {
"use node";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const nodemailer = require("nodemailer");
try {
// Buscar email da fila
const email = await ctx.runQuery(internal.email.getEmailById, {
emailId: args.emailId,
});
if (!email) {
return { sucesso: false, erro: "Email não encontrado" };
}
// Buscar configuração SMTP
const config = await ctx.runQuery(
internal.email.getActiveEmailConfig,
{}
);
if (!config) {
return {
sucesso: false,
erro: "Configuração de email não encontrada ou inativa",
};
}
if (!config.testadoEm) {
return {
sucesso: false,
erro: "Configuração SMTP não foi testada. Teste a conexão primeiro!",
};
}
// Marcar como enviando
await ctx.runMutation(internal.email.markEmailEnviando, {
emailId: args.emailId,
});
// Criar transporter do nodemailer
const transporter = nodemailer.createTransport({
host: config.servidor,
port: config.porta,
secure: config.usarSSL,
auth: {
user: config.usuario,
pass: config.senhaHash, // Note: em produção deve ser descriptografado
},
tls: {
rejectUnauthorized: false,
},
});
// Enviar email REAL
const info = await transporter.sendMail({
from: `"${config.nomeRemetente}" <${config.emailRemetente}>`,
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);
console.log(" Message ID:", info.messageId);
// Marcar como enviado
await ctx.runMutation(internal.email.markEmailEnviado, {
emailId: args.emailId,
});
return { sucesso: true };
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : String(error);
console.error("❌ Erro ao enviar email:", errorMessage);
// Marcar como falha
await ctx.runMutation(internal.email.markEmailFalha, {
emailId: args.emailId,
erro: errorMessage,
});
return { sucesso: false, erro: errorMessage };
}
},
});
// Action de envio foi movida para `actions/email.ts`
/**
* Processar fila de emails (cron job - processa emails pendentes)
@@ -345,9 +263,7 @@ export const processarFilaEmails = internalMutation({
}
// Agendar envio via action
// IMPORTANTE: Não podemos chamar action diretamente de mutation
// Por isso, usaremos o scheduler com string path
await ctx.scheduler.runAfter(0, "email:enviarEmailAction" as any, {
await ctx.scheduler.runAfter(0, api.actions.email.enviar, {
emailId: email._id,
});