Feature: Sprint31 — 9 Features merged (Streak, Ausgaben, KI-Tierarzt, Rückrufe, Adoption, Vet+Befunde, Hundepass, Playdate, Rassenerkennung)
- Trainings-Streak: streak.py, DB training_streaks, Scheduler 19:00, Widget in welcome.js, Ping in uebungen.js
- Ausgaben-Tracker: expenses.py, expenses.js, DB expenses-Tabelle
- KI-Tierarztfragen: ki.py /tierarzt, health.js Button+Modal, DB ki_tierarzt_log
- Rückruf-Alarm: recalls.py, recalls.js, DB feed_recalls, Scheduler 08:00 RASFF
- Adoption: adoption.py, adoption.js, DB adoption_cache
- Tierarzt-Favorit + Befunde: tieraerzte.py /my-favorite+/favorite, health_docs.py, health.js, api.js, DB favorite_vets+health_documents
- Digitaler Hundepass: passport.py, dog-profile.js, main.py /pass/{token}, DB vaccinations+medications+dog_passport_meta+passport_shares, requirements.txt fpdf2
- Playdate-Matching: playdate.py, playdate.js, DB playdate_listings+playdate_requests
- Rassen-Erkennung: ki.py /rasse-erkennung (Claude Vision), dog-profile.js+wiki.js, CSS .rasse-result-card, DB ki_rasse_log
This commit is contained in:
parent
031c6028ac
commit
742ad189e8
26 changed files with 5734 additions and 27 deletions
|
|
@ -63,15 +63,68 @@ def _fmt_opening_hours(raw: str | None) -> str | None:
|
|||
return result
|
||||
|
||||
|
||||
@router.get("/my-favorite")
|
||||
async def get_my_favorite(user=Depends(get_current_user)):
|
||||
"""Favoriten-Tierarzt des Users (oder null)."""
|
||||
with db() as conn:
|
||||
row = conn.execute(
|
||||
"""SELECT t.* FROM tieraerzte t
|
||||
JOIN favorite_vets fv ON fv.vet_id = t.id
|
||||
WHERE fv.user_id = ?
|
||||
LIMIT 1""",
|
||||
(user["id"],)
|
||||
).fetchone()
|
||||
if not row:
|
||||
return None
|
||||
return dict(row)
|
||||
|
||||
|
||||
@router.post("/{vet_id}/favorite")
|
||||
async def toggle_favorite(vet_id: int, user=Depends(get_current_user)):
|
||||
"""Tierarzt als Favorit setzen oder entfernen (toggle). Gibt {is_favorite: bool} zurück."""
|
||||
with db() as conn:
|
||||
vet = conn.execute(
|
||||
"SELECT id FROM tieraerzte WHERE id=?", (vet_id,)
|
||||
).fetchone()
|
||||
if not vet:
|
||||
raise HTTPException(404, "Tierarzt nicht gefunden.")
|
||||
|
||||
existing = conn.execute(
|
||||
"SELECT 1 FROM favorite_vets WHERE user_id=? AND vet_id=?",
|
||||
(user["id"], vet_id)
|
||||
).fetchone()
|
||||
|
||||
if existing:
|
||||
conn.execute(
|
||||
"DELETE FROM favorite_vets WHERE user_id=? AND vet_id=?",
|
||||
(user["id"], vet_id)
|
||||
)
|
||||
return {"is_favorite": False}
|
||||
else:
|
||||
conn.execute(
|
||||
"INSERT INTO favorite_vets (user_id, vet_id) VALUES (?, ?)",
|
||||
(user["id"], vet_id)
|
||||
)
|
||||
return {"is_favorite": True}
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def list_tieraerzte(user=Depends(get_current_user)):
|
||||
"""Alle Tierärzte des Users — aktive zuerst, dann inaktive."""
|
||||
"""Alle Tierärzte des Users — aktive zuerst, dann inaktive. Enthält is_favorite."""
|
||||
with db() as conn:
|
||||
rows = conn.execute(
|
||||
"SELECT * FROM tieraerzte WHERE user_id=? ORDER BY aktiv DESC, name",
|
||||
(user["id"],)
|
||||
).fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
favs = {r["vet_id"] for r in conn.execute(
|
||||
"SELECT vet_id FROM favorite_vets WHERE user_id=?", (user["id"],)
|
||||
).fetchall()}
|
||||
result = []
|
||||
for r in rows:
|
||||
d = dict(r)
|
||||
d["is_favorite"] = r["id"] in favs
|
||||
result.append(d)
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/osm-nearby")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue