Initial commit: MyMidas personal finance tracker
Full-stack self-hosted finance app with FastAPI backend and React frontend. Features: - Accounts, transactions, budgets, investments with GBP base currency - CSV import with auto-detection for 10 UK bank formats - ML predictions: spending forecast, net worth projection, Monte Carlo - 7 selectable themes (Obsidian, Arctic, Midnight, Vault, Terminal, Synthwave, Ledger) - Receipt/document attachments on transactions (JPEG, PNG, WebP, PDF) - AES-256-GCM field encryption, RS256 JWT, TOTP 2FA, RLS, audit log - Encrypted nightly backups + key rotation script - Mobile-responsive layout with bottom nav Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
61a7884ee5
127 changed files with 13323 additions and 0 deletions
67
frontend/src/App.tsx
Normal file
67
frontend/src/App.tsx
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import { useEffect } from "react";
|
||||
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
|
||||
import { useAuthStore } from "@/store/authStore";
|
||||
import { useUiStore } from "@/store/uiStore";
|
||||
import AppShell from "@/components/layout/AppShell";
|
||||
import LoginPage from "@/pages/auth/Login";
|
||||
import TwoFactorSetupPage from "@/pages/auth/TwoFactorSetup";
|
||||
import Dashboard from "@/pages/dashboard/Dashboard";
|
||||
import AccountList from "@/pages/accounts/AccountList";
|
||||
import AccountDetail from "@/pages/accounts/AccountDetail";
|
||||
import TransactionList from "@/pages/transactions/TransactionList";
|
||||
import TransactionImport from "@/pages/transactions/TransactionImport";
|
||||
import BudgetPage from "@/pages/budgets/BudgetPage";
|
||||
import ReportsPage from "@/pages/reports/ReportsPage";
|
||||
import PortfolioPage from "@/pages/investments/PortfolioPage";
|
||||
import AssetDetail from "@/pages/investments/AssetDetail";
|
||||
import PredictionsPage from "@/pages/predictions/PredictionsPage";
|
||||
import SettingsPage from "@/pages/settings/SettingsPage";
|
||||
|
||||
function PrivateRoute({ children }: { children: React.ReactNode }) {
|
||||
const token = useAuthStore((s) => s.token);
|
||||
return token ? <>{children}</> : <Navigate to="/login" replace />;
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const theme = useUiStore((s) => s.theme);
|
||||
|
||||
// Apply theme class to <html> so CSS variables cascade to body and all children
|
||||
useEffect(() => {
|
||||
const html = document.documentElement;
|
||||
html.classList.forEach(c => { if (c.startsWith("theme-")) html.classList.remove(c); });
|
||||
html.classList.add(`theme-${theme}`);
|
||||
}, [theme]);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground">
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route
|
||||
path="/*"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<AppShell>
|
||||
<Routes>
|
||||
<Route path="/" element={<Dashboard />} />
|
||||
<Route path="/security/totp" element={<TwoFactorSetupPage />} />
|
||||
<Route path="/accounts" element={<AccountList />} />
|
||||
<Route path="/accounts/:accountId" element={<AccountDetail />} />
|
||||
<Route path="/transactions" element={<TransactionList />} />
|
||||
<Route path="/transactions/import" element={<TransactionImport />} />
|
||||
<Route path="/budgets" element={<BudgetPage />} />
|
||||
<Route path="/reports" element={<ReportsPage />} />
|
||||
<Route path="/investments" element={<PortfolioPage />} />
|
||||
<Route path="/investments/:assetId" element={<AssetDetail />} />
|
||||
<Route path="/predictions" element={<PredictionsPage />} />
|
||||
<Route path="/settings" element={<SettingsPage />} />
|
||||
</Routes>
|
||||
</AppShell>
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue