From 22bd4e9dc54133b78f68a68afec785b829ae1ec2 Mon Sep 17 00:00:00 2001 From: y-syo Date: Tue, 2 Sep 2025 02:17:16 +0200 Subject: [PATCH 01/46] =?UTF-8?q?=E3=80=8C=F0=9F=8E=89=E3=80=8D=20init(src?= =?UTF-8?q?/front):=20initialized=20the=20frontend,=20ready=20to=20be=20wo?= =?UTF-8?q?rked=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flake.lock | 6 +++--- flake.nix | 1 + src/front/index.html | 2 ++ src/front/main.tsx | 1 + src/front/style.css | 6 ++++-- 5 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 src/front/main.tsx diff --git a/flake.lock b/flake.lock index 782aaad..dade030 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1753250450, - "narHash": "sha256-i+CQV2rPmP8wHxj0aq4siYyohHwVlsh40kV89f3nw1s=", + "lastModified": 1756542300, + "narHash": "sha256-tlOn88coG5fzdyqz6R93SQL5Gpq+m/DsWpekNFhqPQk=", "owner": "nixos", "repo": "nixpkgs", - "rev": "fc02ee70efb805d3b2865908a13ddd4474557ecf", + "rev": "d7600c775f877cd87b4f5a831c28aa94137377aa", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index b61cb1a..ecdab7e 100644 --- a/flake.nix +++ b/flake.nix @@ -50,6 +50,7 @@ echo Installing foundry env forge i fi + alias jarvis=just export PATH+=:$(pwd)/node_modules/.bin echo entering ft_trans env ''; diff --git a/src/front/index.html b/src/front/index.html index f2f5a6a..e7a3f05 100644 --- a/src/front/index.html +++ b/src/front/index.html @@ -7,6 +7,8 @@ + +

Vite + Tailwind

🚀 Looks like it's working!

diff --git a/src/front/main.tsx b/src/front/main.tsx new file mode 100644 index 0000000..2a2392b --- /dev/null +++ b/src/front/main.tsx @@ -0,0 +1 @@ +console.log("test") diff --git a/src/front/style.css b/src/front/style.css index b5c61c9..f5645cf 100644 --- a/src/front/style.css +++ b/src/front/style.css @@ -1,3 +1,5 @@ -@tailwind base; +@import "tailwindcss"; + +/*@tailwind base; @tailwind components; -@tailwind utilities; +@tailwind utilities;*/ From f0c764cc0c83658f44aa45f52299eb8826e4245e Mon Sep 17 00:00:00 2001 From: yosyo Date: Sat, 13 Sep 2025 15:57:43 +0200 Subject: [PATCH 02/46] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D?= =?UTF-8?q?=20wip(src/front):=20first=20try=20at=20a=20basic=20architectur?= =?UTF-8?q?e.=20game=20logic=20+=20SPA=20implemented?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flake.nix | 2 +- src/front/index.html | 41 +++-- src/front/main.tsx | 1 - src/front/static/assets/favicon.ico | Bin 0 -> 16141 bytes src/front/static/css/style.css | 5 + src/front/static/ts/main.ts | 69 +++++++ src/front/static/ts/views/Aview.ts | 10 + src/front/static/ts/views/Game.ts | 214 ++++++++++++++++++++++ src/front/static/ts/views/LoginPage.ts | 66 +++++++ src/front/static/ts/views/MainMenu.ts | 22 +++ src/front/static/ts/views/PongMenu.ts | 21 +++ src/front/static/ts/views/RegisterPage.ts | 27 +++ src/front/style.css | 5 - 13 files changed, 459 insertions(+), 24 deletions(-) delete mode 100644 src/front/main.tsx create mode 100644 src/front/static/assets/favicon.ico create mode 100644 src/front/static/css/style.css create mode 100644 src/front/static/ts/main.ts create mode 100644 src/front/static/ts/views/Aview.ts create mode 100644 src/front/static/ts/views/Game.ts create mode 100644 src/front/static/ts/views/LoginPage.ts create mode 100644 src/front/static/ts/views/MainMenu.ts create mode 100644 src/front/static/ts/views/PongMenu.ts create mode 100644 src/front/static/ts/views/RegisterPage.ts delete mode 100644 src/front/style.css diff --git a/flake.nix b/flake.nix index ecdab7e..fb52ec3 100644 --- a/flake.nix +++ b/flake.nix @@ -39,7 +39,7 @@ nodejs_22 pnpm just - foundry + foundry ]; shellHook = '' if [ ! -d node_modules/ ]; then diff --git a/src/front/index.html b/src/front/index.html index e7a3f05..97c4aea 100644 --- a/src/front/index.html +++ b/src/front/index.html @@ -1,21 +1,28 @@ - - - - Vite + Tailwind Test - - - - - -
-

Vite + Tailwind

-

🚀 Looks like it's working!

- -
- + + + + + + Vite + Tailwind Test + + + + + + + + + + +
+
+ + + diff --git a/src/front/main.tsx b/src/front/main.tsx deleted file mode 100644 index 2a2392b..0000000 --- a/src/front/main.tsx +++ /dev/null @@ -1 +0,0 @@ -console.log("test") diff --git a/src/front/static/assets/favicon.ico b/src/front/static/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..18945be5f045a1017b625d28282b42dc3a4a59c7 GIT binary patch literal 16141 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 literal 0 HcmV?d00001 diff --git a/src/front/static/css/style.css b/src/front/static/css/style.css new file mode 100644 index 0000000..0d686fe --- /dev/null +++ b/src/front/static/css/style.css @@ -0,0 +1,5 @@ +@import "tailwindcss"; + +@theme { + --color-accent-500: #f55151; +} diff --git a/src/front/static/ts/main.ts b/src/front/static/ts/main.ts new file mode 100644 index 0000000..676a313 --- /dev/null +++ b/src/front/static/ts/main.ts @@ -0,0 +1,69 @@ +/*import MainMenu from "./views/MainMenu.ts"; +import PongMenu from "./views/PongMenu.ts"; + +import LoginPage from "./views/LoginPage.ts"; +import RegisterPage from "./views/RegisterPage.ts"; + +import Game from "./views/Game.ts";*/ + +const navigationManager = url => { + history.pushState(null, null, url); + router(); +}; + +let view; + +const routes = [ + /*{ path: "/", view: MainMenu }, + + { path: "/pong", view: PongMenu }, + { path: "/pong/solo", view: Game }, + + { path: "/login", view: LoginPage }, + { path: "/register", view: RegisterPage },*/ + { path: "/", view: () => import("./views/MainMenu.ts") }, + + { path: "/pong", view: () => import("./views/PongMenu.ts") }, + { path: "/pong/solo", view: () => import("./views/Game.ts") }, + + { path: "/login", view: () => import("./views/LoginPage.ts") }, + { path: "/register", view: () => import("./views/RegisterPage.ts") }, +]; + +const router = async () => { + + const routesMap = routes.map(route => { + return { route: route, isMatch: location.pathname === route.path }; + }); + + let match = routesMap.find(routeMap => routeMap.isMatch); + + if (!match) + match = { route: routes[0], isMatch: true }; + + if (view) + view.running = false; + + console.log(match); + + const module = await match.route.view(); + view = new module.default(); + + document.querySelector("#app").innerHTML = await view.getHTML(); + view.run(); +}; + +window.addEventListener("popstate", router); + +document.addEventListener("DOMContentLoaded", () => { + + document.body.addEventListener("click", e=> { + if (e.target.matches("[data-link]")) + { + e.preventDefault(); + navigationManager(e.target.href); + } + }); + + router(); +}); diff --git a/src/front/static/ts/views/Aview.ts b/src/front/static/ts/views/Aview.ts new file mode 100644 index 0000000..810d3ab --- /dev/null +++ b/src/front/static/ts/views/Aview.ts @@ -0,0 +1,10 @@ +export default class { + contructor() + { + } + + setTitle(title) { document.title = title; } + + async getHTML() { return ""; } + async run() { } +}; diff --git a/src/front/static/ts/views/Game.ts b/src/front/static/ts/views/Game.ts new file mode 100644 index 0000000..5610676 --- /dev/null +++ b/src/front/static/ts/views/Game.ts @@ -0,0 +1,214 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + running: boolean; + + constructor() + { + super(); + this.setTitle("pog or pong ? :3"); + this.running = true; + } + + async getHTML() { + return ` + +
+ + +
+ `; + } + + async run() { + let start: number = 0; + let elapsed: number; + + let game_playing: boolean = false; + let match_over: boolean = false; + let p1_score: number = 0; + let p2_score: number = 0; + + let countdown: number = 3; + let countdownTimer: number = 0; + + const canvas = document.getElementById("gameCanvas") as HTMLCanvasElement; + const ctx = canvas.getContext("2d"); + + const paddleOffset: number = 15; + const paddleHeight: number = 100; + const paddleWidth: number = 10; + const ballSize: number = 10; + + let leftPaddleY: number = canvas.height / 2 - paddleHeight / 2; + let rightPaddleY: number = canvas.height / 2 - paddleHeight / 2; + let paddleSpeed: number = 727 * 0.69; + let ballX: number = canvas.width / 2; + let ballY: number = canvas.height / 2; + let ballSpeed: number = 200; + let ballSpeedX: number = 300; + let ballSpeedY: number = 10; + + const keys: Record = {}; + + document.addEventListener("keydown", e => { keys[e.key] = true; }); + document.addEventListener("keyup", e => { keys[e.key] = false; }); + + function movePaddles() { + if (keys["w"] && leftPaddleY > 0) + leftPaddleY -= paddleSpeed * elapsed; + if (keys["s"] && leftPaddleY < canvas.height - paddleHeight) + leftPaddleY += paddleSpeed * elapsed; + if (keys["ArrowUp"] && rightPaddleY > 0) + rightPaddleY -= paddleSpeed * elapsed; + if (keys["ArrowDown"] && rightPaddleY < canvas.height - paddleHeight) + rightPaddleY += paddleSpeed * elapsed; + } + + function getBounceVelocity(paddleY) { + const speed = ballSpeed; + const paddleCenterY = paddleY + paddleHeight / 2; + + let n = (ballY - paddleCenterY) / (paddleHeight / 2); + n = Math.max(-1, Math.min(1, n)); + let theta = n * ((75 * Math.PI) / 180); + ballSpeedY = ballSpeed * Math.sin(theta); + } + + function moveBall() { + let length = Math.sqrt(ballSpeedX * ballSpeedX + ballSpeedY * ballSpeedY); + let scale = ballSpeed / length; + ballX += (ballSpeedX * scale) * elapsed; + ballY += (ballSpeedY * scale) * elapsed; + + if (ballY <= 0 || ballY >= canvas.height - ballSize) + ballSpeedY *= -1; + + if (ballX <= paddleWidth + paddleOffset && ballX >= paddleOffset && + ballY > leftPaddleY && ballY < leftPaddleY + paddleHeight) + { + ballSpeedX *= -1; + ballX = paddleWidth + paddleOffset; + getBounceVelocity(leftPaddleY); + ballSpeed += 10; + } + + if (ballX >= canvas.width - paddleWidth - ballSize - paddleOffset && ballX <= canvas.width - ballSize - paddleOffset && + ballY > rightPaddleY && ballY < rightPaddleY + paddleHeight) + { + ballSpeedX *= -1; + ballX = canvas.width - paddleWidth - ballSize - paddleOffset; + getBounceVelocity(rightPaddleY); + ballSpeed += 10; + } + + // scoring + if (ballX < 0 || ballX > canvas.width - ballSize) + { + game_playing = false; + if (ballX < 0) + p2_score++; + else + p1_score++; + + if (p1_score === 3 || p2_score === 3) + match_over = true; + else + { + countdown = 3; + countdownTimer = performance.now(); + } + + ballX = canvas.width / 2; + ballY = canvas.height / 2; + ballSpeed = 200; + ballSpeedX = 300 * ((ballSpeedX > 0) ? 1 : -1); + ballSpeedY = 10; + ballSpeedX = -ballSpeedX; + leftPaddleY = canvas.height / 2 - paddleHeight / 2; + rightPaddleY = canvas.height / 2 - paddleHeight / 2; + } + } + + function draw() { + ctx.fillStyle = "black"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + ctx.fillStyle = "white"; + ctx.fillRect(paddleOffset, leftPaddleY, paddleWidth, paddleHeight); + ctx.fillRect(canvas.width - paddleWidth - paddleOffset, rightPaddleY, paddleWidth, paddleHeight); + + ctx.fillStyle = "white"; + if (game_playing) + ctx.fillRect(ballX, ballY, ballSize, ballSize); + + ctx.font = "24px sans-serif"; + ctx.fillText(`${p1_score} - ${p2_score}`, canvas.width / 2 - 20, 30); + + if (match_over) + { + ctx.font = "48px sans-serif"; + const winner = p1_score > p2_score ? "Player 1" : "Player 2"; + ctx.fillText(`${winner} won :D`, canvas.width / 2 - 150, canvas.height / 2 + 22); + document.getElementById("game-buttons").classList.remove("hidden"); + } + } + + function startCountdown() + { + const now = performance.now(); + if (countdown > 0) + { + if (now - countdownTimer >= 500) + { + countdown--; + countdownTimer = now; + } + ctx.font = "48px sans-serif"; + ctx.fillText(countdown.toString(), canvas.width / 2 - 10, canvas.height / 2 + 24); + } + else if (countdown === 0) + { + ctx.font = "48px sans-serif"; + ctx.fillText("Go!", canvas.width / 2 - 30, canvas.height / 2 + 24); + setTimeout(() => { + game_playing = true; + countdown = -1; + }, 500); + } + } + + const gameLoop = (timestamp: number) => { + elapsed = (timestamp - start) / 1000; + start = timestamp; + if (game_playing) + { + movePaddles(); + moveBall(); + } + draw(); + console.log(game_playing); + if (!game_playing) + startCountdown(); + if (this.running) + requestAnimationFrame(gameLoop); + }; + + + document.getElementById("game-retry")?.addEventListener("click", () => { + document.getElementById("game-buttons").classList.add("hidden"); + game_playing = false; + match_over = false; + p1_score = 0; + p2_score = 0; + + countdown = 3; + countdownTimer = performance.now(); + }); + requestAnimationFrame(gameLoop); + } +} diff --git a/src/front/static/ts/views/LoginPage.ts b/src/front/static/ts/views/LoginPage.ts new file mode 100644 index 0000000..bdfc553 --- /dev/null +++ b/src/front/static/ts/views/LoginPage.ts @@ -0,0 +1,66 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + constructor() + { + super(); + this.setTitle("login"); + } + + async getHTML() { + return ` +
+

login

+ + + + + + + + register + +
+ `; + } + + async run() { + const login = async () => { + const username = (document.getElementById("username") as HTMLInputElement).value; + const password = (document.getElementById("password") as HTMLInputElement).value; + + try { + /*const response = await fetch("https://localhost/login", { + method: "POST", + headers: { "Content-Type": "application/json", }, + credentials: "include", + body: JSON.stringify({ user: username, password: password }), + }); + + const data = await response.json();*/ + const data = { "error": "invalid password or smth" }; + const response = { status: 400}; + + + if (response.status === 200) + { + navigationManager("/"); + } + else if (response.status === 400) + { + document.getElementById("login-error-message").innerHTML = "error: " + data.error; + document.getElementById("login-error-message").classList.remove("hidden"); + } + + } + catch (error) + { + document.getElementById("login-error-message").innerHTML = "error: server error, try again later..."; + document.getElementById("login-error-message").classList.remove("hidden"); + } + }; + + document.getElementById("login-button")?.addEventListener("click", login); + } +} diff --git a/src/front/static/ts/views/MainMenu.ts b/src/front/static/ts/views/MainMenu.ts new file mode 100644 index 0000000..9d00ee0 --- /dev/null +++ b/src/front/static/ts/views/MainMenu.ts @@ -0,0 +1,22 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + constructor() + { + super(); + this.setTitle("knl is trans(cendence)"); + } + + async getHTML() { + return ` +
+

knl_meowscendence :D

+

i like pong

+ + Pong + +
+ `; + } +} diff --git a/src/front/static/ts/views/PongMenu.ts b/src/front/static/ts/views/PongMenu.ts new file mode 100644 index 0000000..90dabdd --- /dev/null +++ b/src/front/static/ts/views/PongMenu.ts @@ -0,0 +1,21 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + constructor() + { + super(); + this.setTitle("ponging ur mom"); + } + + async getHTML() { + return ` +
+

pong is funny yay

+ + solo + +
+ `; + } +} diff --git a/src/front/static/ts/views/RegisterPage.ts b/src/front/static/ts/views/RegisterPage.ts new file mode 100644 index 0000000..7e97a62 --- /dev/null +++ b/src/front/static/ts/views/RegisterPage.ts @@ -0,0 +1,27 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + constructor() + { + super(); + this.setTitle("ft_trans 🏳️‍⚧️"); + } + + async getHTML() { + return ` +
+

register

+ + + + + + + + i already have an account + +
+ `; + } +} diff --git a/src/front/style.css b/src/front/style.css deleted file mode 100644 index f5645cf..0000000 --- a/src/front/style.css +++ /dev/null @@ -1,5 +0,0 @@ -@import "tailwindcss"; - -/*@tailwind base; -@tailwind components; -@tailwind utilities;*/ From a93d2957890b1ce1b4f0f91828885bbeedcd88cf Mon Sep 17 00:00:00 2001 From: yosyo Date: Wed, 24 Sep 2025 13:00:31 +0200 Subject: [PATCH 03/46] =?UTF-8?q?=E3=80=8C=F0=9F=9A=A7=E3=80=8D=20test(src?= =?UTF-8?q?/front):=20wip=20of=20the=20front?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/front/static/css/style.css | 7 +- src/front/static/ts/main.ts | 18 +-- src/front/static/ts/views/Game.ts | 5 +- src/front/static/ts/views/LoginPage.ts | 13 +- src/front/static/ts/views/PongMenu.ts | 15 ++- src/front/static/ts/views/RegisterPage.ts | 6 +- src/front/static/ts/views/TournamentMenu.ts | 141 ++++++++++++++++++++ tailwind.config.js | 2 +- 8 files changed, 172 insertions(+), 35 deletions(-) create mode 100644 src/front/static/ts/views/TournamentMenu.ts diff --git a/src/front/static/css/style.css b/src/front/static/css/style.css index 0d686fe..09f3bdb 100644 --- a/src/front/static/css/style.css +++ b/src/front/static/css/style.css @@ -1,5 +1,8 @@ @import "tailwindcss"; -@theme { +@source inline("space-y-{18,46,102,214,438,886,1782,3574,7158,14326,28662,57334,114678,229366,458742,917494}"); +@source inline("mt-{28,56,84,112}"); + +/*@theme { --color-accent-500: #f55151; -} +}*/ diff --git a/src/front/static/ts/main.ts b/src/front/static/ts/main.ts index 676a313..8ce2cc8 100644 --- a/src/front/static/ts/main.ts +++ b/src/front/static/ts/main.ts @@ -1,11 +1,3 @@ -/*import MainMenu from "./views/MainMenu.ts"; -import PongMenu from "./views/PongMenu.ts"; - -import LoginPage from "./views/LoginPage.ts"; -import RegisterPage from "./views/RegisterPage.ts"; - -import Game from "./views/Game.ts";*/ - const navigationManager = url => { history.pushState(null, null, url); router(); @@ -14,17 +6,11 @@ const navigationManager = url => { let view; const routes = [ - /*{ path: "/", view: MainMenu }, - - { path: "/pong", view: PongMenu }, - { path: "/pong/solo", view: Game }, - - { path: "/login", view: LoginPage }, - { path: "/register", view: RegisterPage },*/ { path: "/", view: () => import("./views/MainMenu.ts") }, { path: "/pong", view: () => import("./views/PongMenu.ts") }, - { path: "/pong/solo", view: () => import("./views/Game.ts") }, + { path: "/pong/local", view: () => import("./views/Game.ts") }, + { path: "/pong/tournament", view: () => import("./views/TournamentMenu.ts") }, { path: "/login", view: () => import("./views/LoginPage.ts") }, { path: "/register", view: () => import("./views/RegisterPage.ts") }, diff --git a/src/front/static/ts/views/Game.ts b/src/front/static/ts/views/Game.ts index 5610676..3bd39b5 100644 --- a/src/front/static/ts/views/Game.ts +++ b/src/front/static/ts/views/Game.ts @@ -7,7 +7,7 @@ export default class extends Aview { constructor() { super(); - this.setTitle("pog or pong ? :3"); + this.setTitle("pong (local match)"); this.running = true; } @@ -67,7 +67,7 @@ export default class extends Aview { rightPaddleY -= paddleSpeed * elapsed; if (keys["ArrowDown"] && rightPaddleY < canvas.height - paddleHeight) rightPaddleY += paddleSpeed * elapsed; - } + } function getBounceVelocity(paddleY) { const speed = ballSpeed; @@ -209,6 +209,7 @@ export default class extends Aview { countdown = 3; countdownTimer = performance.now(); }); + requestAnimationFrame(gameLoop); } } diff --git a/src/front/static/ts/views/LoginPage.ts b/src/front/static/ts/views/LoginPage.ts index bdfc553..aa7a5c0 100644 --- a/src/front/static/ts/views/LoginPage.ts +++ b/src/front/static/ts/views/LoginPage.ts @@ -13,8 +13,8 @@ export default class extends Aview {

login

- - + + @@ -31,16 +31,16 @@ export default class extends Aview { const password = (document.getElementById("password") as HTMLInputElement).value; try { - /*const response = await fetch("https://localhost/login", { + const response = await fetch("http://localhost:3001/login", { method: "POST", headers: { "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ user: username, password: password }), }); - const data = await response.json();*/ - const data = { "error": "invalid password or smth" }; - const response = { status: 400}; + const data = await response.json(); + /*const data = { "error": "invalid password or smth" }; + const response = { status: 400};*/ if (response.status === 200) @@ -56,6 +56,7 @@ export default class extends Aview { } catch (error) { + console.log(error); document.getElementById("login-error-message").innerHTML = "error: server error, try again later..."; document.getElementById("login-error-message").classList.remove("hidden"); } diff --git a/src/front/static/ts/views/PongMenu.ts b/src/front/static/ts/views/PongMenu.ts index 90dabdd..718b1c0 100644 --- a/src/front/static/ts/views/PongMenu.ts +++ b/src/front/static/ts/views/PongMenu.ts @@ -5,16 +5,21 @@ export default class extends Aview { constructor() { super(); - this.setTitle("ponging ur mom"); + this.setTitle("knl is trans(cendence)"); } async getHTML() { return ` -
+ `; } diff --git a/src/front/static/ts/views/RegisterPage.ts b/src/front/static/ts/views/RegisterPage.ts index 7e97a62..d0534ab 100644 --- a/src/front/static/ts/views/RegisterPage.ts +++ b/src/front/static/ts/views/RegisterPage.ts @@ -5,7 +5,7 @@ export default class extends Aview { constructor() { super(); - this.setTitle("ft_trans 🏳️‍⚧️"); + this.setTitle("register"); } async getHTML() { @@ -13,8 +13,8 @@ export default class extends Aview {

register

- - + + diff --git a/src/front/static/ts/views/TournamentMenu.ts b/src/front/static/ts/views/TournamentMenu.ts new file mode 100644 index 0000000..c36b3d7 --- /dev/null +++ b/src/front/static/ts/views/TournamentMenu.ts @@ -0,0 +1,141 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + constructor() + { + super(); + this.setTitle("Tournament"); + } + + async getHTML() { + return ` +
+

how many players ?

+
+ + +
+
+
+ `; + } + + async run() { + const generateBracket = async (playerCount: number) => { + document.getElementById("bracket").innerHTML = ""; + + const rounds = Math.ceil(Math.log2(playerCount)); + const totalSlots = 2 ** rounds; + const byes = totalSlots - playerCount; + + let odd = 0; + if (playerCount % 2) + { + console.error("odd numbers are temporarily invalids"); + return ; + /*++odd; + --playerCount;*/ + } + + let notPowPlayersCount = 0; + + if ((playerCount & (playerCount - 1)) != 0) + notPowPlayersCount = playerCount - (2 ** Math.floor(Math.log2(playerCount))); + + + let initialPlayers = Array.from({ length: 2 ** Math.floor(Math.log2(playerCount))}, (_, i) => `Player ${i + 1}`); + playerCount = 2 ** Math.floor(Math.log2(playerCount)); + //let initialPlayers = Array.from({ length: playerCount }, (_, i) => `Player ${i + 1}`); + + const bracketWrapper = document.createElement("div"); + bracketWrapper.className = "flex space-x-8 overflow-x-auto"; + + // Round 0: Player input column + const playerInputColumn = document.createElement("div"); + playerInputColumn.className = `flex flex-col mt-${(notPowPlayersCount + odd) * 28} space-y-4`; + + initialPlayers.forEach((name, i) => { + const input = document.createElement("input"); + input.type = "text"; + input.id = `playerName${i}`; + input.value = ""; + input.placeholder = name; + input.className = + "w-32 h-10 p-2 text-sm border rounded bg-white shadow disabled:bg-gray-200"; + playerInputColumn.appendChild(input); + }); + + bracketWrapper.appendChild(playerInputColumn); + + let currentRound = initialPlayers; + let previousPadding = 4; + for (let round = 1; round <= rounds; round++) + { + const roundColumn = document.createElement("div"); + previousPadding = previousPadding * 2 + 10 + roundColumn.className = `flex flex-col justify-center space-y-${previousPadding}`; + + const nextRound: string[] = []; + + if (!notPowPlayersCount) + { + if (odd) + { + const input = document.createElement("input"); + input.type = "text"; + input.id = `playerName${playerCount}`; + input.value = ""; + input.placeholder = `Player ${++playerCount}`; + input.className = + "w-32 h-10 p-2 text-sm border rounded bg-white shadow disabled:bg-gray-200"; + roundColumn.appendChild(input); + odd--; + nextRound.push(""); + } + } + + while (notPowPlayersCount) + { + const input = document.createElement("input"); + input.type = "text"; + input.id = `playerName${playerCount}`; + input.value = ""; + input.placeholder = `Player ${++playerCount}`; + input.className = + "w-32 h-10 p-2 text-sm border rounded bg-white shadow disabled:bg-gray-200"; + roundColumn.appendChild(input); + --notPowPlayersCount; + nextRound.push(""); + } + + for (let i = 0; i < currentRound.length; i += 2) + { + const p1 = currentRound[i]; + const p2 = currentRound[i + 1]; + + const matchDiv = document.createElement("div"); + matchDiv.className = + "w-32 h-10 flex items-center justify-center bg-white border rounded shadow text-center text-sm"; + + matchDiv.textContent = ""; + nextRound.push(""); + + roundColumn.appendChild(matchDiv); + } + + bracketWrapper.appendChild(roundColumn); + currentRound = nextRound; + } + + document.getElementById("bracket").appendChild(bracketWrapper); + }; + + document.getElementById("bracket-generate")?.addEventListener("click", () => { + const input: HTMLInputElement = document.getElementById("playerNumber") as HTMLInputElement; + generateBracket(+input.value); + }); + + + } +} diff --git a/tailwind.config.js b/tailwind.config.js index d2fdab4..9bd8368 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,5 +1,5 @@ export default { - content: ['./src/front/**/*.{html,js}'], + content: ['./src/front/**/*.{html,js,ts,css}'], theme: { extend: {}, }, From 1d2bb02e65df0b193a6a7cb3394fe6842c882646 Mon Sep 17 00:00:00 2001 From: adjoly Date: Wed, 24 Sep 2025 14:12:05 +0200 Subject: [PATCH 04/46] =?UTF-8?q?=E3=80=8C=F0=9F=94=A8=E3=80=8D=20fix(cors?= =?UTF-8?q?=20issue):=20should=20be=20working=20as=20expected?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 11 +++++++++++ src/api/auth/default.js | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/package.json b/package.json index 7eedbe9..93287eb 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "dependencies": { "@avalabs/avalanchejs": "^5.0.0", "@fastify/cookie": "^11.0.2", + "@fastify/cors": "^11.1.0", "@fastify/env": "^5.0.2", "@fastify/jwt": "^9.1.0", "axios": "^1.10.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 91f44c7..0a5a097 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@fastify/cookie': specifier: ^11.0.2 version: 11.0.2 + '@fastify/cors': + specifier: ^11.1.0 + version: 11.1.0 '@fastify/env': specifier: ^5.0.2 version: 5.0.2 @@ -255,6 +258,9 @@ packages: '@fastify/cookie@11.0.2': resolution: {integrity: sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==} + '@fastify/cors@11.1.0': + resolution: {integrity: sha512-sUw8ed8wP2SouWZTIbA7V2OQtMNpLj2W6qJOYhNdcmINTu6gsxVYXjQiM9mdi8UUDlcoDDJ/W2syPo1WB2QjYA==} + '@fastify/deepmerge@2.0.2': resolution: {integrity: sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==} @@ -1758,6 +1764,11 @@ snapshots: cookie: 1.0.2 fastify-plugin: 5.0.1 + '@fastify/cors@11.1.0': + dependencies: + fastify-plugin: 5.0.1 + toad-cache: 3.7.0 + '@fastify/deepmerge@2.0.2': {} '@fastify/env@5.0.2': diff --git a/src/api/auth/default.js b/src/api/auth/default.js index 6a15651..dd706e8 100644 --- a/src/api/auth/default.js +++ b/src/api/auth/default.js @@ -1,5 +1,6 @@ import fastifyJWT from '@fastify/jwt'; import fastifyCookie from '@fastify/cookie'; +import cors from '@fastify/cors' import { register } from './register.js'; import { login } from './login.js'; @@ -22,6 +23,11 @@ authDB.prepareDB(); */ export default async function(fastify, options) { + fastify.register(cors, { + origin: "*", + methods: ["GET", "POST", "DELETE"] + }); + fastify.register(fastifyJWT, { secret: process.env.JWT_SECRET || '123456789101112131415161718192021', cookie: { From cb8823fcf3727eafb62e3dbff6f1c6c17734a5fc Mon Sep 17 00:00:00 2001 From: yosyo Date: Sat, 27 Sep 2025 15:50:09 +0200 Subject: [PATCH 05/46] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D?= =?UTF-8?q?=20wip:=20tmp=20commit,=20will=20be=20overriden=20later,=20can?= =?UTF-8?q?=20be=20ignored?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 11 +++++++ src/api/auth/default.js | 7 +++++ src/front/static/ts/views/LoginPage.ts | 4 --- src/front/static/ts/views/RegisterPage.ts | 38 ++++++++++++++++++++++- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7eedbe9..93287eb 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "dependencies": { "@avalabs/avalanchejs": "^5.0.0", "@fastify/cookie": "^11.0.2", + "@fastify/cors": "^11.1.0", "@fastify/env": "^5.0.2", "@fastify/jwt": "^9.1.0", "axios": "^1.10.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 91f44c7..0a5a097 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@fastify/cookie': specifier: ^11.0.2 version: 11.0.2 + '@fastify/cors': + specifier: ^11.1.0 + version: 11.1.0 '@fastify/env': specifier: ^5.0.2 version: 5.0.2 @@ -255,6 +258,9 @@ packages: '@fastify/cookie@11.0.2': resolution: {integrity: sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==} + '@fastify/cors@11.1.0': + resolution: {integrity: sha512-sUw8ed8wP2SouWZTIbA7V2OQtMNpLj2W6qJOYhNdcmINTu6gsxVYXjQiM9mdi8UUDlcoDDJ/W2syPo1WB2QjYA==} + '@fastify/deepmerge@2.0.2': resolution: {integrity: sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==} @@ -1758,6 +1764,11 @@ snapshots: cookie: 1.0.2 fastify-plugin: 5.0.1 + '@fastify/cors@11.1.0': + dependencies: + fastify-plugin: 5.0.1 + toad-cache: 3.7.0 + '@fastify/deepmerge@2.0.2': {} '@fastify/env@5.0.2': diff --git a/src/api/auth/default.js b/src/api/auth/default.js index 6a15651..0650fa1 100644 --- a/src/api/auth/default.js +++ b/src/api/auth/default.js @@ -1,5 +1,6 @@ import fastifyJWT from '@fastify/jwt'; import fastifyCookie from '@fastify/cookie'; +import cors from '@fastify/cors' import { register } from './register.js'; import { login } from './login.js'; @@ -22,6 +23,12 @@ authDB.prepareDB(); */ export default async function(fastify, options) { + fastify.register(cors, { + origin: "http://localhost:5173", + credentials: true, + methods: [ "GET", "POST", "DELETE", "OPTIONS" ] + }); + fastify.register(fastifyJWT, { secret: process.env.JWT_SECRET || '123456789101112131415161718192021', cookie: { diff --git a/src/front/static/ts/views/LoginPage.ts b/src/front/static/ts/views/LoginPage.ts index aa7a5c0..c8dca62 100644 --- a/src/front/static/ts/views/LoginPage.ts +++ b/src/front/static/ts/views/LoginPage.ts @@ -37,11 +37,7 @@ export default class extends Aview { credentials: "include", body: JSON.stringify({ user: username, password: password }), }); - const data = await response.json(); - /*const data = { "error": "invalid password or smth" }; - const response = { status: 400};*/ - if (response.status === 200) { diff --git a/src/front/static/ts/views/RegisterPage.ts b/src/front/static/ts/views/RegisterPage.ts index d0534ab..13fdf55 100644 --- a/src/front/static/ts/views/RegisterPage.ts +++ b/src/front/static/ts/views/RegisterPage.ts @@ -16,7 +16,7 @@ export default class extends Aview { - + i already have an account @@ -24,4 +24,40 @@ export default class extends Aview {
`; } + + async run() { + const login = async () => { + const username = (document.getElementById("username") as HTMLInputElement).value; + const password = (document.getElementById("password") as HTMLInputElement).value; + + try { + const response = await fetch("http://localhost:3001/register", { + method: "POST", + headers: { "Content-Type": "application/json", }, + credentials: "include", + body: JSON.stringify({ user: username, password: password }), + }); + const data = await response.json(); + + if (response.status === 200) + { + navigationManager("/"); + } + else if (response.status === 400) + { + document.getElementById("login-error-message").innerHTML = "error: " + data.error; + document.getElementById("login-error-message").classList.remove("hidden"); + } + + } + catch (error) + { + console.log(error); + document.getElementById("login-error-message").innerHTML = "error: server error, try again later..."; + document.getElementById("login-error-message").classList.remove("hidden"); + } + }; + + document.getElementById("register-button")?.addEventListener("click", login); + } } From 59bd580136637b0fdc1ca86329d3378409022629 Mon Sep 17 00:00:00 2001 From: y-syo Date: Tue, 30 Sep 2025 16:05:15 +0200 Subject: [PATCH 06/46] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D?= =?UTF-8?q?=20wip:=20work=20in=20progress,=20not=20done=20yet.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/front/index.html | 2 +- src/front/static/ts/main.ts | 44 +++++++++++++++++++++-- src/front/static/ts/views/Game.ts | 18 ++++++++-- src/front/static/ts/views/LoginPage.ts | 16 ++++++--- src/front/static/ts/views/RegisterPage.ts | 25 +++++++++---- 5 files changed, 88 insertions(+), 17 deletions(-) diff --git a/src/front/index.html b/src/front/index.html index 97c4aea..0e7465d 100644 --- a/src/front/index.html +++ b/src/front/index.html @@ -16,7 +16,7 @@
diff --git a/src/front/static/ts/main.ts b/src/front/static/ts/main.ts index 8ce2cc8..910e75e 100644 --- a/src/front/static/ts/main.ts +++ b/src/front/static/ts/main.ts @@ -1,4 +1,41 @@ -const navigationManager = url => { +export async function isLogged(): boolean { + let uuid_req = await fetch("http://localhost:3001/me", { + method: "GET", + credentials: "include", + }); + if (uuid_req.status == 200) + { + let uuid = await uuid_req.json(); + document.cookie = `uuid=${uuid.user};max-age=${60*60*24*7}`; + + const old_button = document.getElementById("profile-button"); + const logged_dropdown = document.createElement("button"); + logged_dropdown.innerHTML = "logged in, more like locked in ahah i'm gonna kill myself the 12th of October"; + logged_dropdown.classList.add("text-neutral-900", "hover:text-neutral-700", "dark:text-white", "dark:hover:text-neutral-400"); + logged_dropdown.id = "profile-button"; + + // add the dropdown button and the dropdown logic + + old_button.replaceWith(logged_dropdown); + return true; + } + else // 401 + { + document.cookie = `uuid=;max-age=0`; + const old_button = document.getElementById("profile-button"); + const login_button = document.createElement("a"); + login_button.id = "profile-button"; + login_button.text = "login"; + login_button.classList.add("text-neutral-900", "hover:text-neutral-700", "dark:text-white", "dark:hover:text-neutral-400"); + login_button.href = "/login"; + login_button.setAttribute("data-link", ""); + + old_button.replaceWith(login_button); + return false; + } +} + +export const navigationManager = url => { history.pushState(null, null, url); router(); }; @@ -14,6 +51,8 @@ const routes = [ { path: "/login", view: () => import("./views/LoginPage.ts") }, { path: "/register", view: () => import("./views/RegisterPage.ts") }, + + { path: "/tetris", view: () => import("./views/Tetris.ts") }, ]; const router = async () => { @@ -30,7 +69,7 @@ const router = async () => { if (view) view.running = false; - console.log(match); + //console.log(match); const module = await match.route.view(); view = new module.default(); @@ -42,6 +81,7 @@ const router = async () => { window.addEventListener("popstate", router); document.addEventListener("DOMContentLoaded", () => { + isLogged(); document.body.addEventListener("click", e=> { if (e.target.matches("[data-link]")) diff --git a/src/front/static/ts/views/Game.ts b/src/front/static/ts/views/Game.ts index 3bd39b5..b814e1b 100644 --- a/src/front/static/ts/views/Game.ts +++ b/src/front/static/ts/views/Game.ts @@ -59,9 +59,9 @@ export default class extends Aview { document.addEventListener("keyup", e => { keys[e.key] = false; }); function movePaddles() { - if (keys["w"] && leftPaddleY > 0) + if ((keys["w"] || keys["W"]) && leftPaddleY > 0) leftPaddleY -= paddleSpeed * elapsed; - if (keys["s"] && leftPaddleY < canvas.height - paddleHeight) + if ((keys["s"] || keys["S"]) && leftPaddleY < canvas.height - paddleHeight) leftPaddleY += paddleSpeed * elapsed; if (keys["ArrowUp"] && rightPaddleY > 0) rightPaddleY -= paddleSpeed * elapsed; @@ -116,7 +116,14 @@ export default class extends Aview { p1_score++; if (p1_score === 3 || p2_score === 3) + { + // ------------------------------------------------------------------------------------------------------------------------------------------ + // + // insert the fetch to the ScoreStore api here + // + // ------------------------------------------------------------------------------------------------------------------------------------------ match_over = true; + } else { countdown = 3; @@ -191,7 +198,6 @@ export default class extends Aview { moveBall(); } draw(); - console.log(game_playing); if (!game_playing) startCountdown(); if (this.running) @@ -210,6 +216,12 @@ export default class extends Aview { countdownTimer = performance.now(); }); + // -------------------------------------------------------------------------------------------------------------------------------------------------------- + // + // insert logic to set both names + // + // -------------------------------------------------------------------------------------------------------------------------------------------------------- + requestAnimationFrame(gameLoop); } } diff --git a/src/front/static/ts/views/LoginPage.ts b/src/front/static/ts/views/LoginPage.ts index c8dca62..fd7ba3e 100644 --- a/src/front/static/ts/views/LoginPage.ts +++ b/src/front/static/ts/views/LoginPage.ts @@ -1,4 +1,5 @@ import Aview from "./Aview.ts" +import { isLogged, navigationManager } from "../main.ts" export default class extends Aview { @@ -31,28 +32,33 @@ export default class extends Aview { const password = (document.getElementById("password") as HTMLInputElement).value; try { - const response = await fetch("http://localhost:3001/login", { + const data_req = await fetch("http://localhost:3001/login", { method: "POST", headers: { "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ user: username, password: password }), }); - const data = await response.json(); + const data = await data_req.json(); - if (response.status === 200) + if (data_req.status === 200) { + isLogged(); navigationManager("/"); } - else if (response.status === 400) + else if (data_req.status === 400) { document.getElementById("login-error-message").innerHTML = "error: " + data.error; document.getElementById("login-error-message").classList.remove("hidden"); } + else + { + throw new Error("invalid response"); + } } catch (error) { - console.log(error); + console.error(error); document.getElementById("login-error-message").innerHTML = "error: server error, try again later..."; document.getElementById("login-error-message").classList.remove("hidden"); } diff --git a/src/front/static/ts/views/RegisterPage.ts b/src/front/static/ts/views/RegisterPage.ts index 13fdf55..0701662 100644 --- a/src/front/static/ts/views/RegisterPage.ts +++ b/src/front/static/ts/views/RegisterPage.ts @@ -1,4 +1,5 @@ import Aview from "./Aview.ts" +import { isLogged, navigationManager } from "../main.ts" export default class extends Aview { @@ -15,7 +16,7 @@ export default class extends Aview { - + @@ -31,28 +32,40 @@ export default class extends Aview { const password = (document.getElementById("password") as HTMLInputElement).value; try { - const response = await fetch("http://localhost:3001/register", { + const data_req = await fetch("http://localhost:3001/register", { method: "POST", headers: { "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ user: username, password: password }), }); - const data = await response.json(); + const data = await data_req.json(); - if (response.status === 200) + if (data_req.status === 200) { + let uuid_req = await fetch("http://localhost:3001/me", { + method: "GET", + credentials: "include", + }); + let uuid = await uuid_req.json(); + document.cookie = `uuid=${uuid.user};max-ages=${60*60*24*7}`; + console.log(document.cookie); + isLogged(); navigationManager("/"); } - else if (response.status === 400) + else if (data_req.status === 400) { document.getElementById("login-error-message").innerHTML = "error: " + data.error; document.getElementById("login-error-message").classList.remove("hidden"); } + else + { + throw new Error("invalid response"); + } } catch (error) { - console.log(error); + console.error(error); document.getElementById("login-error-message").innerHTML = "error: server error, try again later..."; document.getElementById("login-error-message").classList.remove("hidden"); } From 35f5df492496e74a6ded1f57a19fc95318bdd31a Mon Sep 17 00:00:00 2001 From: y-syo Date: Wed, 1 Oct 2025 22:12:50 +0200 Subject: [PATCH 07/46] =?UTF-8?q?=E3=80=8C=F0=9F=9A=A7=E3=80=8D=20test(src?= =?UTF-8?q?/front):=20testing=20things,=20might=20broke.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/front/static/ts/main.ts | 47 +++++++++++++++++++---- src/front/static/ts/views/Game.ts | 32 ++++++++++----- src/front/static/ts/views/LoginPage.ts | 8 ++-- src/front/static/ts/views/RegisterPage.ts | 8 ++-- 4 files changed, 71 insertions(+), 24 deletions(-) diff --git a/src/front/static/ts/main.ts b/src/front/static/ts/main.ts index 910e75e..dd8847a 100644 --- a/src/front/static/ts/main.ts +++ b/src/front/static/ts/main.ts @@ -3,20 +3,53 @@ export async function isLogged(): boolean { method: "GET", credentials: "include", }); - if (uuid_req.status == 200) + if (uuid_req.status === 200) { let uuid = await uuid_req.json(); document.cookie = `uuid=${uuid.user};max-age=${60*60*24*7}`; const old_button = document.getElementById("profile-button"); - const logged_dropdown = document.createElement("button"); - logged_dropdown.innerHTML = "logged in, more like locked in ahah i'm gonna kill myself the 12th of October"; - logged_dropdown.classList.add("text-neutral-900", "hover:text-neutral-700", "dark:text-white", "dark:hover:text-neutral-400"); - logged_dropdown.id = "profile-button"; - // add the dropdown button and the dropdown logic + const dropdown = document.createElement("div"); + dropdown.classList.add("relative", "inline-block", "group"); + dropdown.id = "profile-button"; + const button_dropdown = dropdown.appendChild(document.createElement("button")); + button_dropdown.innerHTML = uuid.user; + button_dropdown.classList.add("text-neutral-900", "group-hover:text-neutral-700", "dark:text-white", "dark:group-hover:text-neutral-400"); - old_button.replaceWith(logged_dropdown); + const menu_div = dropdown.appendChild(document.createElement("div")); + menu_div.classList.add("float:right", "hidden", "absolute", "right-0", "bg-[#f9f9f9]", "min-w-[160px]", "shadow-lg", "z-10", "group-hover:block"); + + const profile_a = menu_div.appendChild(document.createElement("a")); + const settings_a = menu_div.appendChild(document.createElement("a")); + const logout_button = menu_div.appendChild(document.createElement("button")); + + profile_a.text = "profile"; + profile_a.classList.add("block", "no-underline", "px-4", "py-3"); + profile_a.href = "/profile"; + profile_a.setAttribute("data-link", ""); + + settings_a.text = "settings"; + settings_a.classList.add("block", "no-underline", "px-4", "py-3"); + settings_a.href = "/settings"; + settings_a.setAttribute("data-link", ""); + + logout_button.innerHTML = "logout"; + logout_button.classList.add("block", "no-underline", "px-4", "py-3"); + logout_button.id = "logout-button"; + //document.getElementById("logout-button")?.addEventListener("click", async () => { + logout_button.addEventListener("click", async () => { + let req = await fetch("http://localhost:3001/logout", { + method: "GET", + credentials: "include", + }); + if (req.status === 200) + isLogged(); + else + console.error("logout failed"); + }); + + old_button.replaceWith(dropdown); return true; } else // 401 diff --git a/src/front/static/ts/views/Game.ts b/src/front/static/ts/views/Game.ts index b814e1b..41fe224 100644 --- a/src/front/static/ts/views/Game.ts +++ b/src/front/static/ts/views/Game.ts @@ -1,4 +1,5 @@ import Aview from "./Aview.ts" +import { isLogged } from "../main.js" export default class extends Aview { @@ -13,10 +14,13 @@ export default class extends Aview { async getHTML() { return ` - -
- -