From a60db217827213e019a15bca7c0ab05a5b183275 Mon Sep 17 00:00:00 2001 From: rene Date: Fri, 17 Apr 2026 09:20:42 +0200 Subject: [PATCH] =?UTF-8?q?Sprint=2014:=20Profil-Editor=20in=20Settings=20?= =?UTF-8?q?=E2=80=94=20Avatar-Upload,=20Bio,=20Wohnort,=20Erfahrung,=20Soc?= =?UTF-8?q?ial-Link,=20Sichtbarkeit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/static/js/pages/settings.js | 200 +++++++++++++++++++++++++++- 1 file changed, 197 insertions(+), 3 deletions(-) diff --git a/backend/static/js/pages/settings.js b/backend/static/js/pages/settings.js index 8c54919..43cf9e7 100644 --- a/backend/static/js/pages/settings.js +++ b/backend/static/js/pages/settings.js @@ -38,17 +38,51 @@ window.Page_settings = (() => { // ---------------------------------------------------------- function _renderAccount() { const u = _appState.user; + + // Avatar: Bild oder Buchstabe + const avatarInner = u.avatar_url + ? `Avatar` + : _esc(u.name.charAt(0).toUpperCase()); + + // Mitglied seit + const memberSince = (() => { + if (!u.created_at) return ''; + const d = new Date(u.created_at); + return d.toLocaleDateString('de-DE', { month: 'long', year: 'numeric' }); + })(); + + // Erfahrungs-Labels + const erfahrungLabel = { + einsteiger: 'Einsteiger (erster Hund)', + erfahren: 'Erfahrener Hundehalter', + trainer: 'Trainer / Ausbilder', + zuechter: 'Züchter', + }; + _container.innerHTML = `
-
- ${_esc(u.name.charAt(0).toUpperCase())} + font-size:1.5rem;font-weight:700;flex-shrink:0; + cursor:pointer;overflow:hidden;position:relative"> + ${avatarInner} +
+ + + +
+
${_esc(u.name)}
${_esc(u.email)}
@@ -64,6 +98,53 @@ window.Page_settings = (() => {
+ +
+
+ Mein Profil + +
+
+ ${memberSince + ? `
+ Mitglied seit ${_esc(memberSince)} +
` + : ''} + ${u.bio + ? `
${_esc(u.bio)}
` + : ''} + ${u.wohnort + ? `
+ 📍 ${_esc(u.wohnort)} +
` + : ''} + ${u.erfahrung && erfahrungLabel[u.erfahrung] + ? `
+ ${_esc(erfahrungLabel[u.erfahrung])} +
` + : ''} + ${u.social_link + ? `` + : ''} + ${!u.bio && !u.wohnort && !u.erfahrung && !u.social_link + ? `
+ Noch kein Profil ausgefüllt. +
` + : ''} +
+
+
`; + // Avatar-Hover-Overlay + const avatarBtn = document.getElementById('settings-avatar-btn'); + const avatarOverlay = avatarBtn?.querySelector('.avatar-overlay'); + if (avatarBtn && avatarOverlay) { + avatarBtn.addEventListener('mouseenter', () => { avatarOverlay.style.opacity = '1'; }); + avatarBtn.addEventListener('mouseleave', () => { avatarOverlay.style.opacity = '0'; }); + } + + // Avatar-Upload + avatarBtn?.addEventListener('click', () => { + document.getElementById('settings-avatar-input')?.click(); + }); + document.getElementById('settings-avatar-input')?.addEventListener('change', async e => { + const file = e.target.files?.[0]; + if (!file) return; + try { + const fd = new FormData(); + fd.append('file', file); + const res = await API.post('/api/profile/avatar', fd); + _appState.user.avatar_url = res.avatar_url; + UI.toast.success('Avatar aktualisiert.'); + _render(); + } catch { + UI.toast.error('Avatar-Upload fehlgeschlagen.'); + } + }); + + // Profil bearbeiten + document.getElementById('settings-profile-edit-btn')?.addEventListener('click', () => { + const u = _appState.user; + const inputStyle = `width:100%;box-sizing:border-box;padding:var(--space-2) var(--space-3); + border:1.5px solid var(--c-border);border-radius:var(--radius-md); + font-size:var(--text-sm);font-family:inherit; + background:var(--c-surface);color:var(--c-text)`; + + const erfahrungOpts = [ + ['', 'Bitte wählen...'], + ['einsteiger', 'Einsteiger (erster Hund)'], + ['erfahren', 'Erfahrener Hundehalter'], + ['trainer', 'Trainer / Ausbilder'], + ['zuechter', 'Züchter'], + ].map(([val, label]) => + `` + ).join(''); + + const sichtbarkeitOpts = [ + ['public', 'Öffentlich'], + ['friends', 'Nur Freunde'], + ['private', 'Privat'], + ].map(([val, label]) => + `` + ).join(''); + + UI.modal.open({ + title: 'Profil bearbeiten', + body: ` +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ `, + footer: ` + + + `, + }); + + document.getElementById('profile-form')?.addEventListener('submit', async e => { + e.preventDefault(); + const btn = document.querySelector('[form="profile-form"]'); + const fd = UI.formData(e.target); + await UI.asyncButton(btn, async () => { + const updated = await API.patch('/api/profile', { + bio: fd.bio || '', + wohnort: fd.wohnort || '', + erfahrung: fd.erfahrung || '', + social_link: fd.social_link || '', + profil_sichtbarkeit: fd.profil_sichtbarkeit || 'public', + }); + Object.assign(_appState.user, updated); + UI.modal.close?.(); + UI.toast.success('Profil gespeichert.'); + _render(); + }); + }); + }); + document.getElementById('settings-logout-btn')?.addEventListener('click', async () => { const ok = await UI.modal.confirm({ title : 'Abmelden?',