@@ -1,9 +1,9 @@
|
||||
Anweisung: Projektstruktur (Basis-Template) wie in „papa-kind-treff“
|
||||
|
||||
Aktueller Projektstand
|
||||
- Papa-Kind-Treff nutzt im Mitgliederbereich 100 moderne Portrait-Presets im gewünschten Referenzstil.
|
||||
- Papa-Kind-Treff nutzt im Mitgliederbereich DiceBear `lorelei` über einen internen API-Proxy mit lokalem Cache.
|
||||
- Relevante Logik liegt in `src/App/Avatar.php`.
|
||||
- Die Preset-Assets liegen unter `public/assets/avatars/presets/`.
|
||||
- Der Avatar-Proxy liegt unter `public/page/api/avatar.php`.
|
||||
- Änderungen an Funktionen mit Cookies, LocalStorage, SessionStorage, Geolocation, Tracking oder Drittanbietern müssen immer auch in Datenschutz-/Cookie-Hinweisen und im Consent-Flow berücksichtigt werden.
|
||||
|
||||
Ziel
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Papa-Kind-Treff – Chat-Kontext
|
||||
|
||||
Stand: 2026-07-24
|
||||
Stand: 2026-07-26
|
||||
|
||||
## Kurzbeschreibung
|
||||
Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter. Kernbereiche sind lokale Treffen/Events, ein Community-Forum, Mitgliederprofile mit optionalen Kinderinfos und ein Moderations-/Adminbereich.
|
||||
@@ -19,13 +19,13 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter. Kernbereiche sind l
|
||||
- Die Community ist hierarchisch aufgebaut: Kategorien -> Boards -> Threads -> Posts.
|
||||
- Moderation ist getrennt vom normalen Community-Frontend in einem eigenen Adminbereich.
|
||||
- Standortfunktionen sind relevant für lokale Treffen und werden künftig weiter ausgebaut.
|
||||
- Profilbilder werden aktuell über 100 moderne Preset-Portraits im gewünschten Referenzstil statt über freie Bild-Uploads erzeugt.
|
||||
- Profilbilder werden aktuell über DiceBear im Stil `lorelei` serverseitig erzeugt und lokal gecacht.
|
||||
|
||||
## Navigation / Konto
|
||||
- Eingeloggte Nutzer sehen rechts ein Profil-Menü statt einzelner `Dashboard`-/`Logout`-Buttons.
|
||||
- Das Profil-Menü enthält aktuell `Profil`, `Kinder`, `Termine`, `Community`, `Einstellungen`, `Abmelden`.
|
||||
- Der Mitgliederbereich selbst ist als Layout mit linker Bereichsnavigation aufgebaut.
|
||||
- Im Profil kann der Nutzer aktuell aus 100 modernen Preset-Varianten wählen, gruppiert nach Hauttönen.
|
||||
- Im Profil kann der Nutzer aktuell aus Lorelei-Varianten wählen und sich neue Seed-basierte Vorschläge laden.
|
||||
- Debug ist kein Menüpunkt und erscheint nur als Floating-Käfer für `site_admin` bei aktivem Debug-Modus.
|
||||
|
||||
## Community und Rechte
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Papa-Kind-Treff
|
||||
|
||||
Stand: 2026-07-24
|
||||
Stand: 2026-07-26
|
||||
|
||||
Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf lokale Treffen, Community-Austausch und einen geschützten Mitgliederbereich.
|
||||
|
||||
@@ -17,7 +17,7 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf lokale
|
||||
- Impressum, Datenschutz-&-Cookies-Seite und Über-uns
|
||||
- standortbasierte Sortierung für die neuesten Treffen
|
||||
- eigener Einstellungsbereich für Standortfreigabe, Browser-Hinweise und Consent-Verwaltung
|
||||
- modernes Avatar-System auf Basis von 100 festen Portrait-Presets im Referenzstil, gruppiert nach Hauttönen
|
||||
- modernes Avatar-System auf Basis von DiceBear `lorelei`, serverseitig über einen lokalen Proxy mit Cache ausgeliefert
|
||||
- Consent-Manager für Analyse und externe Dienste
|
||||
- Navigation aktuell mit `Home`, `Suche`, `Community`
|
||||
- eingeloggte Nutzer sehen rechts ein Profil-Menü mit Direktlinks zu `Profil`, `Kinder`, `Termine`, `Community`, `Einstellungen`
|
||||
@@ -46,6 +46,7 @@ Der aktuelle Code nutzt oder kann nutzen:
|
||||
- lokale Standortspeicherung via Cookie, `localStorage`, `sessionStorage` (`external_services`)
|
||||
- Leaflet von `unpkg.com` (`external_services`)
|
||||
- OpenStreetMap Nominatim (`external_services`)
|
||||
- DiceBear `lorelei` für serverseitig erzeugte Profilbilder
|
||||
|
||||
Wichtig:
|
||||
- Nicht notwendige Analyse- und Drittanbieterfunktionen dürfen erst nach Einwilligung aktiv werden.
|
||||
|
||||
@@ -6,7 +6,6 @@ $editing = isset($editEvent) && $editEvent !== null;
|
||||
$actionEvent = $editing ? 'event_update' : 'event_add';
|
||||
$startVal = $editEvent ? date('Y-m-d\TH:i', strtotime((string)$editEvent['starts_at'])) : '';
|
||||
$allowNoKidsChecked = $editEvent ? ((int)$editEvent['allow_kids'] === 0) : false;
|
||||
$activeAvatarPresetGroup = \App\Avatar::presetGroupForPreset((string)($profile['avatar_preset'] ?? 'modern_001'));
|
||||
$sectionLinks = [
|
||||
'profile' => 'Profil',
|
||||
'children' => 'Kinder',
|
||||
@@ -68,7 +67,7 @@ $sectionLinks = [
|
||||
</div>
|
||||
<div class="profile-avatar-panel__content">
|
||||
<h3>Dein Profilbild</h3>
|
||||
<p class="muted">Wähle ein modernes Portrait im Stil der Community. Die Varianten bleiben konsistent, frisch und deutlich näher an der gewünschten Optik.</p>
|
||||
<p class="muted">Dein Profilbild wird jetzt mit DiceBear im Stil Lorelei erzeugt. Du wählst eine Variante aus und speicherst deren Seed dauerhaft in deinem Profil.</p>
|
||||
<button class="btn" type="button" data-modal-open="modalAvatar">Profilbild gestalten</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -303,39 +302,32 @@ $sectionLinks = [
|
||||
<div data-avatar-preview>
|
||||
<?= \App\Avatar::render($profile, $profile['display_name'] ?: 'Papa', 'xxl') ?>
|
||||
</div>
|
||||
<p class="muted small">Wähle zuerst einen Hautton-Bereich und dann eine passende Variante. Die Vorschau aktualisiert sich sofort.</p>
|
||||
<p class="muted small">Wähle eine Lorelei-Variante oder lade dir direkt neue Vorschläge. Die Vorschau aktualisiert sich sofort.</p>
|
||||
</div>
|
||||
<div class="avatar-builder__controls">
|
||||
<div class="avatar-preset-filters" role="tablist" aria-label="Hauttöne filtern">
|
||||
<?php foreach ($avatarPresetGroups as $groupKey => $groupMeta): ?>
|
||||
<button
|
||||
type="button"
|
||||
class="avatar-preset-filter <?= $groupKey === $activeAvatarPresetGroup ? 'is-active' : '' ?>"
|
||||
data-avatar-preset-filter="<?= htmlspecialchars((string)$groupKey, ENT_QUOTES) ?>"
|
||||
role="tab"
|
||||
aria-selected="<?= $groupKey === $activeAvatarPresetGroup ? 'true' : 'false' ?>"
|
||||
>
|
||||
<?= htmlspecialchars((string)$groupMeta['label'], ENT_QUOTES) ?>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
<div class="flex gap-12" style="flex-wrap:wrap;">
|
||||
<button class="btn ghost" type="button" data-avatar-reroll>Neue Varianten laden</button>
|
||||
</div>
|
||||
<div class="stack gap-6">
|
||||
<span class="label">Variante wählen</span>
|
||||
<?php foreach ($avatarPresetOptions as $groupKey => $groupPresets): ?>
|
||||
<div class="avatar-preset-group <?= $groupKey === $activeAvatarPresetGroup ? 'is-active' : '' ?>" data-avatar-preset-group="<?= htmlspecialchars((string)$groupKey, ENT_QUOTES) ?>">
|
||||
<div class="avatar-preset-grid">
|
||||
<?php foreach ($groupPresets as $value => $meta): ?>
|
||||
<label class="avatar-preset-card">
|
||||
<input type="radio" name="avatar_preset" value="<?= htmlspecialchars((string)$value, ENT_QUOTES) ?>" data-avatar-field="avatar_preset" <?= $profile['avatar_preset'] === $value ? 'checked' : '' ?>>
|
||||
<span class="avatar-preset-card__thumb">
|
||||
<img src="<?= htmlspecialchars((string)($meta['image'] ?? ''), ENT_QUOTES) ?>" alt="<?= htmlspecialchars((string)$meta['label'], ENT_QUOTES) ?>">
|
||||
</span>
|
||||
<span class="avatar-preset-card__label"><?= htmlspecialchars((string)$meta['label'], ENT_QUOTES) ?></span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<div class="avatar-preset-grid" data-avatar-grid>
|
||||
<?php foreach ($avatarPresetOptions as $index => $meta): ?>
|
||||
<label class="avatar-preset-card">
|
||||
<input
|
||||
type="radio"
|
||||
name="avatar_preset"
|
||||
value="<?= htmlspecialchars((string)$meta['seed'], ENT_QUOTES) ?>"
|
||||
data-avatar-field="avatar_preset"
|
||||
data-avatar-url="<?= htmlspecialchars((string)$meta['image'], ENT_QUOTES) ?>"
|
||||
<?= $profile['avatar_preset'] === $meta['seed'] || ($profile['avatar_preset'] === '' && $index === 0) ? 'checked' : '' ?>
|
||||
>
|
||||
<span class="avatar-preset-card__thumb">
|
||||
<img src="<?= htmlspecialchars((string)$meta['image'], ENT_QUOTES) ?>" alt="<?= htmlspecialchars((string)$meta['label'], ENT_QUOTES) ?>">
|
||||
</span>
|
||||
<span class="avatar-preset-card__label"><?= htmlspecialchars((string)$meta['label'], ENT_QUOTES) ?></span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 58 KiB |