Sprint 12: UI-Vereinheitlichung + Läufigkeits-Tracker
- by-tabs/by-tab: einheitliche Tab/Pill-Navigation in allen Seiten - by-section-label, by-toolbar: einheitliche Section-Labels und Toolbars - Design-Tokens: fehlende --c-amber, --c-primary-soft ergänzt, Fallback-Werte entfernt - sitting.js: sitting-layout für konsistentes flush-Layout (wie walks) - Läufigkeits-Tracker: neuer Health-Tab für Hündinnen mit Zyklusvorhersage, Timeline vergangener Läufigkeiten, Erinnerungen und auto-berechnetem Nächst-Datum - emptyState-Bug: icon-Parameter muss SVG sein, nicht Icon-Name (dog/bell/warning gefixt) - SW-Cache: by-v103, APP_VER: 79
This commit is contained in:
parent
32d630d5a1
commit
b58789373c
30 changed files with 4344 additions and 523 deletions
|
|
@ -8,22 +8,38 @@ router = APIRouter()
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _dogs_subquery():
|
||||
"""JSON-Array der Hunde eines Users als Subquery."""
|
||||
return """(
|
||||
SELECT json_group_array(json_object(
|
||||
'id', d.id,
|
||||
'name', d.name,
|
||||
'rasse', d.rasse,
|
||||
'foto_url',d.foto_url
|
||||
))
|
||||
FROM dogs d WHERE d.user_id = u.id
|
||||
)"""
|
||||
|
||||
|
||||
@router.get("/")
|
||||
async def list_friends(user=Depends(get_current_user)):
|
||||
uid = user["id"]
|
||||
dogs_sq = _dogs_subquery()
|
||||
with db() as conn:
|
||||
friends = conn.execute("""
|
||||
friends = conn.execute(f"""
|
||||
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.name AS friend_name,
|
||||
{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
|
||||
WHERE (f.requester_id=? OR f.addressee_id=?) AND f.status='accepted'
|
||||
ORDER BY u.name
|
||||
""", (uid, uid, uid, uid)).fetchall()
|
||||
|
||||
incoming = conn.execute("""
|
||||
SELECT f.id, f.created_at, u.name AS requester_name, u.id AS requester_id
|
||||
incoming = conn.execute(f"""
|
||||
SELECT f.id, f.created_at, u.name AS requester_name, u.id AS requester_id,
|
||||
{dogs_sq} AS dogs_json
|
||||
FROM friendships f
|
||||
JOIN users u ON u.id=f.requester_id
|
||||
WHERE f.addressee_id=? AND f.status='pending'
|
||||
|
|
@ -38,9 +54,26 @@ async def list_friends(user=Depends(get_current_user)):
|
|||
ORDER BY f.created_at DESC
|
||||
""", (uid,)).fetchall()
|
||||
|
||||
import json
|
||||
|
||||
def _parse(rows):
|
||||
result = []
|
||||
for r in rows:
|
||||
d = dict(r)
|
||||
if d.get("dogs_json"):
|
||||
try:
|
||||
d["dogs"] = json.loads(d["dogs_json"])
|
||||
except Exception:
|
||||
d["dogs"] = []
|
||||
else:
|
||||
d["dogs"] = []
|
||||
d.pop("dogs_json", None)
|
||||
result.append(d)
|
||||
return result
|
||||
|
||||
return {
|
||||
"friends": [dict(r) for r in friends],
|
||||
"incoming": [dict(r) for r in incoming],
|
||||
"friends": _parse(friends),
|
||||
"incoming": _parse(incoming),
|
||||
"outgoing": [dict(r) for r in outgoing],
|
||||
}
|
||||
|
||||
|
|
@ -50,9 +83,12 @@ async def search_users(q: str = "", user=Depends(get_current_user)):
|
|||
if len(q.strip()) < 2:
|
||||
return []
|
||||
uid = user["id"]
|
||||
import json
|
||||
with db() as conn:
|
||||
rows = conn.execute("""
|
||||
SELECT u.id, u.name
|
||||
SELECT u.id, u.name,
|
||||
(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
|
||||
WHERE u.id != ?
|
||||
AND u.name LIKE ?
|
||||
|
|
@ -63,7 +99,17 @@ async def search_users(q: str = "", user=Depends(get_current_user)):
|
|||
)
|
||||
LIMIT 20
|
||||
""", (uid, f"%{q.strip()}%", uid, uid)).fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
result = []
|
||||
for r in rows:
|
||||
d = dict(r)
|
||||
try:
|
||||
d["dogs"] = json.loads(d["dogs_json"]) if d.get("dogs_json") else []
|
||||
except Exception:
|
||||
d["dogs"] = []
|
||||
d.pop("dogs_json", None)
|
||||
result.append(d)
|
||||
return result
|
||||
|
||||
|
||||
@router.post("/request/{target_id}", status_code=201)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue