This commit is contained in:
@@ -17,7 +17,7 @@ if ($editingEvent && !empty($editEvent['starts_at'])) {
|
||||
} elseif ($editingListing && !empty($editListing['starts_at'])) {
|
||||
$startVal = date('Y-m-d\TH:i', strtotime((string)$editListing['starts_at']));
|
||||
}
|
||||
$allowNoKidsChecked = $editingEvent ? ((int)$editEvent['allow_kids'] === 0) : false;
|
||||
$withChildrenValue = $editingEvent ? (((int)($editEvent['allow_kids'] ?? 1)) === 1 ? 'yes' : 'no') : (($editingListing && $currentEntryKind === 'editorial_event' && !empty($editListing['supports_registration'])) ? 'yes' : 'yes');
|
||||
$eventTitle = $editingEvent ? 'Event bearbeiten' : ($editingListing ? ($currentEntryKind === 'place' ? 'Ort bearbeiten' : 'Veranstaltung bearbeiten') : 'Neuen Eintrag anlegen');
|
||||
$submitLabel = $editingEvent ? 'Event speichern' : ($editingListing ? ($currentEntryKind === 'place' ? 'Ort speichern' : 'Veranstaltung speichern') : 'Eintrag anlegen');
|
||||
$titleValue = $editingEvent ? (string)($editEvent['title'] ?? '') : (string)($editListing['title'] ?? '');
|
||||
@@ -31,8 +31,14 @@ $regionValue = $editingEvent ? (string)($editEvent['region'] ?? '') : (string)($
|
||||
$latValue = $editingEvent ? (string)($editEvent['lat'] ?? '') : (string)($editListing['lat'] ?? '');
|
||||
$lngValue = $editingEvent ? (string)($editEvent['lng'] ?? '') : (string)($editListing['lng'] ?? '');
|
||||
$visibilityValue = $editingEvent ? (string)($editEvent['visibility'] ?? 'public') : (string)($editListing['visibility'] ?? 'public');
|
||||
$categorySlugValue = $editingListing ? (string)($editListing['category_slug'] ?? '') : '';
|
||||
$categorySlugValue = $editingEvent ? (string)($editEvent['category_slug'] ?? '') : (string)($editListing['category_slug'] ?? '');
|
||||
$imagePathValue = $editingEvent ? (string)($editEvent['image_path'] ?? '') : (string)($editListing['image_path'] ?? '');
|
||||
$capacityValue = $editingEvent ? (string)($editEvent['max_participants'] ?? '') : (string)($editListing['capacity_total'] ?? '');
|
||||
$phoneValue = $editingListing ? (string)($editListing['phone'] ?? '') : '';
|
||||
$websiteValue = $editingListing ? (string)($editListing['website_url'] ?? '') : '';
|
||||
$specialConditionsValue = $editingListing ? (string)($editListing['special_conditions_note'] ?? '') : '';
|
||||
$openingHoursValue = $editingListing ? (string)($editListing['opening_hours_note'] ?? '') : '';
|
||||
$openingHoursRows = $editingListing && !empty($editListing['opening_hours']) && is_array($editListing['opening_hours']) ? $editListing['opening_hours'] : [['day_label' => '', 'time_from' => '', 'time_to' => '', 'note' => '']];
|
||||
$recurrenceRuleValue = $editingListing ? (string)($editListing['recurrence_rule'] ?? '') : '';
|
||||
$recurrenceUntilValue = '';
|
||||
if ($editingListing && !empty($editListing['recurrence_until'])) {
|
||||
@@ -57,41 +63,14 @@ if (preg_match('/BYDAY=([A-Z,]+)/', $recurrenceRuleValue, $matches)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
$priceModeValue = 'none';
|
||||
$freeChildUntilAge = '';
|
||||
$priceChildAmount = '';
|
||||
$priceChildAgeFrom = '';
|
||||
$priceChildAgeTo = '';
|
||||
$priceAdultAmount = '';
|
||||
$priceAdultAgeFrom = '';
|
||||
if ($editingListing && !empty($editListing['prices']) && is_array($editListing['prices'])) {
|
||||
foreach ($editListing['prices'] as $priceRow) {
|
||||
$audience = (string)($priceRow['audience'] ?? '');
|
||||
$priceType = (string)($priceRow['price_type'] ?? '');
|
||||
$note = (string)($priceRow['note'] ?? '');
|
||||
if ($priceType === 'free') {
|
||||
$priceModeValue = 'free_child_rule';
|
||||
if (preg_match('/bis\s+(\d+)/u', $note, $m)) {
|
||||
$freeChildUntilAge = $m[1];
|
||||
}
|
||||
} elseif ($audience === 'child') {
|
||||
$priceModeValue = 'paid';
|
||||
$priceChildAmount = (string)($priceRow['amount'] ?? '');
|
||||
if (preg_match('/ab\s+(\d+)/u', $note, $m)) {
|
||||
$priceChildAgeFrom = $m[1];
|
||||
}
|
||||
if (preg_match('/bis\s+(\d+)/u', $note, $m)) {
|
||||
$priceChildAgeTo = $m[1];
|
||||
}
|
||||
} elseif ($audience === 'adult') {
|
||||
$priceModeValue = 'paid';
|
||||
$priceAdultAmount = (string)($priceRow['amount'] ?? '');
|
||||
if (preg_match('/ab\s+(\d+)/u', $note, $m)) {
|
||||
$priceAdultAgeFrom = $m[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$priceRows = $editingListing && !empty($editListing['prices']) && is_array($editListing['prices']) ? $editListing['prices'] : [[
|
||||
'label' => '',
|
||||
'audience' => 'general',
|
||||
'price_type' => 'fixed',
|
||||
'amount' => '',
|
||||
'amount_secondary' => '',
|
||||
'note' => '',
|
||||
]];
|
||||
$editingChild = isset($editChild) && $editChild !== null;
|
||||
$childAction = $editingChild ? 'child_update' : 'child_add';
|
||||
$childModalTitle = $editingChild ? 'Kind bearbeiten' : 'Kind hinzufügen';
|
||||
@@ -908,7 +887,7 @@ if (!empty($canManageSystemSettings)) {
|
||||
<h3><?= htmlspecialchars($eventTitle, ENT_QUOTES) ?></h3>
|
||||
<button class="btn ghost" type="button" data-modal-close>✕</button>
|
||||
</div>
|
||||
<form class="stack gap-12" style="margin-top: 10px;" method="post" action="/dashboard?section=events#events">
|
||||
<form class="stack gap-12" style="margin-top: 10px;" method="post" action="/dashboard?section=events#events" enctype="multipart/form-data">
|
||||
<input type="hidden" name="action" value="<?= htmlspecialchars($actionEvent, ENT_QUOTES) ?>">
|
||||
<input type="hidden" name="entry_kind" id="entryKind" value="<?= htmlspecialchars($currentEntryKind, ENT_QUOTES) ?>">
|
||||
<?php if ($editingEvent && $editEvent): ?>
|
||||
@@ -942,16 +921,31 @@ if (!empty($canManageSystemSettings)) {
|
||||
</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="form-grid" id="titleDescriptionRow">
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="evTitle">Titel</label>
|
||||
<input id="evTitle" name="title" class="input" placeholder="z. B. Väter-Kaffee im Park" required value="<?= htmlspecialchars($titleValue, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="evTitle">Titel</label>
|
||||
<input id="evTitle" name="title" class="input" placeholder="z. B. Väter-Kaffee im Park" required value="<?= htmlspecialchars($titleValue, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="evDesc">Beschreibung (voll)</label>
|
||||
<textarea id="evDesc" name="description" class="textarea" rows="3" placeholder="Was soll passieren, was mitbringen?" required><?= htmlspecialchars($descriptionValue, ENT_QUOTES) ?></textarea>
|
||||
<p class="muted small" style="margin:0;">Die Kurzbeschreibung wird intern automatisch aus deinem Text erzeugt.</p>
|
||||
<label class="label" for="evDesc">Beschreibung</label>
|
||||
<textarea id="evDesc" name="description" class="textarea" rows="4" placeholder="Was erwartet Familien vor Ort?" required><?= htmlspecialchars($descriptionValue, ENT_QUOTES) ?></textarea>
|
||||
<p class="muted small" style="margin:0;">Die Kurzbeschreibung wird automatisch aus dem Text erzeugt.</p>
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="listingCategorySlug">Kategorie</label>
|
||||
<select id="listingCategorySlug" name="category_slug" class="select">
|
||||
<option value="">Bitte auswählen</option>
|
||||
<?php foreach ($listingCategories as $category): ?>
|
||||
<option value="<?= htmlspecialchars((string)$category['slug'], ENT_QUOTES) ?>" <?= $categorySlugValue === (string)$category['slug'] ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars((string)$category['title'], ENT_QUOTES) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="categoryCustomTitle">Oder neue Kategorie</label>
|
||||
<input id="categoryCustomTitle" name="category_custom_title" class="input" placeholder="z. B. Tierpark">
|
||||
</div>
|
||||
</div>
|
||||
<div class="stack gap-6" id="placeLookupWrap">
|
||||
<label class="label" for="existingPlaceLookup">Vorhandenen Ort suchen (optional)</label>
|
||||
@@ -959,33 +953,36 @@ if (!empty($canManageSystemSettings)) {
|
||||
<input id="existingPlaceLookup" class="input" list="existingPlacesList" placeholder="z. B. Tierpark, Café, Spielplatz" style="flex:1;">
|
||||
<button class="btn ghost" type="button" id="btnUseExistingPlace">Ort übernehmen</button>
|
||||
</div>
|
||||
<p class="muted small" style="margin:0;">Wenn ein passender Ort schon existiert, kannst du ihn übernehmen. Falls nichts passt, legst du unten einfach einen neuen Ort an.</p>
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="imageFile">Bild (optional)</label>
|
||||
<input id="imageFile" name="image_file" class="input" type="file" accept="image/jpeg,image/png,image/webp">
|
||||
<?php if ($imagePathValue !== ''): ?>
|
||||
<div class="muted small">Aktuelles Bild: <a href="<?= htmlspecialchars($imagePathValue, ENT_QUOTES) ?>" target="_blank" rel="noopener">Ansehen</a></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="form-grid" id="eventDateRow">
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="evDate">Datum & Uhrzeit</label>
|
||||
<label class="label" for="evDate">Start / Termin</label>
|
||||
<input id="evDate" name="starts_at" class="input" type="datetime-local" required value="<?= htmlspecialchars($startVal, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<div class="stack gap-6" id="eventLocationLabelWrap">
|
||||
<label class="label" for "evLoc">Ort/Label</label>
|
||||
<input id="evLoc" name="location_label" class="input" placeholder="Park / Café" value="<?= htmlspecialchars($locationLabelValue, ENT_QUOTES) ?>">
|
||||
<label class="label" for="evLoc">Ort-Label</label>
|
||||
<input id="evLoc" name="location_label" class="input" placeholder="z. B. Café Sonnenseite" value="<?= htmlspecialchars($locationLabelValue, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="stack gap-6" id="eventCategoryWrap">
|
||||
<label class="label" for="listingCategorySlug">Kategorie</label>
|
||||
<select id="listingCategorySlug" name="category_slug" class="select">
|
||||
<option value="">Bitte auswählen</option>
|
||||
<?php foreach ($listingCategories as $category): ?>
|
||||
<option value="<?= htmlspecialchars((string)$category['slug'], ENT_QUOTES) ?>" <?= $categorySlugValue === (string)$category['slug'] ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars((string)$category['title'], ENT_QUOTES) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<p class="muted small" style="margin:0;">Für Orte und sonstige Veranstaltungen, damit Spielplatz, Café, Restaurant, Zoo oder Zirkus sauber unterscheidbar bleiben.</p>
|
||||
</div>
|
||||
<div class="stack gap-6" id="placeOpeningHoursWrap">
|
||||
<label class="label" for="openingHoursNote">Öffnungszeiten / Hinweise</label>
|
||||
<textarea id="openingHoursNote" name="opening_hours_note" class="textarea" rows="2" placeholder="z. B. täglich 10:00 bis 18:00 Uhr"><?= htmlspecialchars($openingHoursValue, ENT_QUOTES) ?></textarea>
|
||||
<div class="form-grid" id="eventMetaRow">
|
||||
<div class="stack gap-6" id="eventChildrenWrap">
|
||||
<label class="label" for="withChildren">Mit Kindern</label>
|
||||
<select id="withChildren" name="with_children" class="select">
|
||||
<option value="yes" <?= $withChildrenValue === 'yes' ? 'selected' : '' ?>>Ja</option>
|
||||
<option value="no" <?= $withChildrenValue === 'no' ? 'selected' : '' ?>>Nein</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="stack gap-6" id="eventCapacityWrap">
|
||||
<label class="label" for="maxParticipants">Platzzahl (optional)</label>
|
||||
<input id="maxParticipants" name="max_participants" class="input" type="number" min="1" value="<?= htmlspecialchars($capacityValue, ENT_QUOTES) ?>" placeholder="leer = offen">
|
||||
</div>
|
||||
</div>
|
||||
<div class="stack gap-6" id="eventRecurrenceWrap">
|
||||
<label class="label" for="recurrenceMode">Wiederholung</label>
|
||||
@@ -1005,7 +1002,7 @@ if (!empty($canManageSystemSettings)) {
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="recurrenceUntil">Wiederholen bis</label>
|
||||
<label class="label" for="recurrenceUntil">Gültig bis</label>
|
||||
<input id="recurrenceUntil" name="recurrence_until" class="input" type="datetime-local" value="<?= htmlspecialchars($recurrenceUntilValue, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
</div>
|
||||
@@ -1032,12 +1029,42 @@ if (!empty($canManageSystemSettings)) {
|
||||
</div>
|
||||
<div class="flex gap-8" style="flex-wrap:wrap; align-items:center;">
|
||||
<button class="btn ghost" type="button" id="btnEventAddressSearch">Adresse suchen</button>
|
||||
<button class="btn ghost" type="button" id="btnEventBrowserLocation">Browser-Adresse übernehmen</button>
|
||||
<button class="btn ghost" type="button" id="btnAddrToMap">Adresse auf Karte setzen</button>
|
||||
<span class="muted small">Hält Karte und Adresse synchron.</span>
|
||||
</div>
|
||||
<div id="eventAddressStatus" class="muted small" style="margin:0;"></div>
|
||||
<input type="hidden" id="evLat" name="lat" value="<?= htmlspecialchars($latValue, ENT_QUOTES) ?>">
|
||||
<input type="hidden" id="evLng" name="lng" value="<?= htmlspecialchars($lngValue, ENT_QUOTES) ?>">
|
||||
<div class="stack gap-6" id="placeContactWrap">
|
||||
<div class="form-grid">
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="placePhone">Telefon (optional)</label>
|
||||
<input id="placePhone" name="phone" class="input" value="<?= htmlspecialchars($phoneValue, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="placeWebsite">Webseite (optional)</label>
|
||||
<input id="placeWebsite" name="website_url" class="input" type="url" placeholder="https://..." value="<?= htmlspecialchars($websiteValue, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stack gap-6" id="placeOpeningHoursWrap">
|
||||
<div class="flex between center-y">
|
||||
<label class="label" for="openingHoursNote">Öffnungszeiten / Zeitfenster</label>
|
||||
<button class="btn ghost" type="button" id="btnAddOpeningRow">Zeit hinzufügen</button>
|
||||
</div>
|
||||
<div id="openingHoursRows" class="stack gap-8">
|
||||
<?php foreach ($openingHoursRows as $openingRow): ?>
|
||||
<div class="form-grid opening-row">
|
||||
<input name="opening_day_label[]" class="input" placeholder="z. B. Montag oder täglich" value="<?= htmlspecialchars((string)($openingRow['day_label'] ?? ''), ENT_QUOTES) ?>">
|
||||
<input name="opening_time_from[]" class="input" type="time" value="<?= htmlspecialchars((string)($openingRow['time_from'] ?? ''), ENT_QUOTES) ?>">
|
||||
<input name="opening_time_to[]" class="input" type="time" value="<?= htmlspecialchars((string)($openingRow['time_to'] ?? ''), ENT_QUOTES) ?>">
|
||||
<input name="opening_note[]" class="input" placeholder="Hinweis" value="<?= htmlspecialchars((string)($openingRow['note'] ?? ''), ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<textarea id="openingHoursNote" name="opening_hours_note" class="textarea" rows="2" placeholder="Freitext-Hinweis zu Öffnungszeiten oder Besonderheiten"><?= htmlspecialchars($openingHoursValue, ENT_QUOTES) ?></textarea>
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<button class="btn ghost" type="button" id="btnMap">Auf Karte suchen</button>
|
||||
<div id="mapWrapper" class="map-wrapper" hidden>
|
||||
@@ -1062,48 +1089,45 @@ if (!empty($canManageSystemSettings)) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="stack gap-10" id="eventPricingWrap">
|
||||
<label class="label" for="priceMode">Eintritt / Kosten</label>
|
||||
<select id="priceMode" name="price_mode" class="select">
|
||||
<option value="none" <?= $priceModeValue === 'none' ? 'selected' : '' ?>>Keine Preisangabe</option>
|
||||
<option value="free_child_rule" <?= $priceModeValue === 'free_child_rule' ? 'selected' : '' ?>>Frei für Kinder bis zu einem Alter</option>
|
||||
<option value="paid" <?= $priceModeValue === 'paid' ? 'selected' : '' ?>>Bezahlter Eintritt</option>
|
||||
</select>
|
||||
<div class="form-grid" id="freeChildRuleWrap">
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="freeChildUntilAge">Kinder frei bis Alter</label>
|
||||
<input id="freeChildUntilAge" name="free_child_until_age" class="input" type="number" min="0" max="25" value="<?= htmlspecialchars($freeChildUntilAge, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<div class="flex between center-y">
|
||||
<label class="label">Eintritt / Kosten</label>
|
||||
<button class="btn ghost" type="button" id="btnAddPriceRow">Preisregel hinzufügen</button>
|
||||
</div>
|
||||
<div class="stack gap-12" id="paidPricingWrap">
|
||||
<div class="form-grid">
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="priceChildAmount">Preis pro Kind</label>
|
||||
<input id="priceChildAmount" name="price_child_amount" class="input" inputmode="decimal" placeholder="z. B. 12,50" value="<?= htmlspecialchars($priceChildAmount, ENT_QUOTES) ?>">
|
||||
<div id="priceRows" class="stack gap-8">
|
||||
<?php foreach ($priceRows as $priceRow): ?>
|
||||
<div class="stack gap-8 price-row card">
|
||||
<div class="form-grid">
|
||||
<input name="price_label[]" class="input" placeholder="z. B. Kinder 4-7" value="<?= htmlspecialchars((string)($priceRow['label'] ?? ''), ENT_QUOTES) ?>">
|
||||
<select name="price_audience[]" class="select">
|
||||
<?php foreach (['general' => 'Allgemein', 'child' => 'Kinder', 'adult' => 'Erwachsene', 'family' => 'Familie', 'group' => 'Gruppe'] as $audienceValue => $audienceLabel): ?>
|
||||
<option value="<?= htmlspecialchars($audienceValue, ENT_QUOTES) ?>" <?= (string)($priceRow['audience'] ?? 'general') === $audienceValue ? 'selected' : '' ?>><?= htmlspecialchars($audienceLabel, ENT_QUOTES) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<select name="price_type[]" class="select">
|
||||
<?php foreach (['free' => 'Frei', 'fixed' => 'Fester Preis', 'from' => 'Preis ab', 'up_to' => 'Preis bis', 'range' => 'Preisspanne', 'request' => 'Auf Anfrage'] as $typeValue => $typeLabel): ?>
|
||||
<option value="<?= htmlspecialchars($typeValue, ENT_QUOTES) ?>" <?= (string)($priceRow['price_type'] ?? 'fixed') === $typeValue ? 'selected' : '' ?>><?= htmlspecialchars($typeLabel, ENT_QUOTES) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input name="price_amount[]" class="input" inputmode="decimal" placeholder="Preis" value="<?= htmlspecialchars((string)($priceRow['amount'] ?? ''), ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<input name="price_amount_secondary[]" class="input" inputmode="decimal" placeholder="Zweiter Preis bei Spanne" value="<?= htmlspecialchars((string)($priceRow['amount_secondary'] ?? ''), ENT_QUOTES) ?>">
|
||||
<input name="price_note[]" class="input" placeholder="Hinweis" value="<?= htmlspecialchars((string)($priceRow['note'] ?? ''), ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<input name="price_age_from[]" class="input" type="number" min="0" max="99" placeholder="Alter von" value="">
|
||||
<input name="price_age_to[]" class="input" type="number" min="0" max="99" placeholder="Alter bis" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="priceAdultAmount">Preis pro Erwachsener</label>
|
||||
<input id="priceAdultAmount" name="price_adult_amount" class="input" inputmode="decimal" placeholder="z. B. 18,00" value="<?= htmlspecialchars($priceAdultAmount, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="priceChildAgeFrom">Kind ab Alter</label>
|
||||
<input id="priceChildAgeFrom" name="price_child_age_from" class="input" type="number" min="0" max="25" value="<?= htmlspecialchars($priceChildAgeFrom, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="priceChildAgeTo">Kind bis Alter</label>
|
||||
<input id="priceChildAgeTo" name="price_child_age_to" class="input" type="number" min="0" max="25" value="<?= htmlspecialchars($priceChildAgeTo, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="priceAdultAgeFrom">Erwachsener ab Alter</label>
|
||||
<input id="priceAdultAgeFrom" name="price_adult_age_from" class="input" type="number" min="0" max="25" value="<?= htmlspecialchars($priceAdultAgeFrom, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="specialConditionsNote">Sonderkonditionen</label>
|
||||
<textarea id="specialConditionsNote" name="special_conditions_note" class="textarea" rows="2" placeholder="z. B. Sonderkonditionen für Senioren oder Menschen mit Behinderung vorhanden"><?= htmlspecialchars($specialConditionsValue, ENT_QUOTES) ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<label class="label" id="eventKidsWrap" style="display:flex; align-items:center; gap:8px;">
|
||||
<input type="checkbox" name="allow_kids" <?= $allowNoKidsChecked ? 'checked' : '' ?>> Event ohne Kinder
|
||||
</label>
|
||||
<div class="flex gap-12">
|
||||
<button class="btn ghost" type="button" data-modal-close>Abbrechen</button>
|
||||
<button class="btn" type="submit"><?= htmlspecialchars($submitLabel, ENT_QUOTES) ?></button>
|
||||
@@ -1140,6 +1164,7 @@ if (!empty($canManageSystemSettings)) {
|
||||
const btnMapSearch = document.getElementById('btnMapSearch');
|
||||
const btnAddrToMap = document.getElementById('btnAddrToMap');
|
||||
const btnEventAddressSearch = document.getElementById('btnEventAddressSearch');
|
||||
const btnEventBrowserLocation = document.getElementById('btnEventBrowserLocation');
|
||||
const eventAddressStatus = document.getElementById('eventAddressStatus');
|
||||
const mapSearch = document.getElementById('mapSearch');
|
||||
const latInput = document.getElementById('evLat');
|
||||
@@ -1149,19 +1174,21 @@ if (!empty($canManageSystemSettings)) {
|
||||
const entryKindButtons = document.querySelectorAll('[data-entry-kind-choice]');
|
||||
const eventDateRow = document.getElementById('eventDateRow');
|
||||
const eventLocationLabelWrap = document.getElementById('eventLocationLabelWrap');
|
||||
const eventCategoryWrap = document.getElementById('eventCategoryWrap');
|
||||
const eventKidsWrap = document.getElementById('eventKidsWrap');
|
||||
const eventChildrenWrap = document.getElementById('eventChildrenWrap');
|
||||
const eventCapacityWrap = document.getElementById('eventCapacityWrap');
|
||||
const eventPricingWrap = document.getElementById('eventPricingWrap');
|
||||
const placeContactWrap = document.getElementById('placeContactWrap');
|
||||
const placeLookupWrap = document.getElementById('placeLookupWrap');
|
||||
const placeOpeningHoursWrap = document.getElementById('placeOpeningHoursWrap');
|
||||
const eventRecurrenceWrap = document.getElementById('eventRecurrenceWrap');
|
||||
const eventDateInput = document.getElementById('evDate');
|
||||
const categorySelect = document.getElementById('listingCategorySlug');
|
||||
const priceModeSelect = document.getElementById('priceMode');
|
||||
const freeChildRuleWrap = document.getElementById('freeChildRuleWrap');
|
||||
const paidPricingWrap = document.getElementById('paidPricingWrap');
|
||||
const recurrenceModeSelect = document.getElementById('recurrenceMode');
|
||||
const recurrenceWeekdaysWrap = document.getElementById('recurrenceWeekdaysWrap');
|
||||
const openingHoursRows = document.getElementById('openingHoursRows');
|
||||
const priceRows = document.getElementById('priceRows');
|
||||
const btnAddOpeningRow = document.getElementById('btnAddOpeningRow');
|
||||
const btnAddPriceRow = document.getElementById('btnAddPriceRow');
|
||||
const existingPlaceLookup = document.getElementById('existingPlaceLookup');
|
||||
const btnUseExistingPlace = document.getElementById('btnUseExistingPlace');
|
||||
const streetInput = document.getElementById('evStreet');
|
||||
@@ -1225,23 +1252,17 @@ if (!empty($canManageSystemSettings)) {
|
||||
if (eventDateRow) eventDateRow.hidden = kind === 'place';
|
||||
if (eventDateInput) eventDateInput.required = kind !== 'place';
|
||||
if (eventLocationLabelWrap) eventLocationLabelWrap.hidden = kind !== 'event';
|
||||
if (eventCategoryWrap) eventCategoryWrap.hidden = kind === 'event';
|
||||
if (categorySelect) categorySelect.required = kind !== 'event';
|
||||
if (eventKidsWrap) eventKidsWrap.hidden = kind !== 'event';
|
||||
if (categorySelect) categorySelect.required = true;
|
||||
if (eventChildrenWrap) eventChildrenWrap.hidden = kind === 'place';
|
||||
if (eventCapacityWrap) eventCapacityWrap.hidden = kind !== 'event';
|
||||
if (eventPricingWrap) eventPricingWrap.hidden = kind === 'event';
|
||||
if (placeLookupWrap) placeLookupWrap.hidden = kind === 'event';
|
||||
if (placeOpeningHoursWrap) placeOpeningHoursWrap.hidden = kind !== 'place';
|
||||
if (placeContactWrap) placeContactWrap.hidden = kind === 'event';
|
||||
if (placeOpeningHoursWrap) placeOpeningHoursWrap.hidden = kind === 'event';
|
||||
if (eventRecurrenceWrap) eventRecurrenceWrap.hidden = kind !== 'editorial_event';
|
||||
syncPriceModeVisibility();
|
||||
syncRecurrenceVisibility();
|
||||
}
|
||||
|
||||
function syncPriceModeVisibility() {
|
||||
const mode = priceModeSelect?.value || 'none';
|
||||
if (freeChildRuleWrap) freeChildRuleWrap.hidden = mode !== 'free_child_rule';
|
||||
if (paidPricingWrap) paidPricingWrap.hidden = mode !== 'paid';
|
||||
}
|
||||
|
||||
function syncRecurrenceVisibility() {
|
||||
const mode = recurrenceModeSelect?.value || 'single';
|
||||
if (recurrenceWeekdaysWrap) recurrenceWeekdaysWrap.hidden = mode !== 'custom_weekdays';
|
||||
@@ -1252,13 +1273,63 @@ if (!empty($canManageSystemSettings)) {
|
||||
syncEventEntryKind(button.getAttribute('data-entry-kind-choice') || 'event');
|
||||
});
|
||||
});
|
||||
priceModeSelect?.addEventListener('change', syncPriceModeVisibility);
|
||||
recurrenceModeSelect?.addEventListener('change', syncRecurrenceVisibility);
|
||||
|
||||
syncEventEntryKind(entryKindInput?.value || 'event');
|
||||
syncPriceModeVisibility();
|
||||
syncRecurrenceVisibility();
|
||||
|
||||
function createOpeningRow() {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'form-grid opening-row';
|
||||
row.innerHTML = `
|
||||
<input name="opening_day_label[]" class="input" placeholder="z. B. Montag oder täglich">
|
||||
<input name="opening_time_from[]" class="input" type="time">
|
||||
<input name="opening_time_to[]" class="input" type="time">
|
||||
<input name="opening_note[]" class="input" placeholder="Hinweis">
|
||||
`;
|
||||
openingHoursRows?.appendChild(row);
|
||||
}
|
||||
|
||||
function createPriceRow() {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'stack gap-8 price-row card';
|
||||
row.innerHTML = `
|
||||
<div class="form-grid">
|
||||
<input name="price_label[]" class="input" placeholder="z. B. Kinder 4-7">
|
||||
<select name="price_audience[]" class="select">
|
||||
<option value="general">Allgemein</option>
|
||||
<option value="child">Kinder</option>
|
||||
<option value="adult">Erwachsene</option>
|
||||
<option value="family">Familie</option>
|
||||
<option value="group">Gruppe</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<select name="price_type[]" class="select">
|
||||
<option value="free">Frei</option>
|
||||
<option value="fixed">Fester Preis</option>
|
||||
<option value="from">Preis ab</option>
|
||||
<option value="up_to">Preis bis</option>
|
||||
<option value="range">Preisspanne</option>
|
||||
<option value="request">Auf Anfrage</option>
|
||||
</select>
|
||||
<input name="price_amount[]" class="input" inputmode="decimal" placeholder="Preis">
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<input name="price_amount_secondary[]" class="input" inputmode="decimal" placeholder="Zweiter Preis bei Spanne">
|
||||
<input name="price_note[]" class="input" placeholder="Hinweis">
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<input name="price_age_from[]" class="input" type="number" min="0" max="99" placeholder="Alter von">
|
||||
<input name="price_age_to[]" class="input" type="number" min="0" max="99" placeholder="Alter bis">
|
||||
</div>
|
||||
`;
|
||||
priceRows?.appendChild(row);
|
||||
}
|
||||
|
||||
btnAddOpeningRow?.addEventListener('click', createOpeningRow);
|
||||
btnAddPriceRow?.addEventListener('click', createPriceRow);
|
||||
|
||||
function applyExistingPlace(place) {
|
||||
if (!place) return;
|
||||
if (document.getElementById('evTitle') && !document.getElementById('evTitle').value.trim()) {
|
||||
@@ -1490,6 +1561,34 @@ if (!empty($canManageSystemSettings)) {
|
||||
});
|
||||
});
|
||||
|
||||
btnEventBrowserLocation?.addEventListener('click', () => {
|
||||
if (!window.PKTConsent || !window.PKTConsent.has('external_services')) {
|
||||
alert('Für Browser-Standort und Adressübernahme bitte zuerst die externen Dienste in den Cookie-Einstellungen erlauben.');
|
||||
window.PKTConsent?.openPreferences?.();
|
||||
return;
|
||||
}
|
||||
if (!navigator.geolocation) {
|
||||
alert('Dein Browser unterstützt keine Standortabfrage.');
|
||||
return;
|
||||
}
|
||||
if (eventAddressStatus) eventAddressStatus.textContent = 'Browser-Standort wird abgerufen ...';
|
||||
navigator.geolocation.getCurrentPosition((position) => {
|
||||
reverseGeocodeProfileAddress(position.coords.latitude, position.coords.longitude, (data) => {
|
||||
const normalized = normalizeGeoResult(data);
|
||||
if (streetInput && normalized.street) streetInput.value = normalized.street;
|
||||
if (zipInput && normalized.zip) zipInput.value = normalized.zip;
|
||||
if (cityInput && normalized.city) cityInput.value = normalized.city;
|
||||
if (regionInput) regionInput.value = normalized.region;
|
||||
if (latInput) latInput.value = Number.isNaN(normalized.lat) ? '' : normalized.lat.toFixed(7);
|
||||
if (lngInput) lngInput.value = Number.isNaN(normalized.lng) ? '' : normalized.lng.toFixed(7);
|
||||
if (eventAddressStatus) eventAddressStatus.textContent = `Browser-Adresse übernommen: ${normalized.label || [normalized.street, `${normalized.zip} ${normalized.city}`.trim(), normalized.region].filter(Boolean).join(', ')}`;
|
||||
});
|
||||
}, () => {
|
||||
if (eventAddressStatus) eventAddressStatus.textContent = '';
|
||||
alert('Der Browser-Standort konnte nicht abgerufen werden.');
|
||||
}, { enableHighAccuracy: true, timeout: 10000, maximumAge: 0 });
|
||||
});
|
||||
|
||||
(function(){
|
||||
const setProfileStatus = (message = '') => {
|
||||
if (!profileAddressStatus) return;
|
||||
|
||||
Reference in New Issue
Block a user