178 lines
4.6 KiB
TypeScript
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>
|
|
);
|