diff --git a/main.go b/main.go index 465f54e..efded11 100644 --- a/main.go +++ b/main.go @@ -87,6 +87,7 @@ func routes() http.Handler { r.Get("/auth/logout", handleLogout) r.Get("/auth/sessioninfo", handleSessionInfo) r.Get("/auth/headerbar", handleHeaderbar) + r.Get("/stats", handleStats) // --- Entries --- r.Get("/entry/feed/{page}", handleFeed) diff --git a/user.go b/user.go index b458494..c77a490 100644 --- a/user.go +++ b/user.go @@ -70,6 +70,18 @@ func handleUserPage(w http.ResponseWriter, r *http.Request) { }) } +// handleStats liefert die Kennzahlen für die Statuszeile unter dem Titel: +// registrierte Nutzer und nicht-gelöschte Beiträge. +func handleStats(w http.ResponseWriter, r *http.Request) { + var users, entries int64 + db.QueryRow(`SELECT COUNT(*) FROM user`).Scan(&users) + db.QueryRow(`SELECT COUNT(*) FROM entry WHERE deleted = 0`).Scan(&entries) + writeJSON(w, http.StatusOK, map[string]any{ + "users": users, + "entries": entries, + }) +} + func handleUserInfo(w http.ResponseWriter, r *http.Request) { uid := uidFromContext(r.Context()) diff --git a/web/css/app.css b/web/css/app.css index 14060f8..7868ec6 100644 --- a/web/css/app.css +++ b/web/css/app.css @@ -80,6 +80,13 @@ h2 { padding: 0 0.3rem; } +/* Kleine Statuszeile direkt unter dem Titel (Tage ohne Datenverlust + Kennzahlen). */ +.tagline { + margin: 0.2rem 0 0; + font-size: 0.85rem; + color: gray; +} + #headerbar { background-color: white; text-align: center; diff --git a/web/index.html b/web/index.html index a4314b6..3184a4f 100644 --- a/web/index.html +++ b/web/index.html @@ -14,6 +14,7 @@ Beitragsordnung

Kontrollverlust

+

diff --git a/web/js/app.js b/web/js/app.js index be92592..ce85b46 100644 --- a/web/js/app.js +++ b/web/js/app.js @@ -95,5 +95,26 @@ document.getElementById("entry-form").addEventListener("submit", async (e) => { } }); +// --- Statuszeile unter dem Titel --- +// Tage ohne Datenverlust (fester Startpunkt, Kontinuität seit der alten +// Version) plus aktuelle Kennzahlen aus /stats. +const dataLossStart = new Date("2025-12-13T12:44:00").getTime(); + +function plural(n, one, many) { + return `${n} ${n === 1 ? one : many}`; +} + +async function renderStats() { + const el = document.getElementById("stats"); + if (!el) return; + const days = Math.floor((Date.now() - dataLossStart) / 86400000); + const s = await api.get("/stats"); + el.textContent = + `Ohne Datenverlust seit ${plural(days, "Tag", "Tagen")} · ` + + `${plural(s.users ?? 0, "Profil", "Profile")} · ` + + `${plural(s.entries ?? 0, "Beitrag", "Beiträge")}`; +} + // --- Start --- refreshHeader(); +renderStats();