refactor: enhance ProtectedRoute and dashboard components for improved access control and user experience
- Updated the ProtectedRoute component to optimize access checking logic, preventing unnecessary re-checks and improving authentication flow. - Enhanced the dashboard page to automatically open the login modal for authentication errors and refined loading states for better user feedback. - Improved UI elements across various components for consistency and visual appeal, including updated tab styles and enhanced alert messages. - Removed redundant footer from the vacation management page to streamline the interface.
This commit is contained in:
@@ -21,11 +21,26 @@
|
||||
let isChecking = $state(true);
|
||||
let hasAccess = $state(false);
|
||||
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
||||
let hasCheckedOnce = $state(false);
|
||||
let lastUserState = $state<typeof currentUser | undefined>(undefined);
|
||||
const currentUser = useQuery(api.auth.getCurrentUser, {});
|
||||
|
||||
// Usar $effect para reagir às mudanças na query
|
||||
// Usar $effect para reagir apenas às mudanças na query currentUser
|
||||
$effect(() => {
|
||||
checkAccess();
|
||||
// Não verificar novamente se já tem acesso concedido e usuário está autenticado
|
||||
if (hasAccess && currentUser?.data) {
|
||||
lastUserState = currentUser;
|
||||
return;
|
||||
}
|
||||
|
||||
// Evitar loop: só verificar se currentUser realmente mudou
|
||||
// Comparar dados, não o objeto proxy
|
||||
const currentData = currentUser?.data;
|
||||
const lastData = lastUserState?.data;
|
||||
if (currentData !== lastData || (currentUser === undefined) !== (lastUserState === undefined)) {
|
||||
lastUserState = currentUser;
|
||||
checkAccess();
|
||||
}
|
||||
});
|
||||
|
||||
function checkAccess() {
|
||||
@@ -42,6 +57,9 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Marcar que já verificou pelo menos uma vez
|
||||
hasCheckedOnce = true;
|
||||
|
||||
// Se a query retornou dados, verificar autenticação
|
||||
if (currentUser?.data) {
|
||||
// Verificar roles
|
||||
@@ -67,20 +85,29 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Se não tem dados e requer autenticação, aguardar um pouco antes de redirecionar
|
||||
// (pode estar carregando ainda)
|
||||
// Se não tem dados e requer autenticação
|
||||
if (requireAuth && !currentUser?.data) {
|
||||
// Se a query já retornou (não está mais undefined), finalizar estado
|
||||
if (currentUser !== undefined) {
|
||||
const currentPath = window.location.pathname;
|
||||
// Evitar redirecionamento em loop - verificar se já está na URL de erro
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (!urlParams.has('error')) {
|
||||
// Só redirecionar se não estiver em loop
|
||||
if (!hasCheckedOnce || currentUser === null) {
|
||||
window.location.href = `${redirectTo}?error=auth_required&redirect=${encodeURIComponent(currentPath)}`;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Se já tem erro na URL, permitir renderização para mostrar o alerta
|
||||
isChecking = false;
|
||||
hasAccess = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Se ainda está carregando (undefined), aguardar
|
||||
isChecking = true;
|
||||
hasAccess = false;
|
||||
|
||||
// Aguardar 3 segundos antes de redirecionar (dar tempo para a query carregar)
|
||||
timeoutId = setTimeout(() => {
|
||||
// Verificar novamente antes de redirecionar
|
||||
if (!currentUser?.data) {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.href = `${redirectTo}?error=auth_required&redirect=${encodeURIComponent(currentPath)}`;
|
||||
}
|
||||
}, 3000);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
import { UserPlus, Mail } from "lucide-svelte";
|
||||
import { useAuth } from "@mmailaender/convex-better-auth-svelte/svelte";
|
||||
import ProtectedRoute from "$lib/components/ProtectedRoute.svelte";
|
||||
import { loginModalStore } from "$lib/stores/loginModal.svelte";
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
const auth = useAuth();
|
||||
const isLoading = $derived(auth.isLoading && !data.currentUser);
|
||||
const isAuthenticated = $derived(auth.isAuthenticated || !!data.currentUser);
|
||||
const isLoading = $derived(auth.isLoading && !data?.currentUser);
|
||||
const isAuthenticated = $derived(auth.isAuthenticated || !!data?.currentUser);
|
||||
|
||||
$inspect({ isLoading, isAuthenticated });
|
||||
|
||||
@@ -56,6 +57,11 @@
|
||||
redirectRoute = route;
|
||||
showAlert = true;
|
||||
|
||||
// Se for erro de autenticação, abrir modal de login automaticamente
|
||||
if (error === "auth_required") {
|
||||
loginModalStore.open(route || to.url.pathname);
|
||||
}
|
||||
|
||||
// Limpar URL usando SvelteKit (após router estar inicializado)
|
||||
try {
|
||||
replaceState(to.url.pathname, {});
|
||||
@@ -75,6 +81,17 @@
|
||||
onMount(() => {
|
||||
mounted = true;
|
||||
|
||||
// Verificar se há erro na URL ao carregar a página
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.has("error")) {
|
||||
const error = urlParams.get("error");
|
||||
const route = urlParams.get("route") || urlParams.get("redirect") || "";
|
||||
|
||||
if (error === "auth_required") {
|
||||
loginModalStore.open(route || window.location.pathname);
|
||||
}
|
||||
}
|
||||
|
||||
// Atualizar relógio e forçar refresh das queries a cada segundo
|
||||
const interval = setInterval(() => {
|
||||
currentTime = new Date();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1993,12 +1993,6 @@
|
||||
{/if}
|
||||
{/await}
|
||||
{/if}
|
||||
|
||||
<footer
|
||||
class="border-base-300/60 bg-base-100 text-base-content/70 mt-8 border-t py-6 text-center text-sm"
|
||||
>
|
||||
SGSE - Sistema de Gerenciamento de Secretaria.
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
/* Calendário de Férias */
|
||||
|
||||
Reference in New Issue
Block a user