Feature+Fix: Referral-Admin, Pro-Gates, Karten-Layer, onDogChange, Staging-Media (SW by-v855)
Features: - Admin: Referral-Tab (Virality Factor, Top-Werber, letzte Einladungen) - Karte: Regenradar (RainViewer, zoom→7, color=4), Temperatur-Layer (OWM) mit Zahlen-Grid + Legende - Wetter-Chip: Umschwung-Warnung bei ≥40%-Sprung in Niederschlagswahrscheinlichkeit - Freundschaftsanfragen: Accept/Decline direkt in Notifications (kein Pro nötig) - Freunde-Seite für Standard-User freigeschaltet Pro-Gates: - KI-Trainer, Routenvorschläge, Regenradar, Temperatur-Layer jetzt Pro-Feature - Pro-Badge (P) auf Chips für Admins/Mods in allen Welten + Welten-einrichten - Oranger Banner auf Pro-Seiten für Admin/Mod/Manager Bugfixes: - onDogChange: uebungen.js (Cache leeren + _render), trainingsplaene.js (war leer) - robots.txt vereinfacht (nur Disallow, kein Allow-Durcheinander) - Hintergrund-Foto: Querformat-Filter korrigiert (kein Fallback auf Hochformat) - Staging Media: FileResponse mit korrektem MIME-Type, no-cache statt immutable - Staging Docker: MEDIA_DIR=/data/media + /prod-media:ro Fallback-Handler - Staging-Fix: Bild-Upload auf zweitem Hund (war Read-only file system)
This commit is contained in:
parent
2f021f54c2
commit
79fa5684b9
22 changed files with 570 additions and 58 deletions
|
|
@ -168,7 +168,7 @@ window.Page_notifications = (() => {
|
|||
? App.callModule('poison', 'openDetail', { id: d.id })
|
||||
: App.navigate('poison');
|
||||
break;
|
||||
case 'friend_request': App.navigate('friends'); break;
|
||||
case 'friend_request': _openFriendRequestModal(); break;
|
||||
case 'health_reminder':App.navigate('health'); break;
|
||||
case 'milestone': App.navigate('diary'); break;
|
||||
default:
|
||||
|
|
@ -379,5 +379,55 @@ window.Page_notifications = (() => {
|
|||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
async function _openFriendRequestModal() {
|
||||
let requests;
|
||||
try { requests = await API.friends.pending(); } catch { requests = []; }
|
||||
|
||||
if (!requests.length) {
|
||||
UI.toast.info('Keine offenen Freundschaftsanfragen.');
|
||||
return;
|
||||
}
|
||||
|
||||
const items = requests.map(r => `
|
||||
<div style="display:flex;align-items:center;gap:var(--space-3);padding:var(--space-3) 0;
|
||||
border-bottom:1px solid var(--c-border)">
|
||||
<div style="width:36px;height:36px;border-radius:50%;overflow:hidden;flex-shrink:0;
|
||||
background:var(--c-surface-2);display:flex;align-items:center;justify-content:center">
|
||||
${r.avatar_url
|
||||
? `<img src="${UI.escape(r.avatar_url)}" style="width:100%;height:100%;object-fit:cover">`
|
||||
: `<svg class="ph-icon" style="width:20px;height:20px;color:var(--c-text-muted)"><use href="/icons/phosphor.svg#user"></use></svg>`}
|
||||
</div>
|
||||
<div style="flex:1;font-weight:600">${UI.escape(r.requester_name)}</div>
|
||||
<button class="btn btn-primary" style="padding:6px 14px;font-size:var(--text-sm)"
|
||||
data-accept="${r.id}">Annehmen</button>
|
||||
<button class="btn btn-secondary" style="padding:6px 10px;font-size:var(--text-sm)"
|
||||
data-decline="${r.id}">✕</button>
|
||||
</div>`).join('');
|
||||
|
||||
UI.modal.open({
|
||||
title: 'Freundschaftsanfragen',
|
||||
body: `<div>${items}</div>`,
|
||||
});
|
||||
|
||||
document.querySelectorAll('[data-accept]').forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
await UI.asyncButton(btn, async () => {
|
||||
await API.friends.accept(parseInt(btn.dataset.accept));
|
||||
UI.modal.close();
|
||||
UI.toast.success('Freundschaft angenommen!');
|
||||
});
|
||||
});
|
||||
});
|
||||
document.querySelectorAll('[data-decline]').forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
await UI.asyncButton(btn, async () => {
|
||||
await API.friends.decline(parseInt(btn.dataset.decline));
|
||||
UI.modal.close();
|
||||
UI.toast.info('Anfrage abgelehnt.');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return { init };
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue