Refactoring: Inline-Styles → CSS-Klassen (worlds.js, dog-profile.js, settings.js) — 20 neue w3-/by-Klassen (SW by-v773)

This commit is contained in:
rene 2026-05-08 12:22:04 +02:00
parent 3b8c9a72d8
commit ce14bb1d2c
8 changed files with 389 additions and 115 deletions

View file

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung.
============================================================ */
const APP_VER = '772'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VER = '773'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.5.0'; // ← 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

@ -108,8 +108,7 @@ window.Page_dog_profile = (() => {
margin-bottom:var(--space-5);text-align:left">
${geburtstag ? `
<div class="card" style="padding:var(--space-3)">
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
margin-bottom:2px"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#calendar-dots"></use></svg> Geburtstag</div>
<div class="dp-info-label"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#calendar-dots"></use></svg> Geburtstag</div>
<div style="font-weight:500;font-size:var(--text-sm)">${geburtstag}</div>
<div style="font-size:var(--text-xs);color:var(--c-text-secondary)">
${_calcAlter(dog.geburtstag)}
@ -118,8 +117,7 @@ window.Page_dog_profile = (() => {
` : ''}
${dog.geschlecht ? `
<div class="card" style="padding:var(--space-3)">
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
margin-bottom:2px">${dog.geschlecht === 'm' ? '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#gender-male"></use></svg>' : '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#gender-female"></use></svg>'} Geschlecht</div>
<div class="dp-info-label">${dog.geschlecht === 'm' ? '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#gender-male"></use></svg>' : '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#gender-female"></use></svg>'} Geschlecht</div>
<div style="font-weight:500;font-size:var(--text-sm)">
${dog.geschlecht === 'm' ? 'Rüde' : 'Hündin'}
</div>
@ -127,8 +125,7 @@ window.Page_dog_profile = (() => {
` : ''}
${dog.gewicht_kg ? `
<div class="card" style="padding:var(--space-3);cursor:pointer" data-action="goto-weight">
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
margin-bottom:2px"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#scales"></use></svg> Gewicht</div>
<div class="dp-info-label"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#scales"></use></svg> Gewicht</div>
<div style="font-weight:500;font-size:var(--text-sm)">${dog.gewicht_kg} kg</div>
</div>
` : ''}
@ -521,9 +518,7 @@ window.Page_dog_profile = (() => {
let activeHtml = '';
if (active.length) {
activeHtml = active.map(s => `
<div style="display:flex;align-items:center;gap:var(--space-2);
padding:var(--space-2) var(--space-3);background:var(--c-surface-2);
border-radius:var(--radius-md);margin-bottom:var(--space-2)">
<div style="display:flex;align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);background:var(--c-surface-2);border-radius:var(--radius-md);margin-bottom:var(--space-2)">
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#user"></use></svg>
<div style="flex:1;font-size:var(--text-sm)">
<strong>${_esc(s.sitter_name)}</strong>
@ -619,7 +614,7 @@ window.Page_dog_profile = (() => {
value="${_esc(dog.chip_nr || '')}" placeholder="z.B. 276009200123456" maxlength="20">
</div>`,
footer: `
<div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
<div class="w3-btn-stack">
<button class="btn btn-primary" id="chip-edit-save-btn" style="width:100%">Speichern</button>
<button class="btn btn-secondary" onclick="UI.modal.close()">Abbrechen</button>
</div>`,
@ -676,7 +671,7 @@ window.Page_dog_profile = (() => {
`;
const footer = `
<div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
<div class="w3-btn-stack">
${hasPhoto ? `<button class="btn btn-primary" id="pe-save-btn" style="width:100%">Speichern</button>` : ''}
<div style="display:flex;gap:var(--space-2)">
${hasPhoto ? `<button class="btn btn-danger" id="pe-delete-btn">${UI.icon('trash')} Löschen</button>` : ''}
@ -1044,7 +1039,7 @@ window.Page_dog_profile = (() => {
title: 'Weiteren Hund anlegen',
body: _formHTML(null, true),
footer: `
<div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
<div class="w3-btn-stack">
<button type="submit" form="dp-form" class="btn btn-primary" style="width:100%">${UI.icon('dog')} Hund anlegen</button>
<button type="button" class="btn btn-secondary" id="dp-form-cancel">Abbrechen</button>
</div>
@ -1061,7 +1056,7 @@ window.Page_dog_profile = (() => {
title: `${dog.name} bearbeiten`,
body: _formHTML(dog, true),
footer: `
<div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
<div class="w3-btn-stack">
<button type="submit" form="dp-form" class="btn btn-primary" style="width:100%">Speichern</button>
<div style="display:flex;gap:var(--space-2)">
<button type="button" class="btn btn-danger" id="dp-delete-btn">Löschen</button>
@ -1657,8 +1652,7 @@ window.Page_dog_profile = (() => {
</div>`
: vaccs.map(v => `
<div class="pp-vacc-row" data-id="${v.id}"
style="display:flex;align-items:flex-start;gap:var(--space-3);
padding:var(--space-3) 0;border-bottom:1px solid var(--c-border)">
class="pp-data-row">
<div style="flex:1">
<div style="font-weight:600;font-size:var(--text-sm)">${_esc(v.krankheit)}</div>
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);margin-top:2px">
@ -1695,8 +1689,7 @@ window.Page_dog_profile = (() => {
</div>`
: meds.map(m => `
<div class="pp-med-row" data-id="${m.id}"
style="display:flex;align-items:flex-start;gap:var(--space-3);
padding:var(--space-3) 0;border-bottom:1px solid var(--c-border)">
class="pp-data-row">
<div style="flex:1">
<div style="font-weight:600;font-size:var(--text-sm)">${_esc(m.name)}</div>
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);margin-top:2px">

View file

@ -120,12 +120,7 @@ window.Page_settings = (() => {
<div class="card" style="padding:var(--space-5);margin-bottom:var(--space-4)">
<div style="display:flex;align-items:center;gap:var(--space-4)">
<div id="settings-avatar-btn"
style="width:56px;height:56px;border-radius:50%;
background:var(--c-primary);color:#fff;
display:flex;align-items:center;justify-content:center;
font-size:1.5rem;font-weight:700;flex-shrink:0;
cursor:pointer;overflow:hidden;position:relative">
<div id="settings-avatar-btn" class="by-avatar-circle">
${avatarInner}
<div style="position:absolute;inset:0;background:rgba(0,0,0,0.25);
display:flex;align-items:center;justify-content:center;
@ -223,9 +218,7 @@ window.Page_settings = (() => {
</div>
<div class="card" id="settings-stats-card" style="margin-bottom:var(--space-4)">
<div style="padding:var(--space-3) var(--space-4);font-size:var(--text-xs);font-weight:600;
color:var(--c-text-secondary);text-transform:uppercase;letter-spacing:0.05em;
border-bottom:1px solid var(--c-border)">Aktivität</div>
<div class="by-card-section-header">Aktivität</div>
<div id="settings-stats-body" style="padding:var(--space-4);display:flex;justify-content:space-around">
<div style="color:var(--c-text-muted);font-size:var(--text-sm)">Lädt</div>
</div>
@ -238,9 +231,7 @@ window.Page_settings = (() => {
<div id="breeder-card-slot"></div>
<div class="card" style="margin-bottom:var(--space-4)">
<div style="padding:var(--space-3) var(--space-4);font-size:var(--text-xs);font-weight:600;
color:var(--c-text-secondary);text-transform:uppercase;letter-spacing:0.05em;
border-bottom:1px solid var(--c-border)">Trophäen</div>
<div class="by-card-section-header">Trophäen</div>
<div id="settings-badges-body" style="padding:var(--space-4)">
<div style="color:var(--c-text-muted);font-size:var(--text-sm)">Lädt</div>
</div>
@ -301,19 +292,15 @@ window.Page_settings = (() => {
</div>
<div class="card" style="margin-bottom:var(--space-4)">
<div style="padding:var(--space-3) var(--space-4);
font-size:var(--text-xs);font-weight:600;
color:var(--c-text-secondary);text-transform:uppercase;
letter-spacing:0.05em;border-bottom:1px solid var(--c-border)">
<div class="by-card-section-header">
App-Einstellungen
</div>
<div class="card-body" style="padding:0">
<!-- Dark-Mode-Auswahl -->
<div style="display:flex;align-items:center;gap:var(--space-3);
padding:var(--space-4);border-bottom:1px solid var(--c-border)">
<div class="settings-toggle-row">
<svg class="ph-icon" aria-hidden="true" style="width:1.25rem;height:1.25rem"><use href="/icons/phosphor.svg#moon"></use></svg>
<div style="flex:1">
<div class="settings-toggle-label">
<div style="font-weight:500">Dark Mode</div>
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);margin-top:2px">
Erscheinungsbild der App
@ -335,9 +322,9 @@ window.Page_settings = (() => {
</div>
<!-- KI-Notiz-Assistent -->
<div style="display:flex;align-items:center;gap:var(--space-3);padding:var(--space-4);border-bottom:1px solid var(--c-border)">
<div class="settings-toggle-row">
<svg class="ph-icon" aria-hidden="true" style="width:1.25rem;height:1.25rem"><use href="/icons/phosphor.svg#brain"></use></svg>
<div style="flex:1">
<div class="settings-toggle-label">
<div style="font-weight:500">KI-Notiz-Assistent</div>
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);margin-top:2px">
Erkennt Muster in deinen Notizen und macht Vorschläge
@ -359,9 +346,9 @@ window.Page_settings = (() => {
</div>
<!-- Goldene Gassi-Stunde -->
<div style="display:flex;align-items:center;gap:var(--space-3);padding:var(--space-4)">
<div class="settings-toggle-row" style="border-bottom:none">
<svg class="ph-icon" aria-hidden="true" style="width:1.25rem;height:1.25rem"><use href="/icons/phosphor.svg#paw-print"></use></svg>
<div style="flex:1">
<div class="settings-toggle-label">
<div style="font-weight:500">Goldene Gassi-Stunde täglich</div>
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);margin-top:2px">
Täglich um 07:00 Uhr: bestes Wetterfenster für den Gassi-Gang
@ -398,10 +385,7 @@ window.Page_settings = (() => {
<!-- App installieren -->
<div class="card" style="margin-bottom:var(--space-4)">
<div style="padding:var(--space-3) var(--space-4);
font-size:var(--text-xs);font-weight:600;
color:var(--c-text-secondary);text-transform:uppercase;
letter-spacing:0.05em;border-bottom:1px solid var(--c-border)">
<div class="by-card-section-header">
App installieren
</div>
<div class="card-body" style="padding:0">
@ -717,7 +701,7 @@ window.Page_settings = (() => {
</form>
`,
footer: `
<div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
<div class="w3-btn-stack">
<button type="submit" form="profile-form" class="btn btn-primary" style="width:100%">Speichern</button>
<button type="button" class="btn btn-secondary" data-modal-close>Abbrechen</button>
</div>
@ -1042,12 +1026,7 @@ window.Page_settings = (() => {
slot.innerHTML = `
<div class="card" style="margin-bottom:var(--space-4)">
<div style="padding:var(--space-3) var(--space-4);
font-size:var(--text-xs);font-weight:600;
color:var(--c-text-secondary);text-transform:uppercase;
letter-spacing:0.05em;border-bottom:1px solid var(--c-border)">
Züchter-Profil
</div>
<div class="by-card-section-header">Züchter-Profil</div>
<div style="padding:var(--space-4)">
${statusBadge}
${actionBlock}
@ -1269,7 +1248,7 @@ window.Page_settings = (() => {
</form>
`,
footer: `
<div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
<div class="w3-btn-stack">
<button type="submit" form="breeder-apply-form" class="btn btn-primary" id="breeder-apply-submit"
style="width:100%">Antrag einreichen</button>
<button type="button" class="btn btn-secondary" data-modal-close>Abbrechen</button>

View file

@ -274,28 +274,20 @@ window.Worlds = (() => {
const ov = document.createElement('div');
ov.id = 'fab-overlay';
ov.style.cssText = 'position:fixed;inset:0;z-index:460;display:flex;flex-direction:column;justify-content:flex-end';
ov.className = 'w3-sheet-overlay';
ov.innerHTML = `
<div id="fab-backdrop" style="position:absolute;inset:0;background:rgba(0,0,0,0.55);backdrop-filter:blur(2px)"></div>
<div style="position:relative;z-index:1;background:var(--c-bg);border-radius:24px 24px 0 0;
padding:20px 16px calc(env(safe-area-inset-bottom,16px) + 16px);
box-shadow:0 -8px 32px rgba(0,0,0,0.2)">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px">
<div style="font-size:var(--text-base);font-weight:700">${options.length ? title : 'Schnellzugriff'}</div>
<button id="fab-close" style="background:var(--c-border);border:none;border-radius:50%;
width:28px;height:28px;cursor:pointer;display:flex;align-items:center;justify-content:center">
<div id="fab-backdrop" class="w3-backdrop"></div>
<div class="w3-sheet-panel">
<div class="w3-sheet-header">
<div class="w3-sheet-title">${options.length ? title : 'Schnellzugriff'}</div>
<button id="fab-close" class="w3-close-btn">
<svg class="ph-icon" style="width:14px;height:14px"><use href="/icons/phosphor.svg#x"></use></svg>
</button>
</div>
<div style="display:flex;flex-direction:column;gap:10px">
${options.map(o => `
<button class="fab-option" data-page="${o.page}" data-action="${o.action || ''}"
style="display:flex;align-items:center;gap:14px;width:100%;
background:var(--c-bg-card);border:1px solid var(--c-border);
border-radius:14px;padding:14px 16px;cursor:pointer;text-align:left;
transition:background .12s">
<div style="width:40px;height:40px;border-radius:12px;background:${o.color}18;
display:flex;align-items:center;justify-content:center;flex-shrink:0">
<button class="fab-option w3-fab-option" data-page="${o.page}" data-action="${o.action || ''}">
<div class="w3-icon-dot" style="background:${o.color}18">
<svg class="ph-icon" style="width:1.2rem;height:1.2rem;color:${o.color}">
<use href="/icons/phosphor.svg#${o.icon}"></use>
</svg>
@ -307,9 +299,7 @@ window.Worlds = (() => {
</button>
`).join('')}
</div>
<button id="fab-all-btn" style="display:flex;align-items:center;justify-content:center;gap:8px;
width:100%;margin-top:${options.length ? '14px' : '0'};padding:12px;border:none;
background:none;cursor:pointer;color:var(--c-primary);font-size:var(--text-sm);font-weight:600">
<button id="fab-all-btn" class="w3-all-btn" style="margin-top:${options.length ? '14px' : '0'}">
<svg class="ph-icon" style="width:16px;height:16px"><use href="/icons/phosphor.svg#squares-four"></use></svg>
Weitere Funktionen
</button>
@ -353,20 +343,14 @@ window.Worlds = (() => {
if (!chips.length) return '';
return `
<div style="margin-bottom:20px">
<div style="font-size:var(--text-xs);font-weight:700;color:var(--c-text-secondary);
letter-spacing:0.08em;margin-bottom:10px">${worldLabels[w]}</div>
<div class="w3-section-label">${worldLabels[w]}</div>
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:8px">
${chips.map(c => `
<button class="all-chip-btn" data-page="${c.page}"
style="display:flex;flex-direction:column;align-items:center;gap:6px;
background:var(--c-bg-card);border:1px solid var(--c-border);
border-radius:14px;padding:12px 6px;cursor:pointer;
transition:background .12s">
<button class="all-chip-btn w3-chip-btn" data-page="${c.page}">
<svg class="ph-icon" style="width:1.4rem;height:1.4rem;color:var(--c-primary)">
<use href="/icons/phosphor.svg#${c.icon}"></use>
</svg>
<span style="font-size:10px;font-weight:600;color:var(--c-text);text-align:center;
line-height:1.2;word-break:break-word">${c.label}</span>
<span class="w3-chip-label">${c.label}</span>
</button>
`).join('')}
</div>
@ -376,16 +360,13 @@ window.Worlds = (() => {
const ov = document.createElement('div');
ov.id = 'fab-overlay';
ov.style.cssText = 'position:fixed;inset:0;z-index:460;display:flex;flex-direction:column;justify-content:flex-end';
ov.className = 'w3-sheet-overlay';
ov.innerHTML = `
<div id="fab-backdrop" style="position:absolute;inset:0;background:rgba(0,0,0,0.55);backdrop-filter:blur(2px)"></div>
<div style="position:relative;z-index:1;background:var(--c-bg);border-radius:24px 24px 0 0;
padding:20px 16px calc(env(safe-area-inset-bottom,16px) + 16px);
box-shadow:0 -8px 32px rgba(0,0,0,0.2);max-height:82vh;overflow-y:auto">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px">
<div style="font-size:var(--text-base);font-weight:700">Ausgeblendete Funktionen</div>
<button id="fab-close" style="background:var(--c-border);border:none;border-radius:50%;
width:28px;height:28px;cursor:pointer;display:flex;align-items:center;justify-content:center">
<div id="fab-backdrop" class="w3-backdrop"></div>
<div class="w3-sheet-panel w3-sheet-panel--scroll">
<div class="w3-sheet-header w3-sheet-header--mb20">
<div class="w3-sheet-title">Ausgeblendete Funktionen</div>
<button id="fab-close" class="w3-close-btn">
<svg class="ph-icon" style="width:14px;height:14px"><use href="/icons/phosphor.svg#x"></use></svg>
</button>
</div>
@ -430,7 +411,8 @@ window.Worlds = (() => {
const ov = document.createElement('div');
ov.id = 'quick-gassi-overlay';
ov.style.cssText = 'position:fixed;inset:0;z-index:400;display:flex;flex-direction:column;justify-content:flex-end';
ov.className = 'w3-sheet-overlay';
ov.style.zIndex = '400';
const weatherLine = weatherData
? `<div style="font-size:var(--text-xs);color:var(--c-text-secondary);margin-top:6px">
@ -438,20 +420,17 @@ window.Worlds = (() => {
</div>` : '';
ov.innerHTML = `
<div id="qg-backdrop" style="position:absolute;inset:0;background:rgba(0,0,0,0.6);backdrop-filter:blur(3px)"></div>
<div style="position:relative;z-index:1;background:var(--c-bg);border-radius:24px 24px 0 0;
padding:24px 16px calc(env(safe-area-inset-bottom,16px) + 20px);
box-shadow:0 -8px 32px rgba(0,0,0,0.25)">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px">
<div id="qg-backdrop" class="w3-backdrop" style="background:rgba(0,0,0,0.6);backdrop-filter:blur(3px)"></div>
<div class="w3-sheet-panel" style="padding:24px 16px calc(env(safe-area-inset-bottom,16px) + 20px)">
<div class="w3-sheet-header w3-sheet-header--mb20">
<div>
<div style="font-size:var(--text-base);font-weight:700">🐾 Schnell-Gassi</div>
<div class="w3-sheet-title">🐾 Schnell-Gassi</div>
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);margin-top:2px">
${_esc(dog.name)} · ohne GPS
</div>
${weatherLine}
</div>
<button id="qg-close" style="background:var(--c-border);border:none;border-radius:50%;
width:32px;height:32px;cursor:pointer;display:flex;align-items:center;justify-content:center">
<button id="qg-close" class="w3-close-btn--lg">
<svg class="ph-icon" style="width:16px;height:16px"><use href="/icons/phosphor.svg#x"></use></svg>
</button>
</div>
@ -459,20 +438,13 @@ window.Worlds = (() => {
<div style="font-size:var(--text-sm);font-weight:600;margin-bottom:10px">Dauer</div>
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:24px">
${durations.map(d => `
<button class="qg-dur" data-min="${d}"
style="padding:12px 6px;border-radius:12px;border:2px solid ${d === selectedMin ? 'var(--c-primary)' : 'var(--c-border)'};
background:${d === selectedMin ? 'var(--c-primary-subtle)' : 'var(--c-bg-card)'};
cursor:pointer;font-weight:700;font-size:var(--text-sm);
color:${d === selectedMin ? 'var(--c-primary)' : 'var(--c-text)'}">
<button class="qg-dur w3-dur-btn${d === selectedMin ? ' active' : ''}" data-min="${d}">
${d} min
</button>
`).join('')}
</div>
<button id="qg-submit" style="width:100%;padding:16px;border-radius:14px;
background:var(--c-primary);color:white;border:none;cursor:pointer;
font-size:var(--text-base);font-weight:700;
display:flex;align-items:center;justify-content:center;gap:8px">
<button id="qg-submit" class="w3-submit-btn">
<svg class="ph-icon" style="width:1.2rem;height:1.2rem"><use href="/icons/phosphor.svg#check"></use></svg>
Eintragen
</button>
@ -490,10 +462,7 @@ window.Worlds = (() => {
btn.addEventListener('click', () => {
selectedMin = parseInt(btn.dataset.min);
ov.querySelectorAll('.qg-dur').forEach(b => {
const active = parseInt(b.dataset.min) === selectedMin;
b.style.borderColor = active ? 'var(--c-primary)' : 'var(--c-border)';
b.style.background = active ? 'var(--c-primary-subtle)' : 'var(--c-bg-card)';
b.style.color = active ? 'var(--c-primary)' : 'var(--c-text)';
b.classList.toggle('active', parseInt(b.dataset.min) === selectedMin);
});
});
});