diff --git a/src/auth/RequireAuth.tsx b/src/auth/RequireAuth.tsx new file mode 100644 index 0000000..040de56 --- /dev/null +++ b/src/auth/RequireAuth.tsx @@ -0,0 +1,43 @@ +import { Navigate, useLocation } from "react-router-dom"; +import { useAuth } from "./useAuth"; +import type { ReactNode } from "react"; + +/** + * Route guard. Wrap any subtree that requires a logged-in operator: + * + * }> + * } /> + * ... + * + * + * Three branches, in priority order: + * + * 1. `status === "loading"` → render a centered "Loading…" + * placeholder so we don't bounce the user to /login before the + * cookie has had a chance to prove itself via /api/auth/me. + * 2. `status === "unauthenticated"` → redirect to + * `/login?next=`. The Login page reads + * `next` and bounces the operator back here on success. + * 3. otherwise → render children (status is + * "authenticated"). + */ +export function RequireAuth({ children }: { children: ReactNode }) { + const { status } = useAuth(); + const location = useLocation(); + if (status === "loading") { + return ( +
+ Loading… +
+ ); + } + if (status === "unauthenticated") { + return ( + + ); + } + return <>{children}; +}