From ac5e6e6496f8e1634eed65b900c3d8ceedd48002 Mon Sep 17 00:00:00 2001 From: AliceDarkest Date: Tue, 14 Jul 2026 16:54:29 +0200 Subject: [PATCH] Show NeuralNet unread messages on dashboard --- CHANGELOG.md | 3 +++ mindfluxfuture.md | 1 + src/main/resources/templates/dashboard.html | 30 ++++++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index acd5fce..01d2193 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ Versionierung [semantisch](https://semver.org/lang/de/). ## [Unreleased] – 2026-07-14 · SysnaptiK Neural Rebrand ### Marke & Plattform +- **NeuralNet-Benachrichtigung:** Die Dashboard-Glocke ist jetzt eine + Sprechblase. Sie zeigt den echten Zähler ungelesener Direktnachrichten und + leuchtet in der Neural-Akzentfarbe, bis die Nachrichten gelesen sind. - **NeuralNet-Chatlayout geschlossen:** Chatkopf, Nachrichtenliste und Eingabefeld bilden nun eine feste Flex-Spalte im Panel. Der Footer kann nicht mehr zwischen Gespräch und Eingabe rutschen. diff --git a/mindfluxfuture.md b/mindfluxfuture.md index 52b66c2..7b57851 100644 --- a/mindfluxfuture.md +++ b/mindfluxfuture.md @@ -492,6 +492,7 @@ Der Verdacht „Profilbutton fehlt / Einstellungen nicht im Profil / irgendwas i > Der Gesprächsbereich öffnet unmittelbar beim Auswählen einer bestätigten Verbindung. > Die dynamisch gerenderten Kontakt- und Chat-Aktionen werden direkt gebunden. > Der Chatbereich hält Kopf, Verlauf und Eingabe als zusammenhängende Spalte. +> Die Dashboard-Sprechblase zeigt im 30-Sekunden-Takt echte ungelesene Nachrichten. > Blockieren, Melden/Moderation, Duelle und Lernlobby bleiben die nächsten Ausbauschritte. > Ersetzt den `/soziales`-Platzhalter („Straßen? Wo wir hingehen, brauchen wir keine Straßen!"). Ziel: User können sich befreunden, intern miteinander schreiben, gemeinsam lernen und Achievements vergleichen – **vollständig selbst gehostet, ohne einen einzigen externen Dienst**, und DSGVO-konform von Grund auf. diff --git a/src/main/resources/templates/dashboard.html b/src/main/resources/templates/dashboard.html index d4c27d2..4e62582 100644 --- a/src/main/resources/templates/dashboard.html +++ b/src/main/resources/templates/dashboard.html @@ -25,6 +25,13 @@ .status-details b { color:var(--text); font-weight:600; text-align:right; } .status-toggle { grid-column:1 / -1; justify-self:start; border:0; padding:0; background:transparent; color:var(--secondary); font:inherit; font-size:.72rem; cursor:pointer; } .status-toggle:hover { text-decoration:underline; } + .nn-trigger { position:relative; color:var(--secondary); } + .nn-trigger.unread { color:var(--accent); border-color:color-mix(in srgb,var(--accent) 72%,var(--border)); background:color-mix(in srgb,var(--accent) 16%,var(--surface)); box-shadow:0 0 18px var(--glow-s); animation:nn-notification-pulse 1.8s ease-in-out infinite; } + .nn-trigger svg { width:20px; height:20px; } + .nn-unread { position:absolute; top:-6px; right:-7px; min-width:17px; height:17px; padding:0 4px; display:grid; place-items:center; border:2px solid var(--surface); border-radius:99px; background:var(--accent); color:var(--accent-ink); font-size:.62rem; font-weight:900; line-height:1; box-shadow:0 0 10px var(--glow-s); } + .nn-unread[hidden] { display:none; } + @keyframes nn-notification-pulse { 50% { box-shadow:0 0 25px var(--glow-s); transform:translateY(-1px); } } + @media (prefers-reduced-motion:reduce) { .nn-trigger.unread { animation:none; } } .prog-top { display:flex; justify-content:space-between; align-items:center; margin-bottom:.4rem; } .pill { font-size:.68rem; color:var(--muted); border:1px solid var(--border); border-radius:7px; padding:.2rem .5rem; } .prog-big { display:flex; align-items:baseline; gap:.5rem; } @@ -64,7 +71,7 @@ - +
@@ -172,6 +179,27 @@ const line = `M${points.join(' L')}`; weekChart.querySelector('svg').innerHTML = ``; + // NeuralNet: Die Sprechblase zeigt ausschließlich echte, ungelesene + // Direktnachrichten. Aktualisierung erfolgt schlank im Hintergrund. + const neuralNetTrigger = document.querySelector('[data-neuralnet-trigger]'); + const neuralNetUnread = document.querySelector('[data-neuralnet-unread]'); + function refreshNeuralNetNotice() { + fetch('/api/neuralnet/overview', { headers: { Accept: 'application/json' } }) + .then(response => response.ok ? response.json() : null) + .then(overview => { + const unread = overview && overview.enabled ? overview.unread || 0 : 0; + neuralNetTrigger.classList.toggle('unread', unread > 0); + neuralNetUnread.hidden = unread === 0; + neuralNetUnread.textContent = unread > 99 ? '99+' : unread; + neuralNetTrigger.setAttribute('aria-label', unread > 0 + ? `NeuralNet – ${unread} ungelesene Nachricht${unread === 1 ? '' : 'en'}` + : 'NeuralNet – keine ungelesenen Nachrichten'); + }) + .catch(() => { neuralNetTrigger.classList.remove('unread'); neuralNetUnread.hidden = true; }); + } + refreshNeuralNetNotice(); + setInterval(refreshNeuralNetNotice, 30000); + // Der Status prüft den Fortschrittsspeicher serverseitig. Die Modulzahl ist // der registrierte Lernkatalog, nicht ein erfundener Prozentwert. const statusCard = document.getElementById('platformStatus');