Feature: Abo & Tarif in Einstellungen — Upgrade-UI für Pro + Züchter (SW by-v919)
- /api/me gibt subscription_tier jetzt zurück (fehlte im SELECT) - settings.js: "Pro kommt bald" durch echte Abo-Karte ersetzt - Zeigt aktuellen Tarif mit farbigem Badge (Kostenlos/Pro/Züchter/Admin) - Standard-Nutzer: zwei Upgrade-Buttons (Pro 29€/Jahr, Züchter 49€/Jahr) - Pro-Nutzer: Pro-Badge + optionaler Züchter-Upgrade - Züchter/Admin: Status-Badge, keine Upgrade-Buttons - Upgrade-Modal: Features-Liste + ehrlicher Hinweis auf manuelle Freischaltung + mailto-Button mit vorausgefülltem Betreff und Account-E-Mail - SW by-v919, APP_VER 919
This commit is contained in:
parent
eaa2e02e88
commit
d61fd155c5
6 changed files with 136 additions and 15 deletions
|
|
@ -599,10 +599,10 @@
|
|||
<div id="modal-container"></div>
|
||||
|
||||
<!-- JS: Reihenfolge ist wichtig — erst Basis, dann Features -->
|
||||
<script src="/js/api.js?v=918"></script>
|
||||
<script src="/js/ui.js?v=918"></script>
|
||||
<script src="/js/app.js?v=918"></script>
|
||||
<script src="/js/worlds.js?v=918"></script>
|
||||
<script src="/js/api.js?v=919"></script>
|
||||
<script src="/js/ui.js?v=919"></script>
|
||||
<script src="/js/app.js?v=919"></script>
|
||||
<script src="/js/worlds.js?v=919"></script>
|
||||
|
||||
<!-- Feature-Seiten werden lazy geladen -->
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Router, State-Management, Navigation, Initialisierung.
|
||||
============================================================ */
|
||||
|
||||
const APP_VER = '918'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VER = '919'; // ← 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
|
||||
|
|
|
|||
|
|
@ -77,6 +77,125 @@ window.Page_settings = (() => {
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// ABO & TARIF
|
||||
// ----------------------------------------------------------
|
||||
function _tierCard(u) {
|
||||
const tier = u.subscription_tier || 'standard';
|
||||
const rolle = u.rolle || 'user';
|
||||
const isAdmin = rolle === 'admin' || rolle === 'moderator';
|
||||
const isPro = ['pro','pro_test'].includes(tier);
|
||||
const isBreeder = ['breeder','breeder_test'].includes(tier) || rolle === 'breeder';
|
||||
const isStandard = !isAdmin && !isPro && !isBreeder;
|
||||
|
||||
const _badge = (label, color) =>
|
||||
`<span style="display:inline-block;padding:2px 10px;border-radius:20px;
|
||||
font-size:var(--text-xs);font-weight:700;letter-spacing:.03em;
|
||||
background:${color};color:#fff">${label}</span>`;
|
||||
|
||||
const _upgradeBtn = (id, label, price, color) =>
|
||||
`<button id="${id}"
|
||||
style="flex:1;min-width:130px;padding:var(--space-3) var(--space-2);
|
||||
border-radius:var(--radius-md);border:none;cursor:pointer;
|
||||
background:${color};color:#fff;
|
||||
font-size:var(--text-sm);font-weight:600;
|
||||
display:flex;flex-direction:column;align-items:center;gap:2px">
|
||||
<span>${label}</span>
|
||||
<span style="font-size:var(--text-xs);font-weight:400;opacity:.9">${price}</span>
|
||||
</button>`;
|
||||
|
||||
let statusHtml = '';
|
||||
let actionsHtml = '';
|
||||
|
||||
if (isAdmin) {
|
||||
statusHtml = _badge('Admin', '#6366f1');
|
||||
} else if (isBreeder) {
|
||||
statusHtml = _badge('Züchter aktiv', '#C4843A');
|
||||
} else if (isPro) {
|
||||
statusHtml = _badge('Pro aktiv', '#16a34a');
|
||||
actionsHtml = `
|
||||
<div style="margin-top:var(--space-3);display:flex;gap:var(--space-2);flex-wrap:wrap">
|
||||
${_upgradeBtn('settings-upgrade-breeder-btn','Züchter werden','49 €/Jahr','#C4843A')}
|
||||
</div>`;
|
||||
} else {
|
||||
statusHtml = _badge('Kostenlos', '#888');
|
||||
actionsHtml = `
|
||||
<div style="margin-top:var(--space-3);display:flex;gap:var(--space-2);flex-wrap:wrap">
|
||||
${_upgradeBtn('settings-upgrade-pro-btn','Ban Yaro Pro','29 €/Jahr','#16a34a')}
|
||||
${_upgradeBtn('settings-upgrade-breeder-btn','Züchter','49 €/Jahr','#C4843A')}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="card" style="margin-bottom:var(--space-4)">
|
||||
<div class="by-card-section-header">Abo & Tarif</div>
|
||||
<div style="padding:var(--space-4)">
|
||||
<div style="display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap">
|
||||
<span style="font-size:var(--text-sm);color:var(--c-text-secondary)">Aktueller Tarif:</span>
|
||||
${statusHtml}
|
||||
</div>
|
||||
${actionsHtml}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function _showUpgradeModal(tier) {
|
||||
const isPro = tier === 'pro';
|
||||
const label = isPro ? 'Ban Yaro Pro' : 'Züchter';
|
||||
const price = isPro ? '29 €/Jahr' : '49 €/Jahr';
|
||||
const features = isPro
|
||||
? ['Mehrere Hunde verwalten', 'Ernährungsbereich mit KI-Berater', 'Erweiterte Karten-Layer', 'Alle künftigen Pro-Features']
|
||||
: ['Vollständige Züchter-Plattform', 'Warteliste, Läufigkeit & Trächtigkeit', 'Wurfverwaltung, Stammbaum, IK-Rechner', 'KI-Züchter-Assistent & Datenexport'];
|
||||
|
||||
const featureList = features.map(f =>
|
||||
`<li style="padding:var(--space-1) 0;font-size:var(--text-sm)">✓ ${f}</li>`
|
||||
).join('');
|
||||
|
||||
const subject = encodeURIComponent(`Upgrade auf ${label} — Ban Yaro`);
|
||||
const body = encodeURIComponent(
|
||||
`Hallo,\n\nich möchte meinen Account auf ${label} upgraden.\n\nMein Account: ${_appState.user?.email || ''}\n\nBitte schickt mir die Zahlungsinformationen.\n\nViele Grüße`
|
||||
);
|
||||
const mailHref = `mailto:hallo@banyaro.app?subject=${subject}&body=${body}`;
|
||||
|
||||
UI.modal.open({
|
||||
title: `${label} freischalten`,
|
||||
body: `
|
||||
<div style="padding:var(--space-2) 0">
|
||||
<div style="display:flex;align-items:center;gap:var(--space-3);margin-bottom:var(--space-4)">
|
||||
<div style="font-size:2rem;font-weight:800;color:var(--c-primary)">${price}</div>
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);line-height:1.5">
|
||||
Einmaliger Jahresbeitrag<br>Kündigung jederzeit möglich
|
||||
</div>
|
||||
</div>
|
||||
<ul style="list-style:none;padding:0;margin:0 0 var(--space-4)">
|
||||
${featureList}
|
||||
</ul>
|
||||
<div style="padding:var(--space-3);border-radius:var(--radius-md);
|
||||
background:var(--c-surface-raised,rgba(0,0,0,.04));
|
||||
font-size:var(--text-xs);color:var(--c-text-secondary);line-height:1.6">
|
||||
Aktuell läuft die Freischaltung noch manuell. Schreib uns kurz eine E-Mail —
|
||||
wir schalten deinen Account innerhalb von 24 Stunden frei und schicken
|
||||
dir die Bankverbindung.
|
||||
</div>
|
||||
</div>`,
|
||||
footer: `
|
||||
<button data-modal-close
|
||||
style="padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);
|
||||
border:1.5px solid var(--c-border);background:transparent;
|
||||
color:var(--c-text);font-size:var(--text-sm);cursor:pointer">
|
||||
Abbrechen
|
||||
</button>
|
||||
<a href="${mailHref}"
|
||||
style="display:inline-flex;align-items:center;gap:var(--space-2);
|
||||
padding:var(--space-2) var(--space-4);
|
||||
border-radius:var(--radius-md);border:none;cursor:pointer;
|
||||
background:var(--c-primary);color:#fff;
|
||||
font-size:var(--text-sm);font-weight:600;text-decoration:none">
|
||||
E-Mail senden
|
||||
</a>`
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// RENDER
|
||||
// ----------------------------------------------------------
|
||||
|
|
@ -276,13 +395,6 @@ window.Page_settings = (() => {
|
|||
<span>Feedback geben</span>
|
||||
<span style="margin-left:auto;color:var(--c-text-secondary)">›</span>
|
||||
</div>
|
||||
${!_appState.user?.subscription_tier || _appState.user.subscription_tier === 'standard' || _appState.user.subscription_tier === 'standard_test' ? `
|
||||
<div style="margin:var(--space-3) 0;padding:var(--space-3) var(--space-4);
|
||||
background:rgba(196,132,58,0.1);border-radius:var(--radius-md);
|
||||
font-size:var(--text-xs);color:var(--c-text-secondary)">
|
||||
⭐ <strong>Ban Yaro Pro</strong> kommt bald — mehr Features, mehrere Hunde.
|
||||
</div>
|
||||
` : ''}
|
||||
<div style="padding:var(--space-3) var(--space-4);border-top:1px solid var(--c-border)">
|
||||
<button id="settings-logout-btn"
|
||||
style="width:100%;display:flex;align-items:center;justify-content:center;
|
||||
|
|
@ -316,6 +428,8 @@ window.Page_settings = (() => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
${_tierCard(u)}
|
||||
|
||||
<div class="card" style="margin-bottom:var(--space-4)">
|
||||
<div class="by-card-section-header">
|
||||
App-Einstellungen
|
||||
|
|
@ -829,6 +943,13 @@ window.Page_settings = (() => {
|
|||
}
|
||||
});
|
||||
|
||||
document.getElementById('settings-upgrade-pro-btn')?.addEventListener('click', () => {
|
||||
_showUpgradeModal('pro');
|
||||
});
|
||||
document.getElementById('settings-upgrade-breeder-btn')?.addEventListener('click', () => {
|
||||
_showUpgradeModal('breeder');
|
||||
});
|
||||
|
||||
document.getElementById('settings-worlds-btn')?.addEventListener('click', () => {
|
||||
if (window.Worlds?._openConfigModal) window.Worlds._openConfigModal();
|
||||
else if (window.Worlds) window.Worlds.openConfig?.();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Offline-Cache + Push Notifications + Tile-Cache
|
||||
============================================================ */
|
||||
|
||||
const CACHE_VERSION = 'by-v918';
|
||||
const CACHE_VERSION = 'by-v919';
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue