import React, { useState, useEffect, useRef, useCallback, Suspense } from "react";
import { Link, Navigate, Route, Routes, useLocation, useNavigate } from "react-router-dom";
import Home from "./pages/Home";
import SearchResults from "./pages/SearchResults";
import TechniquePage from "./pages/TechniquePage";
import CreatorsBrowse from "./pages/CreatorsBrowse";
import CreatorDetail from "./pages/CreatorDetail";
import TopicsBrowse from "./pages/TopicsBrowse";
import SubTopicPage from "./pages/SubTopicPage";
import Login from "./pages/Login";
import Register from "./pages/Register";
// Lazy-loaded pages — admin, creator, and info routes split into separate chunks
const AdminReports = React.lazy(() => import("./pages/AdminReports"));
const AdminPipeline = React.lazy(() => import("./pages/AdminPipeline"));
const AdminTechniquePages = React.lazy(() => import("./pages/AdminTechniquePages"));
const About = React.lazy(() => import("./pages/About"));
const CreatorDashboard = React.lazy(() => import("./pages/CreatorDashboard"));
const CreatorSettings = React.lazy(() => import("./pages/CreatorSettings"));
const WatchPage = React.lazy(() => import("./pages/WatchPage"));
import AdminDropdown from "./components/AdminDropdown";
import AppFooter from "./components/AppFooter";
import SearchAutocomplete from "./components/SearchAutocomplete";
import ProtectedRoute from "./components/ProtectedRoute";
import { AuthProvider, useAuth } from "./context/AuthContext";
function LoadingFallback() {
return (
);
}
function AuthNav() {
const { isAuthenticated, user, logout } = useAuth();
const navigate = useNavigate();
if (isAuthenticated) {
return (
<>
{user?.display_name ?? "Dashboard"}
>
);
}
return Login;
}
function AppShell() {
const location = useLocation();
const navigate = useNavigate();
const showNavSearch = location.pathname !== "/";
const [menuOpen, setMenuOpen] = useState(false);
const headerRef = useRef(null);
// Close menu on route change
useEffect(() => {
setMenuOpen(false);
}, [location.pathname]);
// Close menu on Escape
useEffect(() => {
if (!menuOpen) return;
const handleKey = (e: KeyboardEvent) => {
if (e.key === "Escape") setMenuOpen(false);
};
document.addEventListener("keydown", handleKey);
return () => document.removeEventListener("keydown", handleKey);
}, [menuOpen]);
// Close menu on outside click
const handleOutsideClick = useCallback(
(e: MouseEvent) => {
if (
menuOpen &&
headerRef.current &&
!headerRef.current.contains(e.target as Node)
) {
setMenuOpen(false);
}
},
[menuOpen],
);
useEffect(() => {
if (!menuOpen) return;
document.addEventListener("mousedown", handleOutsideClick);
return () => document.removeEventListener("mousedown", handleOutsideClick);
}, [menuOpen, handleOutsideClick]);
return (
Skip to content
Chrysopedia
{showNavSearch && (
navigate(`/search?q=${encodeURIComponent(q)}`)}
/>
)}
{/* Public routes */}
} />
} />
} />
}>} />
{/* Browse routes */}
} />
} />
} />
} />
{/* Admin routes */}
}>} />
}>} />
}>} />
{/* Info routes */}
}>} />
{/* Auth routes */}
} />
} />
{/* Creator routes (protected) */}
}>} />
}>} />
{/* Fallback */}
} />
);
}
export default function App() {
return (
);
}