This commit is contained in:
Jonas Kappa
2025-11-10 09:57:37 +01:00
commit 1110280899
4 changed files with 141 additions and 0 deletions

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"liveServer.settings.port": 33333
}

3
index.css Normal file
View File

@@ -0,0 +1,3 @@
#timer {
font-size: 64px;
}

24
index.html Normal file
View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" />
<title>Stand Up!</title>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<div class="main">
<label for="interval1">Sitzen (min)</label>
<input type="text" name="interval1" id="interval1" />
<label for="interval2">Stehen (min)</label>
<input type="text" name="interval2" id="interval2" />
<button type="button" onclick="startTimer(event)">Start</button>
<button type="button" onclick="stopTimer(event)">Stop</button>
</div>
<div class="timer">
<div>Laufendes Interval: <span id="interval"></span></div>
<div id="timer">00:00:00</div>
</div>
<script src="index.js"></script>
</body>
</html>

111
index.js Normal file
View File

@@ -0,0 +1,111 @@
class Timer {
i1 = 0;
i2 = 0;
currentInterval = 1;
timerId;
progress = 0;
progressId;
constructor(i1, i2) {
this.i1 = i1;
this.i2 = i2;
}
startTimer() {
console.log("startTimer()");
this.notify();
if (this.timerId !== undefined) clearTimeout(this.timerId);
document.getElementById("interval").innerHTML =
this.currentInterval === 1 ? "Sitzen" : "Stehen";
this.startProgress();
this.timerId = setTimeout(
() => {
this.currentInterval = this.currentInterval === 1 ? 2 : 1;
this.startTimer();
},
this.currentInterval === 1 ? this.i1 : this.i2
);
}
notify() {
console.log("notify()");
if (Notification.permission === "granted") {
new Notification(
this.currentInterval === 1 ? "Du kannst sitzen" : "Steh auf, du Sack!"
);
} else if (Notification.permission !== "denied") {
Notification.requestPermission().then((permission) => {
if (permission === "granted") {
new Notification(
this.currentInterval === 1
? "Du kannst sitzen"
: "Steh auf, du Sack!"
);
}
});
}
}
startProgress() {
console.log("startProgress()");
if (this.progressId !== undefined) clearInterval(this.progressId);
this.progress = 0;
this.draw();
this.progressId = setInterval(() => {
this.progress += 1000;
this.draw();
}, 1e3);
}
draw() {
console.log("draw()");
let timeRemaining =
this.currentInterval === 1
? this.i1 - this.progress
: this.i2 - this.progress;
if (timeRemaining < 0) timeRemaining = 0;
document.getElementById("timer").innerHTML =
this.convertMillisecondsToTime(timeRemaining);
}
stop() {
console.log("stop()");
clearTimeout(this.timerId);
this.timerId = undefined;
clearInterval(this.progressId);
this.progressId = undefined;
this.progress = 0;
document.getElementById("timer").innerHTML = "00:00:00";
}
convertMillisecondsToTime(milliseconds) {
const s = Math.floor(milliseconds / 1000);
const hours = Math.floor(s / 3600);
const minutes = Math.floor((s % 3600) / 60);
const seconds = s % 60;
return `${hours.toString().padStart(2, "0")}:${minutes
.toString()
.padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
}
}
let timer;
function startTimer(e) {
e.preventDefault();
let interval1 = document.getElementById("interval1").value;
let interval2 = document.getElementById("interval2").value;
let i1 = parseInt(interval1);
let i2 = parseInt(interval2);
if (isNaN(i1) || isNaN(i2)) return;
if (timer) timer.stop();
timer = new Timer(i1 * 60 * 1e3, i2 * 60 * 1e3);
timer.startTimer();
}
function stopTimer(e) {
e.preventDefault();
if (timer) timer.stop();
timer = undefined;
}