Merge branch 'worktree-agent-a1140340'

This commit is contained in:
rene 2026-04-17 09:24:01 +02:00
commit 3642995409
2 changed files with 116 additions and 23 deletions

View file

@ -187,7 +187,7 @@ window.Page_friends = (() => {
<div class="card" style="padding:var(--space-4);margin-bottom:var(--space-3);
border-left:3px solid var(--c-primary)">
<div style="display:flex;align-items:center;gap:var(--space-3)">
${_userAvatar(r.requester_name, r.dogs?.[0])}
${_userAvatar(r.requester_name, r.dogs?.[0], r.avatar_url)}
<div style="flex:1;min-width:0">
<div style="font-weight:var(--weight-semibold);color:var(--c-text)">
${_esc(r.requester_name)}
@ -281,39 +281,56 @@ window.Page_friends = (() => {
el.querySelectorAll('.fr-card').forEach(card => {
card.addEventListener('click', e => {
if (e.target.closest('button')) return; // Buttons nicht überschreiben
const fid = parseInt(card.dataset.friendId);
const fname = card.dataset.friendName;
const fdogs = JSON.parse(card.dataset.dogs || '[]');
_showProfile(fid, fname, fdogs);
const fid = parseInt(card.dataset.friendId);
const fname = card.dataset.friendName;
const fdogs = JSON.parse(card.dataset.dogs || '[]');
const fprofile = JSON.parse(card.dataset.profile || '{}');
_showProfile(fid, fname, fdogs, fprofile);
});
});
}
function _friendCard(f) {
const dogs = f.dogs || [];
const profile = {
bio: f.bio || null,
wohnort: f.wohnort || null,
erfahrung: f.erfahrung || null,
social_link: f.social_link || null,
profil_sichtbarkeit: f.profil_sichtbarkeit || null,
avatar_url: f.avatar_url || null,
};
return `
<div class="card fr-card" style="padding:var(--space-4);margin-bottom:var(--space-3);cursor:pointer;
transition:box-shadow 0.15s"
data-friend-id="${f.friend_id}"
data-friend-name="${_esc(f.friend_name)}"
data-dogs="${_esc(JSON.stringify(dogs))}">
data-dogs="${_esc(JSON.stringify(dogs))}"
data-profile="${_esc(JSON.stringify(profile))}">
<div style="display:flex;align-items:center;gap:var(--space-3)">
<!-- Avatar (erstes Hunde-Foto oder Initiale) -->
${_userAvatar(f.friend_name, dogs[0])}
<!-- Avatar (User-Avatar, erstes Hunde-Foto oder Initiale) -->
${_userAvatar(f.friend_name, dogs[0], f.avatar_url)}
<!-- Name + Hunde -->
<!-- Name + Infos + Hunde -->
<div style="flex:1;min-width:0">
<div style="font-weight:var(--weight-semibold);color:var(--c-text);
<div style="display:flex;align-items:center;flex-wrap:wrap;gap:2px;
margin-bottom:var(--space-1)">
${_esc(f.friend_name)}
<span style="font-weight:var(--weight-semibold);color:var(--c-text)">
${_esc(f.friend_name)}
</span>
${_erfahrungSpan(f.erfahrung)}
</div>
${_wohnortLine(f.wohnort)}
${_bioLine(f.bio, f.profil_sichtbarkeit)}
<div style="margin-top:var(--space-1)">
${dogs.length
? `<div style="display:flex;flex-wrap:wrap;gap:var(--space-1);align-items:center">
${_dogPills(dogs, 3)}
</div>`
: `<div style="font-size:var(--text-xs);color:var(--c-text-muted)">Noch kein Hund eingetragen</div>`
}
</div>
${dogs.length
? `<div style="display:flex;flex-wrap:wrap;gap:var(--space-1);align-items:center">
${_dogPills(dogs, 3)}
</div>`
: `<div style="font-size:var(--text-xs);color:var(--c-text-muted)">Noch kein Hund eingetragen</div>`
}
</div>
<!-- Aktionen -->
@ -362,7 +379,7 @@ window.Page_friends = (() => {
// ----------------------------------------------------------
// MINI-PROFIL MODAL
// ----------------------------------------------------------
function _showProfile(friendId, friendName, dogs) {
function _showProfile(friendId, friendName, dogs, profile = {}) {
const dogsHTML = dogs.length
? `<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));
gap:var(--space-3);margin-top:var(--space-4)">
@ -389,10 +406,41 @@ window.Page_friends = (() => {
Noch kein Hund eingetragen.
</p>`;
const profileInfoHTML = (() => {
const parts = [];
if (profile.wohnort) {
parts.push(`<div style="display:flex;align-items:center;gap:var(--space-2);
font-size:var(--text-sm);color:var(--c-text-secondary)">
📍 ${_esc(profile.wohnort)}
</div>`);
}
if (profile.erfahrung && _erfahrungBadge[profile.erfahrung]) {
parts.push(`<div style="font-size:var(--text-sm);color:var(--c-text-secondary)">
${_erfahrungBadge[profile.erfahrung]}
</div>`);
}
if (profile.bio && profile.profil_sichtbarkeit !== 'private') {
parts.push(`<div style="font-size:var(--text-sm);color:var(--c-text);
line-height:1.5;padding-top:var(--space-2)">
${_esc(profile.bio)}
</div>`);
}
if (profile.social_link) {
parts.push(`<div style="font-size:var(--text-xs)">
<a href="${_esc(profile.social_link)}" target="_blank" rel="noopener noreferrer"
style="color:var(--c-primary)">${_esc(profile.social_link)}</a>
</div>`);
}
if (!parts.length) return '';
return `<div style="display:flex;flex-direction:column;gap:var(--space-2);
margin-bottom:var(--space-4)">${parts.join('')}</div>`;
})();
UI.modal.open({
title: _esc(friendName),
body: `
<div>
${profileInfoHTML}
<div class="by-section-label">${dogs.length === 1 ? 'Hund' : 'Hunde'}</div>
${dogsHTML}
</div>
@ -443,12 +491,19 @@ window.Page_friends = (() => {
<div style="display:flex;align-items:center;gap:var(--space-3);
padding:var(--space-3) var(--space-4);
${i < results.length - 1 ? 'border-bottom:1px solid var(--c-border)' : ''}">
${_userAvatar(u.name, null)}
${_userAvatar(u.name, null, u.avatar_url)}
<div style="flex:1;min-width:0">
<div style="font-size:var(--text-sm);font-weight:var(--weight-semibold);
color:var(--c-text)">${_esc(u.name)}</div>
<div style="display:flex;align-items:center;flex-wrap:wrap;gap:2px;
margin-bottom:2px">
<span style="font-size:var(--text-sm);font-weight:var(--weight-semibold);
color:var(--c-text)">${_esc(u.name)}</span>
${_erfahrungSpan(u.erfahrung)}
</div>
${_wohnortLine(u.wohnort)}
${_bioLine(u.bio, u.profil_sichtbarkeit)}
${u.dogs?.length
? `<div style="font-size:var(--text-xs);color:var(--c-text-secondary)">
? `<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
margin-top:2px">
${u.dogs.map(d => _esc(d.name) + (d.rasse ? ` · ${_esc(d.rasse)}` : '')).join(' &nbsp;|&nbsp; ')}
</div>`
: ''}
@ -537,7 +592,12 @@ window.Page_friends = (() => {
// ----------------------------------------------------------
// RENDER-HELPERS
// ----------------------------------------------------------
function _userAvatar(name, firstDog) {
function _userAvatar(name, firstDog, avatarUrl) {
if (avatarUrl) {
return `<img src="${_esc(avatarUrl)}" alt="${_esc(name)}"
style="width:44px;height:44px;border-radius:50%;object-fit:cover;
border:2px solid var(--c-primary);flex-shrink:0">`;
}
if (firstDog?.foto_url) {
return `<img src="${_esc(firstDog.foto_url)}" alt="${_esc(firstDog.name)}"
style="width:44px;height:44px;border-radius:50%;object-fit:cover;
@ -553,6 +613,34 @@ window.Page_friends = (() => {
</div>`;
}
const _erfahrungBadge = {
einsteiger: '🐾 Einsteiger',
erfahren: '⭐ Erfahren',
trainer: '🎓 Trainer',
zuechter: '🏅 Züchter',
};
function _erfahrungSpan(erfahrung) {
if (!erfahrung || !_erfahrungBadge[erfahrung]) return '';
return `<span style="font-size:10px;padding:1px 5px;border-radius:3px;
background:var(--c-surface-2);color:var(--c-text-secondary);
margin-left:4px;white-space:nowrap">${_erfahrungBadge[erfahrung]}</span>`;
}
function _wohnortLine(wohnort) {
if (!wohnort) return '';
return `<span style="font-size:var(--text-xs);color:var(--c-text-muted)">📍 ${_esc(wohnort)}</span>`;
}
function _bioLine(bio, sichtbarkeit) {
if (!bio || sichtbarkeit === 'private') return '';
const text = bio.length > 120 ? bio.substring(0, 120) + '…' : bio;
return `<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
margin-top:var(--space-1);line-height:1.4;
overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;
-webkit-box-orient:vertical">${_esc(text)}</div>`;
}
function _dogPills(dogs, max) {
if (!dogs?.length) return '';
const visible = dogs.slice(0, max);