import { useState, useEffect, useRef, useCallback } 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 AdminReports from "./pages/AdminReports"; import AdminPipeline from "./pages/AdminPipeline"; import AdminTechniquePages from "./pages/AdminTechniquePages"; import About from "./pages/About"; import Login from "./pages/Login"; import Register from "./pages/Register"; import AdminDropdown from "./components/AdminDropdown"; import AppFooter from "./components/AppFooter"; import SearchAutocomplete from "./components/SearchAutocomplete"; import { AuthProvider } from "./context/AuthContext"; export default function App() { 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 */} } /> } /> {/* Fallback */} } />
); }