1
0

implement very basic UI

This commit is contained in:
Adrian Wannenmacher 2026-02-15 22:31:36 +01:00
parent bcb08a64d2
commit 624063b91e
Signed by: tfld
GPG Key ID: 19D986ECB1E492D5
6 changed files with 1854 additions and 0 deletions

33
index.html Normal file
View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="de-AT">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Watterblock</title>
<script src="vendored/mithril-2.3.8.js" defer></script>
<script type="module">
// initialize DB early
import WbDb from "./data/db.js";
WbDb.get();
// mount app
import App from "./ui/app.js";
m.mount(document.body, App);
</script>
</head>
<body>
<p>Watterblock wird geladen…</p>
<noscript>
<p>Das Laden des Watterblocks ist fehlgeschlagen.</p>
<p>
Der Watterblock ist ein Programm, dass direkt in deinem Browser läuft.
Der Server sendet nur am Anfang die benötigten Dateien. Für die
Funktionalität ist daher <em>JavaScript</em> zwingend erforderlich.
</p>
<p><strong>Bitte aktiviere <em>JavaScript</em> wieder.</strong></p>
</noscript>
</body>
</html>

12
ui/app.js Normal file
View File

@ -0,0 +1,12 @@
"use strict";
import Session from "../models/session.js";
import SessionView from "./session.js";
export default class App {
#session = new Session();
view() {
return m(SessionView, { model: this.#session });
}
}

44
ui/game.js Normal file
View File

@ -0,0 +1,44 @@
"use strict";
import { Team } from "../models/round.js";
import Game from "../models/game.js";
import RoundView from "./round.js";
export default class GameView {
/** @param {{ attrs: { model: Game } }} param The game model to use. */
view({ attrs: { model } }) {
let { winner, points, ourPoints, theirPoints } = model.result;
let markers = "•".repeat(points);
return m("section", [
m("table", [
m("thead", [
m("tr", [
m("th", "se"), m("th", "mia"),
]),
winner !== null
? m("tr", [
m("td", winner === Team.We ? markers : ""),
m("td", winner === Team.They ? markers : ""),
])
: null,
]),
m("tbody", model.rounds.map(function(round) {
return m("tr", [
m("td", round.winner === Team.They ? round.points : ""),
m("td", round.winner === Team.We ? round.points : ""),
]);
})),
m("tfoot", [
m("tr", [
m("th", theirPoints), m("th", ourPoints),
]),
]),
]),
(model.currentRound !== null)
? m(RoundView, { model: model.currentRound })
: null,
]);
}
}

51
ui/round.js Normal file
View File

@ -0,0 +1,51 @@
"use strict";
import { Round, Team } from "../models/round.js";
export default class RoundView {
/** @param { { attrs: { model: Round } } } param The round model to use. */
view({ attrs: { model } }) {
let winner = "no koana";
if (model.winner === Team.We)
winner = "mia";
else if (model.winner === Team.They)
winner = "se";
return m("section", [
m("p", `${model.points} Punkte`),
m("div", [
m("button",
{
onclick: () => model.raise(Team.They),
disabled: !model.canRaise(Team.They),
},
"se erhöhn",
),
m("button",
{
onclick: () => model.raise(Team.We),
disabled: !model.canRaise(Team.We),
},
"mia erhöhn",
),
]),
m("div", [
m("button",
{
onclick: () => model.winner = Team.They,
disabled: model.decided,
},
"se habn gwonnen",
),
m("button",
{
onclick: () => model.winner = Team.We,
disabled: model.decided,
},
"mia habn gwonnen",
),
]),
]);
}
}

16
ui/session.js Normal file
View File

@ -0,0 +1,16 @@
"use strict";
import Session from "../models/session.js";
import GameView from "./game.js";
export default class SessionView {
/** @param {{ attrs: { model: Session } }} param The session model to use. */
view({ attrs: { model } }) {
return m("article", [
model.games.map((g) => m(GameView, { model: g })),
model.currentGame !== null
? m(GameView, { model: model.currentGame })
: m("button", { onclick: () => model.anotherGame() }, "no a spiel"),
]);
}
}

1698
vendored/mithril-2.3.8.js Normal file

File diff suppressed because it is too large Load Diff