feat: improve email status querying and URL handling

- Updated email status query to execute only when there are email IDs, enhancing performance.
- Ensured URL handling in email sending functions always includes a protocol, improving reliability.
- Added new queries for fetching emails by IDs and listing scheduled emails, enriching email management capabilities.
This commit is contained in:
2025-11-05 16:23:47 -03:00
parent 36933b53cb
commit 33f305220b
3 changed files with 80 additions and 6 deletions

View File

@@ -52,14 +52,15 @@
// Mapa de emailIds para rastrear status // Mapa de emailIds para rastrear status
let emailIdsRastreados = $state<Set<string>>(new Set()); let emailIdsRastreados = $state<Set<string>>(new Set());
// Query para buscar status dos emails // Query para buscar status dos emails (só executa quando há IDs)
const emailIdsArray = $derived( const emailIdsArray = $derived(
Array.from(emailIdsRastreados).map((id) => id as Id<"notificacoesEmail">), Array.from(emailIdsRastreados).map((id) => id as Id<"notificacoesEmail">),
); );
const emailsStatusQuery = useQuery( // Usar função para evitar execução quando array está vazio
api.email.buscarEmailsPorIds, const emailsStatusQuery = $derived.by(() => {
emailIdsArray.length > 0 ? { emailIds: emailIdsArray } : undefined, if (emailIdsArray.length === 0) return null;
); return useQuery(api.email.buscarEmailsPorIds, { emailIds: emailIdsArray });
});
// Queries para agendamentos // Queries para agendamentos
const agendamentosEmailQuery = useQuery( const agendamentosEmailQuery = useQuery(

View File

@@ -440,7 +440,12 @@ export const enviarMensagem = mutation({
const usuarioParticipante = await ctx.db.get(participanteId); const usuarioParticipante = await ctx.db.get(participanteId);
if (usuarioParticipante?.email) { if (usuarioParticipante?.email) {
// Obter URL do sistema (padrão: localhost para dev) // Obter URL do sistema (padrão: localhost para dev)
const urlSistema = process.env.FRONTEND_URL || "http://localhost:5173"; let urlSistema = process.env.FRONTEND_URL || "http://localhost:5173";
// Garantir que a URL sempre tenha protocolo
if (!urlSistema.match(/^https?:\/\//i)) {
urlSistema = `http://${urlSistema}`;
}
ctx.scheduler.runAfter(1000, api.email.enviarEmailComTemplate, { ctx.scheduler.runAfter(1000, api.email.enviarEmailComTemplate, {
destinatario: usuarioParticipante.email, destinatario: usuarioParticipante.email,

View File

@@ -173,6 +173,12 @@ export const enviarEmailComTemplate = action({
// Renderizar template com variáveis // Renderizar template com variáveis
const variaveisTemplate = args.variaveis || {}; const variaveisTemplate = args.variaveis || {};
// Garantir que urlSistema sempre tenha protocolo se presente
if (variaveisTemplate.urlSistema && !variaveisTemplate.urlSistema.match(/^https?:\/\//i)) {
variaveisTemplate.urlSistema = `http://${variaveisTemplate.urlSistema}`;
}
const tituloRenderizado = renderizarTemplate(template.titulo, variaveisTemplate); const tituloRenderizado = renderizarTemplate(template.titulo, variaveisTemplate);
const corpoRenderizado = renderizarTemplate(template.corpo, variaveisTemplate); const corpoRenderizado = renderizarTemplate(template.corpo, variaveisTemplate);
@@ -327,6 +333,68 @@ export const obterEstatisticasFilaEmails = query({
}, },
}); });
/**
* Buscar emails por IDs (para monitoramento de status)
*/
export const buscarEmailsPorIds = query({
args: {
emailIds: v.array(v.id("notificacoesEmail")),
},
handler: async (ctx, args) => {
const emails = [];
for (const emailId of args.emailIds) {
const email = await ctx.db.get(emailId);
if (email) {
emails.push(email);
}
}
return emails;
},
});
/**
* Listar agendamentos de email (emails com agendadaPara definido)
*/
export const listarAgendamentosEmail = query({
args: {},
handler: async (ctx) => {
// Buscar todos os emails agendados (pendentes ou enviando)
const emailsAgendados = await ctx.db
.query("notificacoesEmail")
.filter((q) => {
const temAgendamento = q.neq(q.field("agendadaPara"), undefined);
const statusValido = q.or(
q.eq(q.field("status"), "pendente"),
q.eq(q.field("status"), "enviando")
);
return q.and(temAgendamento, statusValido);
})
.order("asc")
.collect();
// Enriquecer com informações de destinatário e template
const emailsEnriquecidos = await Promise.all(
emailsAgendados.map(async (email) => {
const destinatarioInfo = email.destinatarioId
? await ctx.db.get(email.destinatarioId)
: null;
const templateInfo = email.templateId
? await ctx.db.get(email.templateId)
: null;
return {
...email,
destinatarioInfo,
templateInfo,
};
})
);
return emailsEnriquecidos;
},
});
// ========== PUBLIC MUTATIONS (MANUAL) ========== // ========== PUBLIC MUTATIONS (MANUAL) ==========
/** /**