website

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

commit 36c7430ca5bf7cbe258333b852af89cf334ffb61
parent e18fcd315136bcad4b76036293c13650aabe630d
Author: hrryt <harry@mayesfield.uk>
Date:   Mon, 17 Aug 2026 12:53:34 +0100

Read questions index structure from /src/data file structure

Diffstat:
Msrc/components/QuestionWindow.jsx | 4++--
Asrc/data/questions/GCSE/adding-fractions.js | 24++++++++++++++++++++++++
Asrc/data/questions/GCSE/double-transformations.js | 16++++++++++++++++
Asrc/data/questions/GCSE/quadratic-equations.js | 31+++++++++++++++++++++++++++++++
Dsrc/data/questions/gcse/adding-fractions.js | 23-----------------------
Dsrc/data/questions/gcse/double-transformations.js | 15---------------
Dsrc/data/questions/gcse/quadratic-equations.js | 30------------------------------
Msrc/pages/QuestionIndex.jsx | 67+++++++++++++++++++++++++++++--------------------------------------
8 files changed, 102 insertions(+), 108 deletions(-)

diff --git a/src/components/QuestionWindow.jsx b/src/components/QuestionWindow.jsx @@ -34,7 +34,7 @@ function shuffleArray(arr, n, seed) { return Array.from({ length: n }).map(() => getRandomChoice(arr, ++seed)); } -export default function QuestionWindow({ data, title }) { +export default function QuestionWindow({ data }) { const dataVariables = data.variables ?? []; @@ -73,7 +73,7 @@ export default function QuestionWindow({ data, title }) { }); return ( - <Window title={title}> + <Window title={data.title}> {fields} <fieldset> <legend>Options</legend> diff --git a/src/data/questions/GCSE/adding-fractions.js b/src/data/questions/GCSE/adding-fractions.js @@ -0,0 +1,24 @@ +import AddingFractionsQuestion from '/src/components/questions/AddingFractionsQuestion.jsx'; + +export const data = { + title: 'Adding Fractions', + questionLists: [{ + id: 0, + n: 10, + questions: [{ + type: AddingFractionsQuestion, + }] + }, { + id: 1, + n: 10, + questions: [{ + type: AddingFractionsQuestion, + }] + }, { + id: 2, + n: 10, + questions: [{ + type: AddingFractionsQuestion, + }] + }] +} diff --git a/src/data/questions/GCSE/double-transformations.js b/src/data/questions/GCSE/double-transformations.js @@ -0,0 +1,16 @@ +import DoubleReflectionQuestion from "../../../components/questions/DoubleReflectionQuestion"; +import RotationTranslationQuestion from "../../../components/questions/RotationTranslationQuestion"; + +export const data = { + title: 'Double Transformations', + questionLists: [{ + id: 0, + n: 3, + questions: [{ + type: RotationTranslationQuestion, + }, + { + type: DoubleReflectionQuestion, + }] + }] +} diff --git a/src/data/questions/GCSE/quadratic-equations.js b/src/data/questions/GCSE/quadratic-equations.js @@ -0,0 +1,31 @@ +import QuadraticEquationQuestion from '/src/components/questions/QuadraticEquationQuestion.jsx'; +import MultipleSelection from '/src/components/MultipleSelection.jsx'; + +export const data = { + title: 'Quadratic Equations', + variables: [{ + id: 'framing', + legend: 'Framing', + type: MultipleSelection, + values: ["Solve", "Factorise"], + }, { + id: 'aPlurality', + legend: 'Coefficient a', + type: MultipleSelection, + values: ["a=1", "a>1"], + default: ["a=1"], + }, { + id: 'cSigns', + legend: 'Coefficient c', + type: MultipleSelection, + values: ["Positive", "Negative"], + }], + questionLists: [{ + id: 0, + n: 10, + questions: [{ + type: QuadraticEquationQuestion, + variables: { aPlurality: 'aPlurality', framing: 'framing', cSigns: 'cSigns' }, + }] + }] +} diff --git a/src/data/questions/gcse/adding-fractions.js b/src/data/questions/gcse/adding-fractions.js @@ -1,23 +0,0 @@ -import AddingFractionsQuestion from '/src/components/questions/AddingFractionsQuestion.jsx'; - -export const data = { - questionLists: [{ - id: 0, - n: 10, - questions: [{ - type: AddingFractionsQuestion, - }] - }, { - id: 1, - n: 10, - questions: [{ - type: AddingFractionsQuestion, - }] - }, { - id: 2, - n: 10, - questions: [{ - type: AddingFractionsQuestion, - }] - }] -} diff --git a/src/data/questions/gcse/double-transformations.js b/src/data/questions/gcse/double-transformations.js @@ -1,15 +0,0 @@ -import DoubleReflectionQuestion from "../../../components/questions/DoubleReflectionQuestion"; -import RotationTranslationQuestion from "../../../components/questions/RotationTranslationQuestion"; - -export const data = { - questionLists: [{ - id: 0, - n: 3, - questions: [{ - type: RotationTranslationQuestion, - }, - { - type: DoubleReflectionQuestion, - }] - }] -} diff --git a/src/data/questions/gcse/quadratic-equations.js b/src/data/questions/gcse/quadratic-equations.js @@ -1,30 +0,0 @@ -import QuadraticEquationQuestion from '/src/components/questions/QuadraticEquationQuestion.jsx'; -import MultipleSelection from '/src/components/MultipleSelection.jsx'; - -export const data = { - variables: [{ - id: 'framing', - legend: 'Framing', - type: MultipleSelection, - values: ["Solve", "Factorise"], - }, { - id: 'aPlurality', - legend: 'Coefficient a', - type: MultipleSelection, - values: ["a=1", "a>1"], - default: ["a=1"], - }, { - id: 'cSigns', - legend: 'Coefficient c', - type: MultipleSelection, - values: ["Positive", "Negative"], - }], - questionLists: [{ - id: 0, - n: 10, - questions: [{ - type: QuadraticEquationQuestion, - variables: { aPlurality: 'aPlurality', framing: 'framing', cSigns: 'cSigns' }, - }] - }] -} diff --git a/src/pages/QuestionIndex.jsx b/src/pages/QuestionIndex.jsx @@ -1,70 +1,61 @@ import { Route, Switch, Link } from 'wouter-preact'; - import QuestionWindow from '../components/QuestionWindow.jsx'; +const data = import.meta.glob('./*/*.js', { + eager: true, import: 'data', base: '../data/questions' +}); -const allQuestions = [{ - id: 'gcse', - label: 'GCSE', - questions: [{ - id: 'quadratic-equations', - label: 'Quadratic Equations' - }, { - id: 'adding-fractions', - label: 'Adding Fractions' - }, { - id: 'double-transformations', - label: 'Double Transformations' - }] -}, { - id: 'a-level', - label: 'A-Level', - questions: [] -}] +function getHref(path) { + const relative = path.match(/\.\/(.+).js/)[1]; + return `/questions/${relative}`; +} -function QuestionItem({ id, question }) { +function QuestionLink({ href, title }) { return ( <li> - <Link href={`/questions/${id}/${question.id}`}> - {question.label} + <Link href={href}> + {title} </Link> </li> ); } -function QuestionsItem({ id, label, questions }) { +const tree = { }; +for (const path in data) { + const category = path.match(/^\.\/(.+)\//)[1]; + tree[category] ??= []; + tree[category].push( + <QuestionLink href={getHref(path)} title={data[path].title} /> + ); +} + +function Category({ category, questionLinks }) { return ( <li> <details open> - <summary>{label}</summary> + <summary>{category}</summary> <ul> - {questions.map(question => - <QuestionItem id={id} question={question} /> - )} + {questionLinks} </ul> </details> </li> ); } -const items = allQuestions.map(({ id, label, questions }) => - <QuestionsItem id={id} label={label} questions={questions} /> +const categories = Object.keys(tree).map(category => + <Category category={category} questionLinks={tree[category]} /> ); -const arr = await Promise.all(allQuestions.map(async ({ id, questions }) => - await Promise.all(questions.map( async question => { - const m = await import(`../data/questions/${id}/${question.id}.js`); - function Component() { return <QuestionWindow data={m.data} title={question.label} />; } - return <Route path={`/questions/${id}/${question.id}`} component={Component} />; - })) -)); -const routes = arr.flat(); +const routes = Object.keys(data).map(path => { + function Component() { return <QuestionWindow data={data[path]} />; } + return <Route path={getHref(path)} component={Component} />; +}) export default function QuestionIndex() { return ( <main> <nav class="sidebar"> <ul class="tree-view"> - {items} + {categories} </ul> </nav> <Switch>