feat: enhance push notification management and error handling
- Implemented error handling for unhandled promise rejections related to message channels, improving stability during push notification operations. - Updated the PushNotificationManager component to manage push subscription registration with timeouts, preventing application hangs. - Enhanced the sidebar and chat components to display user avatars, improving user experience and visual consistency. - Refactored email processing logic to support scheduled email sending, integrating new backend functionalities for better email management. - Improved overall error handling and logging across components to reduce console spam and enhance debugging capabilities.
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
// Estados locais para atualização imediata
|
||||
let fotoPerfilLocal = $state<string | null>(null);
|
||||
let avatarLocal = $state<string | null>(null);
|
||||
let perfilCarregado = $state(false);
|
||||
|
||||
// Estados para Minhas Férias
|
||||
let mostrarWizard = $state(false);
|
||||
@@ -43,13 +44,32 @@
|
||||
// Galeria de avatares (30 avatares profissionais 3D realistas)
|
||||
const avatarGallery = generateAvatarGallery(30);
|
||||
|
||||
// Sincronizar com authStore
|
||||
// Carregar perfil ao montar a página para garantir dados atualizados (apenas uma vez)
|
||||
$effect(() => {
|
||||
if (authStore.usuario?.fotoPerfilUrl !== undefined) {
|
||||
fotoPerfilLocal = authStore.usuario.fotoPerfilUrl;
|
||||
if (authStore.autenticado && authStore.usuario && !perfilCarregado) {
|
||||
perfilCarregado = true;
|
||||
// Atualizar authStore com dados mais recentes do backend
|
||||
authStore.refresh().catch((error) => {
|
||||
console.error("Erro ao carregar perfil:", error);
|
||||
perfilCarregado = false; // Permite tentar novamente em caso de erro
|
||||
});
|
||||
}
|
||||
if (authStore.usuario?.avatar !== undefined) {
|
||||
avatarLocal = authStore.usuario.avatar;
|
||||
});
|
||||
|
||||
// Sincronizar com authStore - atualiza automaticamente quando o authStore muda
|
||||
// Isso garante que a foto/avatar seja carregada imediatamente ao abrir a página
|
||||
$effect(() => {
|
||||
const usuario = authStore.usuario;
|
||||
if (usuario) {
|
||||
// Atualizar foto de perfil (pode ser null ou string)
|
||||
fotoPerfilLocal = usuario.fotoPerfilUrl ?? null;
|
||||
// Atualizar avatar (pode ser undefined ou string)
|
||||
avatarLocal = usuario.avatar ?? null;
|
||||
} else {
|
||||
// Se não há usuário, limpar estados locais
|
||||
fotoPerfilLocal = null;
|
||||
avatarLocal = null;
|
||||
perfilCarregado = false; // Reset para permitir recarregar quando houver usuário novamente
|
||||
}
|
||||
});
|
||||
|
||||
@@ -231,13 +251,21 @@
|
||||
erroUpload = "";
|
||||
|
||||
try {
|
||||
// 1. Gerar URL de upload (NOME CORRETO DA FUNÇÃO!)
|
||||
// 1. Criar preview local IMEDIATAMENTE para feedback visual
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
fotoPerfilLocal = e.target?.result as string;
|
||||
avatarLocal = null;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
// 2. Gerar URL de upload
|
||||
const uploadUrl = await client.mutation(
|
||||
api.usuarios.uploadFotoPerfil,
|
||||
{}
|
||||
);
|
||||
|
||||
// 2. Upload do arquivo
|
||||
// 3. Upload do arquivo
|
||||
const response = await fetch(uploadUrl, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": file.type },
|
||||
@@ -250,21 +278,28 @@
|
||||
|
||||
const { storageId } = await response.json();
|
||||
|
||||
// 3. Atualizar perfil com o novo storageId
|
||||
// 4. Atualizar perfil com o novo storageId
|
||||
await client.mutation(api.usuarios.atualizarPerfil, {
|
||||
fotoPerfil: storageId,
|
||||
avatar: undefined, // Remove avatar se colocar foto
|
||||
});
|
||||
|
||||
// 4. Atualizar authStore para obter a URL da foto
|
||||
// 5. Aguardar um pouco para garantir que o backend processou
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
// 6. Atualizar authStore para obter a URL da foto atualizada
|
||||
await authStore.refresh();
|
||||
|
||||
// 5. Atualizar localmente IMEDIATAMENTE com a URL do authStore
|
||||
// 7. Atualizar localmente com a URL do authStore (substitui o preview temporário)
|
||||
if (authStore.usuario?.fotoPerfilUrl) {
|
||||
fotoPerfilLocal = authStore.usuario.fotoPerfilUrl;
|
||||
avatarLocal = null;
|
||||
}
|
||||
|
||||
// 8. Limpar o input para permitir novo upload
|
||||
input.value = "";
|
||||
|
||||
// 9. Fechar modal após sucesso
|
||||
mostrarModalFoto = false;
|
||||
|
||||
// Toast de sucesso
|
||||
@@ -275,13 +310,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<span>Foto de perfil atualizada!</span>
|
||||
<span>Foto de perfil atualizada com sucesso!</span>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(toast);
|
||||
setTimeout(() => toast.remove(), 3000);
|
||||
} catch (e: any) {
|
||||
erroUpload = e.message || "Erro ao fazer upload da foto";
|
||||
// Reverter mudança local se houver erro
|
||||
fotoPerfilLocal = authStore.usuario?.fotoPerfilUrl || null;
|
||||
avatarLocal = authStore.usuario?.avatar || null;
|
||||
} finally {
|
||||
uploadandoFoto = false;
|
||||
}
|
||||
@@ -292,7 +330,7 @@
|
||||
erroUpload = "";
|
||||
|
||||
try {
|
||||
// 1. Atualizar localmente IMEDIATAMENTE (antes mesmo da API)
|
||||
// 1. Atualizar localmente IMEDIATAMENTE para feedback visual instantâneo
|
||||
avatarLocal = avatarUrl;
|
||||
fotoPerfilLocal = null;
|
||||
|
||||
@@ -302,12 +340,22 @@
|
||||
fotoPerfil: undefined, // Remove foto se colocar avatar
|
||||
});
|
||||
|
||||
// 3. Atualizar authStore em background
|
||||
authStore.refresh();
|
||||
// 3. Aguardar um pouco para garantir que o backend processou
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
// 4. Atualizar authStore e aguardar conclusão
|
||||
await authStore.refresh();
|
||||
|
||||
// 5. Garantir que os estados locais estão sincronizados com o authStore
|
||||
if (authStore.usuario?.avatar) {
|
||||
avatarLocal = authStore.usuario.avatar;
|
||||
fotoPerfilLocal = null;
|
||||
}
|
||||
|
||||
// 6. Fechar modal após sucesso
|
||||
mostrarModalFoto = false;
|
||||
|
||||
// Toast de sucesso mais discreto
|
||||
// Toast de sucesso
|
||||
const toast = document.createElement("div");
|
||||
toast.className = "toast toast-top toast-end";
|
||||
toast.innerHTML = `
|
||||
@@ -315,7 +363,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<span>Avatar atualizado!</span>
|
||||
<span>Avatar atualizado com sucesso!</span>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(toast);
|
||||
|
||||
Reference in New Issue
Block a user