feat: enhance vacation approval process by adding notification system for employees, including email alerts and in-app notifications; improve error handling and user feedback during vacation management

This commit is contained in:
2025-12-10 06:27:25 -03:00
parent 73da995109
commit d27c0b6f91
22 changed files with 1572 additions and 215 deletions

View File

@@ -124,6 +124,116 @@ export const criar = mutation({
atualizadoEm: Date.now()
});
// Obter usuário que está criando (para enviar email e chat)
const usuarioCriador = await getCurrentUserFunction(ctx);
if (!usuarioCriador) {
// Se não conseguir obter o criador, retornar sucesso mesmo assim
return { sucesso: true as const, usuarioId };
}
// Buscar funcionário para obter matrícula se houver
let matricula = '';
if (args.funcionarioId) {
const funcionario = await ctx.db.get(args.funcionarioId);
if (funcionario?.matricula) {
matricula = funcionario.matricula;
}
}
// Preparar credenciais adicionais (matrícula se houver)
const credenciaisAdicionais = matricula
? `<li><strong>Matrícula:</strong> ${matricula}</li>`
: '';
// Obter URL do sistema
let urlSistema = process.env.FRONTEND_URL || 'http://localhost:5173';
if (!urlSistema.match(/^https?:\/\//i)) {
urlSistema = `http://${urlSistema}`;
}
// Enviar email de boas-vindas usando template (agendado via scheduler)
try {
await ctx.scheduler.runAfter(0, api.email.enviarEmailComTemplate, {
destinatario: args.email,
destinatarioId: usuarioId,
templateCodigo: 'BEM_VINDO',
variaveis: {
nome: args.nome,
email: args.email,
credenciaisAdicionais,
senha: senhaTemporaria,
urlSistema
},
enviadoPor: usuarioCriador._id
});
} catch (error) {
// Fallback para envio direto se houver erro ao agendar ou processar o template
console.warn(
'Erro ao agendar envio de email com template BEM_VINDO, usando envio direto:',
error
);
await ctx.runMutation(api.email.enfileirarEmail, {
destinatario: args.email,
destinatarioId: usuarioId,
assunto: 'Bem-vindo ao SGSE',
corpo: `<p>Olá <strong>${args.nome}</strong>,</p>
<p>Seja bem-vindo ao <strong>SGSE - Sistema de Gerenciamento de Secretaria</strong>!</p>
<p>Seu cadastro foi realizado com sucesso.</p>
<div style='background-color: #F3F4F6; border-left: 4px solid #2563EB; padding: 15px; border-radius: 8px; margin: 20px 0;'>
<p style='margin: 0 0 10px 0;'><strong>Suas credenciais de acesso:</strong></p>
<ul style='margin: 0; padding-left: 20px;'>
<li><strong>E-mail:</strong> ${args.email}</li>
${credenciaisAdicionais}
<li><strong>Senha temporária:</strong> ${senhaTemporaria}</li>
</ul>
</div>
<p><strong>⚠️ Importante:</strong> Por favor, altere sua senha no primeiro acesso ao sistema.</p>
<p>Acesse o sistema através do link: <a href='${urlSistema}' style='color: #2563EB;'>${urlSistema}</a></p>
<p style='margin-top: 30px; color: #6B7280; font-size: 14px;'>Equipe de TI - Secretaria de Esportes</p>`,
enviadoPor: usuarioCriador._id
});
}
// Criar ou obter conversa entre criador e novo usuário
const conversasExistentes = await ctx.db
.query('conversas')
.filter((q) => q.eq(q.field('tipo'), 'individual'))
.collect();
let conversaId: Id<'conversas'> | null = null;
for (const conversa of conversasExistentes) {
if (
conversa.participantes.length === 2 &&
conversa.participantes.includes(usuarioCriador._id) &&
conversa.participantes.includes(usuarioId)
) {
conversaId = conversa._id;
break;
}
}
if (!conversaId) {
conversaId = await ctx.db.insert('conversas', {
tipo: 'individual',
participantes: [usuarioCriador._id, usuarioId],
criadoPor: usuarioCriador._id,
criadoEm: Date.now()
});
}
// Criar mensagem de chat (texto simples)
const mensagemChat = matricula
? `Bem-vindo ao SGSE! Seu cadastro foi realizado com sucesso. Suas credenciais de acesso: E-mail: ${args.email}, Matrícula: ${matricula}, Senha temporária: ${senhaTemporaria}. Por favor, altere sua senha no primeiro acesso.`
: `Bem-vindo ao SGSE! Seu cadastro foi realizado com sucesso. Suas credenciais de acesso: E-mail: ${args.email}, Senha temporária: ${senhaTemporaria}. Por favor, altere sua senha no primeiro acesso.`;
await ctx.db.insert('mensagens', {
conversaId,
remetenteId: usuarioCriador._id,
tipo: 'texto',
conteudo: mensagemChat,
enviadaEm: Date.now()
});
return { sucesso: true as const, usuarioId };
}
});