diff --git a/Docs/Tasks.md b/Docs/Tasks.md index c617c66..9fc9901 100644 --- a/Docs/Tasks.md +++ b/Docs/Tasks.md @@ -89,7 +89,9 @@ Issues are grouped by category and ordered roughly by severity. Each entry descr --- -### TASK-005 — `SetupGuard` redirects to `/setup` when the backend is temporarily unreachable +### TASK-005 — `SetupGuard` redirects to `/setup` when the backend is temporarily unreachable (done) + +**Where fixed:** `frontend/src/components/SetupGuard.tsx` **Where found:** `frontend/src/components/SetupGuard.tsx`. When `useSetup` returns `{ loading: false, status: null }` due to a network error, the guard treats this the same as "setup not completed" and redirects to `/setup`. diff --git a/frontend/src/components/SetupGuard.tsx b/frontend/src/components/SetupGuard.tsx index 6a589dd..cf6329a 100644 --- a/frontend/src/components/SetupGuard.tsx +++ b/frontend/src/components/SetupGuard.tsx @@ -7,7 +7,14 @@ */ import { Navigate } from "react-router-dom"; -import { Spinner, makeStyles } from "@fluentui/react-components"; +import { + Button, + MessageBar, + MessageBarBody, + Spinner, + makeStyles, + tokens, +} from "@fluentui/react-components"; import { useSetup } from "../hooks/useSetup"; /** @@ -22,7 +29,7 @@ interface SetupGuardProps { /** * Render `children` only when setup has been completed. * - * Redirects to `/setup` if setup is still pending. + * Redirects to `/setup` only when setup status is known and incomplete. */ const useStyles = makeStyles({ loadingWrapper: { @@ -31,11 +38,30 @@ const useStyles = makeStyles({ alignItems: "center", minHeight: "100vh", }, + errorContainer: { + display: "flex", + justifyContent: "center", + alignItems: "center", + minHeight: "100vh", + padding: tokens.spacingHorizontalM, + backgroundColor: tokens.colorNeutralBackground2, + }, + errorCard: { + width: "100%", + maxWidth: "520px", + display: "flex", + flexDirection: "column", + gap: tokens.spacingVerticalM, + padding: tokens.spacingVerticalL, + backgroundColor: tokens.colorNeutralBackground1, + borderRadius: tokens.borderRadiusXLarge, + boxShadow: tokens.shadow8, + }, }); export function SetupGuard({ children }: SetupGuardProps): React.JSX.Element { const styles = useStyles(); - const { status, loading } = useSetup(); + const { status, loading, error, refresh } = useSetup(); if (loading) { return ( @@ -45,6 +71,21 @@ export function SetupGuard({ children }: SetupGuardProps): React.JSX.Element { ); } + if (error && status === null) { + return ( +