website

source code for the ttmaths.uk website
Log | Files | Refs | README

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'));