Feature: /partner Influencer-Landingpage — Live-Counter, Vorteile, Ranking, CTA, SW by-v564

This commit is contained in:
rene 2026-04-30 17:39:55 +02:00
parent 128aee52de
commit fd97145507
3 changed files with 204 additions and 2 deletions

View file

@ -1400,6 +1400,208 @@ async def knigge_page():
return HTMLResponse(content=html, headers={"Cache-Control": "max-age=7200"})
# ------------------------------------------------------------------
# /partner — Influencer-Landingpage
# ------------------------------------------------------------------
@app.get("/partner")
async def partner_landing():
from fastapi.responses import HTMLResponse
from database import db as _db
with _db() as conn:
total_founders = conn.execute("SELECT COUNT(*) FROM users WHERE is_founder=1").fetchone()[0]
partners = conn.execute(
"""SELECT label, uses FROM partner_codes WHERE grants_founder=1 ORDER BY uses DESC LIMIT 5"""
).fetchall()
open_slots = max(0, 100 - total_founders)
partner_rows = ''.join([
f'<div class="pl-partner-row"><span class="pl-partner-name">{p["label"]}</span>'
f'<span class="pl-partner-score">{p["uses"]} Gründer</span></div>'
for p in partners
]) or '<div style="color:#94a3b8;font-size:0.85rem">Noch keine Partner aktiv — sei der Erste.</div>'
html = f"""<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ban Yaro Partner Werde Teil der ersten 100</title>
<meta name="description" content="Werde Ban Yaro Partner. Gib deiner Community exklusive Gründer-Lizenzen — nur 100 Plätze weltweit, nie wieder erhältlich.">
<meta property="og:title" content="Ban Yaro Partner">
<meta property="og:description" content="Gib deiner Community etwas Besonderes. 100 Gründer-Plätze. Exklusiv. Für immer.">
<meta property="og:image" content="https://banyaro.app/icons/icon-512.png">
<style>
*,*::before,*::after{{box-sizing:border-box;margin:0;padding:0}}
body{{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#faf9f7;color:#1a1a1a;line-height:1.6}}
a{{color:#C4843A;text-decoration:none}}
.pl-wrap{{max-width:680px;margin:0 auto;padding:24px 20px 80px}}
/* Hero */
.pl-hero{{text-align:center;padding:60px 0 48px;border-bottom:1px solid #e8e4df}}
.pl-logo{{width:72px;height:72px;border-radius:18px;margin:0 auto 24px;display:block}}
.pl-eyebrow{{font-size:0.75rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:#C4843A;margin-bottom:12px}}
.pl-h1{{font-size:clamp(1.8rem,5vw,2.8rem);font-weight:800;line-height:1.15;color:#111;margin-bottom:16px}}
.pl-sub{{font-size:1.05rem;color:#555;max-width:480px;margin:0 auto 32px}}
.pl-cta{{display:inline-block;background:#C4843A;color:#fff;font-weight:700;font-size:1rem;padding:14px 32px;border-radius:999px;text-decoration:none;transition:opacity .15s}}
.pl-cta:hover{{opacity:.88}}
/* Slot-Counter */
.pl-counter{{background:#fff;border:1px solid #e8e4df;border-radius:16px;padding:28px 24px;margin:40px 0;text-align:center}}
.pl-counter-num{{font-size:3rem;font-weight:800;color:#C4843A;line-height:1}}
.pl-counter-label{{font-size:0.85rem;color:#888;margin-top:4px}}
.pl-bar-wrap{{background:#f0ece8;border-radius:999px;height:10px;margin:16px 0 8px;overflow:hidden}}
.pl-bar{{background:linear-gradient(90deg,#C4843A,#e0a870);height:100%;border-radius:999px;width:{min(100, round(total_founders/100*100))}%}}
.pl-bar-labels{{display:flex;justify-content:space-between;font-size:0.75rem;color:#aaa}}
/* Vorteile */
.pl-benefits{{margin:40px 0}}
.pl-section-title{{font-size:1.1rem;font-weight:700;margin-bottom:20px;color:#111}}
.pl-benefit{{display:flex;gap:16px;align-items:flex-start;padding:16px 0;border-bottom:1px solid #f0ece8}}
.pl-benefit:last-child{{border-bottom:none}}
.pl-benefit-icon{{font-size:1.6rem;flex-shrink:0;width:40px;text-align:center}}
.pl-benefit-title{{font-weight:700;font-size:0.95rem;margin-bottom:2px}}
.pl-benefit-text{{font-size:0.88rem;color:#555}}
/* Wie es funktioniert */
.pl-steps{{margin:40px 0}}
.pl-step{{display:flex;gap:16px;align-items:flex-start;margin-bottom:24px}}
.pl-step-num{{width:32px;height:32px;border-radius:50%;background:#C4843A;color:#fff;font-weight:800;font-size:0.9rem;display:flex;align-items:center;justify-content:center;flex-shrink:0}}
.pl-step-text{{padding-top:4px;font-size:0.92rem;color:#333}}
.pl-step-text strong{{display:block;font-weight:700;color:#111;margin-bottom:2px}}
/* Leaderboard */
.pl-leaderboard{{background:#fff;border:1px solid #e8e4df;border-radius:16px;padding:24px;margin:40px 0}}
.pl-partner-row{{display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid #f5f3f0;font-size:0.9rem}}
.pl-partner-row:last-child{{border-bottom:none}}
.pl-partner-name{{font-weight:600}}
.pl-partner-score{{color:#C4843A;font-weight:700}}
/* Kontakt */
.pl-contact{{background:linear-gradient(135deg,#C4843A,#d4944a);border-radius:20px;padding:40px 32px;text-align:center;color:#fff;margin:40px 0}}
.pl-contact h2{{font-size:1.5rem;font-weight:800;margin-bottom:12px}}
.pl-contact p{{font-size:0.95rem;opacity:.9;margin-bottom:24px;max-width:400px;margin-left:auto;margin-right:auto}}
.pl-contact-btn{{display:inline-block;background:#fff;color:#C4843A;font-weight:700;padding:12px 28px;border-radius:999px;font-size:0.95rem}}
/* Footer */
.pl-footer{{text-align:center;font-size:0.78rem;color:#aaa;padding-top:32px;border-top:1px solid #f0ece8}}
</style>
</head>
<body>
<div class="pl-wrap">
<!-- Hero -->
<div class="pl-hero">
<img src="/icons/icon-192.png" alt="Ban Yaro" class="pl-logo">
<div class="pl-eyebrow">Ban Yaro · Influencer-Programm</div>
<h1 class="pl-h1">Gib deiner Community<br>etwas für immer.</h1>
<p class="pl-sub">100 Gründer-Plätze. Weltweit. Nie wieder erhältlich.<br>Als Partner bringst du deine Follower nach vorne und steigst im Ranking auf.</p>
<a href="mailto:partner@banyaro.app" class="pl-cta">Jetzt Partner werden</a>
</div>
<!-- Slot-Counter -->
<div class="pl-counter">
<div class="pl-counter-num">{open_slots}</div>
<div class="pl-counter-label">Gründer-Plätze noch frei (von 100)</div>
<div class="pl-bar-wrap"><div class="pl-bar"></div></div>
<div class="pl-bar-labels"><span>0</span><span>{total_founders} vergeben</span><span>100</span></div>
</div>
<!-- Vorteile -->
<div class="pl-benefits">
<div class="pl-section-title">Was du und deine Community bekommen</div>
<div class="pl-benefit">
<div class="pl-benefit-icon">🏆</div>
<div>
<div class="pl-benefit-title">Gründer-Lizenz für deine Follower</div>
<div class="pl-benefit-text">Jeder der sich mit deinem Code registriert bekommt einen der 100 Gründer-Plätze mit einer nummerierten Badge <strong>Gründer #N"</strong> die dauerhaft im Profil und im Forum sichtbar ist. Nie wieder erhältlich.</div>
</div>
</div>
<div class="pl-benefit">
<div class="pl-benefit-icon">🤝</div>
<div>
<div class="pl-benefit-title">Dein persönlicher Partner-Code</div>
<div class="pl-benefit-text">Du bekommst einen eigenen Code (z.B. <strong>HUNDEBLOG</strong>). Follower die sich damit registrieren werden automatisch Gründer du siehst in Echtzeit wie viele du gebracht hast.</div>
</div>
</div>
<div class="pl-benefit">
<div class="pl-benefit-icon">📊</div>
<div>
<div class="pl-benefit-title">Öffentliches Partner-Ranking</div>
<div class="pl-benefit-text">Auf der <a href="/app#gruender">Gründer-Seite</a> siehen alle wer die meisten Gründer gebracht hat. Das Ranking motiviert deine Follower mitzumachen und stärkt deine Position gegenüber anderen Influencern.</div>
</div>
</div>
<div class="pl-benefit">
<div class="pl-benefit-icon">💜</div>
<div>
<div class="pl-benefit-title">Partner-Badge für dich</div>
<div class="pl-benefit-text">Du selbst bekommst ein <strong>Partner"</strong>-Badge in deinem Profil — sichtbar für alle Nutzer der App.</div>
</div>
</div>
<div class="pl-benefit">
<div class="pl-benefit-icon">🎁</div>
<div>
<div class="pl-benefit-title">Lebenslang kostenlos für immer</div>
<div class="pl-benefit-text">Gründer zahlen nie für Premium-Features egal was wir in Zukunft einführen. Das ist ein echtes Dankeschön für die Pioniere.</div>
</div>
</div>
</div>
<!-- Wie es funktioniert -->
<div class="pl-steps">
<div class="pl-section-title">Wie es funktioniert</div>
<div class="pl-step">
<div class="pl-step-num">1</div>
<div class="pl-step-text"><strong>Kontakt aufnehmen</strong>Schreib uns kurz an partner@banyaro.app wir richten deinen persönlichen Code ein.</div>
</div>
<div class="pl-step">
<div class="pl-step-num">2</div>
<div class="pl-step-text"><strong>Code teilen</strong>Du postest deinen Code in Story, Reel oder Post deine Follower registrieren sich auf banyaro.app.</div>
</div>
<div class="pl-step">
<div class="pl-step-num">3</div>
<div class="pl-step-text"><strong>Gründer werden</strong>Jede Registrierung mit deinem Code sichert automatisch einen der 100 Gründer-Plätze. Du siehst deinen Fortschritt in Echtzeit.</div>
</div>
<div class="pl-step">
<div class="pl-step-num">4</div>
<div class="pl-step-text"><strong>Im Ranking aufsteigen</strong>Je mehr Gründer du bringst, desto höher dein Platz auf der öffentlichen Gründer-Seite.</div>
</div>
</div>
<!-- Leaderboard -->
{'<div class="pl-leaderboard"><div class="pl-section-title" style="margin-bottom:16px">🏅 Aktuelles Partner-Ranking</div>' + partner_rows + '</div>' if partners else ''}
<!-- Was ist Ban Yaro -->
<div style="background:#fff;border:1px solid #e8e4df;border-radius:16px;padding:28px 24px;margin:40px 0">
<div class="pl-section-title">Was ist Ban Yaro?</div>
<p style="font-size:0.9rem;color:#555;margin-bottom:12px">Ban Yaro ist die Hunde-App für alles was Halter brauchen Tagebuch, Gesundheit, Routen, Giftköder-Alarm, Community. Kostenlos, ohne App Store, direkt im Browser oder als PWA.</p>
<a href="https://banyaro.app" style="font-weight:700;color:#C4843A;font-size:0.9rem">banyaro.app entdecken </a>
</div>
<!-- CTA -->
<div class="pl-contact">
<h2>Bereit dabei zu sein?</h2>
<p>Schreib uns kurz wer du bist und auf welchem Kanal du aktiv bist wir richten deinen Code binnen 24h ein.</p>
<a href="mailto:partner@banyaro.app?subject=Ban Yaro Partner&body=Hallo,%0A%0Aich bin interessiert am Ban Yaro Partner-Programm.%0A%0AKanal / Reichweite:%0A%0AViele Grüße" class="pl-contact-btn">📧 partner@banyaro.app</a>
</div>
<!-- Footer -->
<div class="pl-footer">
<a href="https://banyaro.app">banyaro.app</a> ·
<a href="/impressum">Impressum</a> ·
<a href="/datenschutz">Datenschutz</a>
</div>
</div>
</body>
</html>"""
return HTMLResponse(content=html, headers={"Cache-Control": "no-cache"})
# SPA Fallback — ALLE nicht-API-Routen gehen zur index.html
@app.get("/{full_path:path}")
async def spa_fallback(full_path: str):

View file

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung.
============================================================ */
const APP_VER = '540'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VER = '541'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.1.4'; // ← semantische Version, wird bei make release gesetzt
const IS_STAGING = location.hostname === 'staging.banyaro.app';

View file

@ -3,7 +3,7 @@
Offline-Cache + Push Notifications + Tile-Cache
============================================================ */
const CACHE_VERSION = 'by-v563';
const CACHE_VERSION = 'by-v564';
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