From 1f83ed8c82848b7bcbfb8cbb96c6e6cb6ecf473b Mon Sep 17 00:00:00 2001 From: Vadym Samoilenko Date: Wed, 11 Mar 2026 14:12:52 +0000 Subject: [PATCH] Add login page with Microsoft SSO button Dark heatmap-inspired design with animated concentric rings, OliVAS wordmark, and a clean Microsoft sign-in button. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/auth/RequireAuth.tsx | 21 +-- frontend/src/pages/Login.tsx | 278 ++++++++++++++++++++++++++++++ 2 files changed, 282 insertions(+), 17 deletions(-) create mode 100644 frontend/src/pages/Login.tsx diff --git a/frontend/src/auth/RequireAuth.tsx b/frontend/src/auth/RequireAuth.tsx index 6fe1402..ba824f3 100644 --- a/frontend/src/auth/RequireAuth.tsx +++ b/frontend/src/auth/RequireAuth.tsx @@ -1,22 +1,13 @@ -import { useEffect } from "react"; import { useIsAuthenticated, useMsal } from "@azure/msal-react"; import { InteractionStatus } from "@azure/msal-browser"; -import { loginRequest } from "./msalConfig"; import LoadingSpinner from "../components/common/LoadingSpinner"; +import Login from "../pages/Login"; export default function RequireAuth({ children }: { children: React.ReactNode }) { const isAuthenticated = useIsAuthenticated(); - const { inProgress, instance } = useMsal(); + const { inProgress } = useMsal(); - useEffect(() => { - if (!isAuthenticated && inProgress === InteractionStatus.None) { - instance.loginRedirect(loginRequest).catch((e) => { - console.error("[Auth] Login redirect failed:", e); - }); - } - }, [isAuthenticated, inProgress, instance]); - - if (inProgress !== InteractionStatus.None) { + if (inProgress === InteractionStatus.HandleRedirect) { return (
@@ -25,11 +16,7 @@ export default function RequireAuth({ children }: { children: React.ReactNode }) } if (!isAuthenticated) { - return ( -
- -
- ); + return ; } return <>{children}; diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx new file mode 100644 index 0000000..a29638f --- /dev/null +++ b/frontend/src/pages/Login.tsx @@ -0,0 +1,278 @@ +import { useState } from "react"; +import { useMsal } from "@azure/msal-react"; +import { InteractionStatus } from "@azure/msal-browser"; +import { loginRequest } from "../auth/msalConfig"; + +export default function Login() { + const { instance, inProgress } = useMsal(); + const [error, setError] = useState(null); + const isLoading = inProgress !== InteractionStatus.None; + + const handleLogin = async () => { + setError(null); + try { + await instance.loginRedirect(loginRequest); + } catch (e) { + setError("Sign-in failed. Please try again."); + console.error("[Auth] Login redirect failed:", e); + } + }; + + return ( +
+ {/* Ambient heatmap glow */} +
+ + {/* Concentric rings — focal point motif */} +