// Ergebnisliste (Cards), rendert die gefilterte Trefferliste // (EventMap.store.getFilteredPlaces()) statt state.places direkt, damit // Kategorie-/Entfernungs-/etc.-Filter aus js/filters/ berücksichtigt werden. // Rendering ausschließlich über textContent/DOM-APIs (el()), niemals // innerHTML mit Place-Daten. (function () { const { subscribe, getState, setState, getFilteredPlaces } = EventMap.store; const { getCategoryById } = EventMap.config; const { getDistanceKm } = EventMap.filters; const { el, clearChildren } = EventMap.utils; function formatDistance(km) { return km < 10 ? `${km.toFixed(1)} km entfernt` : `${Math.round(km)} km entfernt`; } function createCard(place, userLocation) { const category = getCategoryById(place.category); const select = () => setState({ selectedPlaceId: place.id }); const children = [ el('h3', { className: 'place-card__name', text: place.name }), el('span', { className: 'place-card__category', style: { backgroundColor: category.color }, text: `${category.icon} ${category.label}`, }), el('p', { className: 'place-card__desc', text: place.shortDescription }), ]; const distanceKm = getDistanceKm(place, userLocation); if (distanceKm !== null) { children.push(el('p', { className: 'place-card__distance', text: formatDistance(distanceKm) })); } return el( 'li', { className: 'place-card', attrs: { tabindex: '0', role: 'button' }, dataset: { placeId: place.id }, on: { click: select, keydown: (event) => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); select(); } }, }, }, children ); } function render(container, filteredPlaces, totalPlacesCount, userLocation) { clearChildren(container); if (!filteredPlaces || filteredPlaces.length === 0) { const message = totalPlacesCount > 0 ? 'Keine Ausflugsziele gefunden. Filter anpassen?' : 'Keine Ausflugsziele vorhanden.'; container.appendChild(el('p', { className: 'list-empty', text: message })); return; } const list = el('ul', { className: 'place-list' }); for (const place of filteredPlaces) { list.appendChild(createCard(place, userLocation)); } container.appendChild(list); } /** Initialisiert die Liste im Element mit der übergebenen id und abonniert den Store. */ function initList(containerId) { const container = document.getElementById(containerId); if (!container) { console.error(`EventMap: List-Container #${containerId} nicht gefunden.`); return; } const renderFromState = (state) => { render(container, getFilteredPlaces(), state.places.length, state.userLocation); }; renderFromState(getState()); subscribe(renderFromState); } EventMap.ui.initList = initList; })();