Files
SkyMoney/web/src/main.tsx

178 lines
4.6 KiB
TypeScript

import React, { lazy } from "react";
import ReactDOM from "react-dom/client";
import {
RouterProvider,
createBrowserRouter,
createRoutesFromElements,
Route,
Navigate,
} from "react-router-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ToastProvider } from "./components/Toast";
import { RequireAuth } from "./components/RequireAuth";
import App from "./App";
import "./styles.css";
// Initialize theme before React renders
const theme = (localStorage.getItem("theme") as "dark" | "light" | "system") || "system";
const actualTheme = theme === "system"
? (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light")
: theme;
const colorScheme = (localStorage.getItem("colorScheme") as "blue" | "green" | "purple" | "orange") || "blue";
if (actualTheme === "dark") {
document.documentElement.setAttribute("data-theme", "dark");
document.documentElement.classList.add("dark");
document.body.classList.add("dark");
document.body.setAttribute("data-theme", "dark");
} else {
document.documentElement.setAttribute("data-theme", "light");
document.documentElement.classList.remove("dark");
document.body.classList.remove("dark");
document.body.setAttribute("data-theme", "light");
}
document.documentElement.classList.remove("scheme-blue", "scheme-green", "scheme-purple", "scheme-orange");
document.documentElement.classList.add(`scheme-${colorScheme}`);
const client = new QueryClient({
defaultOptions: {
queries: {
retry: 1,
refetchOnWindowFocus: false,
},
},
});
const DashboardPage = lazy(() => import("./pages/DashboardPage"));
const SpendPage = lazy(() => import("./pages/SpendPage"));
const IncomePage = lazy(() => import("./pages/IncomePage"));
const TransactionsPage = lazy(() => import("./pages/TransactionsPage"));
const SettingsPage = lazy(() => import("./pages/settings/SettingsPage"));
const HealthPage = lazy(() => import("./pages/HealthPage"));
const OnboardingPage = lazy(() => import("./pages/OnboardingPage"));
const LoginPage = lazy(() => import("./pages/LoginPage"));
const RegisterPage = lazy(() => import("./pages/RegisterPage"));
const router = createBrowserRouter(
createRoutesFromElements(
<Route element={<App />}>
{/* Public */}
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
{/* Protected onboarding */}
<Route
path="/onboarding"
element={
<RequireAuth>
<OnboardingPage />
</RequireAuth>
}
/>
{/* Authenticated app */}
<Route
path="/"
element={
<RequireAuth>
<DashboardPage />
</RequireAuth>
}
/>
<Route
path="/spend"
element={
<RequireAuth>
<SpendPage />
</RequireAuth>
}
/>
<Route
path="/income"
element={
<RequireAuth>
<IncomePage />
</RequireAuth>
}
/>
<Route
path="/transactions"
element={
<RequireAuth>
<TransactionsPage />
</RequireAuth>
}
/>
<Route
path="/settings"
element={
<RequireAuth>
<SettingsPage />
</RequireAuth>
}
/>
<Route
path="/settings/categories"
element={
<RequireAuth>
<SettingsPage />
</RequireAuth>
}
/>
<Route
path="/settings/plans"
element={
<RequireAuth>
<SettingsPage />
</RequireAuth>
}
/>
<Route
path="/settings/account"
element={
<RequireAuth>
<SettingsPage />
</RequireAuth>
}
/>
<Route
path="/settings/theme"
element={
<RequireAuth>
<SettingsPage />
</RequireAuth>
}
/>
<Route
path="/settings/reconcile"
element={
<RequireAuth>
<SettingsPage />
</RequireAuth>
}
/>
<Route
path="/health"
element={
<RequireAuth>
<HealthPage />
</RequireAuth>
}
/>
{/* Fallback */}
<Route path="*" element={<Navigate to="/" replace />} />
</Route>
)
);
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<QueryClientProvider client={client}>
<ToastProvider>
<RouterProvider router={router} />
</ToastProvider>
</QueryClientProvider>
</React.StrictMode>
);