Compare commits

..

20 commits

Author SHA1 Message Date
07db68aea2 Fix: Geburtstag aller Hunde + Kotbeutel-Stationen in Stats (SW by-v962)
- worlds.js: bdayDog = _dogs.find(...) — Geburtstag gilt für alle Hunde, nicht nur den aktiven
- Banner, KI-Call, "Was hat sich X gewünscht?" nutzen bdayDog.name
- stats.py: kotbeutel-Count aus user_map_pois WHERE type='kotbeutel'
- landing: Stats-Band 5. Kachel "Kotbeutel-Stationen"
2026-05-14 22:00:52 +02:00
ebff9d820d Merge branch 'develop' 2026-05-14 19:59:30 +02:00
dc09b09cc3 Merge branch 'develop' 2026-05-14 17:19:05 +02:00
cd3e3bdbf6 Merge branch 'develop' 2026-05-14 17:01:46 +02:00
86c5400c2e Merge branch 'develop' 2026-05-14 16:54:59 +02:00
8aa7feb91e Merge branch 'develop' 2026-05-14 16:37:47 +02:00
ea655590f7 Merge branch 'develop' 2026-05-14 15:04:11 +02:00
0069454b24 Merge branch 'develop' 2026-05-14 13:46:11 +02:00
c50e43201c Merge branch 'develop' 2026-05-14 13:26:38 +02:00
24217f81d5 Merge branch 'develop' 2026-05-14 13:20:11 +02:00
29e39ee14a Merge branch 'develop' 2026-05-14 13:17:23 +02:00
d597031135 Merge branch 'develop' 2026-05-14 13:08:52 +02:00
f42f181e44 Merge branch 'develop' 2026-05-14 13:04:18 +02:00
33713ad935 Release: Preismodell live 2026-05-14 09:31:59 +02:00
3263fd9939 Fix: UMAMI_URL docker-compose 2026-05-14 09:24:08 +02:00
5e014a981b Fix: Züchter Icon Kontrast maximal 2026-05-14 09:19:05 +02:00
e7c49e52f9 Fix: Züchter Icon Kontrast 2026-05-14 09:10:05 +02:00
e9b67e371c Release: Landing-Page Dual-Audience (Hundebesitzer + Züchter), Verzahnungs-Section 2026-05-14 08:45:11 +02:00
9cf3b3f0cb Fix: /zuechter Staging-Redirect zu Production 2026-05-13 22:34:25 +02:00
5d60b6c841 Release: Züchter-Sprint — Läufigkeit, Warteliste, Privater-Header, Wurfbörse, Z-Badge (by-v918) 2026-05-13 22:22:41 +02:00
6 changed files with 28 additions and 18 deletions

View file

@ -406,7 +406,7 @@ async def serve_media(path: str, request: _Request):
raise _HE(404, "Nicht gefunden.")
return _media_response(filepath)
APP_VER = "961" # muss mit APP_VER in app.js übereinstimmen
APP_VER = "962" # muss mit APP_VER in app.js übereinstimmen
@app.get("/.well-known/assetlinks.json")
async def assetlinks():

View file

@ -30,19 +30,23 @@ async def public_stats():
if _pub_cache["data"] and now - _pub_cache["ts"] < _PUB_TTL:
return _pub_cache["data"]
with db() as conn:
users = conn.execute("SELECT COUNT(*) FROM users").fetchone()[0]
dogs = conn.execute("SELECT COUNT(*) FROM dogs").fetchone()[0]
km = conn.execute(
users = conn.execute("SELECT COUNT(*) FROM users").fetchone()[0]
dogs = conn.execute("SELECT COUNT(*) FROM dogs").fetchone()[0]
km = conn.execute(
"SELECT ROUND(COALESCE(SUM(distanz_km),0),0) FROM routes"
).fetchone()[0]
posts = conn.execute("SELECT COUNT(*) FROM forum_posts").fetchone()[0]
diary = conn.execute("SELECT COUNT(*) FROM diary").fetchone()[0]
posts = conn.execute("SELECT COUNT(*) FROM forum_posts").fetchone()[0]
diary = conn.execute("SELECT COUNT(*) FROM diary").fetchone()[0]
kotbeutel = conn.execute(
"SELECT COUNT(*) FROM user_map_pois WHERE type='kotbeutel'"
).fetchone()[0]
data = {
"users": users,
"dogs": dogs,
"km": int(km or 0),
"forum_posts": posts,
"diary_entries": diary,
"kotbeutel": kotbeutel,
}
_pub_cache["data"] = data
_pub_cache["ts"] = now

View file

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung.
============================================================ */
const APP_VER = '961'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VER = '962'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt
const IS_STAGING = location.hostname === 'staging.banyaro.app';
// Cache-Bust-Parameter nach Update-Reload sofort entfernen

View file

@ -1342,8 +1342,9 @@ window.Worlds = (() => {
if (mmdd === `${mt}-${dt}`) return 'tomorrow';
return null;
}
const bday = _birthdayState(dog.geburtstag);
const bdayYear = dog.geburtstag ? new Date().getFullYear() - parseInt(dog.geburtstag.slice(0, 4)) : null;
const bdayDog = _dogs.find(d => _birthdayState(d.geburtstag)) || null;
const bday = bdayDog ? _birthdayState(bdayDog.geburtstag) : null;
const bdayYear = bdayDog?.geburtstag ? new Date().getFullYear() - parseInt(bdayDog.geburtstag.slice(0, 4)) : null;
const [streakRes, diaryRes] = await Promise.allSettled([
_cachedGet(`streak_${dog.id}`, `/streak/${dog.id}`),
@ -1428,8 +1429,8 @@ window.Worlds = (() => {
</div>
<div style="font-weight:800;font-size:var(--text-sm);color:#fff;letter-spacing:0.01em">
${bday === 'today'
? `Alles Gute zum ${bdayYear}. Geburtstag, ${_esc(dog.name)}!`
: `Morgen hat ${_esc(dog.name)} Geburtstag!`}
? `Alles Gute zum ${bdayYear}. Geburtstag, ${_esc(bdayDog.name)}!`
: `Morgen hat ${_esc(bdayDog.name)} Geburtstag!`}
</div>
<div style="display:flex;gap:8px;align-items:center">
<svg class="ph-icon bday-fw3" style="width:1rem;height:1rem;color:#e8c96e"><use href="/icons/phosphor.svg#sparkle"></use></svg>
@ -1443,7 +1444,7 @@ window.Worlds = (() => {
</div>` : ''}
<div style="display:flex;align-items:center;gap:4px;font-size:10px;color:rgba(196,132,58,0.9);font-weight:700;margin-top:2px">
<svg class="ph-icon" style="width:11px;height:11px"><use href="/icons/phosphor.svg#magic-wand"></use></svg>
${bday === 'today' ? 'Was hat sich Ban Yaro gewünscht?' : 'KI-Überraschungsideen'}
${bday === 'today' ? `Was hat sich ${_esc(bdayDog.name)} gewünscht?` : 'KI-Überraschungsideen'}
</div>
</div>
${bday === 'today' && new Date().getHours() >= 18 ? `
@ -1563,10 +1564,10 @@ window.Worlds = (() => {
try {
const res = await API.post('/ki/geburtstag', {
dog_id: dog.id,
name: dog.name,
rasse: dog.rasse || null,
alter: dog.alter_jahre ? Math.round(dog.alter_jahre) : null,
dog_id: bdayDog.id,
name: bdayDog.name,
rasse: bdayDog.rasse || null,
alter: bdayDog.alter_jahre ? Math.round(bdayDog.alter_jahre) : null,
mode: bdayMode,
});
const body = ov.querySelector('#bday-ki-body');

View file

@ -824,6 +824,10 @@
<div class="stats-band-num" id="big-posts"></div>
<div class="stats-band-label">Forum-Beiträge</div>
</div>
<div class="stats-band-item fade-up">
<div class="stats-band-num" id="big-kotbeutel"></div>
<div class="stats-band-label">Kotbeutel-Stationen</div>
</div>
</div>
</div>
</section>
@ -1579,7 +1583,8 @@
set('big-users', d.users);
set('big-dogs', d.dogs);
set('big-km', d.km);
set('big-posts', d.forum_posts);
set('big-posts', d.forum_posts);
set('big-kotbeutel', d.kotbeutel);
var heroStats = document.getElementById('hero-stats');
if (heroStats && d.users > 0) heroStats.style.display = 'flex';

View file

@ -3,7 +3,7 @@
Offline-Cache + Push Notifications + Tile-Cache
============================================================ */
const CACHE_VERSION = 'by-v961';
const CACHE_VERSION = 'by-v962';
const CACHE_STATIC = `${CACHE_VERSION}-static`;
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache