feat: save progress on web server foundation and add new tickets

This commit is contained in:
syntaxbullet
2026-01-07 13:02:36 +01:00
parent 894cad91a8
commit 6f4426e49d
9 changed files with 191 additions and 59 deletions

36
src/web/public/script.js Normal file
View File

@@ -0,0 +1,36 @@
function formatUptime(seconds) {
if (seconds < 0) return "0s";
const days = Math.floor(seconds / (3600 * 24));
const hours = Math.floor((seconds % (3600 * 24)) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
const parts = [];
if (days > 0) parts.push(`${days}d`);
if (hours > 0) parts.push(`${hours}h`);
if (minutes > 0) parts.push(`${minutes}m`);
parts.push(`${secs}s`);
return parts.join(" ");
}
function updateUptime() {
const el = document.getElementById("uptime-display");
if (!el) return;
const startTimestamp = parseInt(el.getAttribute("data-start-timestamp"), 10);
if (isNaN(startTimestamp)) return;
const now = Date.now();
const elapsedSeconds = (now - startTimestamp) / 1000;
el.textContent = formatUptime(elapsedSeconds);
}
document.addEventListener("DOMContentLoaded", () => {
// Update immediately to prevent stale content flash if possible
updateUptime();
// Update every second
setInterval(updateUptime, 1000);
});

View File

@@ -1,6 +1,10 @@
import { BaseLayout } from "../views/layout";
import { formatUptime } from "../utils/format";
export function homeRoute(): Response {
const uptime = formatUptime(process.uptime());
const startTimestamp = Date.now() - (process.uptime() * 1000);
const content = `
<div class="card">
<h2>Welcome</h2>
@@ -9,6 +13,7 @@ export function homeRoute(): Response {
<div class="card">
<h3>Status</h3>
<p>System operational.</p>
<p><strong>Uptime:</strong> <span id="uptime-display" data-start-timestamp="${Math.floor(startTimestamp)}">${uptime}</span></p>
</div>
`;

View File

@@ -0,0 +1,24 @@
import { describe, expect, it } from "bun:test";
import { formatUptime } from "./format";
describe("formatUptime", () => {
it("formats seconds correctly", () => {
expect(formatUptime(45)).toBe("45s");
});
it("formats minutes and seconds", () => {
expect(formatUptime(65)).toBe("1m 5s");
});
it("formats hours, minutes, and seconds", () => {
expect(formatUptime(3665)).toBe("1h 1m 5s");
});
it("formats days correctly", () => {
expect(formatUptime(90061)).toBe("1d 1h 1m 1s");
});
it("handles zero", () => {
expect(formatUptime(0)).toBe("0s");
});
});

20
src/web/utils/format.ts Normal file
View File

@@ -0,0 +1,20 @@
/**
* Formats a duration in seconds into a human-readable string.
* Example: 3665 -> "1h 1m 5s"
*/
export function formatUptime(seconds: number): string {
if (seconds < 0) return "0s";
const days = Math.floor(seconds / (3600 * 24));
const hours = Math.floor((seconds % (3600 * 24)) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
const parts = [];
if (days > 0) parts.push(`${days}d`);
if (hours > 0) parts.push(`${hours}h`);
if (minutes > 0) parts.push(`${minutes}m`);
parts.push(`${secs}s`);
return parts.join(" ");
}

View File

@@ -29,6 +29,7 @@ export function BaseLayout({ title, content }: LayoutProps): string {
<footer>
<p>&copy; ${new Date().getFullYear()} Aurora Bot</p>
</footer>
<script src="/script.js" defer></script>
</body>
</html>`;
}