import { BrowserRouter, Routes, Route } from "react-router-dom"; import { useEffect, useState, useRef } from "react"; import { useTranslation } from "react-i18next"; import { useProfile } from "./contexts/ProfileContext"; import AppShell from "./components/layout/AppShell"; import DashboardPage from "./pages/DashboardPage"; import ImportPage from "./pages/ImportPage"; import TransactionsPage from "./pages/TransactionsPage"; import CategoriesPage from "./pages/CategoriesPage"; import AdjustmentsPage from "./pages/AdjustmentsPage"; import BudgetPage from "./pages/BudgetPage"; import ReportsPage from "./pages/ReportsPage"; import SettingsPage from "./pages/SettingsPage"; import DocsPage from "./pages/DocsPage"; import ProfileSelectionPage from "./pages/ProfileSelectionPage"; import ErrorPage from "./components/shared/ErrorPage"; const STARTUP_TIMEOUT_MS = 10_000; const MAX_RETRIES = 3; const RETRY_DELAY_MS = 1_000; export default function App() { const { t } = useTranslation(); const { activeProfile, isLoading, refreshKey, connectActiveProfile } = useProfile(); const [dbReady, setDbReady] = useState(false); const [startupError, setStartupError] = useState(null); const timeoutRef = useRef | null>(null); const cancelledRef = useRef(false); useEffect(() => { if (activeProfile && !isLoading) { setDbReady(false); setStartupError(null); cancelledRef.current = false; timeoutRef.current = setTimeout(() => { setStartupError(t("error.startupTimeout")); }, STARTUP_TIMEOUT_MS); const attemptConnect = async (attempt: number): Promise => { try { await connectActiveProfile(); if (cancelledRef.current) return; if (timeoutRef.current) clearTimeout(timeoutRef.current); setDbReady(true); } catch (err) { if (cancelledRef.current) return; console.error(`Failed to connect profile (attempt ${attempt}/${MAX_RETRIES}):`, err); if (attempt < MAX_RETRIES) { await new Promise((r) => setTimeout(r, RETRY_DELAY_MS)); if (!cancelledRef.current) return attemptConnect(attempt + 1); } else { if (timeoutRef.current) clearTimeout(timeoutRef.current); setStartupError(err instanceof Error ? err.message : String(err)); } } }; attemptConnect(1); } return () => { cancelledRef.current = true; if (timeoutRef.current) clearTimeout(timeoutRef.current); }; }, [activeProfile, isLoading, connectActiveProfile, t]); if (isLoading) { return (
); } if (startupError) { return ; } if (!activeProfile) { return ; } if (!dbReady) { return (
); } return ( }> } /> } /> } /> } /> } /> } /> } /> } /> } /> ); }