csadas
All checks were successful
Deploy / deploy (push) Successful in 58s

This commit is contained in:
2026-07-31 21:45:19 +02:00
parent 002108ac83
commit c335fd6f5c
6 changed files with 158 additions and 88 deletions

View File

@@ -78,16 +78,31 @@ $sectionLinks = [
<button class="btn" type="button" data-modal-open="modalAvatar">Profilbild gestalten</button>
</div>
</div>
<dl class="account-kv">
<div><dt>Name</dt><dd><?= htmlspecialchars(trim($profile['first_name'] . ' ' . $profile['last_name']), ENT_QUOTES) ?></dd></div>
<div><dt>Anzeigename</dt><dd><?= htmlspecialchars($profile['display_name'], ENT_QUOTES) ?></dd></div>
<div><dt>Adresse</dt><dd><?= htmlspecialchars(trim(implode(', ', array_filter([(string)($profile['street'] ?? ''), trim((string)$profile['zip'] . ' ' . (string)$profile['city']), (string)($profile['region'] ?? '')]))), ENT_QUOTES) ?></dd></div>
<div><dt>E-Mail</dt><dd><?= htmlspecialchars($profile['email'], ENT_QUOTES) ?></dd></div>
<div><dt>Telefon</dt><dd><?= htmlspecialchars($profile['contact_phone'], ENT_QUOTES) ?></dd></div>
<div><dt>Beruf</dt><dd><?= htmlspecialchars($profile['profession'], ENT_QUOTES) ?></dd></div>
<div><dt>Sprachen</dt><dd><?= htmlspecialchars($profile['languages'], ENT_QUOTES) ?></dd></div>
<div><dt>Über dich</dt><dd><?= htmlspecialchars($profile['about'], ENT_QUOTES) ?></dd></div>
</dl>
<div class="profile-summary-grid">
<section class="profile-summary-card">
<span class="profile-summary-card__eyebrow">Basis</span>
<dl class="account-kv account-kv--compact">
<div><dt>Anzeigename</dt><dd><?= htmlspecialchars($profile['display_name'] ?: 'Nicht hinterlegt', ENT_QUOTES) ?></dd></div>
<div><dt>Name</dt><dd><?= htmlspecialchars(trim($profile['first_name'] . ' ' . $profile['last_name']) ?: 'Nicht hinterlegt', ENT_QUOTES) ?></dd></div>
<div><dt>E-Mail</dt><dd><?= htmlspecialchars($profile['email'] ?: 'Nicht hinterlegt', ENT_QUOTES) ?></dd></div>
<div><dt>Telefon</dt><dd><?= htmlspecialchars($profile['contact_phone'] ?: 'Nicht hinterlegt', ENT_QUOTES) ?></dd></div>
</dl>
</section>
<section class="profile-summary-card">
<span class="profile-summary-card__eyebrow">Standort</span>
<dl class="account-kv account-kv--compact">
<div><dt>Adresse</dt><dd><?= htmlspecialchars(trim(implode(', ', array_filter([(string)($profile['street'] ?? ''), trim((string)$profile['zip'] . ' ' . (string)$profile['city']), (string)($profile['region'] ?? '')]))) ?: 'Nicht hinterlegt', ENT_QUOTES) ?></dd></div>
<div><dt>Sprachen</dt><dd><?= htmlspecialchars($profile['languages'] ?: 'Nicht hinterlegt', ENT_QUOTES) ?></dd></div>
<div><dt>Beruf</dt><dd><?= htmlspecialchars($profile['profession'] ?: 'Nicht hinterlegt', ENT_QUOTES) ?></dd></div>
</dl>
</section>
</div>
<?php if (trim((string)$profile['about']) !== ''): ?>
<div class="profile-about-card">
<strong>Über dich</strong>
<p><?= nl2br(htmlspecialchars((string)$profile['about'], ENT_QUOTES)) ?></p>
</div>
<?php endif; ?>
<div class="flex gap-12" style="margin-top:18px;">
<button class="btn" type="button" data-modal-open="modalProfile">Profil bearbeiten</button>
</div>
@@ -484,91 +499,116 @@ $sectionLinks = [
<h3>Profil bearbeiten</h3>
<button class="btn ghost" type="button" data-modal-close>✕</button>
</div>
<form method="post" class="stack gap-12">
<form method="post" class="stack gap-12 profile-edit-form">
<input type="hidden" name="action" value="profile">
<input type="hidden" id="pRegion" name="region" value="<?= htmlspecialchars((string)($profile['region'] ?? ''), ENT_QUOTES) ?>">
<input type="hidden" id="pLat" name="lat" value="<?= htmlspecialchars((string)($profile['lat'] ?? ''), ENT_QUOTES) ?>">
<input type="hidden" id="pLng" name="lng" value="<?= htmlspecialchars((string)($profile['lng'] ?? ''), ENT_QUOTES) ?>">
<div class="form-grid">
<div class="stack gap-6">
<label class="label" for="pName">Anzeigename</label>
<input id="pName" name="display_name" class="input" value="<?= htmlspecialchars($profile['display_name'], ENT_QUOTES) ?>">
<p class="muted small" style="margin:0;">Persoenliche Angaben werden app-seitig verschluesselt gespeichert. Nur fuer Login und Kontofunktionen wird die E-Mail intern ueber einen separaten Lookup-Hash adressiert.</p>
<details class="profile-edit-section" open>
<summary>Basisdaten</summary>
<div class="profile-edit-section__body">
<div class="form-grid">
<div class="stack gap-6">
<label class="label" for="pName">Anzeigename</label>
<input id="pName" name="display_name" class="input" value="<?= htmlspecialchars($profile['display_name'], ENT_QUOTES) ?>">
</div>
<div class="stack gap-6">
<label class="label" for="pEmail">E-Mail-Adresse</label>
<input id="pEmail" name="email" type="email" class="input" value="<?= htmlspecialchars((string)$profile['email'], ENT_QUOTES) ?>" autocomplete="email" required>
</div>
</div>
<div class="form-grid">
<div class="stack gap-6">
<label class="label" for="pFirst">Vorname</label>
<input id="pFirst" name="first_name" class="input" value="<?= htmlspecialchars($profile['first_name'], ENT_QUOTES) ?>" autocomplete="given-name">
</div>
<div class="stack gap-6">
<label class="label" for="pLast">Nachname</label>
<input id="pLast" name="last_name" class="input" value="<?= htmlspecialchars($profile['last_name'], ENT_QUOTES) ?>" autocomplete="family-name">
</div>
</div>
<div class="stack gap-6">
<label class="label" for="pPhone">Telefon (mobil)</label>
<input id="pPhone" name="contact_phone" class="input" value="<?= htmlspecialchars($profile['contact_phone'], ENT_QUOTES) ?>" autocomplete="tel">
</div>
</div>
<div class="stack gap-6">
<label class="label" for="pFirst">Vorname</label>
<input id="pFirst" name="first_name" class="input" value="<?= htmlspecialchars($profile['first_name'], ENT_QUOTES) ?>">
</details>
<details class="profile-edit-section" open>
<summary>Adresse und Umgebung</summary>
<div class="profile-edit-section__body">
<div class="form-grid">
<div class="stack gap-6">
<label class="label" for="pStreet">Straße / Hausnummer</label>
<input id="pStreet" name="street" class="input" value="<?= htmlspecialchars((string)($profile['street'] ?? ''), ENT_QUOTES) ?>" placeholder="z. B. Musterstraße 12" autocomplete="street-address">
</div>
<div class="stack gap-6">
<label class="label" for="pZip">PLZ</label>
<input id="pZip" name="zip" class="input" value="<?= htmlspecialchars($profile['zip'], ENT_QUOTES) ?>" autocomplete="postal-code">
</div>
</div>
<div class="form-grid">
<div class="stack gap-6">
<label class="label" for="pCity">Ort</label>
<input id="pCity" name="city" class="input" value="<?= htmlspecialchars($profile['city'], ENT_QUOTES) ?>" autocomplete="address-level2">
</div>
<div class="stack gap-6">
<label class="label" for="pRegionView">Region / Bezirk</label>
<input id="pRegionView" class="input" value="<?= htmlspecialchars((string)($profile['region'] ?? ''), ENT_QUOTES) ?>" placeholder="wird bei Lokalisierung ergänzt" autocomplete="address-level1">
</div>
</div>
<div class="flex gap-12" style="flex-wrap:wrap;">
<button class="btn ghost" type="button" id="btnProfileLocate">Adresse suchen</button>
<button class="btn ghost" type="button" id="btnProfileBrowserLocation">Browser-Adresse übernehmen</button>
<button class="btn ghost" type="button" data-modal-open="modalProfileAddressHelp" aria-label="Hilfe zur Profiladresse">?</button>
</div>
<p class="muted small" style="margin:0;">Für Suche und Browser-Übernahme werden dieselben Karten-/Adressdienste wie bei Events genutzt und nur nach Einwilligung in externe Dienste.</p>
<div id="profileAddressStatus" class="muted small" style="margin:0;"></div>
<div id="profileAddressSelectedLabel" class="muted small" style="margin:0;<?= empty($profile['street']) && empty($profile['city']) ? ' display:none;' : '' ?>">
<?php if (!empty($profile['street']) || !empty($profile['city'])): ?>
Gewaehlte Adresse: <?= htmlspecialchars(trim(implode(', ', array_filter([(string)($profile['street'] ?? ''), trim((string)$profile['zip'] . ' ' . (string)$profile['city']), (string)($profile['region'] ?? '')]))), ENT_QUOTES) ?>
<?php endif; ?>
</div>
<div id="profileAddressNeedsValidation" class="muted small" style="margin:0; display:none;">
Die Adresse wurde manuell geaendert. Vor dem Speichern bitte erneut suchen oder die Browser-Adresse uebernehmen.
</div>
</div>
</div>
<div class="form-grid">
<div class="stack gap-6">
<label class="label" for="pStreet">Straße / Hausnummer</label>
<input id="pStreet" name="street" class="input" value="<?= htmlspecialchars((string)($profile['street'] ?? ''), ENT_QUOTES) ?>" placeholder="z. B. Musterstraße 12">
</details>
<details class="profile-edit-section">
<summary>Sprache und Beruf</summary>
<div class="profile-edit-section__body">
<div class="stack gap-6">
<label class="label">Sprachen (Mehrfachauswahl)</label>
<div class="chips" style="flex-wrap: wrap;">
<?php
$langOptions = ['Deutsch','Englisch','Französisch','Spanisch','Türkisch','Arabisch','Polnisch'];
$currentLangs = array_filter(array_map('trim', explode(',', (string)$profile['languages'])));
?>
<?php foreach ($langOptions as $opt): ?>
<label class="chip" style="cursor:pointer;">
<input type="checkbox" name="languages[]" value="<?= htmlspecialchars($opt, ENT_QUOTES) ?>" <?= in_array($opt, $currentLangs, true) ? 'checked' : '' ?> style="margin-right:6px;">
<?= htmlspecialchars($opt, ENT_QUOTES) ?>
</label>
<?php endforeach; ?>
</div>
<label class="label" for="pLangCustom">Weitere Sprachen (Kommagetrennt)</label>
<input id="pLangCustom" name="languages[]" class="input" placeholder="z. B. Italienisch, Niederländisch">
</div>
<div class="stack gap-6">
<label class="label" for="pProf">Beruf</label>
<input id="pProf" name="profession" class="input" value="<?= htmlspecialchars($profile['profession'], ENT_QUOTES) ?>" autocomplete="organization-title">
</div>
</div>
<div class="stack gap-6">
<label class="label" for="pLast">Nachname</label>
<input id="pLast" name="last_name" class="input" value="<?= htmlspecialchars($profile['last_name'], ENT_QUOTES) ?>">
</details>
<details class="profile-edit-section">
<summary>Kurzvorstellung</summary>
<div class="profile-edit-section__body">
<div class="stack gap-6">
<label class="label" for="pAbout">Über dich</label>
<textarea id="pAbout" name="about" class="textarea" rows="4"><?= htmlspecialchars($profile['about'], ENT_QUOTES) ?></textarea>
</div>
</div>
</div>
<div class="form-grid">
<div class="stack gap-6">
<label class="label" for="pZip">PLZ</label>
<input id="pZip" name="zip" class="input" value="<?= htmlspecialchars($profile['zip'], ENT_QUOTES) ?>">
</div>
<div class="stack gap-6">
<label class="label" for="pCity">Ort</label>
<input id="pCity" name="city" class="input" value="<?= htmlspecialchars($profile['city'], ENT_QUOTES) ?>">
</div>
</div>
<div class="form-grid">
<div class="stack gap-6">
<label class="label" for="pRegionView">Region / Bezirk</label>
<input id="pRegionView" class="input" value="<?= htmlspecialchars((string)($profile['region'] ?? ''), ENT_QUOTES) ?>" placeholder="wird bei Lokalisierung ergänzt">
</div>
<div class="stack gap-6">
<label class="label" for="pPhone">Telefon (mobil)</label>
<input id="pPhone" name="contact_phone" class="input" value="<?= htmlspecialchars($profile['contact_phone'], ENT_QUOTES) ?>">
</div>
</div>
<div class="flex gap-12" style="flex-wrap:wrap;">
<button class="btn ghost" type="button" id="btnProfileLocate">Adresse suchen</button>
<button class="btn ghost" type="button" id="btnProfileBrowserLocation">Browser-Adresse übernehmen</button>
<button class="btn ghost" type="button" data-modal-open="modalProfileAddressHelp" aria-label="Hilfe zur Profiladresse">?</button>
</div>
<p class="muted small" style="margin:0;">Für Suche und Browser-Übernahme werden dieselben Karten-/Adressdienste wie bei Events genutzt und nur nach Einwilligung in externe Dienste.</p>
<div id="profileAddressStatus" class="muted small" style="margin:0;"></div>
<div id="profileAddressSelectedLabel" class="muted small" style="margin:0;<?= empty($profile['street']) && empty($profile['city']) ? ' display:none;' : '' ?>">
<?php if (!empty($profile['street']) || !empty($profile['city'])): ?>
Gewaehlte Adresse: <?= htmlspecialchars(trim(implode(', ', array_filter([(string)($profile['street'] ?? ''), trim((string)$profile['zip'] . ' ' . (string)$profile['city']), (string)($profile['region'] ?? '')]))), ENT_QUOTES) ?>
<?php endif; ?>
</div>
<div id="profileAddressNeedsValidation" class="muted small" style="margin:0; display:none;">
Die Adresse wurde manuell geaendert. Vor dem Speichern bitte erneut suchen oder die Browser-Adresse uebernehmen.
</div>
<div class="stack gap-6">
<label class="label">Sprachen (Mehrfachauswahl)</label>
<div class="chips" style="flex-wrap: wrap;">
<?php
$langOptions = ['Deutsch','Englisch','Französisch','Spanisch','Türkisch','Arabisch','Polnisch'];
$currentLangs = array_filter(array_map('trim', explode(',', (string)$profile['languages'])));
?>
<?php foreach ($langOptions as $opt): ?>
<label class="chip" style="cursor:pointer;">
<input type="checkbox" name="languages[]" value="<?= htmlspecialchars($opt, ENT_QUOTES) ?>" <?= in_array($opt, $currentLangs, true) ? 'checked' : '' ?> style="margin-right:6px;">
<?= htmlspecialchars($opt, ENT_QUOTES) ?>
</label>
<?php endforeach; ?>
</div>
<label class="label" for="pLangCustom">Weitere Sprachen (Kommagetrennt)</label>
<input id="pLangCustom" name="languages[]" class="input" placeholder="z. B. Italienisch, Niederländisch">
</div>
<div class="stack gap-6">
<label class="label" for="pProf">Beruf</label>
<input id="pProf" name="profession" class="input" value="<?= htmlspecialchars($profile['profession'], ENT_QUOTES) ?>">
</div>
<div class="stack gap-6">
<label class="label" for="pAbout">Kurzvorstellung</label>
<textarea id="pAbout" name="about" class="textarea" rows="3"><?= htmlspecialchars($profile['about'], ENT_QUOTES) ?></textarea>
</div>
</details>
<div class="flex gap-12">
<button class="btn ghost" type="button" data-modal-close>Abbrechen</button>
<button class="btn" type="submit">Speichern</button>