diff --git a/backend/routes/auth.py b/backend/routes/auth.py index c0e39ce..32d5c6c 100644 --- a/backend/routes/auth.py +++ b/backend/routes/auth.py @@ -149,6 +149,24 @@ async def logout(response: Response): return {"ok": True} +_REFERRAL_TIERS = [ + (50, 50), + (20, 30), + (10, 20), +] + +def _referral_tier(count: int): + for threshold, discount in _REFERRAL_TIERS: + if count >= threshold: + return discount + return 0 + +def _referral_next(count: int): + for threshold, discount in reversed(_REFERRAL_TIERS): + if count < threshold: + return {"count": threshold, "discount": discount} + return None # Maximalstufe erreicht + @router.get("/referral") async def get_referral_info(user=Depends(get_current_user)): with db() as conn: @@ -162,11 +180,14 @@ async def get_referral_info(user=Depends(get_current_user)): if not code: code = _gen_referral_code() conn.execute("UPDATE users SET referral_code=? WHERE id=?", (code, user['id'])) - base = os.getenv("APP_URL", "https://banyaro.app") + count = row["count"] if row else 0 + base = os.getenv("APP_URL", "https://banyaro.app") return { - "code": code, - "count": row["count"] if row else 0, - "link": f"{base}/?ref={code}", + "code": code, + "count": count, + "link": f"{base}/?ref={code}", + "discount_pct": _referral_tier(count), + "next_tier": _referral_next(count), } diff --git a/backend/static/js/app.js b/backend/static/js/app.js index bb05232..8522a64 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '493'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '494'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.0.0'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; diff --git a/backend/static/js/pages/settings.js b/backend/static/js/pages/settings.js index 0dca87e..f415717 100644 --- a/backend/static/js/pages/settings.js +++ b/backend/static/js/pages/settings.js @@ -1100,50 +1100,88 @@ window.Page_settings = (() => { if (!el) return; try { const r = await API.auth.referral(); + + const TIERS = [{t:10,d:20},{t:20,d:30},{t:50,d:50}]; + const currentTier = r.discount_pct; + const next = r.next_tier; + + // Fortschrittsbalken-Berechnung + let barPct = 0, barLabel = ''; + if (!next) { + barPct = 100; + barLabel = 'Maximaler Rabatt erreicht!'; + } else { + const prevT = TIERS.find(t => t.d === currentTier)?.t || 0; + barPct = Math.round(((r.count - prevT) / (next.count - prevT)) * 100); + barLabel = `Noch ${next.count - r.count} ${next.count - r.count === 1 ? 'Person' : 'Personen'} bis ${next.discount}% Rabatt`; + } + el.innerHTML = ` + +
+ Der Rabatt gilt für dich — sobald Bezahlfunktionen aktiv sind, dauerhaft und automatisch. +
`; + document.getElementById('ref-share-btn')?.addEventListener('click', async () => { + const msg = `Ich bin bei Ban Yaro — der coolsten Hunde-App! Registrier dich mit meinem Link und wir wachsen zusammen 🐾`; if (navigator.share) { - navigator.share({ title: 'Ban Yaro — Die Hunde-App', text: 'Schau dir Ban Yaro an!', url: r.link }).catch(() => {}); + navigator.share({ title: 'Ban Yaro', text: msg, url: r.link }).catch(() => {}); } else { await navigator.clipboard.writeText(r.link); UI.toast.success('Link kopiert!'); } }); - // QR-Code rendern (Bibliothek lazy laden) + await App.loadScript('/js/qrcode.min.js'); new QRCode(document.getElementById('ref-qr'), { - text: r.link, - width: 160, - height: 160, - colorDark: '#000000', - colorLight: '#ffffff', + text: r.link, width: 140, height: 140, + colorDark: '#000000', colorLight: '#ffffff', correctLevel: QRCode.CorrectLevel.H, }); } catch { el.innerHTML = ''; } diff --git a/backend/static/sw.js b/backend/static/sw.js index 4f5fbd6..2cae1ed 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v516'; +const CACHE_VERSION = 'by-v517'; 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