Landing Page: neue Welcome-Seite für nicht-eingeloggte Besucher — SW by-v444, APP_VER 423
Hero mit Farbverlauf, großer Headline, primärer CTA-Button. 4 Feature-Abschnitte (Tagebuch, Gesundheit, Community, Training). Privacy-Block in Primärfarbe. Feature-Grid als "und noch mehr". Zweiter CTA am Ende. Eingeloggte sehen weiterhin die kompakte Ansicht.
This commit is contained in:
parent
9cb4a16cc2
commit
f3742ed7a9
3 changed files with 383 additions and 82 deletions
|
|
@ -3,7 +3,7 @@
|
||||||
Router, State-Management, Navigation, Initialisierung.
|
Router, State-Management, Navigation, Initialisierung.
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const APP_VER = '422'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
const APP_VER = '423'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||||
|
|
||||||
const App = (() => {
|
const App = (() => {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,34 +53,200 @@ window.Page_welcome = (() => {
|
||||||
|| window.navigator.standalone === true;
|
|| window.navigator.standalone === true;
|
||||||
const user = _appState?.user;
|
const user = _appState?.user;
|
||||||
|
|
||||||
|
_injectStyles();
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
_renderLoggedIn(isInstalled);
|
||||||
|
} else {
|
||||||
|
_renderLanding(isInstalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
_bindEvents();
|
||||||
|
_pulseMenuBtn();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
// LANDING PAGE — nicht eingeloggte Besucher
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
function _renderLanding(isInstalled) {
|
||||||
|
const hasPrompt = !!App.getInstallPrompt();
|
||||||
|
|
||||||
|
_container.innerHTML = `
|
||||||
|
<div class="wc-landing">
|
||||||
|
|
||||||
|
<!-- ── Hero ─────────────────────────────────────────── -->
|
||||||
|
<div class="wc-lhero">
|
||||||
|
<img src="/icons/icon-180.png" alt="Ban Yaro" class="wc-lhero-icon">
|
||||||
|
<h1 class="wc-lhero-headline">Alles für<br>deinen Hund.</h1>
|
||||||
|
<p class="wc-lhero-sub">
|
||||||
|
Tagebuch, Gesundheit, Karte, Community —<br>
|
||||||
|
auf einem Server in Deutschland. Kostenlos.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="wc-lhero-cta">
|
||||||
|
${hasPrompt ? `
|
||||||
|
<button class="btn wc-btn-hero" id="welcome-install-hero-btn">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#download-simple"></use></svg>
|
||||||
|
App installieren
|
||||||
|
</button>
|
||||||
|
` : `
|
||||||
|
<button class="btn wc-btn-hero" id="welcome-register-btn">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#paw-print"></use></svg>
|
||||||
|
Kostenlos loslegen
|
||||||
|
</button>
|
||||||
|
`}
|
||||||
|
<button class="btn btn-ghost wc-btn-login" id="welcome-login-btn">
|
||||||
|
Schon dabei? Anmelden
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wc-trust-strip">
|
||||||
|
<span>
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#check-circle"></use></svg>
|
||||||
|
Kostenlos
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#device-mobile"></use></svg>
|
||||||
|
Kein App Store
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#shield-check"></use></svg>
|
||||||
|
Daten in Deutschland
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── Feature 1: Tagebuch ───────────────────────────── -->
|
||||||
|
<div class="wc-feature wc-feature--a">
|
||||||
|
<div class="wc-feature-icon">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#book-open"></use></svg>
|
||||||
|
</div>
|
||||||
|
<div class="wc-feature-text">
|
||||||
|
<h2>Tagebuch & Erinnerungen</h2>
|
||||||
|
<p>Halte jeden gemeinsamen Moment fest — Fotos, Einträge, Stimmungen. Nur für dich, privat und sicher.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── Feature 2: Gesundheit ─────────────────────────── -->
|
||||||
|
<div class="wc-feature wc-feature--b">
|
||||||
|
<div class="wc-feature-icon">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>
|
||||||
|
</div>
|
||||||
|
<div class="wc-feature-text">
|
||||||
|
<h2>Gesundheit im Blick</h2>
|
||||||
|
<p>Impfungen, Gewicht, Tierarzttermine — alles an einem Ort. Du siehst immer, wann was ansteht.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── Feature 3: Community ──────────────────────────── -->
|
||||||
|
<div class="wc-feature wc-feature--c">
|
||||||
|
<div class="wc-feature-icon">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#map-trifold"></use></svg>
|
||||||
|
</div>
|
||||||
|
<div class="wc-feature-text">
|
||||||
|
<h2>Community vor Ort</h2>
|
||||||
|
<p>Giftköder-Warnungen, Gassi-Treffen, Events — was in deiner Gegend gerade passiert.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── Feature 4: Training ──────────────────────────── -->
|
||||||
|
<div class="wc-feature wc-feature--d">
|
||||||
|
<div class="wc-feature-icon">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#target"></use></svg>
|
||||||
|
</div>
|
||||||
|
<div class="wc-feature-text">
|
||||||
|
<h2>Training & KI-Trainer</h2>
|
||||||
|
<p>Über 100 Übungen mit Schritt-für-Schritt-Anleitungen. Mit KI-Unterstützung, die deinen Hund kennt.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── Privacy Block ─────────────────────────────────── -->
|
||||||
|
<div class="wc-privacy">
|
||||||
|
<div class="wc-privacy-icon">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#shield-check"></use></svg>
|
||||||
|
</div>
|
||||||
|
<h2 class="wc-privacy-title">Deine Daten gehören dir.</h2>
|
||||||
|
<p class="wc-privacy-sub">
|
||||||
|
Kein Facebook. Kein Google. Keine Werbung.<br>
|
||||||
|
Ban Yaro läuft auf einem eigenen Server in Deutschland —
|
||||||
|
dein Tagebuch, deine Routen, deine Gesundheitsdaten
|
||||||
|
bleiben privat.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── Und noch mehr ─────────────────────────────────── -->
|
||||||
|
<div class="wc-more">
|
||||||
|
<p class="wc-more-label">Und noch viel mehr</p>
|
||||||
|
<div class="wc-grid">
|
||||||
|
${FEATURES.map(f => `
|
||||||
|
<div class="wc-tile wc-tile--static">
|
||||||
|
<div class="wc-tile-icon">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#${f.icon}"></use></svg>
|
||||||
|
</div>
|
||||||
|
<span class="wc-tile-label">${f.label}</span>
|
||||||
|
</div>
|
||||||
|
`).join('')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── Bottom CTA ────────────────────────────────────── -->
|
||||||
|
<div class="wc-bottom-cta">
|
||||||
|
${hasPrompt ? `
|
||||||
|
<button class="btn wc-btn-hero" id="welcome-install-hero-btn2">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#download-simple"></use></svg>
|
||||||
|
App installieren — kostenlos
|
||||||
|
</button>
|
||||||
|
` : `
|
||||||
|
<button class="btn wc-btn-hero" id="welcome-register-btn2">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#paw-print"></use></svg>
|
||||||
|
Jetzt kostenlos starten
|
||||||
|
</button>
|
||||||
|
`}
|
||||||
|
<p class="wc-bottom-hint">Kein App Store · Direkt auf den Home-Bildschirm</p>
|
||||||
|
|
||||||
|
${!isInstalled ? `
|
||||||
|
<button class="wc-install-link" id="welcome-install-link">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#download-simple"></use></svg>
|
||||||
|
Installationsanleitung
|
||||||
|
</button>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── Install Card (via Einstellungen) ──────────────── -->
|
||||||
|
${_showInstall ? `
|
||||||
|
<div class="page-container" style="padding:0 var(--space-4) var(--space-6)">
|
||||||
|
<div class="card wc-install-card">
|
||||||
|
<div class="wc-install-header">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#download-simple"></use></svg>
|
||||||
|
App installieren
|
||||||
|
</div>
|
||||||
|
<div style="padding:var(--space-4)">${_installHTML()}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
|
||||||
|
<p class="wc-footer">Ban Yaro · Deine Daten auf eigenem Server in Deutschland</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
// EINGELOGGTE ANSICHT — kompakter Überblick
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
function _renderLoggedIn(isInstalled) {
|
||||||
_container.innerHTML = `
|
_container.innerHTML = `
|
||||||
<div class="welcome-layout" style="margin:0 auto">
|
<div class="welcome-layout" style="margin:0 auto">
|
||||||
|
|
||||||
<!-- ── Hero ─────────────────────────────────────────── -->
|
|
||||||
<div class="wc-hero">
|
<div class="wc-hero">
|
||||||
<img src="/icons/icon-180.png" alt="Ban Yaro" class="wc-hero-icon">
|
<img src="/icons/icon-180.png" alt="Ban Yaro" class="wc-hero-icon">
|
||||||
<h1 class="wc-hero-title">Ban Yaro</h1>
|
<h1 class="wc-hero-title">Ban Yaro</h1>
|
||||||
<p class="wc-hero-sub">
|
<p class="wc-hero-sub">
|
||||||
${user
|
Schön, dass du wieder da bist${_appState?.user?.name ? ', <strong>' + UI.escape(_appState.user.name) + '</strong>' : ''}!
|
||||||
? `Schön, dass du wieder da bist${user.name ? ', <strong>' + UI.escape(user.name) + '</strong>' : ''}! 🐾`
|
|
||||||
: 'Die Community für Hundebesitzer — Tagebuch, Gesundheit, Karte und mehr.'}
|
|
||||||
</p>
|
</p>
|
||||||
${!user ? `
|
|
||||||
<div class="wc-hero-cta">
|
|
||||||
<button class="btn btn-primary" id="welcome-register-btn">
|
|
||||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#user-plus"></use></svg>
|
|
||||||
Kostenlos registrieren
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-ghost" id="welcome-login-btn">Anmelden</button>
|
|
||||||
</div>
|
|
||||||
` : ''}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── Feature-Grid ──────────────────────────────────── -->
|
|
||||||
<div class="page-container" style="padding:var(--space-6) var(--space-4)">
|
<div class="page-container" style="padding:var(--space-6) var(--space-4)">
|
||||||
|
|
||||||
<h2 class="wc-section-title">Was Ban Yaro kann</h2>
|
<h2 class="wc-section-title">Was Ban Yaro kann</h2>
|
||||||
|
|
||||||
<div class="wc-grid">
|
<div class="wc-grid">
|
||||||
${FEATURES.map(f => `
|
${FEATURES.map(f => `
|
||||||
<button class="wc-tile" data-nav="${f.page}">
|
<button class="wc-tile" data-nav="${f.page}">
|
||||||
|
|
@ -92,42 +258,179 @@ window.Page_welcome = (() => {
|
||||||
`).join('')}
|
`).join('')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── App installieren ──────────────────────────── -->
|
|
||||||
${(!isInstalled || _showInstall) ? `
|
${(!isInstalled || _showInstall) ? `
|
||||||
<div class="card wc-install-card">
|
<div class="card wc-install-card">
|
||||||
<div class="wc-install-header">
|
<div class="wc-install-header">
|
||||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#download-simple"></use></svg>
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#download-simple"></use></svg>
|
||||||
App installieren
|
App installieren
|
||||||
</div>
|
</div>
|
||||||
<div style="padding:var(--space-4)">
|
<div style="padding:var(--space-4)">${_installHTML()}</div>
|
||||||
${_installHTML()}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
|
|
||||||
<!-- ── Footer ────────────────────────────────────── -->
|
<p class="wc-footer">Ban Yaro · Deine Daten auf eigenem Server in Deutschland</p>
|
||||||
<p class="wc-footer">
|
|
||||||
Ban Yaro · Deine Daten auf eigenem Server in Deutschland
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
_injectStyles();
|
|
||||||
_bindEvents();
|
|
||||||
_pulseMenuBtn();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
||||||
// STYLES (einmalig injizieren)
|
// STYLES
|
||||||
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
||||||
function _injectStyles() {
|
function _injectStyles() {
|
||||||
if (document.getElementById('wc-styles')) return;
|
if (document.getElementById('wc-styles')) return;
|
||||||
const s = document.createElement('style');
|
const s = document.createElement('style');
|
||||||
s.id = 'wc-styles';
|
s.id = 'wc-styles';
|
||||||
s.textContent = `
|
s.textContent = `
|
||||||
|
/* ── Landing Page ──────────────────────────────────────── */
|
||||||
|
.wc-landing { display: flex; flex-direction: column; }
|
||||||
|
|
||||||
/* Hero */
|
/* Hero */
|
||||||
|
.wc-lhero {
|
||||||
|
background: linear-gradient(160deg, var(--c-primary) 0%, color-mix(in srgb, var(--c-primary) 70%, transparent) 60%, var(--c-bg) 100%);
|
||||||
|
text-align: center;
|
||||||
|
padding: var(--space-8) var(--space-5) var(--space-8);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.wc-lhero::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute; inset: 0;
|
||||||
|
background: radial-gradient(ellipse at 50% 0%, rgba(255,255,255,0.18) 0%, transparent 65%);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.wc-lhero-icon {
|
||||||
|
width: 80px; height: 80px;
|
||||||
|
border-radius: 20px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0,0,0,0.25);
|
||||||
|
display: block; margin: 0 auto var(--space-5);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.wc-lhero-headline {
|
||||||
|
font-size: 2.6rem; font-weight: 800; line-height: 1.1;
|
||||||
|
color: #fff;
|
||||||
|
margin: 0 0 var(--space-4);
|
||||||
|
text-shadow: 0 2px 12px rgba(0,0,0,0.15);
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.wc-lhero-sub {
|
||||||
|
font-size: var(--text-base); color: rgba(255,255,255,0.88);
|
||||||
|
line-height: 1.6; margin: 0 0 var(--space-6);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.wc-lhero-cta {
|
||||||
|
display: flex; flex-direction: column;
|
||||||
|
align-items: center; gap: var(--space-3);
|
||||||
|
margin-bottom: var(--space-6);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.wc-btn-hero {
|
||||||
|
background: #fff; color: var(--c-primary);
|
||||||
|
font-size: var(--text-base); font-weight: var(--weight-bold);
|
||||||
|
padding: 14px var(--space-6); border-radius: 100px;
|
||||||
|
border: none; width: 100%; max-width: 320px;
|
||||||
|
box-shadow: 0 4px 20px rgba(0,0,0,0.2);
|
||||||
|
display: flex; align-items: center; justify-content: center; gap: var(--space-2);
|
||||||
|
transition: transform 0.1s, box-shadow 0.1s;
|
||||||
|
}
|
||||||
|
.wc-btn-hero:active { transform: scale(0.97); box-shadow: 0 2px 10px rgba(0,0,0,0.15); }
|
||||||
|
.wc-btn-login {
|
||||||
|
color: rgba(255,255,255,0.9) !important;
|
||||||
|
font-size: var(--text-sm);
|
||||||
|
padding: var(--space-2) var(--space-4);
|
||||||
|
border-color: rgba(255,255,255,0.35) !important;
|
||||||
|
}
|
||||||
|
.wc-trust-strip {
|
||||||
|
display: flex; justify-content: center;
|
||||||
|
gap: var(--space-4); flex-wrap: wrap;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.wc-trust-strip span {
|
||||||
|
display: flex; align-items: center; gap: 5px;
|
||||||
|
font-size: var(--text-xs); color: rgba(255,255,255,0.8);
|
||||||
|
font-weight: var(--weight-semibold);
|
||||||
|
}
|
||||||
|
.wc-trust-strip .ph-icon { width: 13px; height: 13px; }
|
||||||
|
|
||||||
|
/* Feature Cards */
|
||||||
|
.wc-feature {
|
||||||
|
display: flex; align-items: flex-start; gap: var(--space-4);
|
||||||
|
padding: var(--space-6) var(--space-5);
|
||||||
|
border-bottom: 1px solid var(--c-border-light);
|
||||||
|
}
|
||||||
|
.wc-feature--a { background: var(--c-bg); }
|
||||||
|
.wc-feature--b { background: var(--c-surface); }
|
||||||
|
.wc-feature--c { background: var(--c-bg); }
|
||||||
|
.wc-feature--d { background: var(--c-surface); }
|
||||||
|
.wc-feature-icon {
|
||||||
|
width: 52px; height: 52px; border-radius: var(--radius-lg); flex-shrink: 0;
|
||||||
|
background: var(--c-primary-subtle);
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
}
|
||||||
|
.wc-feature-icon .ph-icon { width: 26px; height: 26px; color: var(--c-primary); }
|
||||||
|
.wc-feature-text h2 {
|
||||||
|
font-size: var(--text-base); font-weight: var(--weight-bold);
|
||||||
|
color: var(--c-text); margin: 0 0 var(--space-1);
|
||||||
|
}
|
||||||
|
.wc-feature-text p {
|
||||||
|
font-size: var(--text-sm); color: var(--c-text-secondary);
|
||||||
|
line-height: 1.6; margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Privacy Block */
|
||||||
|
.wc-privacy {
|
||||||
|
background: var(--c-primary);
|
||||||
|
padding: var(--space-8) var(--space-5);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.wc-privacy-icon {
|
||||||
|
width: 56px; height: 56px; border-radius: 50%;
|
||||||
|
background: rgba(255,255,255,0.2);
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
margin: 0 auto var(--space-4);
|
||||||
|
}
|
||||||
|
.wc-privacy-icon .ph-icon { width: 28px; height: 28px; color: #fff; }
|
||||||
|
.wc-privacy-title {
|
||||||
|
font-size: var(--text-xl); font-weight: var(--weight-bold);
|
||||||
|
color: #fff; margin: 0 0 var(--space-3);
|
||||||
|
}
|
||||||
|
.wc-privacy-sub {
|
||||||
|
font-size: var(--text-sm); color: rgba(255,255,255,0.85);
|
||||||
|
line-height: 1.7; margin: 0; max-width: 360px; margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Und noch mehr */
|
||||||
|
.wc-more {
|
||||||
|
padding: var(--space-6) var(--space-4);
|
||||||
|
background: var(--c-bg);
|
||||||
|
border-top: 1px solid var(--c-border-light);
|
||||||
|
}
|
||||||
|
.wc-more-label {
|
||||||
|
font-size: var(--text-xs); font-weight: var(--weight-semibold);
|
||||||
|
color: var(--c-text-secondary); text-transform: uppercase;
|
||||||
|
letter-spacing: 0.07em; margin: 0 0 var(--space-4); text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bottom CTA */
|
||||||
|
.wc-bottom-cta {
|
||||||
|
padding: var(--space-8) var(--space-5) var(--space-6);
|
||||||
|
display: flex; flex-direction: column; align-items: center;
|
||||||
|
gap: var(--space-3); background: var(--c-bg);
|
||||||
|
border-top: 1px solid var(--c-border-light);
|
||||||
|
}
|
||||||
|
.wc-bottom-hint {
|
||||||
|
font-size: var(--text-xs); color: var(--c-text-muted); margin: 0;
|
||||||
|
}
|
||||||
|
.wc-install-link {
|
||||||
|
background: none; border: none; cursor: pointer;
|
||||||
|
font-size: var(--text-xs); color: var(--c-text-secondary);
|
||||||
|
display: flex; align-items: center; gap: 4px;
|
||||||
|
padding: var(--space-2); margin-top: var(--space-1);
|
||||||
|
}
|
||||||
|
.wc-install-link .ph-icon { width: 12px; height: 12px; }
|
||||||
|
|
||||||
|
/* ── Logged-in Hero (kompakt) ──────────────────────────── */
|
||||||
.wc-hero {
|
.wc-hero {
|
||||||
background: linear-gradient(160deg, var(--c-primary-subtle) 0%, var(--c-bg) 70%);
|
background: linear-gradient(160deg, var(--c-primary-subtle) 0%, var(--c-bg) 70%);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -135,8 +438,7 @@ window.Page_welcome = (() => {
|
||||||
border-bottom: 1px solid var(--c-border-light);
|
border-bottom: 1px solid var(--c-border-light);
|
||||||
}
|
}
|
||||||
.wc-hero-icon {
|
.wc-hero-icon {
|
||||||
width: 96px; height: 96px;
|
width: 96px; height: 96px; border-radius: 22px;
|
||||||
border-radius: 22px;
|
|
||||||
box-shadow: 0 8px 28px rgba(0,0,0,0.15);
|
box-shadow: 0 8px 28px rgba(0,0,0,0.15);
|
||||||
display: block; margin: 0 auto var(--space-4);
|
display: block; margin: 0 auto var(--space-4);
|
||||||
}
|
}
|
||||||
|
|
@ -146,52 +448,43 @@ window.Page_welcome = (() => {
|
||||||
}
|
}
|
||||||
.wc-hero-sub {
|
.wc-hero-sub {
|
||||||
font-size: var(--text-base); color: var(--c-text-secondary);
|
font-size: var(--text-base); color: var(--c-text-secondary);
|
||||||
margin: 0; line-height: 1.6; max-width: 420px; margin: 0 auto;
|
margin: 0 auto; line-height: 1.6; max-width: 420px;
|
||||||
}
|
|
||||||
.wc-hero-cta {
|
|
||||||
display: flex; gap: var(--space-3); justify-content: center;
|
|
||||||
flex-wrap: wrap; margin-top: var(--space-5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Section title */
|
/* ── Shared ────────────────────────────────────────────── */
|
||||||
.wc-section-title {
|
.wc-section-title {
|
||||||
font-size: var(--text-sm); font-weight: var(--weight-semibold);
|
font-size: var(--text-xs); font-weight: var(--weight-semibold);
|
||||||
color: var(--c-text-secondary); text-transform: uppercase;
|
color: var(--c-text-secondary); text-transform: uppercase;
|
||||||
letter-spacing: 0.06em; margin: 0 0 var(--space-4);
|
letter-spacing: 0.07em; margin: 0 0 var(--space-4); text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Feature Grid */
|
|
||||||
.wc-grid {
|
.wc-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
gap: var(--space-3);
|
gap: var(--space-3);
|
||||||
margin-bottom: var(--space-6);
|
margin-bottom: var(--space-4);
|
||||||
}
|
}
|
||||||
.wc-tile {
|
.wc-tile {
|
||||||
display: flex; flex-direction: column;
|
display: flex; flex-direction: column; align-items: center;
|
||||||
align-items: center; gap: var(--space-2);
|
gap: var(--space-2); padding: var(--space-4) var(--space-2);
|
||||||
padding: var(--space-4) var(--space-2);
|
background: var(--c-surface); border: 1px solid var(--c-border-light);
|
||||||
background: var(--c-surface);
|
border-radius: var(--radius-lg); cursor: pointer;
|
||||||
border: 1px solid var(--c-border-light);
|
transition: background var(--transition-fast), transform 0.1s;
|
||||||
border-radius: var(--radius-lg);
|
|
||||||
cursor: pointer; transition: background var(--transition-fast), transform 0.1s;
|
|
||||||
}
|
}
|
||||||
.wc-tile:hover { background: var(--c-surface-2); }
|
.wc-tile:hover { background: var(--c-surface-2); }
|
||||||
.wc-tile:active { transform: scale(0.96); }
|
.wc-tile:active { transform: scale(0.96); }
|
||||||
|
.wc-tile--static { cursor: default; }
|
||||||
|
.wc-tile--static:hover { background: var(--c-surface); }
|
||||||
|
.wc-tile--static:active { transform: none; }
|
||||||
.wc-tile-icon {
|
.wc-tile-icon {
|
||||||
width: 44px; height: 44px; border-radius: var(--radius-md);
|
width: 40px; height: 40px; border-radius: var(--radius-md);
|
||||||
background: var(--c-primary-subtle);
|
background: var(--c-primary-subtle);
|
||||||
display: flex; align-items: center; justify-content: center;
|
display: flex; align-items: center; justify-content: center;
|
||||||
}
|
}
|
||||||
.wc-tile-icon .ph-icon {
|
.wc-tile-icon .ph-icon { width: 20px; height: 20px; color: var(--c-primary); }
|
||||||
width: 22px; height: 22px; color: var(--c-primary);
|
|
||||||
}
|
|
||||||
.wc-tile-label {
|
.wc-tile-label {
|
||||||
font-size: var(--text-xs); font-weight: var(--weight-semibold);
|
font-size: var(--text-xs); font-weight: var(--weight-semibold);
|
||||||
color: var(--c-text); text-align: center; line-height: 1.3;
|
color: var(--c-text); text-align: center; line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Install card */
|
|
||||||
.wc-install-card { margin-bottom: var(--space-5); }
|
.wc-install-card { margin-bottom: var(--space-5); }
|
||||||
.wc-install-header {
|
.wc-install-header {
|
||||||
display: flex; align-items: center; gap: var(--space-2);
|
display: flex; align-items: center; gap: var(--space-2);
|
||||||
|
|
@ -201,19 +494,23 @@ window.Page_welcome = (() => {
|
||||||
letter-spacing: 0.05em; border-bottom: 1px solid var(--c-border);
|
letter-spacing: 0.05em; border-bottom: 1px solid var(--c-border);
|
||||||
}
|
}
|
||||||
.wc-install-header .ph-icon { width: 14px; height: 14px; }
|
.wc-install-header .ph-icon { width: 14px; height: 14px; }
|
||||||
|
|
||||||
/* Footer */
|
|
||||||
.wc-footer {
|
.wc-footer {
|
||||||
text-align: center; font-size: var(--text-xs);
|
text-align: center; font-size: var(--text-xs);
|
||||||
color: var(--c-text-muted); margin: 0;
|
color: var(--c-text-muted); padding: var(--space-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Desktop: 8-spaltig */
|
@media (min-width: 640px) {
|
||||||
|
.wc-lhero-headline { font-size: 3.2rem; }
|
||||||
|
.wc-lhero-cta { flex-direction: row; justify-content: center; }
|
||||||
|
.wc-btn-hero { width: auto; }
|
||||||
|
.wc-grid { grid-template-columns: repeat(4, 1fr); }
|
||||||
|
}
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
|
.wc-lhero { padding: var(--space-8) var(--space-4) var(--space-10); }
|
||||||
|
.wc-feature { max-width: 680px; margin: 0 auto; }
|
||||||
.wc-grid { grid-template-columns: repeat(8, 1fr); }
|
.wc-grid { grid-template-columns: repeat(8, 1fr); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pulse animation */
|
|
||||||
@keyframes wc-pulse {
|
@keyframes wc-pulse {
|
||||||
0%,100% { transform: scale(1); box-shadow: none; }
|
0%,100% { transform: scale(1); box-shadow: none; }
|
||||||
50% { transform: scale(1.25); box-shadow: 0 0 0 6px var(--c-primary-subtle); }
|
50% { transform: scale(1.25); box-shadow: 0 0 0 6px var(--c-primary-subtle); }
|
||||||
|
|
@ -231,10 +528,8 @@ window.Page_welcome = (() => {
|
||||||
const isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream;
|
const isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream;
|
||||||
const isSafari = /^((?!chrome|android).)*safari/i.test(ua);
|
const isSafari = /^((?!chrome|android).)*safari/i.test(ua);
|
||||||
const isAndroid = /android/i.test(ua);
|
const isAndroid = /android/i.test(ua);
|
||||||
const isMobile = isIOS || isAndroid;
|
|
||||||
const hasPrompt = !!App.getInstallPrompt();
|
const hasPrompt = !!App.getInstallPrompt();
|
||||||
|
|
||||||
// Android: Browser hat Install-Prompt bereit (Chrome, Edge, Samsung Internet neu)
|
|
||||||
if (hasPrompt) {
|
if (hasPrompt) {
|
||||||
return `
|
return `
|
||||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-3);line-height:1.5">
|
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-3);line-height:1.5">
|
||||||
|
|
@ -246,7 +541,6 @@ window.Page_welcome = (() => {
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// iOS Safari: Teilen-Menü
|
|
||||||
if (isIOS && isSafari) {
|
if (isIOS && isSafari) {
|
||||||
return `
|
return `
|
||||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-4);line-height:1.5">
|
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-4);line-height:1.5">
|
||||||
|
|
@ -262,7 +556,6 @@ window.Page_welcome = (() => {
|
||||||
</p>`;
|
</p>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// iOS, aber nicht Safari (Chrome, Firefox, etc.)
|
|
||||||
if (isIOS && !isSafari) {
|
if (isIOS && !isSafari) {
|
||||||
return `
|
return `
|
||||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-4);line-height:1.5">
|
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-4);line-height:1.5">
|
||||||
|
|
@ -280,7 +573,6 @@ window.Page_welcome = (() => {
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Android ohne Prompt (Firefox, älterer Samsung Browser, etc.)
|
|
||||||
if (isAndroid) {
|
if (isAndroid) {
|
||||||
return `
|
return `
|
||||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-4);line-height:1.5">
|
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-4);line-height:1.5">
|
||||||
|
|
@ -298,7 +590,6 @@ window.Page_welcome = (() => {
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Desktop — beide Plattformen zeigen
|
|
||||||
return `
|
return `
|
||||||
<div style="display:flex;gap:var(--space-2);margin-bottom:var(--space-4)">
|
<div style="display:flex;gap:var(--space-2);margin-bottom:var(--space-4)">
|
||||||
<button class="btn btn-sm" id="inst-tab-android"
|
<button class="btn btn-sm" id="inst-tab-android"
|
||||||
|
|
@ -311,9 +602,9 @@ window.Page_welcome = (() => {
|
||||||
</div>
|
</div>
|
||||||
<div id="inst-panel-android">
|
<div id="inst-panel-android">
|
||||||
${_steps([
|
${_steps([
|
||||||
['arrow-square-in', 'Öffne <strong>banyaro.app</strong> in Chrome oder Edge'],
|
['arrow-square-in', 'Öffne <strong>banyaro.app</strong> in Chrome oder Edge'],
|
||||||
['monitor', 'Klicke auf das <strong>Installations-Symbol</strong> in der Adressleiste'],
|
['monitor', 'Klicke auf das <strong>Installations-Symbol</strong> in der Adressleiste'],
|
||||||
['check', 'Bestätigen — fertig!'],
|
['check', 'Bestätigen — fertig!'],
|
||||||
])}
|
])}
|
||||||
</div>
|
</div>
|
||||||
<div id="inst-panel-ios" style="display:none">
|
<div id="inst-panel-ios" style="display:none">
|
||||||
|
|
@ -346,17 +637,30 @@ window.Page_welcome = (() => {
|
||||||
// EVENTS
|
// EVENTS
|
||||||
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
||||||
function _bindEvents() {
|
function _bindEvents() {
|
||||||
_container.querySelector('#install-android-btn')?.addEventListener('click', async () => {
|
// Install-Prompt Buttons
|
||||||
|
const installBtn = async () => {
|
||||||
const prompt = App.getInstallPrompt();
|
const prompt = App.getInstallPrompt();
|
||||||
if (!prompt) return;
|
if (!prompt) return;
|
||||||
prompt.prompt();
|
prompt.prompt();
|
||||||
const { outcome } = await prompt.userChoice;
|
const { outcome } = await prompt.userChoice;
|
||||||
if (outcome === 'accepted') {
|
if (outcome === 'accepted') { UI.toast.success('Ban Yaro wird installiert!'); _render(); }
|
||||||
UI.toast.success('Ban Yaro wird installiert!');
|
};
|
||||||
_render();
|
_container.querySelector('#install-android-btn')?.addEventListener('click', installBtn);
|
||||||
}
|
_container.querySelector('#welcome-install-hero-btn')?.addEventListener('click', installBtn);
|
||||||
|
_container.querySelector('#welcome-install-hero-btn2')?.addEventListener('click', installBtn);
|
||||||
|
|
||||||
|
// Register / Login
|
||||||
|
const toSettings = () => App.navigate('settings');
|
||||||
|
_container.querySelector('#welcome-register-btn')?.addEventListener('click', toSettings);
|
||||||
|
_container.querySelector('#welcome-register-btn2')?.addEventListener('click', toSettings);
|
||||||
|
_container.querySelector('#welcome-login-btn')?.addEventListener('click', toSettings);
|
||||||
|
|
||||||
|
// Installationsanleitung Link
|
||||||
|
_container.querySelector('#welcome-install-link')?.addEventListener('click', () => {
|
||||||
|
App.navigate('welcome', true, { install: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Link kopieren
|
||||||
_container.querySelector('#install-copy-btn')?.addEventListener('click', async () => {
|
_container.querySelector('#install-copy-btn')?.addEventListener('click', async () => {
|
||||||
await navigator.clipboard.writeText('https://banyaro.app');
|
await navigator.clipboard.writeText('https://banyaro.app');
|
||||||
UI.toast.success('Link kopiert!');
|
UI.toast.success('Link kopiert!');
|
||||||
|
|
@ -378,9 +682,7 @@ window.Page_welcome = (() => {
|
||||||
_container.querySelector('#inst-tab-android').style.cssText = 'flex:1';
|
_container.querySelector('#inst-tab-android').style.cssText = 'flex:1';
|
||||||
});
|
});
|
||||||
|
|
||||||
_container.querySelector('#welcome-register-btn')?.addEventListener('click', () => App.navigate('settings'));
|
// Feature-Tiles (nur eingeloggte Ansicht)
|
||||||
_container.querySelector('#welcome-login-btn')?.addEventListener('click', () => App.navigate('settings'));
|
|
||||||
|
|
||||||
_container.querySelectorAll('[data-nav]').forEach(btn => {
|
_container.querySelectorAll('[data-nav]').forEach(btn => {
|
||||||
btn.addEventListener('click', () => App.navigate(btn.dataset.nav));
|
btn.addEventListener('click', () => App.navigate(btn.dataset.nav));
|
||||||
});
|
});
|
||||||
|
|
@ -392,9 +694,8 @@ window.Page_welcome = (() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
btn.classList.add('wc-pulsing');
|
btn.classList.add('wc-pulsing');
|
||||||
btn.addEventListener('animationend', () => btn.classList.remove('wc-pulsing'), { once: true });
|
btn.addEventListener('animationend', () => btn.classList.remove('wc-pulsing'), { once: true });
|
||||||
}, 800);
|
}, 1200);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { init, refresh, onDogChange };
|
return { init, refresh, onDogChange };
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Offline-Cache + Push Notifications + Tile-Cache
|
Offline-Cache + Push Notifications + Tile-Cache
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const CACHE_VERSION = 'by-v443';
|
const CACHE_VERSION = 'by-v444';
|
||||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||||
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue