Files
frontend/src/app/routes/RouteGuards.tsx
T
codex-bot 3af9df0ae2
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 1m3s
Frontend verify / verify (push) Failing after 7m11s
fix: keep session when refresh fails on network error or 5xx (WealthLedger/frontend#97)
2026-10-23 15:06:20 +03:00

72 lines
1.9 KiB
TypeScript

import { Button, Container } from "@mantine/core";
import { StateView } from "@wealthledger/ui";
import { type FC, type PropsWithChildren, useState } from "react";
import { useTranslation } from "react-i18next";
import { Navigate, useLocation } from "react-router";
import { useAuth } from "@/features/auth";
import { RouteSkeleton } from "./RouteFallback";
const Protected: FC<PropsWithChildren> = (props) => {
const { children } = props;
const { ready, retry, signedOut, unavailable, user } = useAuth();
const { t } = useTranslation();
const location = useLocation();
const [wasAuthenticated, setWasAuthenticated] = useState(false);
if (user && !wasAuthenticated) setWasAuthenticated(true);
if (!ready) return <RouteSkeleton variant="shell" />;
// The server was unreachable (e.g. mid-deploy), so the session is unproven, not gone.
if (!user && unavailable)
return (
<Container py="xl" size={560}>
<StateView
action={<Button onClick={retry}>{t("auth.retry")}</Button>}
error
text={t("auth.unavailableText")}
title={t("auth.unavailableTitle")}
/>
</Container>
);
const loginState = signedOut && wasAuthenticated
? undefined
: { returnTo: `${location.pathname}${location.search}` };
return user
? <>{children}</>
: (
<Navigate
replace
state={loginState}
to="/login"
/>
);
};
const Public: FC<PropsWithChildren> = (props) => {
const { children } = props;
const { ready, user } = useAuth();
const location = useLocation();
if (!ready) return <RouteSkeleton variant="shell" />;
const state: unknown = location.state;
const requested = state && typeof state === "object" && "returnTo" in state
? state.returnTo
: undefined;
const returnTo
= typeof requested === "string"
&& requested.startsWith("/")
&& !requested.startsWith("//")
? requested
: "/accounts";
return user ? <Navigate replace to={returnTo} /> : <>{children}</>;
};
export { Protected, Public };