Pflege-System: Pflegetipps im Hundeprofil + Rassen-Autocomplete

- GET /api/dogs/{id}/pflege: rassenspezifische Pflegetipps
- pflege_tipps DB-Tabelle (43 Tipps, 10 Kategorien) geseedet
- dogs.rasse_id für Wiki-Verknüpfung (Migration)
- Hundeprofil: Tipp des Tages + alle Tipps aufklappbar
- Hundeprofil-Edit: Rassen-Autocomplete mit Wiki-Match-Badge
- Social: Post-Bestätigung (Gepostet!-Button, Quick-Mark, Pending-Banner)
- Social: Pflegetipp-Button (allg. + rassenspezifisch)
- Social: Diversitäts-Check, Kategorie-Tagging
- Social: 104 Übungen, Übungsübersicht-Modal
- Admin: Social-Media-Tracking-Sektion
- SW by-v356, APP_VER 343
This commit is contained in:
rene 2026-04-24 20:56:47 +02:00
parent 75615140c4
commit ba5547f993
7 changed files with 797 additions and 9 deletions

View file

@ -28,6 +28,7 @@ class DogCreate(BaseModel):
class DogUpdate(BaseModel):
name: Optional[str] = None
rasse: Optional[str] = None
rasse_id: Optional[int] = None
geburtstag: Optional[str] = None
geschlecht: Optional[str] = None
gewicht_kg: Optional[float] = None
@ -330,3 +331,81 @@ async def report_found(dog_id: int, data: FoundReport = FoundReport()):
})
return {"ok": True}
# ------------------------------------------------------------------
# GET /api/dogs/{id}/pflege — Pflegetipps für diesen Hund
# ------------------------------------------------------------------
@router.get("/{dog_id}/pflege")
async def get_pflege_tipps(dog_id: int, user=Depends(get_current_user)):
import json as _json
with db() as conn:
dog = conn.execute(
"SELECT id, name, rasse, rasse_id FROM dogs WHERE id=? AND user_id=?",
(dog_id, user["id"])
).fetchone()
if not dog:
raise HTTPException(404, "Hund nicht gefunden.")
# Rassen-Infos für Fell-Typ
rasse_info = None
with db() as conn:
if dog["rasse_id"]:
rasse_info = conn.execute(
"SELECT name, groesse, beschreibung FROM wiki_rassen WHERE id=?",
(dog["rasse_id"],)
).fetchone()
elif dog["rasse"]:
rasse_info = conn.execute(
"SELECT name, groesse, beschreibung FROM wiki_rassen WHERE name LIKE ? LIMIT 1",
(f"%{dog['rasse']}%",)
).fetchone()
# Fell-Typ ableiten
fell_filter = None
if rasse_info:
beschr = (rasse_info["beschreibung"] or "").lower()
if any(w in beschr for w in ["lockig", "wellig", "kraus", "pudel", "doodle"]):
fell_filter = "lockig"
elif any(w in beschr for w in ["langhaar", "seidiges", "fließendes", "langes fell"]):
fell_filter = "lang"
elif any(w in beschr for w in ["kurzhaar", "kurzes fell", "glatthaarig"]):
fell_filter = "kurz"
elif rasse_info["groesse"] in ("gross", "sehr_gross"):
fell_filter = "doppel"
with db() as conn:
alle_tipps = conn.execute(
"SELECT * FROM pflege_tipps ORDER BY kategorie, titel"
).fetchall()
# Relevante Tipps: kein Fell-Filter oder passend
from datetime import date
heute_saison = {1:"winter",2:"winter",3:"fruehling",4:"fruehling",5:"fruehling",
6:"sommer",7:"sommer",8:"sommer",9:"herbst",10:"herbst",
11:"herbst",12:"winter"}[date.today().month]
result = []
for t in alle_tipps:
t = dict(t)
# Fell-Filter
if fell_filter and t["fell_typ"] and t["fell_typ"] != "alle":
if fell_filter not in t["fell_typ"].split(","):
continue
t["schritte"] = _json.loads(t["schritte"] or "[]")
t["saisonal_aktuell"] = bool(t["saison"] and heute_saison in t["saison"])
result.append(t)
# Tipp des Tages: erster aktuell-saisonaler oder zufällig deterministisch
from hashlib import md5
day_hash = int(md5(str(date.today()).encode()).hexdigest(), 16)
saisonal = [t for t in result if t["saisonal_aktuell"]]
tipp_des_tages = (saisonal or result)[day_hash % len(saisonal or result)] if result else None
return {
"dog_name": dog["name"],
"rasse_name": rasse_info["name"] if rasse_info else dog["rasse"],
"tipp_des_tages": tipp_des_tages,
"tipps": result,
"kategorien": list(dict.fromkeys(t["kategorie"] for t in result)),
}