sdfdsf
This commit is contained in:
@@ -45,18 +45,22 @@ if ($pdo && ($q !== '' || $loc !== '' || ($lat !== null && $lng !== null))) {
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<p class="eyebrow">Suche</p>
|
<p class="eyebrow">Suche</p>
|
||||||
<h1>Events finden</h1>
|
<h1>Events finden</h1>
|
||||||
<form method="get" class="form-grid single" style="margin: 14px 0; gap:12px; align-items:end;">
|
<form method="get" class="form-grid single" style="margin: 14px 0; gap:12px; align-items:end;" id="searchForm">
|
||||||
<div class="stack gap-6">
|
<div class="stack gap-6">
|
||||||
<label class="label" for="q">Suchbegriff (Titel, Ort, Beschreibung)</label>
|
<label class="label" for="q">Suchbegriff (Titel, Ort, Beschreibung)</label>
|
||||||
<input id="q" name="q" class="input" value="<?= htmlspecialchars($q, ENT_QUOTES) ?>" placeholder="z. B. Berlin oder Spielplatz">
|
<input id="q" name="q" class="input" value="<?= htmlspecialchars($q, ENT_QUOTES) ?>" placeholder="z. B. Berlin oder Spielplatz">
|
||||||
</div>
|
</div>
|
||||||
<div class="stack gap-6">
|
<div class="stack gap-6">
|
||||||
<label class="label" for="loc">Ort oder PLZ (optional)</label>
|
<label class="label" for="loc">Ort oder PLZ (optional)</label>
|
||||||
<input id="loc" name="loc" class="input" value="<?= htmlspecialchars($loc, ENT_QUOTES) ?>" placeholder="z. B. 10437 oder Berlin">
|
<div class="flex gap-8" style="align-items:center;">
|
||||||
<input type="hidden" name="lat" value="<?= $lat !== null ? htmlspecialchars((string)$lat, ENT_QUOTES) : '' ?>">
|
<input id="loc" name="loc" class="input" value="<?= htmlspecialchars($loc, ENT_QUOTES) ?>" placeholder="z. B. 10437 oder Berlin" style="flex:1;">
|
||||||
<input type="hidden" name="lng" value="<?= $lng !== null ? htmlspecialchars((string)$lng, ENT_QUOTES) : '' ?>">
|
<button class="btn ghost" type="button" id="btnGeo">📍</button>
|
||||||
|
<button class="btn ghost" type="button" id="btnMap">Karte</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="stack gap-6">
|
<input type="hidden" id="lat" name="lat" value="<?= $lat !== null ? htmlspecialchars((string)$lat, ENT_QUOTES) : '' ?>">
|
||||||
|
<input type="hidden" id="lng" name="lng" value="<?= $lng !== null ? htmlspecialchars((string)$lng, ENT_QUOTES) : '' ?>">
|
||||||
|
</div>
|
||||||
|
<div class="stack gap-6" id="radiusWrap">
|
||||||
<label class="label" for="radius">Umkreis (km)</label>
|
<label class="label" for="radius">Umkreis (km)</label>
|
||||||
<select id="radius" name="radius" class="select">
|
<select id="radius" name="radius" class="select">
|
||||||
<?php foreach ([1,2,5,10,15,25] as $r): ?>
|
<?php foreach ([1,2,5,10,15,25] as $r): ?>
|
||||||
@@ -66,6 +70,12 @@ if ($pdo && ($q !== '' || $loc !== '' || ($lat !== null && $lng !== null))) {
|
|||||||
</div>
|
</div>
|
||||||
<button class="btn" type="submit">Suchen</button>
|
<button class="btn" type="submit">Suchen</button>
|
||||||
</form>
|
</form>
|
||||||
|
<div id="mapWrapper" class="map-wrapper" hidden>
|
||||||
|
<div class="stack gap-6">
|
||||||
|
<p class="muted small">Karte anklicken, um Standort zu wählen. Ziehen/Zoomen möglich.</p>
|
||||||
|
<div id="mapContainer" class="map-container" style="height: 320px; border:1px solid #e5e7eb; border-radius:8px;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<?php if ($q === '' && $loc === '' && $lat === null && $lng === null): ?>
|
<?php if ($q === '' && $loc === '' && $lat === null && $lng === null): ?>
|
||||||
<p class="muted">Bitte gib einen Suchbegriff oder einen Ort ein.</p>
|
<p class="muted">Bitte gib einen Suchbegriff oder einen Ort ein.</p>
|
||||||
@@ -104,3 +114,105 @@ if ($pdo && ($q !== '' || $loc !== '' || ($lat !== null && $lng !== null))) {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
<script>
|
||||||
|
(function(){
|
||||||
|
const locInput = document.getElementById('loc');
|
||||||
|
const latInput = document.getElementById('lat');
|
||||||
|
const lngInput = document.getElementById('lng');
|
||||||
|
const radiusWrap = document.getElementById('radiusWrap');
|
||||||
|
const radiusSelect = document.getElementById('radius');
|
||||||
|
const btnGeo = document.getElementById('btnGeo');
|
||||||
|
const btnMap = document.getElementById('btnMap');
|
||||||
|
const mapWrapper = document.getElementById('mapWrapper');
|
||||||
|
const mapContainer = document.getElementById('mapContainer');
|
||||||
|
let map, marker;
|
||||||
|
|
||||||
|
function toggleRadius(show) {
|
||||||
|
if (!radiusWrap) return;
|
||||||
|
radiusWrap.hidden = !show;
|
||||||
|
if (radiusSelect) radiusSelect.disabled = !show;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearGeo() {
|
||||||
|
if (latInput) latInput.value = '';
|
||||||
|
if (lngInput) lngInput.value = '';
|
||||||
|
toggleRadius(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureLeaflet(cb) {
|
||||||
|
if (window.L) { cb(); return; }
|
||||||
|
const css = document.createElement('link');
|
||||||
|
css.rel = 'stylesheet';
|
||||||
|
css.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';
|
||||||
|
document.head.appendChild(css);
|
||||||
|
const s = document.createElement('script');
|
||||||
|
s.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';
|
||||||
|
s.onload = cb;
|
||||||
|
document.body.appendChild(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMarker(latlng) {
|
||||||
|
if (!map) return;
|
||||||
|
if (marker) {
|
||||||
|
marker.setLatLng(latlng);
|
||||||
|
} else {
|
||||||
|
marker = L.marker(latlng, { draggable:true }).addTo(map);
|
||||||
|
marker.on('dragend', () => {
|
||||||
|
const ll = marker.getLatLng();
|
||||||
|
latInput.value = ll.lat.toFixed(6);
|
||||||
|
lngInput.value = ll.lng.toFixed(6);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
latInput.value = latlng.lat.toFixed(6);
|
||||||
|
lngInput.value = latlng.lng.toFixed(6);
|
||||||
|
map.setView(latlng, 13);
|
||||||
|
toggleRadius(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initMap() {
|
||||||
|
if (map) { map.invalidateSize(); return; }
|
||||||
|
map = L.map(mapContainer).setView([51.1657, 10.4515], 5);
|
||||||
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19 }).addTo(map);
|
||||||
|
map.on('click', (e) => setMarker(e.latlng));
|
||||||
|
const lat = parseFloat(latInput.value);
|
||||||
|
const lng = parseFloat(lngInput.value);
|
||||||
|
if (!Number.isNaN(lat) && !Number.isNaN(lng)) {
|
||||||
|
setMarker({ lat, lng });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
locInput?.addEventListener('input', () => {
|
||||||
|
if (!locInput.value.trim()) {
|
||||||
|
clearGeo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
btnGeo?.addEventListener('click', () => {
|
||||||
|
if (!navigator.geolocation) {
|
||||||
|
alert('Geolocation wird nicht unterstützt.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
navigator.geolocation.getCurrentPosition((pos) => {
|
||||||
|
const lat = pos.coords.latitude;
|
||||||
|
const lng = pos.coords.longitude;
|
||||||
|
latInput.value = lat.toFixed(6);
|
||||||
|
lngInput.value = lng.toFixed(6);
|
||||||
|
if (locInput && !locInput.value.trim()) locInput.value = 'Mein Standort';
|
||||||
|
toggleRadius(true);
|
||||||
|
}, () => alert('Standort konnte nicht ermittelt werden.'));
|
||||||
|
});
|
||||||
|
|
||||||
|
btnMap?.addEventListener('click', () => {
|
||||||
|
if (!mapWrapper) return;
|
||||||
|
mapWrapper.hidden = !mapWrapper.hidden;
|
||||||
|
if (!mapWrapper.hidden) {
|
||||||
|
ensureLeaflet(() => setTimeout(() => initMap(), 50));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Init radius visibility based on current state
|
||||||
|
if (!latInput?.value || !lngInput?.value) {
|
||||||
|
toggleRadius(false);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ final class Search
|
|||||||
// Radius for HAVING
|
// Radius for HAVING
|
||||||
$bind[] = $radius;
|
$bind[] = $radius;
|
||||||
} else {
|
} else {
|
||||||
$sql = "SELECT id, title, teaser_public, description, city, region, zip, starts_at, visibility, allow_kids, location_label, lat, lng, 1 AS distance_km";
|
$sql = "SELECT id, title, teaser_public, description, city, region, zip, starts_at, visibility, allow_kids, location_label, lat, lng, NULL AS distance_km";
|
||||||
$bind = $bindTokens;
|
$bind = $bindTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +107,12 @@ final class Search
|
|||||||
try {
|
try {
|
||||||
$stmt->execute($bind);
|
$stmt->execute($bind);
|
||||||
$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC) ?: [];
|
$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC) ?: [];
|
||||||
|
if (!$hasGeo) {
|
||||||
|
foreach ($rows as &$r) {
|
||||||
|
unset($r['distance_km']);
|
||||||
|
}
|
||||||
|
unset($r);
|
||||||
|
}
|
||||||
// Fuzzy filter: allow slight typos (Levenshtein <= 1 or 2)
|
// Fuzzy filter: allow slight typos (Levenshtein <= 1 or 2)
|
||||||
if ($tokens) {
|
if ($tokens) {
|
||||||
$rows = array_values(array_filter($rows, function ($row) use ($tokens) {
|
$rows = array_values(array_filter($rows, function ($row) use ($tokens) {
|
||||||
|
|||||||
Reference in New Issue
Block a user