JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
HTML
<!--
Create timer that keeps you on track to do n questions in m minutes
(default 23 questions in 35 minutes)
-->
CSS
* {
box-sizing: border-box;
}
h1 {
text-align: center;
}
label {
display: block;
margin-bottom: 16px;
}
label div {
font-size: 20px;
margin-bottom: 4px;
}
input[type="number"] {
font-size: 24px;
padding: 8px 16px;
text-align: center;
width: 100%;
}
button,
input[type="submit"] {
font-size: 24px;
padding: 8px 16px;
}
.mainButtonWrapper {
text-align: center;
}
JavaScript
import { html, render, useState, useReducer, useEffect, useCallback } from "https://unpkg.com/htm/preact/standalone.module.js";
function App() {
const [settings, setSettings] = useState(null);
const { time, status, start, pause, reset } = useStopwatch();
useEffect(() => {
if (settings === null) {
document.title = "LSAT Timer";
} else {
const durationPerQuestion = settings.totalTime / settings.questions;
const currentQuestion = 1 + Math.floor(time / durationPerQuestion);
const done = time > settings.totalTime;
if (done) {
document.title = "Done! | LSAT Timer";
} else {
document.title = `Q${currentQuestion} | LSAT Timer`
}
}
}, [settings, time]);
if (settings === null) {
const onSubmit = (event) => {
event.preventDefault();
const data = new FormData(event.target);
reset();
setSettings({
totalTime: 60 * Number(data.get("totalTime")),
questions: Number(data.get("questions"))
});
}
return html`
<h1>LSAT Timer</h1>
<form onSubmit=${onSubmit}>
<label>
<div>Number of questions:</div>
<input type="number" name="questions" defaultValue=${23} min=${1} />
</label>
<label>
<div>Total time (minutes):</div>
<input type="number" name="totalTime" defaultValue=${35} step="any" min=${0} />
</label>
<div>
<input type="submit" value="Confirm" />
</div>
</form>
`;
}
const durationPerQuestion = settings.totalTime / settings.questions;
const currentQuestion = 1 + Math.floor(time / durationPerQuestion);
const timeSpentOnQuestion = (time % durationPerQuestion) / durationPerQuestion;
const done = time > settings.totalTime;
return html`
${done
? html`<h1>Done</h1>`
: html`
<h1>Question ${currentQuestion}</h1>
<div
style=${{
position: "fixed",
...