This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Papa-Kind-Treff – Projektkontext
|
# Papa-Kind-Treff – Projektkontext
|
||||||
|
|
||||||
Stand: 2026-08-04
|
Stand: 2026-08-05
|
||||||
|
|
||||||
## Kurzbeschreibung
|
## Kurzbeschreibung
|
||||||
Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter. Kernbereiche sind lokale Events, Termine und Treffen, ein Community-Forum, Mitgliederprofile mit optionalen Kinderinfos und ein Moderations-/Adminbereich.
|
Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter. Kernbereiche sind lokale Events, Termine und Treffen, ein Community-Forum, Mitgliederprofile mit optionalen Kinderinfos und ein Moderations-/Adminbereich.
|
||||||
@@ -16,17 +16,16 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter. Kernbereiche sind l
|
|||||||
- Seiten-Admins erhalten eine eigene System-Sektion für globale Betriebs- und Diensteschalter.
|
- Seiten-Admins erhalten eine eigene System-Sektion für globale Betriebs- und Diensteschalter.
|
||||||
|
|
||||||
## Konto / Mitgliederbereich
|
## Konto / Mitgliederbereich
|
||||||
- Profil-Menü aktuell: `Profil`, `Kinder`, `Events`, `Community`, `Einstellungen`, `Abmelden`
|
- Profil-Menü aktuell: `Profil`, `Kinder`, `Events`, `Ausflugsziele`, `Community`, `Einstellungen`, `Abmelden`
|
||||||
- Kinder können angelegt, bearbeitet und gelöscht werden.
|
- Kinder können angelegt, bearbeitet und gelöscht werden.
|
||||||
- Wenn ein Geburtsdatum gesetzt ist, wird das Alter automatisch berechnet und später bei Bedarf aktualisiert.
|
- Wenn ein Geburtsdatum gesetzt ist, wird das Alter automatisch berechnet und später bei Bedarf aktualisiert.
|
||||||
- Die Konto-E-Mail wird app-seitig verschlüsselt gespeichert und über einen separaten HMAC-Lookup-Hash adressiert.
|
- Die Konto-E-Mail wird app-seitig verschlüsselt gespeichert und über einen separaten HMAC-Lookup-Hash adressiert.
|
||||||
- Profiladresse kann per Suche oder Browser-Standort übernommen werden.
|
- Profiladresse kann per Suche oder Browser-Standort übernommen werden.
|
||||||
- Im Bereich `Events` gibt es jetzt drei Eintragstypen: eigenes Event, Ort und sonstige Veranstaltung.
|
- Der Bereich `Events` ist wieder auf echte eigene Events und Event-Teilnahmen begrenzt.
|
||||||
- Die Eingabe im Bereich `Events` soll so einfach wie möglich bleiben und zeigt deshalb zuerst nur Pflichtangaben.
|
- Orte und Veranstaltungen als Ausflugsziele sind vorerst in einen separaten Mitgliederbereichspunkt `Ausflugsziele` verschoben.
|
||||||
- Kategorien werden im Mitgliederbereich nicht mehr per Select gewählt, sondern per Sucheingabe mit bestehenden Vorschlägen und automatischer Neuanlage gepflegt.
|
- Die Eingabe im Bereich `Events` soll so einfach wie möglich bleiben und zeigt deshalb nur die für echte Termine relevanten Felder.
|
||||||
- Eigene Events unterstützen Kategorie, optionales Bild, Ja/Nein-Angabe `Mit Kindern`, optionale Platzzahl und Sichtbarkeit.
|
- Kategorien werden im Mitgliederbereich per Sucheingabe mit bestehenden Vorschlägen und automatischer Neuanlage gepflegt.
|
||||||
- `Ort` nutzt die gleiche Adresslogik wie das Profil, blendet den Event-Termin aus und erlaubt stattdessen flexible Öffnungs-/Zeitfenster, optionale Kontaktangaben und flexible Preisregeln.
|
- Eigene Events unterstützen Kategorie, optionales Bild, Ja/Nein-Angabe `Mit Kindern`, optionale Platzzahl und direkte Karten-/Adress-Synchronisierung.
|
||||||
- `Sonstige Veranstaltung` nutzt ebenfalls die Profil-Adresslogik, unterstützt Wiederholungen, ein Pflichtfeld `Gültig bis`, flexible Preisregeln, Bild-Upload und die Angabe `Mit Kindern`.
|
|
||||||
|
|
||||||
## Technischer Rahmen
|
## Technischer Rahmen
|
||||||
- eigener Front-Controller in `public/index.php`
|
- eigener Front-Controller in `public/index.php`
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Papa-Kind-Treff – Projektstruktur
|
# Papa-Kind-Treff – Projektstruktur
|
||||||
|
|
||||||
Stand: 2026-08-04
|
Stand: 2026-08-05
|
||||||
|
|
||||||
## Projektordner
|
## Projektordner
|
||||||
- `config/`: Konfigurationen, inklusive `prod/` und `staging/`
|
- `config/`: Konfigurationen, inklusive `prod/` und `staging/`
|
||||||
@@ -14,12 +14,12 @@ Stand: 2026-08-04
|
|||||||
## Aktuelle Strukturhinweise
|
## Aktuelle Strukturhinweise
|
||||||
- Avatar-Verwaltung: `src/App/Avatar/AvatarManager.php`
|
- Avatar-Verwaltung: `src/App/Avatar/AvatarManager.php`
|
||||||
- aktive Styles: `src/App/Avatar/Lorelei.php`, `src/App/Avatar/Croodles.php`
|
- aktive Styles: `src/App/Avatar/Lorelei.php`, `src/App/Avatar/Croodles.php`
|
||||||
- Profil-/Kinder-/Event-Logik im Mitgliederbereich: `partials/landing/account/dashboard.php`
|
- Profil-/Kinder-/Event-/Ausflugsziel-Logik im Mitgliederbereich: `partials/landing/account/dashboard.php`
|
||||||
- Consent- und rechtliche Texte: `public/page/datenschutz.php`
|
- Consent- und rechtliche Texte: `public/page/datenschutz.php`
|
||||||
- System-Einstellungen: `src/App/SystemSettings.php`
|
- System-Einstellungen: `src/App/SystemSettings.php`
|
||||||
- neue Listing-/Ort-Basis: `src/App/ListingCatalog.php`
|
- neue Listing-/Ort-Basis: `src/App/ListingCatalog.php`
|
||||||
- UI für Eintragstyp-Auswahl im Mitgliederbereich: `partials/landing/account/dashboard.php`
|
- UI für getrennte Bereiche `Events` und `Ausflugsziele` im Mitgliederbereich: `partials/landing/account/dashboard.php`
|
||||||
- Preis-, Wiederholungs-, Bild- und Ortseingabe für neue Listing-Typen: `partials/landing/account/dashboard.php` plus Speicherung in `src/App/ListingCatalog.php`
|
- Preis-, Bild- und Ortseingabe für Ausflugsziele sowie reduzierte Event-Maske: `partials/landing/account/dashboard.php` plus Speicherung in `src/App/ListingCatalog.php`
|
||||||
- Legacy-Eigen-Events wurden erweitert in `src/App/AccountPages.php` und `schema.sql` um Kategorie- und Bildfelder
|
- Legacy-Eigen-Events wurden erweitert in `src/App/AccountPages.php` und `schema.sql` um Kategorie- und Bildfelder
|
||||||
- Kategorien-Prüfung und Zusammenführung für Seiten-Admins liegen ebenfalls in `partials/landing/account/dashboard.php` mit Logik in `src/App/ListingCatalog.php`
|
- Kategorien-Prüfung und Zusammenführung für Seiten-Admins liegen ebenfalls in `partials/landing/account/dashboard.php` mit Logik in `src/App/ListingCatalog.php`
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Papa-Kind-Treff
|
# Papa-Kind-Treff
|
||||||
|
|
||||||
Stand: 2026-08-04
|
Stand: 2026-08-05
|
||||||
|
|
||||||
Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf lokale Events, Termine und Treffen, Community-Austausch und einen geschützten Mitgliederbereich.
|
Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf lokale Events, Termine und Treffen, Community-Austausch und einen geschützten Mitgliederbereich.
|
||||||
|
|
||||||
@@ -16,15 +16,15 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf lokale
|
|||||||
- Community-Admin-Bereich für Bewerbungen, Meldungen, Rollen und Migration
|
- Community-Admin-Bereich für Bewerbungen, Meldungen, Rollen und Migration
|
||||||
- standortbasierte Sortierung für die neuesten Events
|
- standortbasierte Sortierung für die neuesten Events
|
||||||
- Mitgliederbereich mit linker Bereichsnavigation
|
- Mitgliederbereich mit linker Bereichsnavigation
|
||||||
- Profil-Menü mit `Profil`, `Kinder`, `Events`, `Community`, `Einstellungen`
|
- Profil-Menü mit `Profil`, `Kinder`, `Events`, `Ausflugsziele`, `Community`, `Einstellungen`
|
||||||
- Konto-E-Mails sowie sensible Profilfelder werden app-seitig verschlüsselt gespeichert
|
- Konto-E-Mails sowie sensible Profilfelder werden app-seitig verschlüsselt gespeichert
|
||||||
- Kinder können angelegt, bearbeitet und gelöscht werden
|
- Kinder können angelegt, bearbeitet und gelöscht werden
|
||||||
- Profiladresse mit verschlüsselter Straße/Hausnummer, Adresssuche, Browser-Übernahme und Validierung
|
- Profiladresse mit verschlüsselter Straße/Hausnummer, Adresssuche, Browser-Übernahme und Validierung
|
||||||
- System-Sektion für Seiten-Admins mit Wartungs- und Diensteschaltern
|
- System-Sektion für Seiten-Admins mit Wartungs- und Diensteschaltern
|
||||||
- neue Datenbasis für ein späteres Termin-, Ort- und Veranstaltungssystem angelegt
|
- neue Datenbasis für ein späteres Termin-, Ort- und Veranstaltungssystem angelegt
|
||||||
- Mitgliederbereich `Events` unterstützt jetzt drei Anlagetypen: `Eigenes Event`, `Ort`, `Sonstige Veranstaltung`
|
- Mitgliederbereich `Events` ist wieder auf echte eigene Events und Event-Teilnahmen fokussiert
|
||||||
- Eigene Events haben jetzt Kategorie, optionales Bild, klare Kinderangabe, optionale Platzzahl und serverseitig validierte Adressdaten
|
- Eigene Events haben jetzt Kategorie, optionales Bild, klare Kinderangabe, optionale Platzzahl und eine direktere Karten-/Adress-Synchronisierung
|
||||||
- Orte und sonstige Veranstaltungen haben jetzt eine angepasste Eingabemaske mit Ortssuche, Browser-Adressübernahme, serverseitiger Adressvalidierung, flexiblen Preisregeln, flexiblen Öffnungs-/Zeitfenstern und Bild-Upload
|
- Orte und sonstige Veranstaltungen wurden vorerst in einen separaten Bereich `Ausflugsziele` verschoben
|
||||||
- Die Eingabemasken sind jetzt progressiv aufgebaut: erst Pflichtangaben, optionale Daten in einklappbaren Bereichen
|
- Die Eingabemasken sind jetzt progressiv aufgebaut: erst Pflichtangaben, optionale Daten in einklappbaren Bereichen
|
||||||
- Kategorien laufen jetzt über eine Sucheingabe mit bestehenden Vorschlägen; neue Kategorien werden automatisch angelegt und können im Systembereich von Seiten-Admins zusammengeführt werden
|
- Kategorien laufen jetzt über eine Sucheingabe mit bestehenden Vorschlägen; neue Kategorien werden automatisch angelegt und können im Systembereich von Seiten-Admins zusammengeführt werden
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Papa-Kind-Treff – Project Context
|
# Papa-Kind-Treff – Project Context
|
||||||
|
|
||||||
Updated: 2026-08-04
|
Updated: 2026-08-05
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
Papa-Kind-Treff is a PHP-based platform for fathers. Core areas are local events, appointments, and meetups, a community forum, member profiles with optional child information, and a moderation/admin area.
|
Papa-Kind-Treff is a PHP-based platform for fathers. Core areas are local events, appointments, and meetups, a community forum, member profiles with optional child information, and a moderation/admin area.
|
||||||
@@ -16,17 +16,16 @@ Papa-Kind-Treff is a PHP-based platform for fathers. Core areas are local events
|
|||||||
- Site admins get a dedicated system section for global operating and service flags.
|
- Site admins get a dedicated system section for global operating and service flags.
|
||||||
|
|
||||||
## Account / Member Area
|
## Account / Member Area
|
||||||
- Profile menu currently contains `Profile`, `Children`, `Events`, `Community`, `Settings`, `Logout`.
|
- Profile menu currently contains `Profile`, `Children`, `Events`, `Outings`, `Community`, `Settings`, `Logout`.
|
||||||
- Children can be created, edited, and deleted.
|
- Children can be created, edited, and deleted.
|
||||||
- If a birth date is set, age is calculated automatically and updated later when needed.
|
- If a birth date is set, age is calculated automatically and updated later when needed.
|
||||||
- Account email is encrypted application-side and addressed through a separate HMAC lookup hash.
|
- Account email is encrypted application-side and addressed through a separate HMAC lookup hash.
|
||||||
- Profile address can be completed via address search or browser-based location import.
|
- Profile address can be completed via address search or browser-based location import.
|
||||||
- The `Events` area now distinguishes between own events, places, and other time-limited event entries.
|
- The `Events` area is limited again to real own events and event participations.
|
||||||
- The `Events` input flow should stay as simple as possible and therefore shows required fields first.
|
- Places and event-like outing targets were moved for now into a separate member-area section `Outings`.
|
||||||
- Categories in the member area are no longer chosen via select only, but via a search input with existing suggestions and automatic creation when needed.
|
- The `Events` input flow should stay as simple as possible and therefore only shows fields relevant for real scheduled events.
|
||||||
- Own events support category, optional image, a clear `with children` yes/no field, optional capacity, and visibility.
|
- Categories in the member area are handled via a search input with existing suggestions and automatic creation when needed.
|
||||||
- `Place` uses the same address flow as the profile, hides the event date, and instead supports flexible opening/time slots, optional contact data, and flexible pricing rules.
|
- Own events support category, optional image, a clear `with children` yes/no field, optional capacity, and direct map/address synchronization.
|
||||||
- `Other Event` also uses the profile-style address flow, supports recurrence, a required `valid until` field, flexible pricing rules, image upload, and a `with children` flag.
|
|
||||||
|
|
||||||
## Technical Frame
|
## Technical Frame
|
||||||
- custom front controller in `public/index.php`
|
- custom front controller in `public/index.php`
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Papa-Kind-Treff – Project Structure
|
# Papa-Kind-Treff – Project Structure
|
||||||
|
|
||||||
Updated: 2026-08-04
|
Updated: 2026-08-05
|
||||||
|
|
||||||
## Main Directories
|
## Main Directories
|
||||||
- `config/`: configuration, including `prod/` and `staging/`
|
- `config/`: configuration, including `prod/` and `staging/`
|
||||||
@@ -14,12 +14,12 @@ Updated: 2026-08-04
|
|||||||
## Current Structure Notes
|
## Current Structure Notes
|
||||||
- avatar management: `src/App/Avatar/AvatarManager.php`
|
- avatar management: `src/App/Avatar/AvatarManager.php`
|
||||||
- active avatar styles: `src/App/Avatar/Lorelei.php`, `src/App/Avatar/Croodles.php`
|
- active avatar styles: `src/App/Avatar/Lorelei.php`, `src/App/Avatar/Croodles.php`
|
||||||
- profile/children/event logic inside member area: `partials/landing/account/dashboard.php`
|
- profile/children/event/outing logic inside member area: `partials/landing/account/dashboard.php`
|
||||||
- consent and legal texts: `public/page/datenschutz.php`
|
- consent and legal texts: `public/page/datenschutz.php`
|
||||||
- system settings: `src/App/SystemSettings.php`
|
- system settings: `src/App/SystemSettings.php`
|
||||||
- new listing/place base: `src/App/ListingCatalog.php`
|
- new listing/place base: `src/App/ListingCatalog.php`
|
||||||
- entry type selector UI in member area: `partials/landing/account/dashboard.php`
|
- separated `Events` and `Outings` UI in member area: `partials/landing/account/dashboard.php`
|
||||||
- pricing, recurrence, image upload, and place/address input for new listing types: `partials/landing/account/dashboard.php` with persistence in `src/App/ListingCatalog.php`
|
- pricing, image upload, and place/address input for outings plus a reduced own-event form: `partials/landing/account/dashboard.php` with persistence in `src/App/ListingCatalog.php`
|
||||||
- legacy own events were extended in `src/App/AccountPages.php` and `schema.sql` with category and image fields
|
- legacy own events were extended in `src/App/AccountPages.php` and `schema.sql` with category and image fields
|
||||||
|
|
||||||
## Documentation Rule
|
## Documentation Rule
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Papa-Kind-Treff
|
# Papa-Kind-Treff
|
||||||
|
|
||||||
Updated: 2026-08-04
|
Updated: 2026-08-05
|
||||||
|
|
||||||
Papa-Kind-Treff is a PHP-based platform for fathers focused on local events, appointments, and meetups, community exchange, and a protected member area.
|
Papa-Kind-Treff is a PHP-based platform for fathers focused on local events, appointments, and meetups, community exchange, and a protected member area.
|
||||||
|
|
||||||
@@ -16,15 +16,15 @@ Papa-Kind-Treff is a PHP-based platform for fathers focused on local events, app
|
|||||||
- community admin area for applications, reports, roles, and migrations
|
- community admin area for applications, reports, roles, and migrations
|
||||||
- location-based ordering for the newest events
|
- location-based ordering for the newest events
|
||||||
- member area with left-side section navigation
|
- member area with left-side section navigation
|
||||||
- profile menu with `Profile`, `Children`, `Events`, `Community`, `Settings`
|
- profile menu with `Profile`, `Children`, `Events`, `Outings`, `Community`, `Settings`
|
||||||
- account emails and sensitive profile fields are stored encrypted application-side
|
- account emails and sensitive profile fields are stored encrypted application-side
|
||||||
- children can be created, edited, and deleted
|
- children can be created, edited, and deleted
|
||||||
- profile address supports encrypted street/house number, address search, browser import, and validation
|
- profile address supports encrypted street/house number, address search, browser import, and validation
|
||||||
- system section for site admins with maintenance and service toggles
|
- system section for site admins with maintenance and service toggles
|
||||||
- new data foundation prepared for a broader event, place, and listing system
|
- new data foundation prepared for a broader event, place, and listing system
|
||||||
- member area `Events` now supports three creation types: `Own Event`, `Place`, and `Other Event`
|
- member area `Events` is now limited again to real own events and event participations
|
||||||
- own events now include category, optional image, explicit child suitability, optional capacity, and server-side validated address data
|
- own events now include category, optional image, explicit child suitability, optional capacity, and more direct map/address synchronization
|
||||||
- places and other events now use adaptive forms with place lookup, browser address pickup, server-side address validation, flexible pricing rules, flexible opening/time slots, and image upload
|
- places and other events were moved for now into a separate member-area section `Outings`
|
||||||
- the member-area entry forms now follow a progressive approach: required fields first, optional data inside collapsible sections
|
- the member-area entry forms now follow a progressive approach: required fields first, optional data inside collapsible sections
|
||||||
- categories now use a search input with existing suggestions; new categories are created automatically and can be merged by site admins in the system area
|
- categories now use a search input with existing suggestions; new categories are created automatically and can be merged by site admins in the system area
|
||||||
|
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -1,6 +1,6 @@
|
|||||||
# Papa-Kind-Treff – Start-Doku
|
# Papa-Kind-Treff – Start-Doku
|
||||||
|
|
||||||
Stand: 2026-08-04
|
Stand: 2026-08-05
|
||||||
|
|
||||||
Diese Datei ist die zentrale Start-Doku für neue Chats und den schnellen Projekteinstieg.
|
Diese Datei ist die zentrale Start-Doku für neue Chats und den schnellen Projekteinstieg.
|
||||||
|
|
||||||
@@ -33,12 +33,12 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf:
|
|||||||
- Primärbegriff im Produkt: `Events`
|
- Primärbegriff im Produkt: `Events`
|
||||||
- `Termine` und `Treffen` ergänzend in SEO- und Erklärungstexten
|
- `Termine` und `Treffen` ergänzend in SEO- und Erklärungstexten
|
||||||
- Hauptnavigation aktuell: `Home`, `Event Suche`, `Community`
|
- Hauptnavigation aktuell: `Home`, `Event Suche`, `Community`
|
||||||
- Profil-Menü aktuell: `Profil`, `Kinder`, `Events`, `Community`, `Einstellungen`, `Abmelden`
|
- Profil-Menü aktuell: `Profil`, `Kinder`, `Events`, `Ausflugsziele`, `Community`, `Einstellungen`, `Abmelden`
|
||||||
- neue interne Grundstruktur: `listing_places`, `listings`, `listing_occurrences`, `listing_prices`, `listing_benefits`
|
- neue interne Grundstruktur: `listing_places`, `listings`, `listing_occurrences`, `listing_prices`, `listing_benefits`
|
||||||
- Seiten-Admins haben zusätzlich eine System-Sektion für globale Wartungs- und Diensteschalter
|
- Seiten-Admins haben zusätzlich eine System-Sektion für globale Wartungs- und Diensteschalter
|
||||||
- Im Mitgliederbereich unter `Events` können Nutzer jetzt zwischen `Eigenes Event`, `Ort` und `sonstiger Veranstaltung` unterscheiden
|
- Im Mitgliederbereich ist `Events` jetzt wieder auf echte eigene Events und Event-Teilnahmen beschränkt
|
||||||
- Für Orte und sonstige Veranstaltungen gibt es jetzt typabhängige Masken mit Ortssuche, Browser-Adressübernahme, Adressprüfung, flexiblen Preisregeln, flexiblen Öffnungs-/Zeitfenstern und Bild-Upload
|
- Orte und sonstige Veranstaltungen laufen jetzt separat unter `Ausflugsziele`
|
||||||
- Eigene Events unterstützen jetzt zusätzlich Kategorie, Bild-Upload, klare Kinderangabe und optionale Platzzahl
|
- Eigene Events unterstützen aktuell Kategorie, Bild-Upload, klare Kinderangabe, optionale Platzzahl und direkte Karten-/Adress-Synchronisierung
|
||||||
- Die Eingabe im Mitgliederbereich ist jetzt bewusst vereinfacht: zuerst nur Pflichtangaben, optionale Angaben in einklappbaren Bereichen
|
- 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
|
- 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
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ $dashboardUserId = (int)($_SESSION['user_id'] ?? 0);
|
|||||||
$editingEvent = isset($editEvent) && $editEvent !== null;
|
$editingEvent = isset($editEvent) && $editEvent !== null;
|
||||||
$editingListing = isset($editListing) && $editListing !== null;
|
$editingListing = isset($editListing) && $editListing !== null;
|
||||||
$editing = $editingEvent || $editingListing;
|
$editing = $editingEvent || $editingListing;
|
||||||
$currentEntryKind = $editingListing ? (string)($editListing['listing_type'] ?? 'editorial_event') : 'event';
|
$currentEntryKind = $editingListing ? (string)($editListing['listing_type'] ?? 'editorial_event') : (($section ?? 'events') === 'places' ? 'place' : 'event');
|
||||||
$actionEvent = $editing ? 'event_update' : 'event_add';
|
$actionEvent = $editing ? 'event_update' : 'event_add';
|
||||||
$startVal = '';
|
$startVal = '';
|
||||||
if ($editingEvent && !empty($editEvent['starts_at'])) {
|
if ($editingEvent && !empty($editEvent['starts_at'])) {
|
||||||
@@ -18,8 +18,8 @@ if ($editingEvent && !empty($editEvent['starts_at'])) {
|
|||||||
$startVal = date('Y-m-d', strtotime((string)$editListing['starts_at']));
|
$startVal = date('Y-m-d', strtotime((string)$editListing['starts_at']));
|
||||||
}
|
}
|
||||||
$withChildrenValue = $editingEvent ? (((int)($editEvent['allow_kids'] ?? 1)) === 1 ? 'yes' : 'no') : (($editingListing && $currentEntryKind === 'editorial_event' && !empty($editListing['supports_registration'])) ? 'yes' : 'yes');
|
$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');
|
$eventTitle = $editingEvent ? 'Event bearbeiten' : ($editingListing ? ($currentEntryKind === 'place' ? 'Ort bearbeiten' : 'Veranstaltung bearbeiten') : ((($section ?? 'events') === 'places') ? 'Ausflugsziel anlegen' : 'Neues Event anlegen'));
|
||||||
$submitLabel = $editingEvent ? 'Event speichern' : ($editingListing ? ($currentEntryKind === 'place' ? 'Ort speichern' : 'Veranstaltung speichern') : 'Eintrag anlegen');
|
$submitLabel = $editingEvent ? 'Event speichern' : ($editingListing ? ($currentEntryKind === 'place' ? 'Ort speichern' : 'Veranstaltung speichern') : ((($section ?? 'events') === 'places') ? 'Ausflugsziel anlegen' : 'Event anlegen'));
|
||||||
$titleValue = $editingEvent ? (string)($editEvent['title'] ?? '') : (string)($editListing['title'] ?? '');
|
$titleValue = $editingEvent ? (string)($editEvent['title'] ?? '') : (string)($editListing['title'] ?? '');
|
||||||
$teaserValue = $editingEvent ? (string)($editEvent['teaser_public'] ?? '') : (string)($editListing['teaser_public'] ?? '');
|
$teaserValue = $editingEvent ? (string)($editEvent['teaser_public'] ?? '') : (string)($editListing['teaser_public'] ?? '');
|
||||||
$descriptionValue = $editingEvent ? (string)($editEvent['description'] ?? '') : (string)($editListing['description'] ?? '');
|
$descriptionValue = $editingEvent ? (string)($editEvent['description'] ?? '') : (string)($editListing['description'] ?? '');
|
||||||
@@ -87,9 +87,12 @@ $sectionLinks = [
|
|||||||
'profile' => 'Profil',
|
'profile' => 'Profil',
|
||||||
'children' => 'Kinder',
|
'children' => 'Kinder',
|
||||||
'events' => 'Events',
|
'events' => 'Events',
|
||||||
|
'places' => 'Ausflugsziele',
|
||||||
'community' => 'Community',
|
'community' => 'Community',
|
||||||
'settings' => 'Einstellungen',
|
'settings' => 'Einstellungen',
|
||||||
];
|
];
|
||||||
|
$showEventTypeChoice = !$editing && (($section ?? 'events') === 'places');
|
||||||
|
$modalSectionTarget = ($editingListing || ($section ?? '') === 'places') ? 'places' : 'events';
|
||||||
if (!empty($canManageSystemSettings)) {
|
if (!empty($canManageSystemSettings)) {
|
||||||
$sectionLinks['system'] = 'System';
|
$sectionLinks['system'] = 'System';
|
||||||
}
|
}
|
||||||
@@ -275,12 +278,12 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
<?php if ($section === 'events'): ?>
|
<?php if ($section === 'events'): ?>
|
||||||
<section class="account-panel" id="events">
|
<section class="account-panel" id="events">
|
||||||
<div class="account-panel__head">
|
<div class="account-panel__head">
|
||||||
<h2>Deine Einträge</h2>
|
<h2>Deine Events</h2>
|
||||||
<p class="muted">Lege eigene Events, dauerhafte Orte und sonstige zeitlich begrenzte Veranstaltungen sauber getrennt an.</p>
|
<p class="muted">Hier verwaltest du nur echte eigene Events und Events, an denen du teilnimmst.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="account-panel__body">
|
<div class="account-panel__body">
|
||||||
<div class="flex gap-12" style="margin:0 0 16px 0; flex-wrap: wrap;">
|
<div class="flex gap-12" style="margin:0 0 16px 0; flex-wrap: wrap;">
|
||||||
<button class="btn" type="button" data-modal-open="modalEvent">Eintrag anlegen</button>
|
<button class="btn" type="button" data-modal-open="modalEvent">Eigenes Event anlegen</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="card" style="margin-bottom:18px;">
|
<div class="card" style="margin-bottom:18px;">
|
||||||
<strong>Eigene Events</strong>
|
<strong>Eigene Events</strong>
|
||||||
@@ -353,11 +356,72 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
<div class="card" style="margin:22px 0 14px;">
|
<div class="card" style="margin:22px 0 14px;">
|
||||||
<strong>Orte und sonstige Veranstaltungen</strong>
|
<strong>Events mit deiner Teilnahme</strong>
|
||||||
<p class="muted small" style="margin:8px 0 0;">Hier erscheinen dauerhafte Orte wie Spielplätze, Cafés oder Restaurants sowie zeitlich begrenzte Hinweise wie Zirkus oder Aktionsflächen.</p>
|
<p class="muted small" style="margin:8px 0 0;">Events anderer Nutzer, bei denen du eingetragen bist.</p>
|
||||||
|
</div>
|
||||||
|
<?php if (!$eventsJoinedUpcoming): ?>
|
||||||
|
<p class="muted small">Aktuell nimmst du an keinen zukünftigen Events teil.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<ul class="dash-list" style="margin-top:10px;">
|
||||||
|
<?php foreach ($eventsJoinedUpcoming as $entry): ?>
|
||||||
|
<li>
|
||||||
|
<div style="display:flex; justify-content:space-between; gap:12px; align-items:center; flex-wrap: wrap;">
|
||||||
|
<div>
|
||||||
|
<strong><?= htmlspecialchars((string)$entry['title'], ENT_QUOTES) ?></strong>
|
||||||
|
<div class="muted small" style="margin-top:4px;">
|
||||||
|
<?= htmlspecialchars(trim(implode(' · ', array_filter([
|
||||||
|
(string)($entry['city'] ?? ''),
|
||||||
|
!empty($entry['starts_at']) ? (string)$entry['starts_at'] : null,
|
||||||
|
!empty($entry['host_name']) ? 'Von ' . (string)$entry['host_name'] : null,
|
||||||
|
!empty($entry['participation_status']) ? 'Status: ' . (string)$entry['participation_status'] : null,
|
||||||
|
]))), ENT_QUOTES) ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
<?php endif; ?>
|
||||||
|
<details style="margin-top:12px;">
|
||||||
|
<summary style="cursor:pointer;">Vergangene Teilnahmen anzeigen</summary>
|
||||||
|
<?php if (!$eventsJoinedPast): ?>
|
||||||
|
<p class="muted small">Keine vergangenen Event-Teilnahmen.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<ul class="dash-list" style="margin-top:10px;">
|
||||||
|
<?php foreach ($eventsJoinedPast as $entry): ?>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
<strong><?= htmlspecialchars((string)$entry['title'], ENT_QUOTES) ?></strong>
|
||||||
|
<div class="muted small" style="margin-top:4px;">
|
||||||
|
<?= htmlspecialchars(trim(implode(' · ', array_filter([
|
||||||
|
(string)($entry['city'] ?? ''),
|
||||||
|
!empty($entry['starts_at']) ? (string)$entry['starts_at'] : null,
|
||||||
|
!empty($entry['host_name']) ? 'Von ' . (string)$entry['host_name'] : null,
|
||||||
|
!empty($entry['participation_status']) ? 'Status: ' . (string)$entry['participation_status'] : null,
|
||||||
|
]))), ENT_QUOTES) ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
<?php endif; ?>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($section === 'places'): ?>
|
||||||
|
<section class="account-panel" id="places">
|
||||||
|
<div class="account-panel__head">
|
||||||
|
<h2>Ausflugsziele</h2>
|
||||||
|
<p class="muted">Hier pflegst du Orte und sonstige Veranstaltungen als mögliche Ausflugsziele.</p>
|
||||||
|
</div>
|
||||||
|
<div class="account-panel__body">
|
||||||
|
<div class="flex gap-12" style="margin:0 0 16px 0; flex-wrap: wrap;">
|
||||||
|
<button class="btn" type="button" data-modal-open="modalEvent">Ausflugsziel anlegen</button>
|
||||||
</div>
|
</div>
|
||||||
<?php if (!$otherListings): ?>
|
<?php if (!$otherListings): ?>
|
||||||
<p class="muted small">Noch keine Orte oder sonstigen Veranstaltungen angelegt.</p>
|
<p class="muted small">Noch keine Orte oder Veranstaltungen angelegt.</p>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<ul class="dash-list" style="margin-top:10px;">
|
<ul class="dash-list" style="margin-top:10px;">
|
||||||
<?php foreach ($otherListings as $entry): ?>
|
<?php foreach ($otherListings as $entry): ?>
|
||||||
@@ -365,7 +429,7 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
<div style="display:flex; justify-content:space-between; gap:12px; align-items:center; flex-wrap: wrap;">
|
<div style="display:flex; justify-content:space-between; gap:12px; align-items:center; flex-wrap: wrap;">
|
||||||
<div>
|
<div>
|
||||||
<strong><?= htmlspecialchars((string)$entry['title'], ENT_QUOTES) ?></strong>
|
<strong><?= htmlspecialchars((string)$entry['title'], ENT_QUOTES) ?></strong>
|
||||||
<span class="badge"><?= ($entry['listing_type'] ?? '') === 'place' ? 'Ort' : 'Sonstige Veranstaltung' ?></span>
|
<span class="badge"><?= ($entry['listing_type'] ?? '') === 'place' ? 'Ort' : 'Veranstaltung' ?></span>
|
||||||
<?php if (!empty($entry['category_title'])): ?>
|
<?php if (!empty($entry['category_title'])): ?>
|
||||||
<span class="badge"><?= htmlspecialchars((string)$entry['category_title'], ENT_QUOTES) ?></span>
|
<span class="badge"><?= htmlspecialchars((string)$entry['category_title'], ENT_QUOTES) ?></span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@@ -373,13 +437,12 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
<?= htmlspecialchars(trim(implode(' · ', array_filter([
|
<?= htmlspecialchars(trim(implode(' · ', array_filter([
|
||||||
(string)($entry['city'] ?? ''),
|
(string)($entry['city'] ?? ''),
|
||||||
!empty($entry['starts_at']) ? (string)$entry['starts_at'] : null,
|
!empty($entry['starts_at']) ? (string)$entry['starts_at'] : null,
|
||||||
(string)($entry['visibility'] ?? ''),
|
|
||||||
]))), ENT_QUOTES) ?>
|
]))), ENT_QUOTES) ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-8" style="flex-wrap: wrap;">
|
<div class="flex gap-8" style="flex-wrap: wrap;">
|
||||||
<a class="btn ghost" href="/dashboard?section=events&edit_listing=<?= (int)$entry['id'] ?>#events">Bearbeiten</a>
|
<a class="btn ghost" href="/dashboard?section=places&edit_listing=<?= (int)$entry['id'] ?>#places">Bearbeiten</a>
|
||||||
<form method="post" action="/dashboard?section=events#events" onsubmit="return confirm('Eintrag wirklich löschen?');">
|
<form method="post" action="/dashboard?section=places#places" onsubmit="return confirm('Eintrag wirklich löschen?');">
|
||||||
<input type="hidden" name="action" value="listing_delete">
|
<input type="hidden" name="action" value="listing_delete">
|
||||||
<input type="hidden" name="listing_id" value="<?= (int)$entry['id'] ?>">
|
<input type="hidden" name="listing_id" value="<?= (int)$entry['id'] ?>">
|
||||||
<button class="btn ghost" type="submit">Löschen</button>
|
<button class="btn ghost" type="submit">Löschen</button>
|
||||||
@@ -934,7 +997,7 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
<h3><?= htmlspecialchars($eventTitle, ENT_QUOTES) ?></h3>
|
<h3><?= htmlspecialchars($eventTitle, ENT_QUOTES) ?></h3>
|
||||||
<button class="btn ghost" type="button" data-modal-close>✕</button>
|
<button class="btn ghost" type="button" data-modal-close>✕</button>
|
||||||
</div>
|
</div>
|
||||||
<form class="stack gap-12" style="margin-top: 10px;" method="post" action="/dashboard?section=events#events" enctype="multipart/form-data">
|
<form class="stack gap-12" style="margin-top: 10px;" method="post" action="/dashboard?section=<?= htmlspecialchars($modalSectionTarget, ENT_QUOTES) ?>#<?= htmlspecialchars($modalSectionTarget, ENT_QUOTES) ?>" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="action" value="<?= htmlspecialchars($actionEvent, ENT_QUOTES) ?>">
|
<input type="hidden" name="action" value="<?= htmlspecialchars($actionEvent, ENT_QUOTES) ?>">
|
||||||
<input type="hidden" name="entry_kind" id="entryKind" value="<?= htmlspecialchars($currentEntryKind, ENT_QUOTES) ?>">
|
<input type="hidden" name="entry_kind" id="entryKind" value="<?= htmlspecialchars($currentEntryKind, ENT_QUOTES) ?>">
|
||||||
<?php if ($editingEvent && $editEvent): ?>
|
<?php if ($editingEvent && $editEvent): ?>
|
||||||
@@ -950,17 +1013,16 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
</option>
|
</option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</datalist>
|
</datalist>
|
||||||
<?php if (!$editing): ?>
|
<?php if (!$editing && $showEventTypeChoice): ?>
|
||||||
<div class="stack gap-8">
|
<div class="stack gap-8">
|
||||||
<label class="label">Was möchtest du anlegen?</label>
|
<label class="label">Was möchtest du anlegen?</label>
|
||||||
<div class="chips" style="flex-wrap:wrap;">
|
<div class="chips" style="flex-wrap:wrap;">
|
||||||
<button class="btn ghost" type="button" data-entry-kind-choice="event">Eigenes Event</button>
|
|
||||||
<button class="btn ghost" type="button" data-entry-kind-choice="place">Ort</button>
|
<button class="btn ghost" type="button" data-entry-kind-choice="place">Ort</button>
|
||||||
<button class="btn ghost" type="button" data-entry-kind-choice="editorial_event">Sonstige Veranstaltung</button>
|
<button class="btn ghost" type="button" data-entry-kind-choice="editorial_event">Sonstige Veranstaltung</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="muted small" id="entryKindHint" style="margin:0;">Eigenes Event: von dir organisiert und mit konkretem Termin.</p>
|
<p class="muted small" id="entryKindHint" style="margin:0;">Ort: dauerhaft verfügbar oder Veranstaltung: zeitlich begrenzter Hinweis.</p>
|
||||||
</div>
|
</div>
|
||||||
<?php else: ?>
|
<?php elseif ($editing): ?>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<strong>Eintragstyp</strong>
|
<strong>Eintragstyp</strong>
|
||||||
<p class="muted small" style="margin:8px 0 0;">
|
<p class="muted small" style="margin:8px 0 0;">
|
||||||
@@ -1047,28 +1109,25 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
<div id="eventAddressStatus" class="muted small" style="margin:0;"></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="evLat" name="lat" value="<?= htmlspecialchars($latValue, ENT_QUOTES) ?>">
|
||||||
<input type="hidden" id="evLng" name="lng" value="<?= htmlspecialchars($lngValue, ENT_QUOTES) ?>">
|
<input type="hidden" id="evLng" name="lng" value="<?= htmlspecialchars($lngValue, ENT_QUOTES) ?>">
|
||||||
<details class="card" id="mapDetails">
|
<div class="card" id="mapDetails">
|
||||||
<summary style="cursor:pointer; font-weight:600;">Adresse auf Karte wählen</summary>
|
<div class="stack gap-6">
|
||||||
<div class="stack gap-6" style="margin-top:12px;">
|
|
||||||
<div class="flex gap-8" style="flex-wrap:wrap; align-items:center;">
|
<div class="flex gap-8" style="flex-wrap:wrap; align-items:center;">
|
||||||
|
<strong>Karte</strong>
|
||||||
<button class="btn ghost" type="button" id="btnEventMapCurrentLocation">📍 Aktuellen Standort auf Karte zeigen</button>
|
<button class="btn ghost" type="button" id="btnEventMapCurrentLocation">📍 Aktuellen Standort auf Karte zeigen</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="stack gap-6">
|
<div id="mapWrapper" class="map-wrapper">
|
||||||
<button class="btn ghost" type="button" id="btnMap">Auf Karte suchen</button>
|
<div class="form-row">
|
||||||
<div id="mapWrapper" class="map-wrapper" hidden>
|
<label class="label" for="mapSearch">Adresse suchen (optional)</label>
|
||||||
<div class="form-row">
|
<div class="flex gap-8">
|
||||||
<label class="label" for="mapSearch">Adresse suchen (optional)</label>
|
<input id="mapSearch" class="input" placeholder="Straße, PLZ, Ort">
|
||||||
<div class="flex gap-8">
|
<button class="btn ghost" type="button" id="btnMapSearch">Suchen</button>
|
||||||
<input id="mapSearch" class="input" placeholder="Straße, PLZ, Ort">
|
|
||||||
<button class="btn ghost" type="button" id="btnMapSearch">Suchen</button>
|
|
||||||
</div>
|
|
||||||
<p class="muted small">Klick auf die Karte setzt den Treffpunkt. Zoom/Scroll möglich.</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="mapContainer" class="map-container"></div>
|
<p class="muted small">Klick auf die Karte setzt den Treffpunkt. Änderungen an der Adresse aktualisieren die Karte automatisch.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="mapContainer" class="map-container"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</div>
|
||||||
<details class="card" id="placeContactWrap">
|
<details class="card" id="placeContactWrap">
|
||||||
<summary style="cursor:pointer; font-weight:600;">Kontaktangaben</summary>
|
<summary style="cursor:pointer; font-weight:600;">Kontaktangaben</summary>
|
||||||
<div class="form-grid" style="margin-top:12px;">
|
<div class="form-grid" style="margin-top:12px;">
|
||||||
@@ -1165,6 +1224,11 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
const id = btn.getAttribute('data-modal-open');
|
const id = btn.getAttribute('data-modal-open');
|
||||||
const modal = document.getElementById(id);
|
const modal = document.getElementById(id);
|
||||||
if (modal) modal.classList.add('open');
|
if (modal) modal.classList.add('open');
|
||||||
|
if (id === 'modalEvent' && window.PKTConsent?.has?.('external_services')) {
|
||||||
|
ensureLeaflet(() => {
|
||||||
|
setTimeout(() => initMap(), 80);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
document.querySelectorAll('[data-modal-close]').forEach(btn => {
|
document.querySelectorAll('[data-modal-close]').forEach(btn => {
|
||||||
@@ -1180,7 +1244,6 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Map picker for events (Leaflet)
|
// Map picker for events (Leaflet)
|
||||||
const btnMap = document.getElementById('btnMap');
|
|
||||||
const mapWrapper = document.getElementById('mapWrapper');
|
const mapWrapper = document.getElementById('mapWrapper');
|
||||||
const mapContainer = document.getElementById('mapContainer');
|
const mapContainer = document.getElementById('mapContainer');
|
||||||
const btnMapSearch = document.getElementById('btnMapSearch');
|
const btnMapSearch = document.getElementById('btnMapSearch');
|
||||||
@@ -1520,13 +1583,6 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btnMap?.addEventListener('click', () => {
|
|
||||||
mapWrapper.hidden = false;
|
|
||||||
ensureLeaflet(() => {
|
|
||||||
setTimeout(() => initMap(), 50);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
btnMapSearch?.addEventListener('click', () => {
|
btnMapSearch?.addEventListener('click', () => {
|
||||||
const q = (mapSearch?.value || '').trim();
|
const q = (mapSearch?.value || '').trim();
|
||||||
if (!q) return;
|
if (!q) return;
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ final class AccountPages
|
|||||||
$listingCatalog = $pdo ? new ListingCatalog($pdo) : null;
|
$listingCatalog = $pdo ? new ListingCatalog($pdo) : null;
|
||||||
$section = (string)($_GET['section'] ?? 'profile');
|
$section = (string)($_GET['section'] ?? 'profile');
|
||||||
$canManageSystemSettings = $communityAccess ? $communityAccess->canManageApplications($userId) : false;
|
$canManageSystemSettings = $communityAccess ? $communityAccess->canManageApplications($userId) : false;
|
||||||
$allowedSections = ['profile', 'children', 'events', 'community', 'settings'];
|
$allowedSections = ['profile', 'children', 'events', 'places', 'community', 'settings'];
|
||||||
if ($canManageSystemSettings) {
|
if ($canManageSystemSettings) {
|
||||||
$allowedSections[] = 'system';
|
$allowedSections[] = 'system';
|
||||||
}
|
}
|
||||||
@@ -691,6 +691,8 @@ final class AccountPages
|
|||||||
|
|
||||||
$eventsUpcoming = [];
|
$eventsUpcoming = [];
|
||||||
$eventsPast = [];
|
$eventsPast = [];
|
||||||
|
$eventsJoinedUpcoming = [];
|
||||||
|
$eventsJoinedPast = [];
|
||||||
$editEvent = null;
|
$editEvent = null;
|
||||||
$otherListings = [];
|
$otherListings = [];
|
||||||
$editListing = null;
|
$editListing = null;
|
||||||
@@ -717,6 +719,32 @@ final class AccountPages
|
|||||||
$stmt?->execute(['id' => $userId]);
|
$stmt?->execute(['id' => $userId]);
|
||||||
$eventsPast = $stmt?->fetchAll(\PDO::FETCH_ASSOC) ?: [];
|
$eventsPast = $stmt?->fetchAll(\PDO::FETCH_ASSOC) ?: [];
|
||||||
|
|
||||||
|
$stmt = $pdo?->prepare(
|
||||||
|
'SELECT e.id, e.title, e.teaser_public, e.image_path, e.starts_at, e.city, e.visibility, e.status,
|
||||||
|
ep.status AS participation_status,
|
||||||
|
u.display_name AS host_name
|
||||||
|
FROM event_participants ep
|
||||||
|
INNER JOIN events e ON e.id = ep.event_id
|
||||||
|
INNER JOIN users u ON u.id = e.created_by
|
||||||
|
WHERE ep.user_id = :id AND e.created_by <> :id AND e.starts_at >= NOW()
|
||||||
|
ORDER BY e.starts_at ASC'
|
||||||
|
);
|
||||||
|
$stmt?->execute(['id' => $userId]);
|
||||||
|
$eventsJoinedUpcoming = $stmt?->fetchAll(\PDO::FETCH_ASSOC) ?: [];
|
||||||
|
|
||||||
|
$stmt = $pdo?->prepare(
|
||||||
|
'SELECT e.id, e.title, e.teaser_public, e.image_path, e.starts_at, e.city, e.visibility, e.status,
|
||||||
|
ep.status AS participation_status,
|
||||||
|
u.display_name AS host_name
|
||||||
|
FROM event_participants ep
|
||||||
|
INNER JOIN events e ON e.id = ep.event_id
|
||||||
|
INNER JOIN users u ON u.id = e.created_by
|
||||||
|
WHERE ep.user_id = :id AND e.created_by <> :id AND e.starts_at < NOW()
|
||||||
|
ORDER BY e.starts_at DESC'
|
||||||
|
);
|
||||||
|
$stmt?->execute(['id' => $userId]);
|
||||||
|
$eventsJoinedPast = $stmt?->fetchAll(\PDO::FETCH_ASSOC) ?: [];
|
||||||
|
|
||||||
if (isset($_GET['edit_event'])) {
|
if (isset($_GET['edit_event'])) {
|
||||||
$editId = (int)$_GET['edit_event'];
|
$editId = (int)$_GET['edit_event'];
|
||||||
$stmt = $pdo?->prepare('SELECT * FROM events WHERE id = :id AND created_by = :uid AND starts_at >= NOW() LIMIT 1');
|
$stmt = $pdo?->prepare('SELECT * FROM events WHERE id = :id AND created_by = :uid AND starts_at >= NOW() LIMIT 1');
|
||||||
@@ -759,6 +787,8 @@ final class AccountPages
|
|||||||
'editChild',
|
'editChild',
|
||||||
'eventsUpcoming',
|
'eventsUpcoming',
|
||||||
'eventsPast',
|
'eventsPast',
|
||||||
|
'eventsJoinedUpcoming',
|
||||||
|
'eventsJoinedPast',
|
||||||
'editEvent',
|
'editEvent',
|
||||||
'otherListings',
|
'otherListings',
|
||||||
'editListing',
|
'editListing',
|
||||||
|
|||||||
Reference in New Issue
Block a user