Sprint 18: Notification Center, Routen entdecken, Onboarding, Admin-Erweiterungen
- Notifications: History-Tabelle, /api/notifications Endpoints, push.py schreibt in DB - Notifications: Page (notifications.js) mit Badge, Typen-Icons, gelesen-Markierung - Routen: Entdecken-Modus mit Ersteller-Anzeige, Nearby-Filter, Mine/Discover Toggle - Onboarding: Willkommens-Modal nach Registrierung, Push-Angebot nach Login - Admin: Scheduler-Tab (Jobs anzeigen + manuell triggern), System-Health (DB/Disk/Uptime) - Admin: Audit-Log (wer hat was wann gemacht), erweiterte Stats (Push-Abos, aktive User, Routen) - SW: by-v152, APP_VER 125
This commit is contained in:
parent
5927d384bf
commit
92620c2c52
14 changed files with 1035 additions and 46 deletions
|
|
@ -3,7 +3,7 @@
|
|||
Router, State-Management, Navigation, Initialisierung.
|
||||
============================================================ */
|
||||
|
||||
const APP_VER = '123'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VER = '124'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
|
||||
const App = (() => {
|
||||
|
||||
|
|
@ -56,7 +56,8 @@ const App = (() => {
|
|||
admin: { title: 'Admin', module: null, requiresAuth: true },
|
||||
impressum: { title: 'Impressum', module: null },
|
||||
datenschutz: { title: 'Datenschutz', module: null },
|
||||
widget: { title: 'Widget', module: null, requiresAuth: true },
|
||||
widget: { title: 'Widget', module: null, requiresAuth: true },
|
||||
notifications: { title: 'Benachrichtigungen', module: null, requiresAuth: true },
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
|
@ -409,6 +410,26 @@ const App = (() => {
|
|||
adminItem.style.display = isMod ? '' : 'none';
|
||||
}
|
||||
await _loadDogs();
|
||||
|
||||
// Eingeloggter User ohne Hund (z.B. nach Reload) → direkt zur Hund-Anlage
|
||||
if (state.dogs.length === 0) {
|
||||
navigate('dog-profile');
|
||||
}
|
||||
|
||||
_updateNotifBadge();
|
||||
// Badge alle 60s aktualisieren
|
||||
setInterval(_updateNotifBadge, 60_000);
|
||||
}
|
||||
|
||||
async function _updateNotifBadge() {
|
||||
if (!state.user) return;
|
||||
try {
|
||||
const { count } = await API.notifications.unreadCount();
|
||||
const badge = document.getElementById('notif-badge');
|
||||
if (!badge) return;
|
||||
badge.textContent = count;
|
||||
badge.style.display = count > 0 ? '' : 'none';
|
||||
} catch { /* ignorieren */ }
|
||||
}
|
||||
|
||||
function _onLoggedOut() {
|
||||
|
|
@ -446,6 +467,50 @@ const App = (() => {
|
|||
} catch { /* kein Hund vorhanden */ }
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// ONBOARDING — Willkommens-Modal für neue User
|
||||
// ----------------------------------------------------------
|
||||
function _showOnboardingModal() {
|
||||
UI.modal.open({
|
||||
title: `${UI.icon('paw-print')} Willkommen bei Ban Yaro!`,
|
||||
body: `
|
||||
<div style="display:flex;flex-direction:column;align-items:center;
|
||||
gap:var(--space-4);text-align:center;padding:var(--space-2) 0">
|
||||
<div style="width:64px;height:64px;border-radius:50%;
|
||||
background:var(--c-primary-subtle);
|
||||
display:flex;align-items:center;justify-content:center">
|
||||
<svg style="width:32px;height:32px;color:var(--c-primary)" aria-hidden="true">
|
||||
<use href="/icons/phosphor.svg#dog"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<div style="max-width:300px">
|
||||
<p style="margin:0 0 var(--space-3);font-size:var(--text-sm);
|
||||
color:var(--c-text-secondary);line-height:1.6">
|
||||
Schön, dass du dabei bist! Ban Yaro hilft dir, alles rund um
|
||||
deinen Hund im Blick zu behalten — Spaziergänge, Gesundheit,
|
||||
Termine und vieles mehr.
|
||||
</p>
|
||||
<p style="margin:0;font-size:var(--text-sm);
|
||||
color:var(--c-text-secondary);line-height:1.6">
|
||||
Fang jetzt an und leg ein Profil für deinen Hund an.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
footer: `
|
||||
<button type="button" class="btn btn-primary" id="onboarding-start-btn">
|
||||
${UI.icon('dog')} Meinen ersten Hund anlegen
|
||||
</button>
|
||||
<button type="button" class="btn btn-ghost" data-modal-close>Später</button>
|
||||
`,
|
||||
});
|
||||
|
||||
document.getElementById('onboarding-start-btn')?.addEventListener('click', () => {
|
||||
UI.modal.close();
|
||||
navigate('dog-profile');
|
||||
});
|
||||
}
|
||||
|
||||
function _notifyDogChange() {
|
||||
Object.values(pages).forEach(p => p.module?.onDogChange?.(state.activeDog));
|
||||
}
|
||||
|
|
@ -646,7 +711,9 @@ const App = (() => {
|
|||
// (andere Module können App.state, App.navigate etc. nutzen)
|
||||
// ----------------------------------------------------------
|
||||
return { init, navigate, state, setActiveDog, renderDogSwitcher: _renderDogSwitcher,
|
||||
getInstallPrompt: () => _installPrompt, requireAuth };
|
||||
getInstallPrompt: () => _installPrompt, requireAuth,
|
||||
showOnboarding: _showOnboardingModal,
|
||||
updateNotifBadge: _updateNotifBadge };
|
||||
|
||||
})();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue