Feature: Ratings, Lightbox, Forum-Standort, Notifications, Routen-Recording, Chat-Picker
- Bewertungssystem (ratings.py): Sterne für Sitter/Walks/Places/Routen - Admin: Server-Log-Viewer + OSM-Cache-Statistiken - Chat: "Neue Nachricht"-Button mit Freundesliste-Picker - Forum: 5 neue Kategorien, Standorteingabe (locationPicker), Absende-Toast, Lightbox - Freunde: Aktivitäts-Filter (Chips), Freundschaftsanfrage → In-App-Notification - Sitter: locationPicker statt manuelle Koordinateneingabe + ratingStars - Tagebuch: Bilder-Lightbox im Detail-View, iOS-Modal-Header-Fix (90svh) - Routen: Start/Stopp-Button wechselt Zustand, nutzt Page_map.isRecording() - Benachrichtigungen: Delete-Button sichtbar, typ-basierte Navigation, Toast-Feedback - OSM: globales Semaphore + 429-Retry-Logic; Scheduler: München-Umland, täglich - SW by-v225, APP_VER 202
This commit is contained in:
parent
aa70a838f2
commit
e56183b642
21 changed files with 648 additions and 175 deletions
|
|
@ -27,6 +27,11 @@ window.Page_forum = (() => {
|
|||
{ key: 'region', label: 'Region' },
|
||||
{ key: 'gesundheit', label: 'Gesundheit' },
|
||||
{ key: 'erziehung', label: 'Erziehung' },
|
||||
{ key: 'spaziergang', label: 'Spaziergang' },
|
||||
{ key: 'ausflug', label: 'Ausflug' },
|
||||
{ key: 'training', label: 'Training & Lektionen' },
|
||||
{ key: 'ernaehrung', label: 'Ernährung & Rezepte' },
|
||||
{ key: 'probleme', label: 'Probleme' },
|
||||
{ key: 'tauschboerse', label: 'Tauschbörse' },
|
||||
];
|
||||
|
||||
|
|
@ -463,9 +468,7 @@ window.Page_forum = (() => {
|
|||
|
||||
// Foto-Vollbild
|
||||
document.getElementById('modal-container')?.querySelectorAll('.forum-foto-img').forEach(img => {
|
||||
img.addEventListener('click', () => {
|
||||
window.open(img.dataset.src || img.src, '_blank');
|
||||
});
|
||||
img.addEventListener('click', () => _showLightbox(img.dataset.src || img.src));
|
||||
});
|
||||
|
||||
// Reply file preview
|
||||
|
|
@ -515,6 +518,7 @@ window.Page_forum = (() => {
|
|||
if (placeholder) listEl.innerHTML = '';
|
||||
listEl.insertAdjacentHTML('beforeend', _postHTML(post, uid, isMod));
|
||||
_bindPostActions(listEl, thread.id, uid, isMod);
|
||||
listEl.lastElementChild?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
}
|
||||
document.getElementById('forum-reply-text').value = '';
|
||||
const previews = document.getElementById('forum-reply-previews');
|
||||
|
|
@ -620,7 +624,7 @@ window.Page_forum = (() => {
|
|||
// Foto-Fullscreen
|
||||
container.querySelectorAll('.forum-foto-img:not([data-bound])').forEach(img => {
|
||||
img.dataset.bound = '1';
|
||||
img.addEventListener('click', () => window.open(img.dataset.src || img.src, '_blank'));
|
||||
img.addEventListener('click', () => _showLightbox(img.dataset.src || img.src));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -755,6 +759,10 @@ window.Page_forum = (() => {
|
|||
<textarea class="form-control" name="text" rows="5"
|
||||
placeholder="Beschreibe dein Thema ausführlich…" required></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Standort <span style="color:var(--c-text-secondary)">(optional)</span></label>
|
||||
<div id="forum-location-picker"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Fotos (max. 5)</label>
|
||||
<div class="forum-upload-area">
|
||||
|
|
@ -776,6 +784,11 @@ window.Page_forum = (() => {
|
|||
|
||||
UI.modal.open({ title: '+ Neues Thema', body, footer });
|
||||
|
||||
let _picker = null;
|
||||
setTimeout(() => {
|
||||
_picker = UI.locationPicker({ containerId: 'forum-location-picker' });
|
||||
}, 50);
|
||||
|
||||
document.getElementById('ff-cancel')?.addEventListener('click', UI.modal.close);
|
||||
document.getElementById('ff-rules-link')?.addEventListener('click', _showRules);
|
||||
|
||||
|
|
@ -803,10 +816,15 @@ window.Page_forum = (() => {
|
|||
}
|
||||
|
||||
await UI.asyncButton(btn, async () => {
|
||||
const loc = _picker ? _picker.getValue() : { lat: null, lon: null, name: null };
|
||||
|
||||
const created = await API.forum.create({
|
||||
kategorie: fd.kategorie,
|
||||
titel: (fd.titel || '').trim(),
|
||||
text: (fd.text || '').trim(),
|
||||
kategorie: fd.kategorie,
|
||||
titel: (fd.titel || '').trim(),
|
||||
text: (fd.text || '').trim(),
|
||||
thread_lat: loc.lat ?? null,
|
||||
thread_lon: loc.lon ?? null,
|
||||
thread_ort: loc.name ?? null,
|
||||
});
|
||||
|
||||
// Fotos hochladen
|
||||
|
|
@ -824,7 +842,8 @@ window.Page_forum = (() => {
|
|||
});
|
||||
UI.modal.close();
|
||||
_renderList();
|
||||
UI.toast.success('Thema erstellt!');
|
||||
UI.toast.success('Beitrag erstellt!');
|
||||
document.getElementById('forum-thread-list')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -888,7 +907,16 @@ window.Page_forum = (() => {
|
|||
try {
|
||||
const members = await API.forum.membersMap();
|
||||
members.forEach(m => {
|
||||
L.marker([m.lat, m.lon])
|
||||
const icon = L.divIcon({
|
||||
className: '',
|
||||
html: `<div style="width:32px;height:32px;border-radius:50%;
|
||||
background:var(--c-primary);color:#fff;font-size:13px;font-weight:700;
|
||||
display:flex;align-items:center;justify-content:center;
|
||||
box-shadow:0 2px 5px rgba(0,0,0,0.35);
|
||||
border:2px solid rgba(255,255,255,0.8)">${_esc((m.vorname||'?')[0].toUpperCase())}</div>`,
|
||||
iconSize: [32, 32], iconAnchor: [16, 16],
|
||||
});
|
||||
L.marker([m.lat, m.lon], { icon })
|
||||
.bindPopup(`<strong>${_esc(m.vorname || '?')}</strong>`)
|
||||
.addTo(_map);
|
||||
});
|
||||
|
|
@ -967,6 +995,20 @@ window.Page_forum = (() => {
|
|||
});
|
||||
}
|
||||
|
||||
return { init, refresh, onDogChange };
|
||||
function openNew() {
|
||||
if (!_appState?.user) { UI.toast.info('Bitte erst anmelden.'); return; }
|
||||
_showCreateForm();
|
||||
}
|
||||
|
||||
function _showLightbox(src) {
|
||||
const lb = document.createElement('div');
|
||||
lb.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.92);z-index:9999;display:flex;align-items:center;justify-content:center;cursor:zoom-out';
|
||||
lb.innerHTML = `<img src="${UI.escape(src)}" style="max-width:100%;max-height:100%;object-fit:contain;touch-action:pinch-zoom">
|
||||
<button style="position:absolute;top:16px;right:16px;background:rgba(255,255,255,.2);border:none;border-radius:50%;width:40px;height:40px;color:#fff;font-size:22px;cursor:pointer;display:flex;align-items:center;justify-content:center">✕</button>`;
|
||||
lb.addEventListener('click', () => lb.remove());
|
||||
document.body.appendChild(lb);
|
||||
}
|
||||
|
||||
return { init, refresh, onDogChange, openNew };
|
||||
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue