Sprint 18: Lost-Dog CSS, Freunde-Aktivitäts-Feed, Events-Karte

This commit is contained in:
rene 2026-04-17 23:43:35 +02:00
parent cfdb3fbc19
commit 10d30bf565
8 changed files with 595 additions and 41 deletions

View file

@ -187,6 +187,131 @@ async def decline_request(friendship_id: int, user=Depends(get_current_user)):
return {"ok": True}
@router.get("/activity")
async def get_activity(user=Depends(get_current_user)):
"""Aggregierter Aktivitäts-Feed der Freunde (max. 30 Einträge, neueste zuerst)."""
import json
uid = user["id"]
with db() as conn:
# Alle akzeptierten Freunde ermitteln
friend_rows = conn.execute("""
SELECT CASE WHEN requester_id=? THEN addressee_id ELSE requester_id END AS fid
FROM friendships
WHERE (requester_id=? OR addressee_id=?) AND status='accepted'
""", (uid, uid, uid)).fetchall()
friend_ids = [r["fid"] for r in friend_rows]
if not friend_ids:
return []
ph = ",".join("?" * len(friend_ids))
# Tagebuch-Einträge der Freunde
diary_rows = conn.execute(f"""
SELECT
'diary' AS type,
u.id AS user_id,
u.name AS user_name,
u.avatar_url,
d.name AS dog_name,
d.foto_url AS dog_foto,
dg.titel AS text,
dg.created_at
FROM diary dg
JOIN dogs d ON d.id = dg.dog_id
JOIN users u ON u.id = d.user_id
WHERE d.user_id IN ({ph})
ORDER BY dg.created_at DESC
LIMIT 30
""", friend_ids).fetchall()
# Gesundheitseinträge der Freunde (nur Typ + Datum, kein Inhalt)
health_rows = conn.execute(f"""
SELECT
'health' AS type,
u.id AS user_id,
u.name AS user_name,
u.avatar_url,
d.name AS dog_name,
d.foto_url AS dog_foto,
h.created_at
FROM health h
JOIN dogs d ON d.id = h.dog_id
JOIN users u ON u.id = d.user_id
WHERE d.user_id IN ({ph})
ORDER BY h.created_at DESC
LIMIT 30
""", friend_ids).fetchall()
# Gassi-Treffen der Freunde
walk_rows = conn.execute(f"""
SELECT
'walk' AS type,
u.id AS user_id,
u.name AS user_name,
u.avatar_url,
NULL AS dog_name,
NULL AS dog_foto,
w.titel AS text,
w.created_at
FROM walks w
JOIN users u ON u.id = w.user_id
WHERE w.user_id IN ({ph})
ORDER BY w.created_at DESC
LIMIT 30
""", friend_ids).fetchall()
# Neue Hunde (angelegt in den letzten 30 Tagen)
new_dog_rows = conn.execute(f"""
SELECT
'new_dog' AS type,
u.id AS user_id,
u.name AS user_name,
u.avatar_url,
d.name AS dog_name,
d.foto_url AS dog_foto,
d.created_at
FROM dogs d
JOIN users u ON u.id = d.user_id
WHERE d.user_id IN ({ph})
AND d.created_at >= datetime('now', '-30 days')
ORDER BY d.created_at DESC
LIMIT 30
""", friend_ids).fetchall()
_ICON = {
"diary": "book-open",
"health": "heart",
"walk": "paw-print",
"new_dog": "dog",
}
_TEXT = {
"health": "Hat einen Gesundheitseintrag hinzugefügt",
"new_dog": "Hat einen neuen Hund eingetragen",
}
items = []
for row in [*diary_rows, *health_rows, *walk_rows, *new_dog_rows]:
d = dict(row)
t = d["type"]
items.append({
"type": t,
"user_id": d["user_id"],
"user_name": d["user_name"],
"avatar_url": d.get("avatar_url"),
"dog_name": d.get("dog_name"),
"dog_foto": d.get("dog_foto"),
"text": _TEXT.get(t) or (d.get("text") or ""),
"created_at": d["created_at"],
"icon": _ICON[t],
})
# Zusammenführen und nach created_at absteigend sortieren, max. 30
items.sort(key=lambda x: x["created_at"] or "", reverse=True)
return items[:30]
@router.delete("/{friend_user_id}")
async def remove_friend(friend_user_id: int, user=Depends(get_current_user)):
uid = user["id"]