Fix geo_re_resolve async mocks and mark tasks complete

This commit is contained in:
2026-03-17 18:54:25 +01:00
parent 25d43ffb96
commit 6515164d53
12 changed files with 208 additions and 136 deletions

View File

@@ -99,37 +99,18 @@ export function SetupPage(): React.JSX.Element {
const styles = useStyles();
const navigate = useNavigate();
const [checking, setChecking] = useState(true);
const { status, loading, error, submit, submitting, submitError } = useSetup();
const [values, setValues] = useState<FormValues>(DEFAULT_VALUES);
const [errors, setErrors] = useState<Partial<Record<keyof FormValues, string>>>({});
const [apiError, setApiError] = useState<string | null>(null);
const [submitting, setSubmitting] = useState(false);
const apiError = error ?? submitError;
// Redirect to /login if setup has already been completed.
// Show a full-screen spinner while the check is in flight to prevent
// the form from flashing before the redirect fires.
// Show a full-screen spinner while the initial status check is in flight.
useEffect(() => {
let cancelled = false;
getSetupStatus()
.then((res) => {
if (!cancelled) {
if (res.completed) {
navigate("/login", { replace: true });
} else {
setChecking(false);
}
}
})
.catch(() => {
// Failed check: the backend may still be starting up. Stay on this
// page so the user can attempt setup once the backend is ready.
console.warn("SetupPage: setup status check failed — rendering setup form");
if (!cancelled) setChecking(false);
});
return (): void => {
cancelled = true;
};
}, [navigate]);
if (status?.completed) {
navigate("/login", { replace: true });
}
}, [navigate, status]);
// ---------------------------------------------------------------------------
// Handlers
@@ -169,13 +150,11 @@ export function SetupPage(): React.JSX.Element {
async function handleSubmit(ev: FormEvent<HTMLFormElement>): Promise<void> {
ev.preventDefault();
setApiError(null);
if (!validate()) return;
setSubmitting(true);
try {
await submitSetup({
await submit({
master_password: values.masterPassword,
database_path: values.databasePath,
fail2ban_socket: values.fail2banSocket,
@@ -183,14 +162,8 @@ export function SetupPage(): React.JSX.Element {
session_duration_minutes: parseInt(values.sessionDurationMinutes, 10),
});
navigate("/login", { replace: true });
} catch (err) {
if (err instanceof ApiError) {
setApiError(err.message || `Error ${String(err.status)}`);
} else {
setApiError("An unexpected error occurred. Please try again.");
}
} finally {
setSubmitting(false);
} catch {
// Errors are surfaced through the hook via `submitError`.
}
}
@@ -198,7 +171,7 @@ export function SetupPage(): React.JSX.Element {
// Render
// ---------------------------------------------------------------------------
if (checking) {
if (loading) {
return (
<div
style={{
@@ -224,7 +197,7 @@ export function SetupPage(): React.JSX.Element {
is complete.
</Text>
{apiError !== null && (
{apiError && (
<MessageBar intent="error" className={styles.error}>
<MessageBarBody>{apiError}</MessageBarBody>
</MessageBar>