index.jsx (3049B)
1 import { render } from 'preact'; 2 import { Route, Switch, Link } from 'wouter-preact'; 3 import QuestionCard from './components/QuestionCard.jsx'; 4 import Card from './components/Card.jsx'; 5 6 import Home from './pages/Home.jsx'; 7 import LatexRenderer from './pages/LatexRenderer.jsx'; 8 import NotFound from './pages/NotFound.jsx'; 9 10 import './styles/index.css'; 11 12 const data = import.meta.glob('./*/*.js', { 13 eager: true, import: 'data', base: './data/questions' 14 }); 15 16 function getHref(path) { 17 const relative = path.match(/([^\/]+).js$/)[1]; 18 return `/questions/${relative}`; 19 } 20 21 const tree = { }; 22 for (const path in data) { 23 const category = path.match(/^\.\/(.+)\//)[1]; 24 tree[category] ??= []; 25 tree[category].push({ 26 href: getHref(path), 27 title: data[path].title 28 }); 29 } 30 31 function getActiveClass(active) { 32 return active ? "active" : ""; 33 } 34 35 function SidebarLink({ href, title, children }) { 36 return ( 37 <li> 38 <Link href={href} className={getActiveClass}> 39 {title} 40 </Link> 41 {children} 42 </li> 43 ); 44 } 45 46 function SidebarQuestionCategory({ categoryName, categoryList }) { 47 const questionLinks = categoryList.map(c => <SidebarLink href={c.href} title={c.title} />); 48 return ( 49 <li> 50 <details open> 51 <summary>{categoryName}</summary> 52 <ul> 53 {questionLinks} 54 </ul> 55 </details> 56 </li> 57 ); 58 } 59 60 const sidebarQuestions = Object.keys(tree).map(categoryName => { 61 return <SidebarQuestionCategory categoryName={categoryName} categoryList={tree[categoryName]} />; 62 }); 63 64 const questionRoutes = Object.keys(data).map(path => { 65 return <Route path={getHref(path)}><QuestionCard data={data[path]} /></Route>; 66 }) 67 68 function Sidebar() { 69 return ( 70 <nav id="sidebar"> 71 <ul> 72 <SidebarLink href="/" title="Home" /> 73 <SidebarLink href="/questions" title="Questions"> 74 <Route path="/questions/*?"> 75 <ul> 76 {sidebarQuestions} 77 </ul> 78 </Route> 79 </SidebarLink> 80 <SidebarLink href="/renderer" title="LaTeX Renderer" /> 81 <li><a href="https://git.ttmaths.uk" target="_blank">Source Code</a></li> 82 </ul> 83 </nav> 84 ); 85 } 86 87 function QuestionIndex() { 88 return ( 89 <Card title="Questions"> 90 <nav class="index"> 91 <ul> 92 {sidebarQuestions} 93 </ul> 94 </nav> 95 </Card> 96 ); 97 } 98 99 export function App() { 100 return ( 101 <> 102 <header> 103 <a id="logo" href="/"><h1>TTMaths</h1></a> 104 <span id="tagline">resources for learning</span> 105 </header> 106 <div id="sidebar-and-main"> 107 <Sidebar /> 108 <main> 109 <Switch> 110 <Route path="/" component={Home} /> 111 <Route path="/questions" component={QuestionIndex} /> 112 <Route path="/questions/*"> 113 {questionRoutes} 114 </Route> 115 <Route path="/renderer" component={LatexRenderer} /> 116 <Route component={NotFound} /> 117 </Switch> 118 </main> 119 </div> 120 </> 121 ); 122 } 123 124 render(<App />, document.getElementById('app'));