Feature: Suchfeld in Routen, Events und Places

Alle drei Seiten haben jetzt ein debounced Suchfeld (300ms) mit
Lupe-Icon über der Liste. Die Suche filtert clientseitig:
- Routen: Name, Beschreibung, Username (bereits vorhandener State verbessert)
- Events: Titel, Ort, Beschreibung
- Places: Name, Adresse, Typ
Leerer Zustand zeigt passendes UI.emptyState() mit Suchbegriff.
SW by-v209, APP_VER 178.
This commit is contained in:
rene 2026-04-18 18:42:13 +02:00
parent 5acfa9d8f6
commit 6581a9a88c
3 changed files with 90 additions and 18 deletions

View file

@ -35,6 +35,7 @@ window.Page_events = (() => {
let _events = [];
let _filter = 'alle';
let _quellFilter = 'alle'; // 'alle' | 'vdh' | 'nutzer'
let _search = '';
let _view = 'liste'; // liste | karte
let _map = null;
let _markers = [];
@ -78,6 +79,12 @@ window.Page_events = (() => {
${_state.user ? `<button class="btn btn-primary btn-sm" id="ev-new-btn">${UI.icon('plus')} Event</button>` : ''}
</div>
<div class="diary-search-wrap" style="margin:var(--space-2) var(--space-3) 0" id="ev-search-wrap">
<svg class="ph-icon diary-search-icon" aria-hidden="true"><use href="/icons/phosphor.svg#magnifying-glass"></use></svg>
<input type="search" class="diary-search-input" id="ev-search"
placeholder="Events durchsuchen…" autocomplete="off">
</div>
<div class="events-filter-bar by-tabs" id="ev-filter-bar">
${TYPEN.map(t => `
<button class="by-tab ${t.id === 'alle' ? 'active' : ''}" data-ev-typ="${t.id}">
@ -99,6 +106,16 @@ window.Page_events = (() => {
`;
_container.addEventListener('click', _onClick);
// Suche mit Debounce
let _searchTimer = null;
document.getElementById('ev-search')?.addEventListener('input', e => {
clearTimeout(_searchTimer);
_searchTimer = setTimeout(() => {
_search = e.target.value.trim().toLowerCase();
if (_view === 'karte') { _renderMap(_filtered()); } else { _renderList(); }
}, 300);
});
}
// ----------------------------------------------------------
@ -124,6 +141,14 @@ window.Page_events = (() => {
if (_quellFilter !== 'alle') {
evs = evs.filter(e => (e.quelle || 'nutzer') === _quellFilter);
}
if (_search) {
const q = _search;
evs = evs.filter(e =>
(e.titel || '').toLowerCase().includes(q) ||
(e.ort_name || '').toLowerCase().includes(q) ||
(e.beschreibung|| '').toLowerCase().includes(q)
);
}
return evs;
}
@ -138,8 +163,10 @@ window.Page_events = (() => {
if (!filtered.length) {
listEl.innerHTML = UI.emptyState({
icon: UI.icon('calendar-blank'),
title: 'Keine Events in der Nähe',
text: 'Hier erscheinen Hundeveranstaltungen, Treffen und Aktivitäten in deiner Umgebung.',
title: _search ? 'Keine Events gefunden' : 'Keine Events in der Nähe',
text: _search
? `Keine Events passen zu „${UI.escape(_search)}".`
: 'Hier erscheinen Hundeveranstaltungen, Treffen und Aktivitäten in deiner Umgebung.',
});
return;
}