diff --git a/frontend/src/components/auth/LoginForm.vue b/frontend/src/components/auth/LoginForm.vue index 92c7c21..8903b46 100644 --- a/frontend/src/components/auth/LoginForm.vue +++ b/frontend/src/components/auth/LoginForm.vue @@ -20,22 +20,15 @@ const handleLogin = async () => { try { await authStore.login(email.value.trim().toLowerCase(), password.value) - - // Esperar hasta que el perfil esté cargado (máx 3 segundos) - let attempts = 0 - while (!authStore.role && attempts < 30) { - await new Promise(res => setTimeout(res, 100)) - attempts++ - } - + // El rol ya está disponible en el store (del JWT), navegar directo navigateByUserRole(authStore.role || 'PASSENGER') } catch (error: any) { - console.error('Error Login detallado:', error) - if (error.message.includes('Invalid login credentials')) { + console.error('Error Login:', error) + if (error.message?.includes('Invalid login credentials')) { errorMessage.value = 'Correo o contraseña incorrectos.' } else { - errorMessage.value = `Error: ${error.message || 'Error en el servidor.'}` + errorMessage.value = `Error: ${error.message || 'Error desconocido.'}` } } finally { isLoading.value = false diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index c37e2be..7706555 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -1,6 +1,7 @@ /** Vue Router configuration */ import { createRouter, createWebHistory } from 'vue-router' import { supabase } from '@/supabase' +import { useAuthStore } from '@/stores/auth' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -147,48 +148,34 @@ const router = createRouter({ }) router.beforeEach(async (to, _from, next) => { - // Rutas completamente públicas (splash, login) - const publicRoutes = ['/login', '/splash', '/'] - if (publicRoutes.includes(to.path)) { + // Rutas sin protección → pasar directo + if (!to.meta.requiresAuth && !to.meta.role) { return next() } - // Leer sesión activa de Supabase + // Verificar sesión activa const { data: { session } } = await supabase.auth.getSession() - // Ruta protegida sin sesión → redirige a login - if (to.meta.requiresAuth && !session) { + // Sin sesión en ruta protegida → login + if (!session) { return next('/login') } - // Si hay sesión, obtener el rol real del usuario - if (session) { - const { data: profile } = await supabase - .from('users') - .select('role') - .eq('id', session.user.id) - .single() + // Si la ruta requiere un rol específico, verificar usando el store + if (to.meta.role) { + // Usar el store de auth (ya tiene el rol cargado desde el JWT) + const authStore = useAuthStore() + const userRole = authStore.role?.toUpperCase() || 'PASSENGER' - const userRole = profile?.role?.toUpperCase() || 'PASSENGER' + const allowedRoles = Array.isArray(to.meta.role) + ? (to.meta.role as string[]).map(r => r.toUpperCase()) + : [(to.meta.role as string).toUpperCase()] - // Si el admin entra a rutas de pasajero → redirigir al panel admin - const passengerRoutes = ['/map', '/schedule', '/discover', '/transport', '/favorites', '/profile', '/coupons'] - if (userRole === 'ADMIN' && passengerRoutes.some(r => to.path.startsWith(r))) { - return next('/admin') - } - - // Ruta con restricción de rol → verificar permiso - if (to.meta.role) { - const allowedRoles = Array.isArray(to.meta.role) - ? (to.meta.role as string[]).map(r => r.toUpperCase()) - : [(to.meta.role as string).toUpperCase()] - - if (!allowedRoles.includes(userRole)) { - if (userRole === 'ADMIN') return next('/admin') - else if (userRole === 'DRIVER') return next('/driver') - else if (userRole === 'PROMOTER') return next('/promoter') - else return next('/map') - } + if (!allowedRoles.includes(userRole)) { + if (userRole === 'ADMIN') return next('/admin') + else if (userRole === 'DRIVER') return next('/driver') + else if (userRole === 'PROMOTER') return next('/promoter') + else return next('/map') } } diff --git a/frontend/src/stores/auth.ts b/frontend/src/stores/auth.ts index 136a70e..673662c 100644 --- a/frontend/src/stores/auth.ts +++ b/frontend/src/stores/auth.ts @@ -40,19 +40,14 @@ export const useAuthStore = defineStore('auth', () => { if (error) throw new Error(error.message) if (data.user) { - // Establecer sesión y rol inmediatamente desde el JWT (sin esperar BD) + // Rol disponible al instante desde el JWT — sin consultas BD bloqueantes userSession.value = data.session - // Usar user_metadata como perfil temporal para que el rol esté listo al instante userProfile.value = { id: data.user.id, email: data.user.email, full_name: data.user.user_metadata?.full_name || data.user.email, role: data.user.user_metadata?.role || 'PASSENGER' } - // Cargar perfil completo de BD en background (sin bloquear navegación) - supabase.from('users').select('*').eq('id', data.user.id).single() - .then(({ data: profile }) => { if (profile) userProfile.value = profile }) - .catch(() => { }) } }