Add session validation UI and expose isValidating in auth context
- LoginPage now shows a loading spinner while validating the session - Redirect to dashboard automatically once validation completes and session is valid - Expose isValidating state through AuthProvider for components to track validation status - Update useAuth hook to return isValidating along with isAuthenticated Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
* parameter) or the dashboard.
|
* parameter) or the dashboard.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Field,
|
Field,
|
||||||
@@ -75,7 +75,7 @@ export function LoginPage(): React.JSX.Element {
|
|||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const { login } = useAuth();
|
const { login, isAuthenticated, isValidating } = useAuth();
|
||||||
|
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
@@ -84,6 +84,33 @@ export function LoginPage(): React.JSX.Element {
|
|||||||
const next = searchParams.get("next") ?? "";
|
const next = searchParams.get("next") ?? "";
|
||||||
const safePath = /^\/(?!\/)/.test(next) ? next : "/";
|
const safePath = /^\/(?!\/)/.test(next) ? next : "/";
|
||||||
|
|
||||||
|
// Redirect to dashboard if session is valid and validation is complete
|
||||||
|
useEffect(() => {
|
||||||
|
if (isAuthenticated && !isValidating) {
|
||||||
|
navigate(safePath, { replace: true });
|
||||||
|
}
|
||||||
|
}, [isAuthenticated, isValidating, navigate, safePath]);
|
||||||
|
|
||||||
|
// Show loading state while validating session
|
||||||
|
if (isValidating) {
|
||||||
|
return (
|
||||||
|
<div className={styles.root}>
|
||||||
|
<div className={styles.card}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
minHeight: "200px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Spinner size="large" label="Checking session…" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function handlePasswordChange(ev: ChangeEvent<HTMLInputElement>): void {
|
function handlePasswordChange(ev: ChangeEvent<HTMLInputElement>): void {
|
||||||
setPassword(ev.target.value);
|
setPassword(ev.target.value);
|
||||||
setError(null);
|
setError(null);
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ import { useSessionValidation } from "../hooks/useSessionValidation";
|
|||||||
export interface AuthContextValue {
|
export interface AuthContextValue {
|
||||||
/** `true` when the backend considers the session valid. */
|
/** `true` when the backend considers the session valid. */
|
||||||
isAuthenticated: boolean;
|
isAuthenticated: boolean;
|
||||||
|
/** `true` while the session is being validated on app mount. */
|
||||||
|
isValidating: boolean;
|
||||||
/**
|
/**
|
||||||
* Authenticate with the master password.
|
* Authenticate with the master password.
|
||||||
* Throws an `ApiError` on failure.
|
* Throws an `ApiError` on failure.
|
||||||
@@ -216,8 +218,8 @@ export function AuthProvider({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const value = useMemo<AuthContextValue>(
|
const value = useMemo<AuthContextValue>(
|
||||||
() => ({ isAuthenticated, login, logout }),
|
() => ({ isAuthenticated, isValidating, login, logout }),
|
||||||
[isAuthenticated, login, logout],
|
[isAuthenticated, isValidating, login, logout],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Show loading spinner while validating session on mount.
|
// Show loading spinner while validating session on mount.
|
||||||
|
|||||||
Reference in New Issue
Block a user