diff --git a/src/App.tsx b/src/App.tsx
index cf051cb..28a58d8 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,43 +1,45 @@
import { useState, useEffect } from "react";
import OnboardingTour from "./components/OnboardingTour";
-import { BrowserRouter, Routes, Route } from 'react-router-dom';
-import { Toaster } from 'react-hot-toast';
-import Layout from './components/Layout';
-import LandingPage from './pages/LandingPage';
-import AuthPage from './pages/AuthPage';
-import ModeSelectPage from './pages/ModeSelectPage';
-import ScannerPage from './pages/ScannerPage';
-import AnalysisDashboard from './pages/AnalysisDashboard';
-import MarketMapPage from './pages/MarketMapPage';
-import ResultsPage from './pages/ResultsPage';
-import Leaderboard from './pages/Leaderboard';
-import PostHogPageView from './components/PostHogPageView';
-import NotFound from './pages/NotFound';
-import InstallPrompt from './components/InstallPrompt';
+import { BrowserRouter, Routes, Route } from "react-router-dom";
+import { Toaster } from "react-hot-toast";
+import Layout from "./components/Layout";
+import LandingPage from "./pages/LandingPage";
+import AuthPage from "./pages/AuthPage";
+import ModeSelectPage from "./pages/ModeSelectPage";
+import ScannerPage from "./pages/ScannerPage";
+import AnalysisDashboard from "./pages/AnalysisDashboard";
+import MarketMapPage from "./pages/MarketMapPage";
+import ResultsPage from "./pages/ResultsPage";
+import Leaderboard from "./pages/Leaderboard";
+import PostHogPageView from "./components/PostHogPageView";
+import NotFound from "./pages/NotFound";
+import InstallPrompt from "./components/InstallPrompt";
import PublicReport from "./pages/PublicReport";
+import BackToTopButton from "./components/BackToTopButton";
export default function App() {
const [runTour, setRunTour] = useState(false);
-useEffect(() => {
- const completed = localStorage.getItem("tour-completed");
+ useEffect(() => {
+ const completed = localStorage.getItem("tour-completed");
- if (!completed) {
- setTimeout(() => {
- setRunTour(true);
- localStorage.setItem("tour-completed", "true");
- }, 0);
- }
-}, []);
+ if (!completed) {
+ setTimeout(() => {
+ setRunTour(true);
+ localStorage.setItem("tour-completed", "true");
+ }, 0);
+ }
+ }, []);
return (
{/* Toast provider for global error notifications */}
-
+
{/* Fires a $pageview event to PostHog on every SPA route change */}
+
}>
} />
@@ -48,7 +50,7 @@ useEffect(() => {
} />
} />
} />
-
+
{/* Public shareable report — MUST be before the * catchall */}
} />
@@ -58,4 +60,4 @@ useEffect(() => {
);
-}
\ No newline at end of file
+}
diff --git a/src/components/BackToTopButton.tsx b/src/components/BackToTopButton.tsx
new file mode 100644
index 0000000..1ae4a23
--- /dev/null
+++ b/src/components/BackToTopButton.tsx
@@ -0,0 +1,42 @@
+import { useEffect, useState } from "react";
+import { ArrowUp } from "lucide-react";
+
+export default function BackToTopButton() {
+ const [isVisible, setIsVisible] = useState(false);
+
+ useEffect(() => {
+ const toggleVisibility = () => {
+ setIsVisible(window.scrollY > 300);
+ };
+
+ window.addEventListener("scroll", toggleVisibility);
+ toggleVisibility();
+
+ return () => window.removeEventListener("scroll", toggleVisibility);
+ }, []);
+
+ const scrollToTop = () => {
+ window.scrollTo({
+ top: 0,
+ behavior: "smooth",
+ });
+ };
+
+ return (
+
+ );
+}