UX: Nearby-POIs einklappbar + klickbar + nur relevante Typen
- NEARBY_TYPES: Bänke/Wasserstellen entfernt → nur Restaurant, Tierarzt, Zoobedarf - Gruppen einklappbar (Chevron dreht sich) - POI-Namen anklickbar → öffnet Apple Maps/Google Maps am POI-Standort - CSS: Card-Stil für Gruppen, gute Touch-Targets
This commit is contained in:
parent
9a56978f81
commit
3144e100f3
3 changed files with 95 additions and 29 deletions
|
|
@ -2339,24 +2339,50 @@ html.modal-open {
|
||||||
}
|
}
|
||||||
.rk-nearby-group {
|
.rk-nearby-group {
|
||||||
margin-bottom: var(--space-3);
|
margin-bottom: var(--space-3);
|
||||||
|
border: 1px solid var(--c-border-light);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.rk-nearby-group-label {
|
.rk-nearby-group-header {
|
||||||
font-size: var(--text-sm);
|
display: flex;
|
||||||
font-weight: var(--weight-medium);
|
align-items: center;
|
||||||
color: var(--c-text-secondary);
|
justify-content: space-between;
|
||||||
margin-bottom: var(--space-1);
|
width: 100%;
|
||||||
|
padding: var(--space-2) var(--space-3);
|
||||||
|
background: var(--c-surface-2);
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: var(--text-sm);
|
||||||
|
font-weight: var(--weight-semibold);
|
||||||
|
color: var(--c-text);
|
||||||
|
text-align: left;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
}
|
}
|
||||||
|
.rk-nearby-group-header:hover { background: var(--c-border-light); }
|
||||||
|
.rk-nearby-items { padding: var(--space-1) 0; }
|
||||||
.rk-nearby-item {
|
.rk-nearby-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
gap: var(--space-2);
|
gap: var(--space-2);
|
||||||
align-items: baseline;
|
padding: var(--space-2) var(--space-3);
|
||||||
padding: var(--space-1) 0;
|
|
||||||
border-bottom: 1px solid var(--c-border-light);
|
border-bottom: 1px solid var(--c-border-light);
|
||||||
|
width: 100%;
|
||||||
|
background: none;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
border-top: none;
|
||||||
|
text-align: left;
|
||||||
|
font: inherit;
|
||||||
}
|
}
|
||||||
.rk-nearby-item:last-child { border-bottom: none; }
|
.rk-nearby-item:last-child { border-bottom: none; }
|
||||||
.rk-nearby-name { font-size: var(--text-sm); color: var(--c-text); }
|
.rk-nearby-item--link {
|
||||||
.rk-nearby-detail { font-size: var(--text-xs); color: var(--c-text-muted); }
|
cursor: pointer;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
.rk-nearby-item--link:hover { background: var(--c-surface-2); }
|
||||||
|
.rk-nearby-name { font-size: var(--text-sm); color: var(--c-text); display: block; }
|
||||||
|
.rk-nearby-detail { font-size: var(--text-xs); color: var(--c-text-muted); display: block; margin-top: 1px; }
|
||||||
.rk-nearby-phone { color: var(--c-primary); text-decoration: none; }
|
.rk-nearby-phone { color: var(--c-primary); text-decoration: none; }
|
||||||
|
|
||||||
/* Hundetauglichkeit-Auswahl im Formular */
|
/* Hundetauglichkeit-Auswahl im Formular */
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Router, State-Management, Navigation, Initialisierung.
|
Router, State-Management, Navigation, Initialisierung.
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const APP_VER = '226'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
const APP_VER = '227'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||||
|
|
||||||
const App = (() => {
|
const App = (() => {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,11 @@ window.Page_routes = (() => {
|
||||||
const TERRAIN_LABEL = { wald: '🌲 Wald', asphalt: '🛣️ Asphalt', wiese: '🌿 Wiese', mix: '🔀 Mix' };
|
const TERRAIN_LABEL = { wald: '🌲 Wald', asphalt: '🛣️ Asphalt', wiese: '🌿 Wiese', mix: '🔀 Mix' };
|
||||||
const HUNDE_LABEL = { eingeschränkt: '🐾', gut: '🐾🐾', sehr_gut: '🐾🐾🐾', premium: '🐾🐾🐾🐾' };
|
const HUNDE_LABEL = { eingeschränkt: '🐾', gut: '🐾🐾', sehr_gut: '🐾🐾🐾', premium: '🐾🐾🐾🐾' };
|
||||||
|
|
||||||
// POI-Typen die entlang einer Route gezeigt werden
|
// POI-Typen entlang der Route — nur relevante/interessante Orte
|
||||||
const NEARBY_TYPES = [
|
const NEARBY_TYPES = [
|
||||||
{ type: 'restaurant', icon: '🍽️', label: 'Restaurant/Café' },
|
{ type: 'restaurant', icon: '🍽️', label: 'Restaurant/Café' },
|
||||||
{ type: 'parkplatz', icon: '🅿️', label: 'Parkplatz' },
|
{ type: 'tierarzt', icon: '🏥', label: 'Tierarzt' },
|
||||||
{ type: 'drinking_water', icon: '💧', label: 'Wasserstelle' },
|
{ type: 'shop', icon: '🐾', label: 'Zoobedarf' },
|
||||||
{ type: 'bank', icon: '🪑', label: 'Bank' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// _esc und _emptyState ersetzt durch UI.escape() / UI.emptyState()
|
// _esc und _emptyState ersetzt durch UI.escape() / UI.emptyState()
|
||||||
|
|
@ -936,7 +935,6 @@ window.Page_routes = (() => {
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
if (!pois.length) { el.innerHTML = ''; return; }
|
if (!pois.length) { el.innerHTML = ''; return; }
|
||||||
|
|
||||||
// Gruppieren nach Typ
|
|
||||||
const byType = {};
|
const byType = {};
|
||||||
pois.forEach(p => {
|
pois.forEach(p => {
|
||||||
const key = p._label;
|
const key = p._label;
|
||||||
|
|
@ -944,22 +942,64 @@ window.Page_routes = (() => {
|
||||||
byType[key].items.push(p);
|
byType[key].items.push(p);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let gIdx = 0;
|
||||||
el.innerHTML = `
|
el.innerHTML = `
|
||||||
<div class="rk-nearby-title">${UI.icon('map-pin')} Entlang der Route</div>
|
<div class="rk-nearby-title">${UI.icon('map-pin')} Entlang der Route</div>
|
||||||
${Object.values(byType).map(group => `
|
${Object.values(byType).map(group => {
|
||||||
<div class="rk-nearby-group">
|
const id = `rk-ng-${gIdx++}`;
|
||||||
<div class="rk-nearby-group-label">${group.icon} ${UI.escape(group.label)} (${group.items.length})</div>
|
return `
|
||||||
${group.items.slice(0, 5).map(p => `
|
<div class="rk-nearby-group">
|
||||||
<div class="rk-nearby-item">
|
<button class="rk-nearby-group-header" data-target="${id}" type="button">
|
||||||
<span class="rk-nearby-name">${UI.escape(p.name || group.label)}</span>
|
<span>${group.icon} ${UI.escape(group.label)} (${group.items.length})</span>
|
||||||
${p.opening_hours ? `<span class="rk-nearby-detail">${UI.icon('clock')} ${UI.escape(p.opening_hours)}</span>` : ''}
|
<svg class="ph-icon rk-nearby-chevron" aria-hidden="true" style="transition:transform 0.2s">
|
||||||
${p.phone ? `<a href="tel:${UI.escape(p.phone)}" class="rk-nearby-detail rk-nearby-phone">${UI.icon('phone')} ${UI.escape(p.phone)}</a>` : ''}
|
<use href="/icons/phosphor.svg#caret-down"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div id="${id}" class="rk-nearby-items">
|
||||||
|
${group.items.map(p => `
|
||||||
|
<button class="rk-nearby-item rk-nearby-item--link" type="button"
|
||||||
|
data-lat="${p.lat}" data-lon="${p.lon}"
|
||||||
|
data-name="${UI.escape(p.name || group.label)}">
|
||||||
|
<div>
|
||||||
|
<span class="rk-nearby-name">${UI.escape(p.name || group.label)}</span>
|
||||||
|
${p.opening_hours ? `<span class="rk-nearby-detail">${UI.icon('clock')} ${UI.escape(p.opening_hours)}</span>` : ''}
|
||||||
|
${p.phone ? `<span class="rk-nearby-detail">${UI.icon('phone')} ${UI.escape(p.phone)}</span>` : ''}
|
||||||
|
</div>
|
||||||
|
<svg class="ph-icon" style="width:14px;height:14px;color:var(--c-text-muted);flex-shrink:0" aria-hidden="true">
|
||||||
|
<use href="/icons/phosphor.svg#map-pin"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
`).join('')}
|
||||||
</div>
|
</div>
|
||||||
`).join('')}
|
</div>`;
|
||||||
${group.items.length > 5 ? `<div style="font-size:var(--text-xs);color:var(--c-text-muted);padding:2px 0">+${group.items.length-5} weitere</div>` : ''}
|
}).join('')}
|
||||||
</div>
|
|
||||||
`).join('')}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
// Einklapp-Logik
|
||||||
|
el.querySelectorAll('.rk-nearby-group-header').forEach(btn => {
|
||||||
|
const target = document.getElementById(btn.dataset.target);
|
||||||
|
const chevron = btn.querySelector('.rk-nearby-chevron');
|
||||||
|
let open = true;
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
open = !open;
|
||||||
|
target.style.display = open ? '' : 'none';
|
||||||
|
chevron.style.transform = open ? '' : 'rotate(-90deg)';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// POI auf Karte zeigen
|
||||||
|
el.querySelectorAll('.rk-nearby-item--link').forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const lat = parseFloat(btn.dataset.lat);
|
||||||
|
const lon = parseFloat(btn.dataset.lon);
|
||||||
|
const name = btn.dataset.name;
|
||||||
|
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
|
||||||
|
const url = isIOS
|
||||||
|
? `maps://maps.apple.com/?q=${encodeURIComponent(name)}&ll=${lat},${lon}`
|
||||||
|
: `https://www.google.com/maps/search/?api=1&query=${lat},${lon}`;
|
||||||
|
window.open(url, '_blank');
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue