diff --git a/frontend/nginx.conf b/frontend/nginx.conf index 9bc3c7c..bb7577a 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -50,6 +50,11 @@ server { try_files $uri =404; } + # Raíz sin barra final → login (evita pantalla en blanco por basename) + location = /generadorexamenesllm { + return 301 /generadorexamenesllm/login; + } + location / { try_files $uri $uri/ /index.html; } diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 0b84c72..8bb44fa 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,9 +1,9 @@ import { Navigate, Route, Routes } from "react-router-dom"; import Layout from "./components/layout/Layout"; import ProtectedRoute from "./components/layout/ProtectedRoute"; +import RootRoute from "./components/layout/RootRoute"; import LoginPage from "./pages/LoginPage"; import RegisterPage from "./pages/RegisterPage"; -import DashboardPage from "./pages/DashboardPage"; import CreateTemplatePage from "./pages/CreateTemplatePage"; import TemplateDetailPage from "./pages/TemplateDetailPage"; import NotFoundPage from "./pages/NotFoundPage"; @@ -21,7 +21,7 @@ export default function App() { } > - } /> + } /> } /> } /> diff --git a/frontend/src/components/layout/RootRoute.jsx b/frontend/src/components/layout/RootRoute.jsx new file mode 100644 index 0000000..dbbf7a9 --- /dev/null +++ b/frontend/src/components/layout/RootRoute.jsx @@ -0,0 +1,17 @@ +import { Navigate } from "react-router-dom"; +import { useAuth } from "../../context/AuthContext"; +import { SpinnerCenter } from "../ui/Spinner"; +import DashboardPage from "../../pages/DashboardPage"; + +/** Raíz de la app: login si no hay sesión, dashboard si la hay. */ +export default function RootRoute() { + const { isAuthenticated, loading } = useAuth(); + + if (loading) return ; + + if (!isAuthenticated) { + return ; + } + + return ; +} diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index 0ea2e26..69acaf1 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -4,8 +4,11 @@ import { BrowserRouter } from "react-router-dom"; import App from "./App"; import { AuthProvider } from "./context/AuthContext"; import { ToastProvider } from "./context/ToastContext"; +import { redirectRootToLoginIfNeeded } from "./utils/redirectRoot"; import "./index.css"; +redirectRootToLoginIfNeeded(); + ReactDOM.createRoot(document.getElementById("root")).render( diff --git a/frontend/src/utils/redirectRoot.js b/frontend/src/utils/redirectRoot.js new file mode 100644 index 0000000..d53abfe --- /dev/null +++ b/frontend/src/utils/redirectRoot.js @@ -0,0 +1,25 @@ +const TOKEN_KEY = "genex_token"; + +/** + * Si el usuario entra en la raíz de la app sin sesión, redirige a /login + * antes de montar React (evita pantalla en blanco por basename sin barra final). + */ +export function redirectRootToLoginIfNeeded() { + const base = import.meta.env.BASE_URL || "/"; + const baseNoSlash = base.replace(/\/$/, ""); + const { pathname, search, hash } = window.location; + const normalizedPath = pathname.replace(/\/$/, "") || "/"; + + const isAppRoot = + normalizedPath === baseNoSlash || + normalizedPath === "/" || + pathname === base; + + if (!isAppRoot) return; + if (localStorage.getItem(TOKEN_KEY)) return; + + const loginUrl = `${baseNoSlash}/login${search}${hash}`; + if (pathname + search + hash !== `${baseNoSlash}/login${search}${hash}`) { + window.location.replace(loginUrl); + } +}