This commit is contained in:
@@ -35,6 +35,9 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter. Kernbereiche sind l
|
||||
- Eigene Events nutzen jetzt als Pflichtfelder nur noch Titel, Datum und `Mit Kindern`; die Beschreibung ist optional.
|
||||
- Für die Event-Location gibt es jetzt die Auswahl `Ort aus Datenbank`, `Veranstaltung aus Datenbank` oder `Benutzerdefiniert`.
|
||||
- Bei `Ort` oder `Veranstaltung` werden Adresse und Kategorie direkt aus dem gewählten Datenbank-Eintrag übernommen.
|
||||
- Im Formular für eigene Events sind `Gültig bis` und `Wiederholung` ausgeblendet.
|
||||
- Bei eigener Event-Location aus der Datenbank werden Adresse und Kategorie nur als Info angezeigt und nicht direkt bearbeitet.
|
||||
- Aus dem Formular für eigene Events kann direkt in das Anlegen eines neuen Orts oder einer neuen Veranstaltung gewechselt werden.
|
||||
- Bei `Veranstaltung aus Datenbank` muss das Event-Datum innerhalb des hinterlegten Gültigkeitszeitraums dieser Veranstaltungs-Quelle liegen.
|
||||
- Kategorien werden im Mitgliederbereich per Sucheingabe mit bestehenden Vorschlägen und automatischer Neuanlage gepflegt.
|
||||
- Eigene Events unterstützen optionalen Beschreibungstext, Ja/Nein-Angabe `Mit Kindern`, optionale Platzzahl, optionales Bild sowie eine Location aus Datenbank oder benutzerdefinierte Adresse.
|
||||
|
||||
@@ -24,6 +24,7 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf lokale
|
||||
- neue Datenbasis für ein späteres Termin-, Ort- und Veranstaltungssystem angelegt
|
||||
- Mitgliederbereich `Events` ist wieder auf echte eigene Events und Event-Teilnahmen fokussiert
|
||||
- Eigene Events haben jetzt optionalen Beschreibungstext, klare Kinderangabe, optionale Platzzahl, optionales Bild sowie eine Location aus Datenbank oder benutzerdefinierte Adresse
|
||||
- Bei eigener Event-Location aus der Datenbank werden Adresse und Kategorie nur informativ übernommen und nicht direkt im Event geändert
|
||||
- Orte und sonstige Veranstaltungen wurden vorerst in einen separaten Bereich `Orte & Veranstaltungen` verschoben
|
||||
- Neue Orte und Veranstaltungen müssen vor Veröffentlichung erst durch einen Admin freigegeben werden; Änderungs- und Löschwünsche laufen ebenfalls nur als begründete Anfrage
|
||||
- Die Eingabemasken sind jetzt progressiv aufgebaut: erst Pflichtangaben, optionale Daten in einklappbaren Bereichen
|
||||
|
||||
@@ -35,6 +35,9 @@ Papa-Kind-Treff is a PHP-based platform for fathers. Core areas are local events
|
||||
- Own events now only require title, date, and the `with children` choice; the description is optional.
|
||||
- Event locations now support the modes `place from database`, `event from database`, or `custom`.
|
||||
- When a database-backed place or event is selected, the address and category are taken directly from that source entry.
|
||||
- Inside the own-event form, `valid until` and `recurrence` are hidden.
|
||||
- When an own event uses a database-backed location, address and category are shown as informational values and are not edited directly.
|
||||
- The own-event form now offers direct links into creating a new place or a new event-style listing.
|
||||
- When `event from database` is selected, the event date must fall inside that source event's valid date window.
|
||||
- Categories in the member area are handled via a search input with existing suggestions and automatic creation when needed.
|
||||
- Own events support an optional description, a clear `with children` yes/no field, optional capacity, an optional image, and either a database-backed location or a custom address.
|
||||
|
||||
@@ -24,6 +24,7 @@ Papa-Kind-Treff is a PHP-based platform for fathers focused on local events, app
|
||||
- new data foundation prepared for a broader event, place, and listing system
|
||||
- member area `Events` is now limited again to real own events and event participations
|
||||
- own events now support an optional description, explicit child suitability, optional capacity, an optional image, and either a database-backed location or a custom address
|
||||
- when an own event uses a database-backed location, address and category are shown as informational values and are not edited directly inside the event
|
||||
- places and other event-style entries were moved for now into a separate member-area section `Places & Events`
|
||||
- new places and event-style entries must be approved by an admin before publication; change and deletion wishes also run as reasoned requests
|
||||
- the member-area entry forms now follow a progressive approach: required fields first, optional data inside collapsible sections
|
||||
|
||||
@@ -43,6 +43,8 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf:
|
||||
- Orte und sonstige Veranstaltungen laufen jetzt separat unter `Orte & Veranstaltungen`
|
||||
- Neue Orte und Veranstaltungen müssen vor Veröffentlichung erst durch einen Admin freigegeben werden; Änderungs- und Löschwünsche laufen ebenfalls als begründete Anfrage
|
||||
- Eigene Events unterstützen aktuell optionalen Beschreibungstext, klare Kinderangabe, optionale Platzzahl, Bild-Upload sowie eine Location aus Datenbank oder benutzerdefinierte Adresse
|
||||
- Bei eigener Event-Location aus der Datenbank werden Adresse und Kategorie nur informativ aus dem gewählten Ort bzw. der gewählten Veranstaltung übernommen und nicht manuell geändert
|
||||
- Aus dem Formular für eigene Events kann direkt in das Anlegen eines neuen Orts oder einer neuen Veranstaltung verzweigt werden
|
||||
- Die Eingabe im Mitgliederbereich ist jetzt bewusst vereinfacht: zuerst nur Pflichtangaben, optionale Angaben in einklappbaren Bereichen
|
||||
- Kategorien werden jetzt über eine Sucheingabe mit bestehenden Vorschlägen gepflegt; neue Kategorien werden automatisch angelegt und sind für Seiten-Admins im Systembereich zusammenführbar
|
||||
- Im Mitgliederbereich `Events` gibt es jetzt zusätzlich einen ICS-Download und einen persönlichen abonnierbaren Kalender-Feed für alle eigenen Events und Event-Teilnahmen
|
||||
|
||||
@@ -6,10 +6,15 @@ $avatarPlaceholder = 'data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/
|
||||
$avatarStyleKeys = array_keys($avatarBuilder ?? []);
|
||||
$currentAvatarStyle = (string)($profile['avatar_style'] ?? ($avatarStyleKeys[0] ?? 'lorelei'));
|
||||
$dashboardUserId = (int)($_SESSION['user_id'] ?? 0);
|
||||
$requestedCreateListingKind = isset($_GET['create_listing']) && in_array((string)$_GET['create_listing'], ['place', 'editorial_event'], true)
|
||||
? (string)$_GET['create_listing']
|
||||
: null;
|
||||
$editingEvent = isset($editEvent) && $editEvent !== null;
|
||||
$editingListing = isset($editListing) && $editListing !== null;
|
||||
$editing = $editingEvent || $editingListing;
|
||||
$currentEntryKind = $editingListing ? (string)($editListing['listing_type'] ?? 'editorial_event') : (($section ?? 'events') === 'places' ? 'place' : 'event');
|
||||
$currentEntryKind = $editingListing
|
||||
? (string)($editListing['listing_type'] ?? 'editorial_event')
|
||||
: ((($section ?? 'events') === 'places') ? ($requestedCreateListingKind ?? 'place') : 'event');
|
||||
$actionEvent = $editing ? 'event_update' : 'event_add';
|
||||
$startVal = '';
|
||||
if ($editingEvent && !empty($editEvent['starts_at'])) {
|
||||
@@ -116,7 +121,7 @@ $sectionLinks = [
|
||||
'community' => 'Community',
|
||||
'settings' => 'Einstellungen',
|
||||
];
|
||||
$showEventTypeChoice = !$editing && (($section ?? 'events') === 'places');
|
||||
$showEventTypeChoice = !$editing && (($section ?? 'events') === 'places') && $requestedCreateListingKind === null;
|
||||
$modalSectionTarget = ($editingListing || ($section ?? '') === 'places') ? 'places' : 'events';
|
||||
if (!empty($canManageSystemSettings)) {
|
||||
$sectionLinks['system'] = 'System';
|
||||
@@ -1189,7 +1194,13 @@ if (!empty($canManageSystemSettings)) {
|
||||
<label class="label" for="eventLocationSourceInput" id="eventLocationSourceLabel">Ort aus Datenbank</label>
|
||||
<input id="eventLocationSourceInput" class="input" list="eventLocationOptionList" placeholder="Eintrag aus der Datenbank auswählen" value="<?= htmlspecialchars($eventLocationSourceInputValue, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<?php if (($section ?? 'events') === 'events' && !$editingListing): ?>
|
||||
<div class="flex gap-8" style="flex-wrap:wrap;" id="eventCreateListingActionsWrap">
|
||||
<a class="btn ghost" href="/dashboard?section=places&create_listing=place#places">Neuen Ort anlegen</a>
|
||||
<a class="btn ghost" href="/dashboard?section=places&create_listing=editorial_event#places">Neue Veranstaltung anlegen</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="stack gap-6" id="categoryInputWrap">
|
||||
<label class="label" for="categoryInput">Kategorie</label>
|
||||
<input id="categoryInput" name="category_input" class="input" list="listingCategoryList" placeholder="z. B. Spielplatz, Café, Zirkus" value="<?= htmlspecialchars($categoryInputValue, ENT_QUOTES) ?>">
|
||||
<input type="hidden" id="listingCategorySlug" name="category_slug" value="<?= htmlspecialchars($categorySlugValue, ENT_QUOTES) ?>">
|
||||
@@ -1200,6 +1211,10 @@ if (!empty($canManageSystemSettings)) {
|
||||
</datalist>
|
||||
<div id="categoryInputStatus" class="muted small" style="margin:0;"></div>
|
||||
</div>
|
||||
<div class="card" id="eventCategoryInfoWrap" hidden>
|
||||
<strong>Kategorie</strong>
|
||||
<div class="muted small" id="eventCategoryInfoText" style="margin-top:8px;">Keine Kategorie ausgewählt.</div>
|
||||
</div>
|
||||
<div class="form-grid" id="eventDateRow">
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="evDate" id="eventDateLabel">Datum</label>
|
||||
@@ -1218,12 +1233,12 @@ if (!empty($canManageSystemSettings)) {
|
||||
<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 class="stack gap-6" id="eventValidUntilWrap">
|
||||
<div class="stack gap-6" id="eventValidUntilWrap"<?= $currentEntryKind === 'event' ? ' hidden' : '' ?>>
|
||||
<label class="label" for="recurrenceUntil">Gültig bis</label>
|
||||
<input id="recurrenceUntil" name="recurrence_until" class="input" type="date" value="<?= htmlspecialchars($recurrenceUntilValue, ENT_QUOTES) ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="stack gap-6" id="eventRecurrenceWrap">
|
||||
<div class="stack gap-6" id="eventRecurrenceWrap"<?= $currentEntryKind === 'event' ? ' hidden' : '' ?>>
|
||||
<label class="label" for="recurrenceMode">Wiederholung</label>
|
||||
<select id="recurrenceMode" name="recurrence_mode" class="select">
|
||||
<option value="single" <?= $recurrenceModeValue === 'single' ? 'selected' : '' ?>>Einmalig</option>
|
||||
@@ -1264,6 +1279,10 @@ if (!empty($canManageSystemSettings)) {
|
||||
<button class="btn ghost" type="button" id="btnEventAddressSearch">Adresse suchen</button>
|
||||
<button class="btn ghost" type="button" id="btnEventBrowserLocation">📍 Aktuellen Standort</button>
|
||||
</div>
|
||||
<div class="card" id="eventAddressInfoWrap" hidden>
|
||||
<strong>Adresse</strong>
|
||||
<div class="muted small" id="eventAddressInfoText" style="margin-top:8px;">Kein Ort ausgewählt.</div>
|
||||
</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) ?>">
|
||||
@@ -1426,9 +1445,14 @@ if (!empty($canManageSystemSettings)) {
|
||||
const eventLocationSourceInput = document.getElementById('eventLocationSourceInput');
|
||||
const eventLocationSourceIdInput = document.getElementById('eventLocationSourceId');
|
||||
const eventLocationSourceLabel = document.getElementById('eventLocationSourceLabel');
|
||||
const categoryInputWrap = document.getElementById('categoryInputWrap');
|
||||
const eventCategoryInfoWrap = document.getElementById('eventCategoryInfoWrap');
|
||||
const eventCategoryInfoText = document.getElementById('eventCategoryInfoText');
|
||||
const eventAddressFieldsWrap = document.getElementById('eventAddressFieldsWrap');
|
||||
const eventAddressStreetWrap = document.getElementById('eventAddressStreetWrap');
|
||||
const eventAddressActionsWrap = document.getElementById('eventAddressActionsWrap');
|
||||
const eventAddressInfoWrap = document.getElementById('eventAddressInfoWrap');
|
||||
const eventAddressInfoText = document.getElementById('eventAddressInfoText');
|
||||
const eventValidUntilWrap = document.getElementById('eventValidUntilWrap');
|
||||
const eventPricingWrap = document.getElementById('eventPricingWrap');
|
||||
const visibilityDetails = document.getElementById('visibilityDetails');
|
||||
@@ -1522,10 +1546,43 @@ if (!empty($canManageSystemSettings)) {
|
||||
if (eventAddressStatus) eventAddressStatus.textContent = '';
|
||||
}
|
||||
|
||||
function syncEventLocationInfo() {
|
||||
const usesDatabaseLocation = (entryKindInput?.value || 'event') === 'event' && (eventLocationModeSelect?.value || 'custom') !== 'custom';
|
||||
const addressLabel = [streetInput?.value || '', `${zipInput?.value || ''} ${cityInput?.value || ''}`.trim(), regionInput?.value || '']
|
||||
.filter(Boolean)
|
||||
.join(', ');
|
||||
|
||||
setSectionState(categoryInputWrap, !usesDatabaseLocation);
|
||||
if (eventCategoryInfoWrap) {
|
||||
eventCategoryInfoWrap.hidden = !usesDatabaseLocation;
|
||||
}
|
||||
if (eventCategoryInfoText) {
|
||||
eventCategoryInfoText.textContent = (categoryInput?.value || '').trim() || 'Keine Kategorie ausgewählt.';
|
||||
}
|
||||
if (eventAddressInfoWrap) {
|
||||
eventAddressInfoWrap.hidden = !usesDatabaseLocation;
|
||||
}
|
||||
if (eventAddressInfoText) {
|
||||
eventAddressInfoText.textContent = addressLabel || 'Kein Ort ausgewählt.';
|
||||
}
|
||||
if (eventAddressStatus) {
|
||||
eventAddressStatus.hidden = usesDatabaseLocation;
|
||||
}
|
||||
}
|
||||
|
||||
function clearEventLocationSelection() {
|
||||
if (eventLocationSourceIdInput) eventLocationSourceIdInput.value = '';
|
||||
if (eventLocationSourceInput) eventLocationSourceInput.value = '';
|
||||
if (streetInput) streetInput.value = '';
|
||||
if (zipInput) zipInput.value = '';
|
||||
if (cityInput) cityInput.value = '';
|
||||
if (regionInput) regionInput.value = '';
|
||||
if (latInput) latInput.value = '';
|
||||
if (lngInput) lngInput.value = '';
|
||||
if (categoryInput) categoryInput.value = '';
|
||||
if (categorySlugInput) categorySlugInput.value = '';
|
||||
if (categoryInputStatus) categoryInputStatus.textContent = '';
|
||||
syncEventLocationInfo();
|
||||
}
|
||||
|
||||
function syncEventLocationMode() {
|
||||
@@ -1546,7 +1603,6 @@ if (!empty($canManageSystemSettings)) {
|
||||
}
|
||||
|
||||
if (categoryInput) {
|
||||
categoryInput.readOnly = usesDatabaseLocation;
|
||||
if (usesDatabaseLocation) {
|
||||
categoryInput.removeAttribute('list');
|
||||
} else {
|
||||
@@ -1564,6 +1620,7 @@ if (!empty($canManageSystemSettings)) {
|
||||
} else if (isOwnEvent) {
|
||||
if (eventLocationSourceIdInput) eventLocationSourceIdInput.value = '';
|
||||
}
|
||||
syncEventLocationInfo();
|
||||
}
|
||||
|
||||
function syncEventEntryKind(nextKind) {
|
||||
@@ -1621,6 +1678,7 @@ if (!empty($canManageSystemSettings)) {
|
||||
return;
|
||||
}
|
||||
applyEventLocationOption(option);
|
||||
syncEventLocationInfo();
|
||||
});
|
||||
syncEventEntryKind(entryKindInput?.value || 'event');
|
||||
|
||||
@@ -2115,7 +2173,7 @@ if (!empty($canManageSystemSettings)) {
|
||||
setNeedsValidation(false);
|
||||
})();
|
||||
|
||||
<?php if ($editing): ?>
|
||||
<?php if ($editing || $requestedCreateListingKind !== null): ?>
|
||||
(function(){
|
||||
const modal = document.getElementById('modalEvent');
|
||||
if (modal) {
|
||||
|
||||
Reference in New Issue
Block a user