feat(auth): RequireAuth route guard
This commit is contained in:
@@ -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:
|
||||
*
|
||||
* <Route element={<RequireAuth><Layout/></RequireAuth>}>
|
||||
* <Route path="/" element={<Dashboard />} />
|
||||
* ...
|
||||
* </Route>
|
||||
*
|
||||
* 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=<current path+search>`. 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 (
|
||||
<div className="min-h-screen flex items-center justify-center text-muted-foreground text-sm">
|
||||
Loading…
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (status === "unauthenticated") {
|
||||
return (
|
||||
<Navigate
|
||||
to={`/login?next=${encodeURIComponent(location.pathname + location.search)}`}
|
||||
replace
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <>{children}</>;
|
||||
}
|
||||
Reference in New Issue
Block a user