diff --git a/backend/routes/friends.py b/backend/routes/friends.py
index 273ef1c..56528dd 100644
--- a/backend/routes/friends.py
+++ b/backend/routes/friends.py
@@ -30,6 +30,8 @@ async def list_friends(user=Depends(get_current_user)):
SELECT f.id, f.status, f.created_at,
CASE WHEN f.requester_id=? THEN f.addressee_id ELSE f.requester_id END AS friend_id,
u.name AS friend_name,
+ u.bio, u.wohnort, u.erfahrung, u.social_link,
+ u.profil_sichtbarkeit, u.avatar_url,
{dogs_sq} AS dogs_json
FROM friendships f
JOIN users u ON u.id = CASE WHEN f.requester_id=? THEN f.addressee_id ELSE f.requester_id END
@@ -39,6 +41,7 @@ async def list_friends(user=Depends(get_current_user)):
incoming = conn.execute(f"""
SELECT f.id, f.created_at, u.name AS requester_name, u.id AS requester_id,
+ u.avatar_url,
{dogs_sq} AS dogs_json
FROM friendships f
JOIN users u ON u.id=f.requester_id
@@ -87,6 +90,8 @@ async def search_users(q: str = "", user=Depends(get_current_user)):
with db() as conn:
rows = conn.execute("""
SELECT u.id, u.name,
+ u.bio, u.wohnort, u.erfahrung, u.social_link,
+ u.profil_sichtbarkeit, u.avatar_url,
(SELECT json_group_array(json_object('name', d.name, 'rasse', d.rasse))
FROM dogs d WHERE d.user_id=u.id AND d.is_public=1) AS dogs_json
FROM users u
diff --git a/backend/static/js/pages/friends.js b/backend/static/js/pages/friends.js
index 61adb19..17a4ff2 100644
--- a/backend/static/js/pages/friends.js
+++ b/backend/static/js/pages/friends.js
@@ -187,7 +187,7 @@ window.Page_friends = (() => {
- ${_userAvatar(r.requester_name, r.dogs?.[0])}
+ ${_userAvatar(r.requester_name, r.dogs?.[0], r.avatar_url)}
${_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 `
+ data-dogs="${_esc(JSON.stringify(dogs))}"
+ data-profile="${_esc(JSON.stringify(profile))}">
-
- ${_userAvatar(f.friend_name, dogs[0])}
+
+ ${_userAvatar(f.friend_name, dogs[0], f.avatar_url)}
-
+
-
- ${_esc(f.friend_name)}
+
+ ${_esc(f.friend_name)}
+
+ ${_erfahrungSpan(f.erfahrung)}
+
+ ${_wohnortLine(f.wohnort)}
+ ${_bioLine(f.bio, f.profil_sichtbarkeit)}
+
+ ${dogs.length
+ ? `
+ ${_dogPills(dogs, 3)}
+
`
+ : `
Noch kein Hund eingetragen
`
+ }
- ${dogs.length
- ? `
- ${_dogPills(dogs, 3)}
-
`
- : `
Noch kein Hund eingetragen
`
- }
@@ -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
? `
@@ -389,10 +406,41 @@ window.Page_friends = (() => {
Noch kein Hund eingetragen.
`;
+ const profileInfoHTML = (() => {
+ const parts = [];
+ if (profile.wohnort) {
+ parts.push(`
+ 📍 ${_esc(profile.wohnort)}
+
`);
+ }
+ if (profile.erfahrung && _erfahrungBadge[profile.erfahrung]) {
+ parts.push(`
+ ${_erfahrungBadge[profile.erfahrung]}
+
`);
+ }
+ if (profile.bio && profile.profil_sichtbarkeit !== 'private') {
+ parts.push(`
+ ${_esc(profile.bio)}
+
`);
+ }
+ if (profile.social_link) {
+ parts.push(`
`);
+ }
+ if (!parts.length) return '';
+ return `
${parts.join('')}
`;
+ })();
+
UI.modal.open({
title: _esc(friendName),
body: `
+ ${profileInfoHTML}
${dogs.length === 1 ? 'Hund' : 'Hunde'}
${dogsHTML}
@@ -443,12 +491,19 @@ window.Page_friends = (() => {
- ${_userAvatar(u.name, null)}
+ ${_userAvatar(u.name, null, u.avatar_url)}
-
${_esc(u.name)}
+
+ ${_esc(u.name)}
+ ${_erfahrungSpan(u.erfahrung)}
+
+ ${_wohnortLine(u.wohnort)}
+ ${_bioLine(u.bio, u.profil_sichtbarkeit)}
${u.dogs?.length
- ? `
+ ? `
${u.dogs.map(d => _esc(d.name) + (d.rasse ? ` · ${_esc(d.rasse)}` : '')).join(' | ')}
`
: ''}
@@ -537,7 +592,12 @@ window.Page_friends = (() => {
// ----------------------------------------------------------
// RENDER-HELPERS
// ----------------------------------------------------------
- function _userAvatar(name, firstDog) {
+ function _userAvatar(name, firstDog, avatarUrl) {
+ if (avatarUrl) {
+ return `
})
`;
+ }
if (firstDog?.foto_url) {
return `
})
${_erfahrungBadge[erfahrung]}`;
+ }
+
+ function _wohnortLine(wohnort) {
+ if (!wohnort) return '';
+ return `
📍 ${_esc(wohnort)}`;
+ }
+
+ function _bioLine(bio, sichtbarkeit) {
+ if (!bio || sichtbarkeit === 'private') return '';
+ const text = bio.length > 120 ? bio.substring(0, 120) + '…' : bio;
+ return `
${_esc(text)}
`;
+ }
+
function _dogPills(dogs, max) {
if (!dogs?.length) return '';
const visible = dogs.slice(0, max);