Fix: Design-System-Regression v1102 — .hidden(!important) vs style.display app-weit
Rene: 'Tagebuch Kalenderansicht/Karte nicht mehr da' — Root-Cause: 459cd42
ersetzte style="display:none" durch class="hidden", aber die Show-Pfade
setzten weiter style.display. .hidden hat !important und gewinnt immer
(gleiche Klasse wie Filter-Panel-Hotfix v1242). Prod-Logs bewiesen: kein
einziger /diary/calendar- oder /locations-Request kam je an.
Unsichtbar seit v1102, jetzt per classList gefixt:
- diary: Stats-Bar mit View-Switcher (Liste/Medien/Kalender/Karte) + Medien-Grid neuer Eintrag
- health: KI-Tierarzt-Ergebnis erschien nie
- walks: Challenge-/Stamm-Gassi-Tabs leer
- welcome: iOS-Panel der Desktop-Install-Anleitung
- wiki: Fotos-Mod-Badge + Foto-Fallback (via app.js data-fb show-el/sibling-Handler)
- routes: Filter-Badge; breeder: Fotos-Section
Zweite Fehlerklasse aus demselben Sprint: doppelte class-Attribute
(class="x" id=… class="hidden") — Browser verwirft das zweite Attribut.
87 Vorkommen in 23 Dateien zusammengeführt; betroffene Show/Hide-Pfade
(ev-map, rk-mine/nearby-group, chat-partner-dot, eh-panel, zh-section)
auf classList umgestellt.
This commit is contained in:
parent
5acbaaa97b
commit
178aef7fb0
32 changed files with 197 additions and 188 deletions
|
|
@ -86,14 +86,14 @@
|
|||
<title>Ban Yaro</title>
|
||||
|
||||
<!-- Theme + theme-color Statusleiste vor CSS setzen -->
|
||||
<script src="/js/boot-early.js?v=1251"></script>
|
||||
<script src="/js/boot-early.js?v=1252"></script>
|
||||
|
||||
<!-- CSS: Reihenfolge ist wichtig — ?v= zwingt Browser zur Neuladung -->
|
||||
<link rel="stylesheet" href="/css/design-system.css?v=1251">
|
||||
<link rel="stylesheet" href="/css/layout.css?v=1251">
|
||||
<link rel="stylesheet" href="/css/components.css?v=1251">
|
||||
<link rel="stylesheet" href="/css/utilities.css?v=1251">
|
||||
<link rel="stylesheet" href="/css/lists.css?v=1251">
|
||||
<link rel="stylesheet" href="/css/design-system.css?v=1252">
|
||||
<link rel="stylesheet" href="/css/layout.css?v=1252">
|
||||
<link rel="stylesheet" href="/css/components.css?v=1252">
|
||||
<link rel="stylesheet" href="/css/utilities.css?v=1252">
|
||||
<link rel="stylesheet" href="/css/lists.css?v=1252">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
@ -612,11 +612,11 @@
|
|||
<div id="modal-container"></div>
|
||||
|
||||
<!-- JS: Reihenfolge ist wichtig — erst Basis, dann Features -->
|
||||
<script src="/js/api.js?v=1251"></script>
|
||||
<script src="/js/ui.js?v=1251"></script>
|
||||
<script src="/js/app.js?v=1251"></script>
|
||||
<script src="/js/worlds.js?v=1251"></script>
|
||||
<script src="/js/offline-indicator.js?v=1251"></script>
|
||||
<script src="/js/api.js?v=1252"></script>
|
||||
<script src="/js/ui.js?v=1252"></script>
|
||||
<script src="/js/app.js?v=1252"></script>
|
||||
<script src="/js/worlds.js?v=1252"></script>
|
||||
<script src="/js/offline-indicator.js?v=1252"></script>
|
||||
|
||||
<!-- Feature-Seiten werden lazy geladen -->
|
||||
|
||||
|
|
@ -626,7 +626,7 @@
|
|||
|
||||
|
||||
<!-- Boot: Offline-Banner + SW-Registration (extrahiert für CSP) -->
|
||||
<script src="/js/boot.js?v=1251"></script>
|
||||
<script src="/js/boot.js?v=1252"></script>
|
||||
|
||||
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Router, State-Management, Navigation, Initialisierung.
|
||||
============================================================ */
|
||||
|
||||
const APP_VER = '1251'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VER = '1252'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt
|
||||
window.APP_VER = APP_VER; // global verfügbar für andere Module (z.B. offline-indicator)
|
||||
window.APP_VERSION = APP_VERSION;
|
||||
|
|
@ -469,12 +469,15 @@ const App = (() => {
|
|||
break;
|
||||
case 'sibling':
|
||||
el.style.display = 'none';
|
||||
if (el.nextElementSibling) el.nextElementSibling.style.display = 'flex';
|
||||
if (el.nextElementSibling) {
|
||||
el.nextElementSibling.classList.remove('hidden'); // .hidden hat !important
|
||||
el.nextElementSibling.style.display = 'flex';
|
||||
}
|
||||
break;
|
||||
case 'show-el': {
|
||||
el.style.display = 'none';
|
||||
const t = el.dataset.fbEl && document.getElementById(el.dataset.fbEl);
|
||||
if (t) t.style.display = 'flex';
|
||||
if (t) { t.classList.remove('hidden'); t.style.display = 'flex'; } // .hidden hat !important
|
||||
break;
|
||||
}
|
||||
case 'emoji':
|
||||
|
|
|
|||
|
|
@ -745,7 +745,7 @@ window.Page_admin = (() => {
|
|||
|
||||
<div class="card p-4">
|
||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0;line-height:1.6">
|
||||
<svg class="ph-icon" aria-hidden="true" class="text-primary">
|
||||
<svg class="ph-icon text-primary" aria-hidden="true">
|
||||
<use href="/icons/phosphor.svg#info"></use>
|
||||
</svg>
|
||||
Ersten Admin per SQL setzen:
|
||||
|
|
@ -875,12 +875,12 @@ window.Page_admin = (() => {
|
|||
<!-- Aktionen -->
|
||||
<div style="display:flex;gap:var(--space-1);flex-shrink:0">
|
||||
${u.is_banned
|
||||
? `<button class="btn btn-sm btn-ghost adm-unban" data-uid="${u.id}" data-name="${UI.escape(u.name)}"
|
||||
title="Sperre aufheben" class="text-success">
|
||||
? `<button class="btn btn-sm btn-ghost adm-unban text-success" data-uid="${u.id}" data-name="${UI.escape(u.name)}"
|
||||
title="Sperre aufheben">
|
||||
<svg class="ph-icon"><use href="/icons/phosphor.svg#lock-open"></use></svg>
|
||||
</button>`
|
||||
: `<button class="btn btn-sm btn-ghost adm-ban" data-uid="${u.id}" data-name="${UI.escape(u.name)}"
|
||||
title="Sperren" class="text-danger">
|
||||
: `<button class="btn btn-sm btn-ghost adm-ban text-danger" data-uid="${u.id}" data-name="${UI.escape(u.name)}"
|
||||
title="Sperren">
|
||||
<svg class="ph-icon"><use href="/icons/phosphor.svg#lock"></use></svg>
|
||||
</button>`
|
||||
}
|
||||
|
|
@ -895,9 +895,9 @@ window.Page_admin = (() => {
|
|||
title="Abo-Stufe ändern">
|
||||
<svg class="ph-icon"><use href="/icons/phosphor.svg#star"></use></svg>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-ghost adm-delete" data-uid="${u.id}"
|
||||
<button class="btn btn-sm btn-ghost adm-delete text-danger" data-uid="${u.id}"
|
||||
data-name="${UI.escape(u.name)}" title="Löschen"
|
||||
class="text-danger">
|
||||
>
|
||||
<svg class="ph-icon"><use href="/icons/phosphor.svg#trash"></use></svg>
|
||||
</button>
|
||||
` : ''}
|
||||
|
|
@ -1108,9 +1108,9 @@ window.Page_admin = (() => {
|
|||
<svg class="ph-icon"><use href="/icons/phosphor.svg#${r.resolved ? 'arrow-square-out' : 'check'}"></use></svg>
|
||||
</button>
|
||||
${!r.resolved ? `
|
||||
<button class="btn btn-sm btn-ghost adm-del-content"
|
||||
<button class="btn btn-sm btn-ghost adm-del-content text-danger"
|
||||
data-type="${r.target_type}" data-id="${r.target_id}"
|
||||
title="Inhalt löschen" class="text-danger">
|
||||
title="Inhalt löschen">
|
||||
<svg class="ph-icon"><use href="/icons/phosphor.svg#trash"></use></svg>
|
||||
</button>` : ''}
|
||||
</div>
|
||||
|
|
@ -1193,13 +1193,13 @@ window.Page_admin = (() => {
|
|||
data-locked="${t.is_locked}" title="${t.is_locked ? 'Entsperren' : 'Sperren'}">
|
||||
<svg class="ph-icon"><use href="/icons/phosphor.svg#${t.is_locked ? 'lock-open' : 'lock'}"></use></svg>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-ghost adm-del-thread" data-tid="${t.id}"
|
||||
title="Löschen" class="text-danger">
|
||||
<button class="btn btn-sm btn-ghost adm-del-thread text-danger" data-tid="${t.id}"
|
||||
title="Löschen">
|
||||
<svg class="ph-icon"><use href="/icons/phosphor.svg#trash"></use></svg>
|
||||
</button>
|
||||
` : `
|
||||
<button class="btn btn-sm btn-ghost adm-restore-thread" data-tid="${t.id}"
|
||||
title="Wiederherstellen" class="text-success">
|
||||
<button class="btn btn-sm btn-ghost adm-restore-thread text-success" data-tid="${t.id}"
|
||||
title="Wiederherstellen">
|
||||
<svg class="ph-icon"><use href="/icons/phosphor.svg#arrow-square-out"></use></svg>
|
||||
</button>
|
||||
`}
|
||||
|
|
@ -1712,7 +1712,7 @@ window.Page_admin = (() => {
|
|||
<td class="adm-td">${z.website ? `<a href="${UI.escape(z.website)}" target="_blank" style="color:var(--c-primary);font-size:var(--text-xs)">Link</a>` : '—'}</td>
|
||||
<td class="adm-td" style="text-align:right;white-space:nowrap">
|
||||
<button class="btn btn-sm btn-primary adm-zuchter-approve" data-id="${z.id}" style="margin-right:4px"><svg class="ph-icon" style="width:14px;height:14px" aria-hidden="true"><use href="/icons/phosphor.svg#check"></use></svg> Freigeben</button>
|
||||
<button class="btn btn-sm btn-ghost adm-zuchter-delete" data-id="${z.id}" class="text-danger"><svg class="ph-icon" style="width:14px;height:14px" aria-hidden="true"><use href="/icons/phosphor.svg#x"></use></svg></button>
|
||||
<button class="btn btn-sm btn-ghost adm-zuchter-delete text-danger" data-id="${z.id}"><svg class="ph-icon" style="width:14px;height:14px" aria-hidden="true"><use href="/icons/phosphor.svg#x"></use></svg></button>
|
||||
</td>
|
||||
</tr>`).join('')}
|
||||
</tbody></table></div></div>`;
|
||||
|
|
@ -1747,8 +1747,8 @@ window.Page_admin = (() => {
|
|||
opacity:.5;margin-bottom:var(--space-2)">
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-muted);margin-bottom:var(--space-3)">↑ aktuelles Foto</div>` : ''}
|
||||
<div class="flex-gap-2">
|
||||
<button class="btn btn-sm btn-primary adm-foto-approve" data-id="${f.id}" class="flex-1">✓</button>
|
||||
<button class="btn btn-sm btn-ghost adm-foto-reject" data-id="${f.id}" class="text-danger">✗</button>
|
||||
<button class="btn btn-sm btn-primary adm-foto-approve flex-1" data-id="${f.id}">✓</button>
|
||||
<button class="btn btn-sm btn-ghost adm-foto-reject text-danger" data-id="${f.id}">✗</button>
|
||||
</div>
|
||||
</div>`).join('')}
|
||||
</div>`;
|
||||
|
|
@ -1841,7 +1841,7 @@ window.Page_admin = (() => {
|
|||
<button class="btn btn-sm btn-primary adm-poi-approve" data-id="${e.id}" style="margin-right:4px">
|
||||
${UI.icon('check')}
|
||||
</button>
|
||||
<button class="btn btn-sm btn-ghost adm-poi-reject" data-id="${e.id}" class="text-danger">
|
||||
<button class="btn btn-sm btn-ghost adm-poi-reject text-danger" data-id="${e.id}">
|
||||
${UI.icon('x')}
|
||||
</button>
|
||||
</td>
|
||||
|
|
@ -2024,9 +2024,9 @@ window.Page_admin = (() => {
|
|||
data-uid="${a.user_id || a.id}" data-name="${UI.escape(a.name)}">
|
||||
${UI.icon('check')} Freischalten
|
||||
</button>
|
||||
<button class="btn btn-sm btn-ghost adm-breeder-reject"
|
||||
<button class="btn btn-sm btn-ghost adm-breeder-reject text-danger"
|
||||
data-uid="${a.user_id || a.id}" data-name="${UI.escape(a.name)}"
|
||||
class="text-danger">
|
||||
>
|
||||
${UI.icon('x')} Ablehnen
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -2170,9 +2170,9 @@ window.Page_admin = (() => {
|
|||
${b.verified_at ? new Date(b.verified_at).toLocaleDateString('de-DE') : '—'}
|
||||
</td>
|
||||
<td style="padding:var(--space-2) var(--space-3)">
|
||||
<button class="btn btn-sm btn-ghost adm-breeder-tier-btn"
|
||||
<button class="btn btn-sm btn-ghost adm-breeder-tier-btn text-xs"
|
||||
data-uid="${b.id}" data-name="${UI.escape(b.name)}" data-tier="${UI.escape(b.subscription_tier || 'standard')}"
|
||||
class="text-xs">
|
||||
>
|
||||
Abo
|
||||
</button>
|
||||
</td>
|
||||
|
|
@ -2251,8 +2251,8 @@ window.Page_admin = (() => {
|
|||
${UI.escape(j.trigger)}
|
||||
</td>
|
||||
<td class="adm-td text-right">
|
||||
<button class="btn btn-sm btn-ghost adm-job-trigger adm-icon-btn" data-id="${UI.escape(j.id)}" data-name="${UI.escape(j.name)}"
|
||||
title="Jetzt ausführen" class="text-primary">
|
||||
<button class="btn btn-sm btn-ghost adm-job-trigger adm-icon-btn text-primary" data-id="${UI.escape(j.id)}" data-name="${UI.escape(j.name)}"
|
||||
title="Jetzt ausführen">
|
||||
${UI.icon('play')}
|
||||
</button>
|
||||
</td>
|
||||
|
|
@ -3203,10 +3203,10 @@ window.Page_admin = (() => {
|
|||
border:1.5px solid var(--c-border);border-radius:var(--radius-md);
|
||||
background:var(--c-surface);color:var(--c-text);font-size:var(--text-sm)">
|
||||
<div class="flex-1"></div>
|
||||
<button class="btn btn-secondary btn-sm adm-hilfe-edit-cancel" data-id="${a.id}"
|
||||
class="text-xs">Abbrechen</button>
|
||||
<button class="btn btn-primary btn-sm adm-hilfe-edit-save" data-id="${a.id}"
|
||||
class="text-xs">Speichern</button>
|
||||
<button class="btn btn-secondary btn-sm adm-hilfe-edit-cancel text-xs" data-id="${a.id}"
|
||||
>Abbrechen</button>
|
||||
<button class="btn btn-primary btn-sm adm-hilfe-edit-save text-xs" data-id="${a.id}"
|
||||
>Speichern</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3839,8 +3839,8 @@ window.Page_admin = (() => {
|
|||
</button>`);
|
||||
}
|
||||
if (inv.status === 'sent') {
|
||||
actions.push(`<button class="btn btn-sm btn-ghost adm-inv-send" data-id="${inv.id}" data-num="${UI.escape(inv.invoice_number)}" title="Erneut senden"
|
||||
class="text-muted">
|
||||
actions.push(`<button class="btn btn-sm btn-ghost adm-inv-send text-muted" data-id="${inv.id}" data-num="${UI.escape(inv.invoice_number)}" title="Erneut senden"
|
||||
>
|
||||
${UI.icon('paper-plane-tilt')} Erneut senden
|
||||
</button>`);
|
||||
}
|
||||
|
|
@ -3848,8 +3848,8 @@ window.Page_admin = (() => {
|
|||
actions.push(`<button class="btn btn-sm btn-secondary adm-inv-pay" data-id="${inv.id}" data-amount="${inv.amount_gross}" title="Als bezahlt markieren">
|
||||
${UI.icon('check-circle')} Bezahlt
|
||||
</button>`);
|
||||
actions.push(`<button class="btn btn-sm btn-ghost adm-inv-cancel" data-id="${inv.id}" data-num="${UI.escape(inv.invoice_number)}"
|
||||
class="text-danger" title="Stornieren">
|
||||
actions.push(`<button class="btn btn-sm btn-ghost adm-inv-cancel text-danger" data-id="${inv.id}" data-num="${UI.escape(inv.invoice_number)}"
|
||||
title="Stornieren">
|
||||
${UI.icon('x-circle')} Storno
|
||||
</button>`);
|
||||
}
|
||||
|
|
@ -4067,7 +4067,7 @@ window.Page_admin = (() => {
|
|||
footer: `
|
||||
<div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
|
||||
${isLocked
|
||||
? `<button class="btn btn-secondary" data-modal-close class="w-full">Schließen</button>`
|
||||
? `<button class="btn btn-secondary w-full" data-modal-close>Schließen</button>`
|
||||
: `<div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-2)">
|
||||
<button class="btn btn-secondary" data-modal-close>Abbrechen</button>
|
||||
<button class="btn btn-primary" form="${id}" type="submit" style="min-width:0">
|
||||
|
|
@ -4112,8 +4112,8 @@ window.Page_admin = (() => {
|
|||
itemEl.className = 'adm-inv-item-row';
|
||||
itemEl.style.cssText = 'display:grid;grid-template-columns:1fr 60px 100px auto;gap:var(--space-2);align-items:center';
|
||||
itemEl.innerHTML = `
|
||||
<input class="form-control inv-item-desc" type="text" placeholder="Beschreibung *"
|
||||
value="${UI.escape(desc)}" class="text-sm">
|
||||
<input class="form-control inv-item-desc text-sm" type="text" placeholder="Beschreibung *"
|
||||
value="${UI.escape(desc)}">
|
||||
<input class="form-control inv-item-qty" type="number" min="1" value="${qty}"
|
||||
style="font-size:var(--text-sm);text-align:right" title="Menge">
|
||||
<input class="form-control inv-item-price" type="number" min="0" step="0.01" value="${price.toFixed(2)}"
|
||||
|
|
|
|||
|
|
@ -196,8 +196,8 @@ window.Page_breeder_editor = (() => {
|
|||
<label class="btn btn-secondary btn-sm" style="cursor:pointer">
|
||||
<svg class="ph-icon" style="width:14px;height:14px"><use href="/icons/phosphor.svg#upload-simple"></use></svg>
|
||||
Upload
|
||||
<input type="file" class="be-litter-input" data-litter-id="${l.id}"
|
||||
data-label="${UI.escape(label)}" accept="image/*,video/*" class="hidden">
|
||||
<input type="file" class="be-litter-input hidden" data-litter-id="${l.id}"
|
||||
data-label="${UI.escape(label)}" accept="image/*,video/*">
|
||||
</label>
|
||||
</div>
|
||||
</div>`;
|
||||
|
|
|
|||
|
|
@ -390,6 +390,7 @@ window.Page_breeder = (() => {
|
|||
</a>`).join('')}
|
||||
</div>
|
||||
</div>`;
|
||||
section.classList.remove('hidden'); // Template startet mit .hidden (!important)
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ window.Page_chat = (() => {
|
|||
</button>`}
|
||||
<div style="position:relative;flex-shrink:0">
|
||||
<div class="chat-conv-avatar" id="chat-partner-av" style="width:32px;height:32px;font-size:var(--text-sm)">?</div>
|
||||
<span class="online-dot chat-avatar-dot" id="chat-partner-dot" class="hidden"></span>
|
||||
<span class="online-dot chat-avatar-dot hidden" id="chat-partner-dot"></span>
|
||||
</div>
|
||||
<span class="chat-thread-partner" id="chat-partner-name">…</span>
|
||||
</div>
|
||||
|
|
@ -265,7 +265,7 @@ window.Page_chat = (() => {
|
|||
const dotEl = document.getElementById('chat-partner-dot');
|
||||
if (nameEl) nameEl.textContent = data.partner_name;
|
||||
if (avEl) avEl.textContent = (data.partner_name || '?')[0].toUpperCase();
|
||||
if (dotEl) dotEl.style.display = data.partner_online ? '' : 'none';
|
||||
if (dotEl) dotEl.classList.toggle('hidden', !data.partner_online);
|
||||
|
||||
if (!data.messages.length) {
|
||||
el.innerHTML = `
|
||||
|
|
@ -304,7 +304,7 @@ window.Page_chat = (() => {
|
|||
|
||||
// Online-Dot aktualisieren
|
||||
const dotEl = document.getElementById('chat-partner-dot');
|
||||
if (dotEl) dotEl.style.display = data.partner_online ? '' : 'none';
|
||||
if (dotEl) dotEl.classList.toggle('hidden', !data.partner_online);
|
||||
|
||||
await API.chat.markRead(_convId).catch(() => {});
|
||||
await _updateChatBadge();
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ window.Page_diary = (() => {
|
|||
const bar = _container.querySelector('#diary-stats-bar');
|
||||
if (!bar) return;
|
||||
const s = _totalStats;
|
||||
if (!s && _entries.length === 0) { bar.style.display = 'none'; return; }
|
||||
if (!s && _entries.length === 0) { bar.classList.add('hidden'); return; }
|
||||
const entries = s?.entries ?? _entries.length;
|
||||
const photos = s?.photos ?? _entries.reduce((n, e) => n + _allMedia(e).length, 0);
|
||||
const days = s?.days ?? new Set(_entries.map(e => e.datum).filter(Boolean)).size;
|
||||
|
|
@ -425,7 +425,8 @@ window.Page_diary = (() => {
|
|||
</button>
|
||||
</div>
|
||||
`;
|
||||
bar.style.display = 'flex';
|
||||
// .hidden hat !important → nur per classList togglen (style.display verliert immer)
|
||||
bar.classList.remove('hidden');
|
||||
|
||||
bar.querySelectorAll('.diary-view-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
|
|
@ -1332,8 +1333,9 @@ window.Page_diary = (() => {
|
|||
function _renderNewGrid() {
|
||||
const grid = document.getElementById('diary-new-media-grid');
|
||||
if (!grid) return;
|
||||
if (_newFiles.length === 0) { grid.style.display = 'none'; grid.innerHTML = ''; return; }
|
||||
grid.style.cssText = 'display:grid;grid-template-columns:repeat(auto-fill,minmax(90px,1fr));gap:8px;margin-bottom:8px';
|
||||
if (_newFiles.length === 0) { grid.classList.add('hidden'); grid.innerHTML = ''; return; }
|
||||
// .hidden hat !important → classList togglen; Grid-Layout kommt aus .diary-media-grid
|
||||
grid.classList.remove('hidden');
|
||||
grid.innerHTML = _newFiles.map((f, i) => {
|
||||
const objUrl = URL.createObjectURL(f);
|
||||
const thumb = f.type === 'application/pdf' || f.name?.endsWith('.pdf')
|
||||
|
|
|
|||
|
|
@ -559,8 +559,8 @@ window.Page_dog_profile = (() => {
|
|||
value="${defaultUntil}" min="${today}">
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm w-full" id="sa-grant-btn"
|
||||
class="mt-2">
|
||||
<button class="btn btn-primary btn-sm w-full mt-2" id="sa-grant-btn"
|
||||
>
|
||||
Zugang gewähren
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -615,7 +615,7 @@ window.Page_dog_profile = (() => {
|
|||
</div>`,
|
||||
footer: `
|
||||
<div class="w3-btn-stack">
|
||||
<button class="btn btn-primary" id="chip-edit-save-btn" class="w-full">Speichern</button>
|
||||
<button class="btn btn-primary w-full" id="chip-edit-save-btn">Speichern</button>
|
||||
<button class="btn btn-secondary" data-modal-close>Abbrechen</button>
|
||||
</div>`,
|
||||
});
|
||||
|
|
@ -672,7 +672,7 @@ window.Page_dog_profile = (() => {
|
|||
|
||||
const footer = `
|
||||
<div class="w3-btn-stack">
|
||||
${hasPhoto ? `<button class="btn btn-primary" id="pe-save-btn" class="w-full">Speichern</button>` : ''}
|
||||
${hasPhoto ? `<button class="btn btn-primary w-full" id="pe-save-btn">Speichern</button>` : ''}
|
||||
<div class="flex-gap-2">
|
||||
${hasPhoto ? `<button class="btn btn-danger" id="pe-delete-btn">${UI.icon('trash')} Löschen</button>` : ''}
|
||||
<button class="btn btn-secondary flex-1" data-modal-close>Abbrechen</button>
|
||||
|
|
@ -945,8 +945,8 @@ window.Page_dog_profile = (() => {
|
|||
<div id="share-link-result" style="display:none;margin-top:var(--space-4)">
|
||||
<label class="form-label">Einladungslink</label>
|
||||
<div style="display:flex;gap:var(--space-2);align-items:center">
|
||||
<input class="form-control" id="share-link-input" type="text" readonly
|
||||
class="text-xs">
|
||||
<input class="form-control text-xs" id="share-link-input" type="text" readonly
|
||||
>
|
||||
<button class="btn btn-secondary btn-sm" id="share-link-copy">
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#clipboard-text"></use></svg>
|
||||
</button>
|
||||
|
|
@ -1509,11 +1509,11 @@ window.Page_dog_profile = (() => {
|
|||
</div>
|
||||
${r.beschreibung ? `<div class="rasse-result-desc">${UI.escape(r.beschreibung)}</div>` : ''}
|
||||
<div style="display:flex;gap:var(--space-2);margin-top:var(--space-3);flex-wrap:wrap">
|
||||
${isTop ? `<button class="btn btn-primary btn-sm" data-action="uebernehmen"
|
||||
data-rasse="${UI.escape(r.name)}" class="flex-1">
|
||||
${isTop ? `<button class="btn btn-primary btn-sm flex-1" data-action="uebernehmen"
|
||||
data-rasse="${UI.escape(r.name)}">
|
||||
Rasse übernehmen
|
||||
</button>` : `<button class="btn btn-secondary btn-sm" data-action="uebernehmen"
|
||||
data-rasse="${UI.escape(r.name)}" class="flex-1">
|
||||
</button>` : `<button class="btn btn-secondary btn-sm flex-1" data-action="uebernehmen"
|
||||
data-rasse="${UI.escape(r.name)}">
|
||||
Diese wählen
|
||||
</button>`}
|
||||
${r.wiki_slug ? `<button class="btn btn-ghost btn-sm" data-action="wiki"
|
||||
|
|
@ -1711,8 +1711,8 @@ window.Page_dog_profile = (() => {
|
|||
<p style="font-size:var(--text-sm);margin:0">Noch keine Impfungen eingetragen.<br>Klicke auf „+ Eintragen" um loszulegen.</p>
|
||||
</div>`
|
||||
: vaccs.map(v => `
|
||||
<div class="pp-vacc-row" data-id="${v.id}"
|
||||
class="pp-data-row">
|
||||
<div class="pp-vacc-row pp-data-row" data-id="${v.id}"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div style="font-weight:600;font-size:var(--text-sm)">${UI.escape(v.krankheit)}</div>
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);margin-top:2px">
|
||||
|
|
@ -1748,8 +1748,8 @@ window.Page_dog_profile = (() => {
|
|||
<p style="font-size:var(--text-sm);margin:0">Noch keine Medikamente eingetragen.<br>Klicke auf „+ Eintragen" um loszulegen.</p>
|
||||
</div>`
|
||||
: meds.map(m => `
|
||||
<div class="pp-med-row" data-id="${m.id}"
|
||||
class="pp-data-row">
|
||||
<div class="pp-med-row pp-data-row" data-id="${m.id}"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div style="font-weight:600;font-size:var(--text-sm)">${UI.escape(m.name)}</div>
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);margin-top:2px">
|
||||
|
|
@ -2005,8 +2005,8 @@ window.Page_dog_profile = (() => {
|
|||
Dieser Link ist 30 Tage gültig. Tierärzte und Sitter können den Pass ohne Login öffnen.
|
||||
</p>
|
||||
<div style="display:flex;gap:var(--space-2);align-items:center">
|
||||
<input id="pp-sharelink-input" class="form-control" type="text" readonly
|
||||
value="${UI.escape(url)}" class="text-xs">
|
||||
<input id="pp-sharelink-input" class="form-control text-xs" type="text" readonly
|
||||
value="${UI.escape(url)}">
|
||||
<button class="btn btn-secondary btn-sm" id="pp-sharelink-copy" style="flex-shrink:0">
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#clipboard-text"></use></svg>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -567,9 +567,9 @@ window.Page_ernaehrung = (() => {
|
|||
'Ist Getreide im Futter schlecht?',
|
||||
'Welche Leckerlis sind gesund?',
|
||||
].map(q => `
|
||||
<button class="btn btn-sm btn-secondary ern-ki-vorschlag"
|
||||
<button class="btn btn-sm btn-secondary ern-ki-vorschlag text-xs"
|
||||
data-q="${UI.escape(q)}"
|
||||
class="text-xs">${UI.escape(q)}</button>
|
||||
>${UI.escape(q)}</button>
|
||||
`).join('')}
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -254,13 +254,13 @@ window.Page_erste_hilfe = (() => {
|
|||
</div>
|
||||
|
||||
${KATEGORIEN.map(k => `
|
||||
<div class="eh-tab-panel" id="eh-panel-${k.id}" class="hidden">
|
||||
<div class="eh-tab-panel hidden" id="eh-panel-${k.id}">
|
||||
${k.eintraege.map((e, i) => _renderEintrag(e, k.id, i, k.color)).join('')}
|
||||
</div>
|
||||
`).join('')}
|
||||
|
||||
<div style="margin-top:var(--space-6);padding:var(--space-4);background:var(--c-surface-2);border-radius:var(--radius-md);font-size:var(--text-sm);color:var(--c-text-secondary);line-height:1.6">
|
||||
<svg class="ph-icon" aria-hidden="true" class="text-primary"><use href="/icons/phosphor.svg#info"></use></svg>
|
||||
<svg class="ph-icon text-primary" aria-hidden="true"><use href="/icons/phosphor.svg#info"></use></svg>
|
||||
Diese Inhalte ersetzen keinen Tierarztbesuch. Im Zweifel immer sofort zum Tierarzt oder den tierärztlichen Notdienst anrufen.
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -346,7 +346,7 @@ window.Page_erste_hilfe = (() => {
|
|||
return `
|
||||
<div class="card" style="padding:0;overflow:hidden;margin-bottom:var(--space-4)">
|
||||
<div style="padding:var(--space-3) var(--space-4);background:var(--c-surface-2);font-weight:var(--weight-semibold);font-size:var(--text-sm);display:flex;align-items:center;gap:var(--space-2)">
|
||||
<svg class="ph-icon" aria-hidden="true" class="text-primary"><use href="/icons/phosphor.svg#list-bullets"></use></svg>
|
||||
<svg class="ph-icon text-primary" aria-hidden="true"><use href="/icons/phosphor.svg#list-bullets"></use></svg>
|
||||
Schnellübersicht: Was tun bei …
|
||||
</div>
|
||||
<div style="overflow-x:auto">
|
||||
|
|
@ -433,7 +433,7 @@ window.Page_erste_hilfe = (() => {
|
|||
btn.style.color = active ? '#fff' : kat.color;
|
||||
});
|
||||
_container.querySelectorAll('.eh-tab-panel').forEach(panel => {
|
||||
panel.style.display = panel.id === `eh-panel-${id}` ? 'block' : 'none';
|
||||
panel.classList.toggle('hidden', panel.id !== `eh-panel-${id}`); // .hidden hat !important
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ window.Page_events = (() => {
|
|||
</div>
|
||||
|
||||
<div class="events-list" id="ev-list"></div>
|
||||
<div class="events-map" id="ev-map" class="hidden"></div>
|
||||
<div class="events-map hidden" id="ev-map"></div>
|
||||
`;
|
||||
|
||||
_container.addEventListener('click', _onClick);
|
||||
|
|
@ -228,10 +228,10 @@ window.Page_events = (() => {
|
|||
</div>
|
||||
<div style="display:flex;flex-direction:column;align-items:flex-end;gap:var(--space-1)">
|
||||
${isOwn ? `<button class="btn-icon" data-ev-edit="${ev.id}" title="Bearbeiten">${_icon('pencil-simple')}</button>` : ''}
|
||||
${_state.user ? `<button class="btn-icon ev-note-btn" data-ev-note-id="${ev.id}"
|
||||
${_state.user ? `<button class="btn-icon ev-note-btn text-muted" data-ev-note-id="${ev.id}"
|
||||
data-ev-note-label="${UI.escape(ev.titel + ' ' + ev.datum)}"
|
||||
data-ev-note-ort="${UI.escape(ev.ort_name || '')}"
|
||||
title="Notiz" class="text-muted">
|
||||
title="Notiz">
|
||||
${_icon('note-pencil')}</button>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -507,7 +507,7 @@ window.Page_events = (() => {
|
|||
|
||||
const footer = `
|
||||
<div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
|
||||
<button class="btn btn-primary" type="submit" form="${id}" id="ev-submit-btn" class="w-full">
|
||||
<button class="btn btn-primary w-full" type="submit" form="${id}" id="ev-submit-btn">
|
||||
${isEdit ? 'Speichern' : 'Event erstellen'}
|
||||
</button>
|
||||
<div class="flex-gap-2">
|
||||
|
|
@ -605,7 +605,7 @@ window.Page_events = (() => {
|
|||
const mapEl = document.getElementById('ev-map');
|
||||
if (_view === 'karte') {
|
||||
listEl.style.display = 'none';
|
||||
mapEl.style.display = 'block';
|
||||
mapEl.classList.remove('hidden'); // .hidden hat !important → nur classList
|
||||
// Erst div sichtbar machen, dann Karte initialisieren
|
||||
_renderMap(_filtered());
|
||||
} else {
|
||||
|
|
@ -616,7 +616,7 @@ window.Page_events = (() => {
|
|||
_clusterGroup = null;
|
||||
_markers = [];
|
||||
}
|
||||
mapEl.style.display = 'none';
|
||||
mapEl.classList.add('hidden');
|
||||
listEl.style.display = '';
|
||||
_renderList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ function _fmtDate(iso) {
|
|||
<h2 class="forum-header-title">Forum</h2>
|
||||
<div class="forum-header-actions">
|
||||
${isMod ? `<button class="btn btn-ghost btn-sm" id="forum-mod-btn" title="Moderationsberichte">${UI.icon('warning')}</button>` : ''}
|
||||
<button class="btn btn-ghost btn-sm" id="forum-rules-btn" title="Regeln & Netiquette" class="text-muted">${UI.icon('info')} Regeln</button>
|
||||
<button class="btn btn-ghost btn-sm text-muted" id="forum-rules-btn" title="Regeln & Netiquette">${UI.icon('info')} Regeln</button>
|
||||
<button class="btn btn-primary btn-sm" id="forum-new-btn">${UI.icon('plus')} Neues Thema</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -271,9 +271,9 @@ function _fmtDate(iso) {
|
|||
: `<div class="hdm-section">
|
||||
<h3 class="hdm-section-title">Für welchen Hund möchtest du abstimmen?</h3>
|
||||
<div class="hdm-kandidaten-search">
|
||||
<input type="search" id="hdm-search" class="form-control"
|
||||
<input type="search" id="hdm-search" class="form-control text-sm"
|
||||
placeholder="Name oder Rasse suchen …" autocomplete="off"
|
||||
class="text-sm">
|
||||
>
|
||||
</div>
|
||||
<div id="hdm-kandidaten-grid" class="hdm-vote-grid">
|
||||
${UI.skeleton(3)}
|
||||
|
|
@ -1293,7 +1293,7 @@ function _fmtDate(iso) {
|
|||
<div class="text-xs-muted">
|
||||
von ${UI.escape(r.melder_name || '?')} · ${_fmtDate(r.created_at)}
|
||||
</div>
|
||||
<button class="btn btn-sm btn-secondary forum-resolve-btn" data-id="${r.id}" class="mt-2">
|
||||
<button class="btn btn-sm btn-secondary forum-resolve-btn mt-2" data-id="${r.id}">
|
||||
${UI.icon('check')} Erledigt
|
||||
</button>
|
||||
</div>`).join('')}
|
||||
|
|
|
|||
|
|
@ -657,8 +657,8 @@ window.Page_friends = (() => {
|
|||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#chat-circle-dots"></use></svg>
|
||||
Nachricht schreiben
|
||||
</button>
|
||||
<button class="btn btn-ghost" id="modal-remove-btn" form=""
|
||||
class="text-danger">
|
||||
<button class="btn btn-ghost text-danger" id="modal-remove-btn" form=""
|
||||
>
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#user-minus"></use></svg>
|
||||
Entfernen
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -2919,8 +2919,8 @@ function _showPoiKorrekturModal(osmId, poiName, currentOh) {
|
|||
<form id="poi-korrektur-form">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Aktuelle Angabe</label>
|
||||
<input class="form-control" type="text" value="${UI.escape(currentOh)}" disabled
|
||||
class="text-muted">
|
||||
<input class="form-control text-muted" type="text" value="${UI.escape(currentOh)}" disabled
|
||||
>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Korrekte Öffnungszeiten *</label>
|
||||
|
|
@ -3009,7 +3009,8 @@ function _showPoiKorrekturModal(osmId, poiName, currentOh) {
|
|||
}
|
||||
|
||||
await UI.asyncButton(btn, async () => {
|
||||
resultEl.style.display = 'none';
|
||||
// .hidden hat !important → nur per classList togglen (style.display verliert immer)
|
||||
resultEl.classList.add('hidden');
|
||||
resultEl.innerHTML = '';
|
||||
|
||||
let result;
|
||||
|
|
@ -3040,7 +3041,7 @@ function _showPoiKorrekturModal(osmId, poiName, currentOh) {
|
|||
UI.toast.error(err.message || 'Fehler bei der KI-Anfrage.');
|
||||
return;
|
||||
}
|
||||
resultEl.style.display = '';
|
||||
resultEl.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3074,7 +3075,7 @@ function _showPoiKorrekturModal(osmId, poiName, currentOh) {
|
|||
<strong>⚠️ Dies ist keine medizinische Diagnose.</strong>
|
||||
Bei ernsthaften Symptomen sofort zum Tierarzt.
|
||||
</div>`;
|
||||
resultEl.style.display = '';
|
||||
resultEl.classList.remove('hidden');
|
||||
|
||||
// Submit-Button ausblenden wenn Limit erschöpft
|
||||
if (result.anfragen_heute >= result.limit) {
|
||||
|
|
|
|||
|
|
@ -191,9 +191,9 @@ window.Page_jobs = (() => {
|
|||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Anhänge (optional)</label>
|
||||
<input class="form-control" type="file" name="files" id="jobs-files"
|
||||
<input class="form-control p-2" type="file" name="files" id="jobs-files"
|
||||
multiple accept=".pdf,.jpg,.jpeg,.png,.webp,.mp4,.mov"
|
||||
class="p-2">
|
||||
>
|
||||
<p style="margin:var(--space-1) 0 0;font-size:var(--text-xs);color:var(--c-text-muted)">
|
||||
Beispiel-Posts, Portfolio, kurzes Video von dir und deinem Hund — max. 3 Dateien, je 10 MB.
|
||||
PDF, Bild oder Video.
|
||||
|
|
|
|||
|
|
@ -297,11 +297,11 @@ window.Page_knigge = (() => {
|
|||
</h2>
|
||||
<div class="card">
|
||||
<div style="padding:var(--space-5)">
|
||||
<textarea id="ki-situation-input" class="form-control"
|
||||
<textarea id="ki-situation-input" class="form-control mb-3"
|
||||
rows="3"
|
||||
placeholder="Beschreibe deine Situation…"
|
||||
class="mb-3"></textarea>
|
||||
<button class="btn btn-primary" id="ki-rat-btn" class="w-full">
|
||||
></textarea>
|
||||
<button class="btn btn-primary w-full" id="ki-rat-btn">
|
||||
Rat holen ${UI.icon('robot')}
|
||||
</button>
|
||||
<div id="ki-rat-result" style="margin-top:var(--space-4);display:none"></div>
|
||||
|
|
|
|||
|
|
@ -285,8 +285,8 @@ window.Page_laeufi = (() => {
|
|||
<button class="btn btn-ghost btn-xs laeufi-edit-btn" data-id="${l.id}" title="Bearbeiten">
|
||||
${UI.icon('pencil-simple')}
|
||||
</button>
|
||||
<button class="btn btn-ghost btn-xs laeufi-delete-btn" data-id="${l.id}"
|
||||
title="Löschen" class="text-danger">
|
||||
<button class="btn btn-ghost btn-xs laeufi-delete-btn text-danger" data-id="${l.id}"
|
||||
title="Löschen">
|
||||
${UI.icon('trash')}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -335,7 +335,7 @@ window.Page_laeufi = (() => {
|
|||
</div>
|
||||
<div style="display:flex;gap:var(--space-1);flex-shrink:0">
|
||||
<button class="btn btn-ghost btn-xs deck-edit-btn" data-id="${d.id}" title="Bearbeiten">${UI.icon('pencil-simple')}</button>
|
||||
<button class="btn btn-ghost btn-xs deck-delete-btn" data-id="${d.id}" title="Löschen" class="text-danger">${UI.icon('trash')}</button>
|
||||
<button class="btn btn-ghost btn-xs deck-delete-btn text-danger" data-id="${d.id}" title="Löschen">${UI.icon('trash')}</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Meilensteine -->
|
||||
|
|
@ -542,8 +542,8 @@ window.Page_laeufi = (() => {
|
|||
</td>
|
||||
<td style="padding:var(--space-2);color:var(--c-text-secondary)">${t.labor ? UI.escape(t.labor) : '—'}</td>
|
||||
<td style="padding:var(--space-2);text-align:right">
|
||||
<button class="btn btn-ghost btn-xs prog-delete-btn" data-id="${t.id}"
|
||||
class="text-danger">${UI.icon('trash')}</button>
|
||||
<button class="btn btn-ghost btn-xs prog-delete-btn text-danger" data-id="${t.id}"
|
||||
>${UI.icon('trash')}</button>
|
||||
</td>
|
||||
</tr>`).join('')}
|
||||
</tbody>
|
||||
|
|
|
|||
|
|
@ -385,8 +385,8 @@ window.Page_litters = (() => {
|
|||
<button class="btn btn-ghost btn-sm litters-edit-btn" data-id="${l.id}" title="Bearbeiten">
|
||||
${UI.icon('pencil-simple')}
|
||||
</button>
|
||||
<button class="btn btn-ghost btn-sm litters-delete-btn" data-id="${l.id}" title="Löschen"
|
||||
class="text-danger">
|
||||
<button class="btn btn-ghost btn-sm litters-delete-btn text-danger" data-id="${l.id}" title="Löschen"
|
||||
>
|
||||
${UI.icon('trash')}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -399,8 +399,8 @@ window.Page_litters = (() => {
|
|||
<div id="puppies-inner-${l.id}">
|
||||
<p class="text-sm-muted">Lädt…</p>
|
||||
</div>
|
||||
<button class="btn btn-secondary btn-sm litters-add-puppy-btn" data-id="${l.id}"
|
||||
class="mt-3">
|
||||
<button class="btn btn-secondary btn-sm litters-add-puppy-btn mt-3" data-id="${l.id}"
|
||||
>
|
||||
${UI.icon('plus')} Welpen hinzufügen
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -410,8 +410,8 @@ window.Page_litters = (() => {
|
|||
<div id="waitlist-inner-${l.id}">
|
||||
<p class="text-sm-muted">Lädt…</p>
|
||||
</div>
|
||||
<button class="btn btn-secondary btn-sm litters-add-waitlist-btn" data-id="${l.id}"
|
||||
class="mt-3">
|
||||
<button class="btn btn-secondary btn-sm litters-add-waitlist-btn mt-3" data-id="${l.id}"
|
||||
>
|
||||
${UI.icon('plus')} Interessent eintragen
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -468,7 +468,7 @@ window.Page_litters = (() => {
|
|||
<span class="litters-puppy-name">${p.name ? UI.escape(p.name) : '<em class="text-muted">Unbenannt</em>'}</span>
|
||||
${p.farbe ? `<span style="color:var(--c-text-secondary);font-size:var(--text-xs)">${UI.escape(p.farbe)}</span>` : ''}
|
||||
${_puppyStatusBadge(p.status)}
|
||||
<span class="litters-puppy-last-weight" id="puppy-last-weight-${p.id}" class="text-xs-secondary"></span>
|
||||
<span class="litters-puppy-last-weight text-xs-secondary" id="puppy-last-weight-${p.id}"></span>
|
||||
</div>
|
||||
<div class="litters-puppy-actions">
|
||||
<button class="btn btn-ghost btn-xs litters-puppy-photo-btn" data-litter-id="${litterId}" data-puppy-id="${p.id}"
|
||||
|
|
@ -787,7 +787,7 @@ window.Page_litters = (() => {
|
|||
</div>
|
||||
<div style="display:flex;gap:var(--space-1);flex-shrink:0">
|
||||
<button class="btn btn-ghost btn-xs wl-edit-btn" data-entry-id="${e.id}" title="Bearbeiten">${UI.icon('pencil-simple')}</button>
|
||||
<button class="btn btn-ghost btn-xs wl-delete-btn" data-entry-id="${e.id}" title="Entfernen" class="text-danger">${UI.icon('trash')}</button>
|
||||
<button class="btn btn-ghost btn-xs wl-delete-btn text-danger" data-entry-id="${e.id}" title="Entfernen">${UI.icon('trash')}</button>
|
||||
</div>
|
||||
</div>`).join('')}
|
||||
</div>`;
|
||||
|
|
@ -918,7 +918,7 @@ window.Page_litters = (() => {
|
|||
return `<option value="${h.id}" data-name="${UI.escape(h.name)}" ${currentId == h.id ? 'selected' : ''}>${UI.escape(label)}</option>`;
|
||||
}).join('');
|
||||
return `
|
||||
<select class="form-control" name="${idName}" id="${idName}-sel" class="mb-2">
|
||||
<select class="form-control mb-2" name="${idName}" id="${idName}-sel">
|
||||
<option value="">— ${placeholder} —</option>
|
||||
${opts}
|
||||
</select>
|
||||
|
|
@ -1496,7 +1496,7 @@ window.Page_litters = (() => {
|
|||
Trotzdem fortfahren
|
||||
</button>
|
||||
</div>` : `
|
||||
<button class="btn btn-primary" data-modal-close class="w-full">
|
||||
<button class="btn btn-primary w-full" data-modal-close>
|
||||
${UI.icon('check')} Verstanden
|
||||
</button>`,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -190,10 +190,10 @@ window.Page_moderation = (() => {
|
|||
` : `<div style="font-size:var(--text-xs);color:var(--c-warning);
|
||||
margin-bottom:var(--space-3)">Noch kein Foto vorhanden</div>`}
|
||||
<div class="flex-gap-2">
|
||||
<button class="btn btn-sm btn-primary mod-foto-approve"
|
||||
data-id="${f.id}" class="flex-1"><svg class="ph-icon" style="width:14px;height:14px" aria-hidden="true"><use href="/icons/phosphor.svg#check"></use></svg> Freigeben</button>
|
||||
<button class="btn btn-sm btn-ghost mod-foto-reject"
|
||||
data-id="${f.id}" class="text-danger"><svg class="ph-icon" style="width:14px;height:14px" aria-hidden="true"><use href="/icons/phosphor.svg#x"></use></svg> Ablehnen</button>
|
||||
<button class="btn btn-sm btn-primary mod-foto-approve flex-1"
|
||||
data-id="${f.id}"><svg class="ph-icon" style="width:14px;height:14px" aria-hidden="true"><use href="/icons/phosphor.svg#check"></use></svg> Freigeben</button>
|
||||
<button class="btn btn-sm btn-ghost mod-foto-reject text-danger"
|
||||
data-id="${f.id}"><svg class="ph-icon" style="width:14px;height:14px" aria-hidden="true"><use href="/icons/phosphor.svg#x"></use></svg> Ablehnen</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('')}
|
||||
|
|
@ -322,14 +322,14 @@ window.Page_moderation = (() => {
|
|||
<div style="flex-shrink:0">
|
||||
${canAction
|
||||
? (u.is_banned
|
||||
? `<button class="btn btn-sm btn-ghost mod-unban"
|
||||
? `<button class="btn btn-sm btn-ghost mod-unban text-success"
|
||||
data-uid="${u.id}" data-name="${UI.escape(u.name)}"
|
||||
title="Sperre aufheben" class="text-success">
|
||||
title="Sperre aufheben">
|
||||
${UI.icon('lock-open')}
|
||||
</button>`
|
||||
: `<button class="btn btn-sm btn-ghost mod-ban"
|
||||
: `<button class="btn btn-sm btn-ghost mod-ban text-danger"
|
||||
data-uid="${u.id}" data-name="${UI.escape(u.name)}"
|
||||
title="Sperren" class="text-danger">
|
||||
title="Sperren">
|
||||
${UI.icon('lock')}
|
||||
</button>`)
|
||||
: ''
|
||||
|
|
|
|||
|
|
@ -163,11 +163,11 @@ window.Page_onboarding = (() => {
|
|||
|
||||
<!-- Buttons -->
|
||||
<div class="flex-col-gap-3">
|
||||
<button class="btn btn-primary" id="ob-next-btn" class="w-full">
|
||||
<button class="btn btn-primary w-full" id="ob-next-btn">
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#arrow-right"></use></svg>
|
||||
Los geht's
|
||||
</button>
|
||||
<button class="btn btn-ghost" id="ob-skip-btn" class="w-full">
|
||||
<button class="btn btn-ghost w-full" id="ob-skip-btn">
|
||||
Überspringen
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -255,14 +255,14 @@ window.Page_onboarding = (() => {
|
|||
<button class="btn btn-secondary" id="ob-back-btn">
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#arrow-left"></use></svg>
|
||||
</button>
|
||||
<button type="submit" form="ob-dog-form" class="btn btn-primary" id="ob-save-btn"
|
||||
class="flex-1">
|
||||
<button type="submit" form="ob-dog-form" class="btn btn-primary flex-1" id="ob-save-btn"
|
||||
>
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#dog"></use></svg>
|
||||
Hund anlegen
|
||||
</button>
|
||||
</div>
|
||||
<div style="text-align:center;margin-top:var(--space-3)">
|
||||
<button class="btn btn-ghost" id="ob-skip-btn" class="text-sm">
|
||||
<button class="btn btn-ghost text-sm" id="ob-skip-btn">
|
||||
Ohne Hund fortfahren
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -317,12 +317,12 @@ window.Page_onboarding = (() => {
|
|||
|
||||
<!-- CTA -->
|
||||
<div class="flex-col-gap-3">
|
||||
<button class="btn btn-primary" id="ob-diary-btn" class="w-full">
|
||||
<button class="btn btn-primary w-full" id="ob-diary-btn">
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#book-open"></use></svg>
|
||||
Zum Tagebuch
|
||||
</button>
|
||||
${dogName ? `
|
||||
<button class="btn btn-secondary" id="ob-profile-btn" class="w-full">
|
||||
<button class="btn btn-secondary w-full" id="ob-profile-btn">
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#dog"></use></svg>
|
||||
Profil vervollständigen
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ function _fmtDate(iso) {
|
|||
<div class="playdate-layout">
|
||||
|
||||
<!-- Tabs -->
|
||||
<div class="by-tabs" id="playdate-tabs" class="mb-4">
|
||||
<div class="by-tabs mb-4" id="playdate-tabs">
|
||||
<button class="by-tab active" data-tab="nearby">In der Nähe</button>
|
||||
<button class="by-tab" data-tab="listings">Meine Inserate</button>
|
||||
<button class="by-tab" data-tab="requests">
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ window.Page_poison = (() => {
|
|||
<a href="tel:110" class="btn btn-secondary" style="flex:1;text-align:center;text-decoration:none">
|
||||
${UI.icon('phone')} <strong>110</strong> Polizei
|
||||
</a>
|
||||
<button class="btn btn-secondary" id="poison-btn-erstehilfe" class="flex-1">
|
||||
<button class="btn btn-secondary flex-1" id="poison-btn-erstehilfe">
|
||||
${UI.icon('first-aid')} Erste Hilfe & Tiergift
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -215,7 +215,7 @@ window.Page_poison = (() => {
|
|||
${r.beschreibung ? UI.escape(r.beschreibung.slice(0, 80)) + '<br>' : ''}
|
||||
<small>📍 ${distStr} entfernt</small><br>
|
||||
<small>📅 ${_fmtDate(r.created_at)}</small>
|
||||
${r.bestaetigt ? '<br><small><svg class="ph-icon" aria-hidden="true" class="text-success"><use href="/icons/phosphor.svg#check-circle"></use></svg> Bestätigt</small>' : ''}
|
||||
${r.bestaetigt ? '<br><small><svg class="ph-icon text-success" aria-hidden="true"><use href="/icons/phosphor.svg#check-circle"></use></svg> Bestätigt</small>' : ''}
|
||||
`);
|
||||
|
||||
marker.on('click', () => _openDetail(r));
|
||||
|
|
@ -276,7 +276,7 @@ window.Page_poison = (() => {
|
|||
<span class="badge"
|
||||
style="background:${typ.color};color:#fff">${typ.label}</span>
|
||||
${r.bestaetigt
|
||||
? '<span class="badge badge-success"><svg class="ph-icon" aria-hidden="true" class="text-success"><use href="/icons/phosphor.svg#check-circle"></use></svg> Bestätigt</span>'
|
||||
? '<span class="badge badge-success"><svg class="ph-icon text-success" aria-hidden="true"><use href="/icons/phosphor.svg#check-circle"></use></svg> Bestätigt</span>'
|
||||
: ''}
|
||||
<span style="margin-left:auto;color:var(--c-text-secondary);
|
||||
font-size:var(--text-sm);white-space:nowrap">
|
||||
|
|
@ -330,7 +330,7 @@ window.Page_poison = (() => {
|
|||
<span class="badge" style="background:${typ.color};color:#fff">
|
||||
${UI.icon(typ.icon)} ${typ.label}
|
||||
</span>
|
||||
${r.bestaetigt ? '<span class="badge badge-success"><svg class="ph-icon" aria-hidden="true" class="text-success"><use href="/icons/phosphor.svg#check-circle"></use></svg> Bestätigt</span>' : ''}
|
||||
${r.bestaetigt ? '<span class="badge badge-success"><svg class="ph-icon text-success" aria-hidden="true"><use href="/icons/phosphor.svg#check-circle"></use></svg> Bestätigt</span>' : ''}
|
||||
</div>
|
||||
|
||||
${r.beschreibung
|
||||
|
|
@ -347,7 +347,7 @@ window.Page_poison = (() => {
|
|||
|
||||
<div style="display:flex;gap:var(--space-2);flex-wrap:wrap">
|
||||
${!r.bestaetigt && _appState.user && !isOwnEntry
|
||||
? `<button class="btn btn-secondary flex-1" id="detail-confirm"><svg class="ph-icon" aria-hidden="true" class="text-success"><use href="/icons/phosphor.svg#check-circle"></use></svg> Bestätigen</button>`
|
||||
? `<button class="btn btn-secondary flex-1" id="detail-confirm"><svg class="ph-icon text-success" aria-hidden="true"><use href="/icons/phosphor.svg#check-circle"></use></svg> Bestätigen</button>`
|
||||
: ''}
|
||||
<button class="btn btn-secondary flex-1" id="detail-show-map">🗺️ Auf Karte</button>
|
||||
${isOwnEntry || isAdmin
|
||||
|
|
|
|||
|
|
@ -352,13 +352,13 @@ window.Page_routes = (() => {
|
|||
<button class="rk-chip" data-filter="sort" data-val="dog">Hundefreundlich</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rk-filter-group" id="rk-mine-group" class="hidden">
|
||||
<div class="rk-filter-group hidden" id="rk-mine-group">
|
||||
<div class="rk-filter-label">Eigene</div>
|
||||
<div class="rk-chips-row">
|
||||
<button class="rk-chip" data-filter="mine" data-val="mine">🔒 Nur meine</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rk-filter-group" id="rk-nearby-group" class="hidden">
|
||||
<div class="rk-filter-group hidden" id="rk-nearby-group">
|
||||
<div class="rk-filter-label">Umgebung</div>
|
||||
<div class="rk-chips-row">
|
||||
<button class="rk-chip" id="rk-nearby-btn" data-filter="nearby" data-val="">${UI.icon('map-pin')} In meiner Nähe</button>
|
||||
|
|
@ -430,7 +430,7 @@ window.Page_routes = (() => {
|
|||
const badge = document.getElementById('rk-filter-badge');
|
||||
if (!badge) return;
|
||||
const hasFilter = _difficulty !== '' || _terrain !== '' || _sortBy !== 'newest' || _onlyMine;
|
||||
badge.style.display = hasFilter ? '' : 'none';
|
||||
badge.classList.toggle('hidden', !hasFilter); // .hidden hat !important → nur classList
|
||||
}
|
||||
|
||||
function _setBrowseMode(mode) {
|
||||
|
|
@ -450,8 +450,8 @@ window.Page_routes = (() => {
|
|||
if (mode === 'suggest') {
|
||||
if (recBtn) recBtn.style.display = 'none';
|
||||
if (impWrap) impWrap.style.display = 'none';
|
||||
if (mineGrp) mineGrp.style.display = 'none';
|
||||
if (nearbyGrp) nearbyGrp.style.display = 'none';
|
||||
if (mineGrp) mineGrp.classList.add('hidden');
|
||||
if (nearbyGrp) nearbyGrp.classList.add('hidden');
|
||||
if (searchRow) searchRow.style.display = 'none';
|
||||
if (actRow) actRow.style.display = 'none';
|
||||
const filterPanel = document.getElementById('rk-filter-panel');
|
||||
|
|
@ -474,13 +474,13 @@ window.Page_routes = (() => {
|
|||
if (mode === 'discover') {
|
||||
if (recBtn) recBtn.style.display = 'none';
|
||||
if (impWrap) impWrap.style.display = 'none';
|
||||
if (mineGrp) mineGrp.style.display = 'none';
|
||||
if (nearbyGrp && _userPos) nearbyGrp.style.display = '';
|
||||
if (mineGrp) mineGrp.classList.add('hidden');
|
||||
if (nearbyGrp && _userPos) nearbyGrp.classList.remove('hidden');
|
||||
} else {
|
||||
if (recBtn) recBtn.style.display = '';
|
||||
if (impWrap) impWrap.style.display = '';
|
||||
if (_appState.user && mineGrp) mineGrp.style.display = '';
|
||||
if (nearbyGrp) nearbyGrp.style.display = 'none';
|
||||
if (_appState.user && mineGrp) mineGrp.classList.remove('hidden');
|
||||
if (nearbyGrp) nearbyGrp.classList.add('hidden');
|
||||
}
|
||||
_onlyMine = false;
|
||||
document.querySelectorAll('#rk-mine-group .rk-chip').forEach(c => c.classList.remove('active'));
|
||||
|
|
@ -1439,9 +1439,9 @@ window.Page_routes = (() => {
|
|||
const pending = _getPending();
|
||||
if (pending.length) _data = [...pending, ..._data];
|
||||
if (_appState.user && _browseMode === 'mine')
|
||||
document.getElementById('rk-mine-group')?.style.setProperty('display', '');
|
||||
document.getElementById('rk-mine-group')?.classList.remove('hidden');
|
||||
if (_browseMode === 'discover' && _userPos)
|
||||
document.getElementById('rk-nearby-group')?.style.setProperty('display', '');
|
||||
document.getElementById('rk-nearby-group')?.classList.remove('hidden');
|
||||
if (!online && pending.length)
|
||||
UI.toast.info('Offline — ' + pending.length + ' Route(n) warten auf Sync.');
|
||||
_applyFilter();
|
||||
|
|
|
|||
|
|
@ -652,7 +652,7 @@ window.Page_settings = (() => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" id="settings-stats-card" class="mb-4">
|
||||
<div class="card mb-4" id="settings-stats-card">
|
||||
<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 class="text-sm-muted">Lädt…</div>
|
||||
|
|
@ -1721,15 +1721,15 @@ window.Page_settings = (() => {
|
|||
${profile?.rasse_text ? `<div class="text-secondary">Rasse: <strong>${UI.escape(profile.rasse_text)}</strong></div>` : ''}
|
||||
</div>
|
||||
${rolle === 'breeder' && profile ? `
|
||||
<button class="btn btn-secondary btn-sm" id="breeder-edit-profile-btn" class="mt-3">
|
||||
<button class="btn btn-secondary btn-sm mt-3" id="breeder-edit-profile-btn">
|
||||
${UI.icon('pencil-simple')} Profil bearbeiten
|
||||
</button>` : ''}
|
||||
${rolle === 'admin' && !profile ? `
|
||||
<button class="btn btn-primary btn-sm" id="breeder-admin-create-btn" class="mt-3">
|
||||
<button class="btn btn-primary btn-sm mt-3" id="breeder-admin-create-btn">
|
||||
${UI.icon('plus')} Admin-Züchterprofil anlegen
|
||||
</button>` : ''}
|
||||
${rolle === 'admin' && profile ? `
|
||||
<button class="btn btn-secondary btn-sm" id="breeder-edit-profile-btn" class="mt-3">
|
||||
<button class="btn btn-secondary btn-sm mt-3" id="breeder-edit-profile-btn">
|
||||
${UI.icon('pencil-simple')} Profil bearbeiten
|
||||
</button>` : ''}
|
||||
${profile ? `
|
||||
|
|
@ -1991,8 +1991,8 @@ window.Page_settings = (() => {
|
|||
`,
|
||||
footer: `
|
||||
<div class="w3-btn-stack">
|
||||
<button type="submit" form="breeder-apply-form" class="btn btn-primary" id="breeder-apply-submit"
|
||||
class="w-full">Antrag einreichen</button>
|
||||
<button type="submit" form="breeder-apply-form" class="btn btn-primary w-full" id="breeder-apply-submit"
|
||||
>Antrag einreichen</button>
|
||||
<button type="button" class="btn btn-secondary" data-modal-close>Abbrechen</button>
|
||||
</div>
|
||||
`,
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@ window.Page_sitting = (() => {
|
|||
`;
|
||||
const footer = `
|
||||
<div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
|
||||
<button class="btn btn-primary" type="submit" form="${id}" id="sit-profil-submit" class="w-full">
|
||||
<button class="btn btn-primary w-full" type="submit" form="${id}" id="sit-profil-submit">
|
||||
${s ? `${UI.icon('floppy-disk')} Speichern` : `${UI.icon('plus')} Profil erstellen`}
|
||||
</button>
|
||||
<button class="btn btn-secondary" data-modal-close>Abbrechen</button>
|
||||
|
|
|
|||
|
|
@ -202,9 +202,10 @@ window.Page_walks = (() => {
|
|||
_tab = tab;
|
||||
document.querySelectorAll('.by-tab').forEach(b =>
|
||||
b.classList.toggle('active', b.dataset.tab === tab));
|
||||
document.querySelectorAll('.walks-tab-panel').forEach(p => p.style.display = 'none');
|
||||
// .hidden hat !important → nur per classList togglen (style.display verliert immer)
|
||||
document.querySelectorAll('.walks-tab-panel').forEach(p => p.classList.add('hidden'));
|
||||
const panel = document.getElementById(`walks-tab-${tab}`);
|
||||
if (panel) panel.style.display = '';
|
||||
if (panel) panel.classList.remove('hidden');
|
||||
|
||||
if (tab === 'challenge' && !_challengeData) _loadChallenge();
|
||||
if (tab === 'stamm' && !_gassiZeiten.length) _loadGassiZeiten();
|
||||
|
|
@ -1058,7 +1059,7 @@ window.Page_walks = (() => {
|
|||
${UI.icon('calendar')} ${_fmtDate(challenge.start_date)} – ${_fmtDate(challenge.end_date)}
|
||||
· ${UI.icon('timer')} Noch ${dayLabel}
|
||||
</div>
|
||||
${canSubmit ? `<button class="btn btn-primary btn-sm" id="challenge-submit-btn" class="mt-3">${UI.icon('camera')} Foto einreichen</button>` : ''}
|
||||
${canSubmit ? `<button class="btn btn-primary btn-sm mt-3" id="challenge-submit-btn">${UI.icon('camera')} Foto einreichen</button>` : ''}
|
||||
${my_submission_id ? `<span class="badge badge-success mt-2">${UI.icon('check')} Du hast bereits teilgenommen</span>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1098,7 +1098,7 @@ window.Page_welcome = (() => {
|
|||
style="flex:1;background:var(--c-primary);color:#fff;border:none">
|
||||
Android
|
||||
</button>
|
||||
<button class="btn btn-sm btn-ghost" id="inst-tab-ios" class="flex-1">
|
||||
<button class="btn btn-sm btn-ghost flex-1" id="inst-tab-ios">
|
||||
iPhone / iPad
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -1174,15 +1174,15 @@ window.Page_welcome = (() => {
|
|||
|
||||
// Desktop-Tabs Android / iOS
|
||||
_container.querySelector('#inst-tab-android')?.addEventListener('click', () => {
|
||||
_container.querySelector('#inst-panel-android').style.display = '';
|
||||
_container.querySelector('#inst-panel-ios').style.display = 'none';
|
||||
_container.querySelector('#inst-panel-android').classList.remove('hidden');
|
||||
_container.querySelector('#inst-panel-ios').classList.add('hidden');
|
||||
_container.querySelector('#inst-tab-android').style.cssText += ';background:var(--c-primary);color:#fff;border:none';
|
||||
_container.querySelector('#inst-tab-ios').className = 'btn btn-sm btn-ghost';
|
||||
_container.querySelector('#inst-tab-ios').style.cssText = 'flex:1';
|
||||
});
|
||||
_container.querySelector('#inst-tab-ios')?.addEventListener('click', () => {
|
||||
_container.querySelector('#inst-panel-android').style.display = 'none';
|
||||
_container.querySelector('#inst-panel-ios').style.display = '';
|
||||
_container.querySelector('#inst-panel-android').classList.add('hidden');
|
||||
_container.querySelector('#inst-panel-ios').classList.remove('hidden');
|
||||
_container.querySelector('#inst-tab-ios').style.cssText += ';background:var(--c-primary);color:#fff;border:none';
|
||||
_container.querySelector('#inst-tab-android').className = 'btn btn-sm btn-ghost';
|
||||
_container.querySelector('#inst-tab-android').style.cssText = 'flex:1';
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ window.Page_wiki = (() => {
|
|||
|
||||
// Badge updaten
|
||||
const badge = document.getElementById('wiki-fotos-badge');
|
||||
if (badge) { badge.textContent = subs.length; badge.style.display = subs.length ? '' : 'none'; }
|
||||
if (badge) { badge.textContent = subs.length; badge.classList.toggle('hidden', !subs.length); }
|
||||
|
||||
if (!subs.length) {
|
||||
el.innerHTML = `
|
||||
|
|
@ -216,7 +216,7 @@ window.Page_wiki = (() => {
|
|||
const badge = document.getElementById('wiki-fotos-badge');
|
||||
if (badge) {
|
||||
const n = Math.max(0, parseInt(badge.textContent || '0') - 1);
|
||||
badge.textContent = n; badge.style.display = n ? '' : 'none';
|
||||
badge.textContent = n; badge.classList.toggle('hidden', !n);
|
||||
}
|
||||
} catch (e) { UI.toast(e.message, 'danger'); }
|
||||
}
|
||||
|
|
@ -269,8 +269,8 @@ window.Page_wiki = (() => {
|
|||
</select>
|
||||
</div>
|
||||
<div style="padding:0 0 var(--space-3)">
|
||||
<button class="btn btn-secondary w-full" id="wiki-rasse-erkennen-btn"
|
||||
class="text-sm">
|
||||
<button class="btn btn-secondary w-full text-sm" id="wiki-rasse-erkennen-btn"
|
||||
>
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#magnifying-glass"></use></svg>
|
||||
Welche Rasse ist das? — Foto analysieren
|
||||
</button>
|
||||
|
|
@ -669,7 +669,7 @@ window.Page_wiki = (() => {
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<button class="btn btn-secondary btn-sm" id="wiki-zuchter-add-btn" class="mt-3">
|
||||
<button class="btn btn-secondary btn-sm mt-3" id="wiki-zuchter-add-btn">
|
||||
+ Züchter eintragen
|
||||
</button>
|
||||
` : '';
|
||||
|
|
@ -835,14 +835,14 @@ window.Page_wiki = (() => {
|
|||
${berichteHtml}
|
||||
</div>
|
||||
${_appState.user
|
||||
? `<button class="btn btn-secondary w-full" id="wiki-bericht-add-btn" class="mt-3">+ Eigenen Bericht hinzufügen</button>`
|
||||
? `<button class="btn btn-secondary w-full mt-3" id="wiki-bericht-add-btn">+ Eigenen Bericht hinzufügen</button>`
|
||||
: `<p style="color:var(--c-text-secondary);font-size:var(--text-sm);margin-top:var(--space-3)">
|
||||
<a href="#settings" class="text-primary">Anmelden</a>, um einen Bericht zu schreiben.
|
||||
</p>`
|
||||
}
|
||||
${_appState.user ? `
|
||||
<div style="margin-top:var(--space-4);padding-top:var(--space-4);border-top:1px solid var(--c-border-light)">
|
||||
<button class="btn btn-ghost w-full" id="wiki-foto-submit-btn" class="text-sm">
|
||||
<button class="btn btn-ghost w-full text-sm" id="wiki-foto-submit-btn">
|
||||
${UI.icon('camera')} ${rasse.foto_url ? 'Besseres Foto vorschlagen' : 'Foto hinzufügen'}
|
||||
</button>
|
||||
</div>` : ''}`}
|
||||
|
|
@ -878,7 +878,8 @@ window.Page_wiki = (() => {
|
|||
const idx = parseInt(btn.dataset.idx);
|
||||
mainImg.src = allFotos[idx].foto_url;
|
||||
mainImg.style.display = '';
|
||||
document.getElementById('wiki-photo-fallback').style.display = 'none';
|
||||
const fb = document.getElementById('wiki-photo-fallback');
|
||||
fb.classList.add('hidden'); fb.style.display = '';
|
||||
strip.querySelectorAll('.wiki-gallery-thumb').forEach(b => b.classList.toggle('active', b === btn));
|
||||
});
|
||||
});
|
||||
|
|
@ -1255,7 +1256,7 @@ window.Page_wiki = (() => {
|
|||
<span>${UI.icon('house-line')} ${r.wohnung_geeignet ? 'Wohnung' : 'Haus'}</span>
|
||||
<span>${UI.icon('users')} ${r.kinder_geeignet ? 'Kinderfreundlich' : 'Erfahrung nötig'}</span>
|
||||
</div>
|
||||
<button class="btn btn-secondary btn-sm wiki-quiz-mehr" data-slug="${UI.escape(r.slug)}" class="mt-2">Mehr erfahren</button>
|
||||
<button class="btn btn-secondary btn-sm wiki-quiz-mehr mt-2" data-slug="${UI.escape(r.slug)}">Mehr erfahren</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
|
@ -1268,7 +1269,7 @@ window.Page_wiki = (() => {
|
|||
</div>
|
||||
<h3 style="margin:var(--space-4) 0 var(--space-2);text-align:center">Deine Top 3 Rassen</h3>
|
||||
<div class="wiki-quiz-results">${cardsHtml}</div>
|
||||
<button class="btn btn-secondary w-full" id="quiz-restart" class="mt-4">Quiz neu starten</button>
|
||||
<button class="btn btn-secondary w-full mt-4" id="quiz-restart">Quiz neu starten</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -341,8 +341,8 @@ window.Page_zuchthunde = (() => {
|
|||
title="Bearbeiten">
|
||||
${UI.icon('pencil-simple')}
|
||||
</button>
|
||||
<button class="btn btn-ghost btn-sm zh-delete-btn" data-id="${h.id}"
|
||||
title="Löschen" class="text-danger">
|
||||
<button class="btn btn-ghost btn-sm zh-delete-btn text-danger" data-id="${h.id}"
|
||||
title="Löschen">
|
||||
${UI.icon('trash')}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -360,7 +360,7 @@ window.Page_zuchthunde = (() => {
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<div class="zh-section-wrap" id="zh-section-${h.id}" class="hidden"></div>
|
||||
<div class="zh-section-wrap hidden" id="zh-section-${h.id}"></div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
|
|
@ -379,7 +379,7 @@ window.Page_zuchthunde = (() => {
|
|||
|
||||
function _closeSection(hundId) {
|
||||
const wrap = document.getElementById(`zh-section-${hundId}`);
|
||||
if (wrap) wrap.style.display = 'none';
|
||||
if (wrap) wrap.classList.add('hidden'); // .hidden hat !important → nur classList
|
||||
_openSections[hundId] = null;
|
||||
_updateSectionButtons(hundId, null);
|
||||
}
|
||||
|
|
@ -389,7 +389,7 @@ window.Page_zuchthunde = (() => {
|
|||
_updateSectionButtons(hundId, section);
|
||||
const wrap = document.getElementById(`zh-section-${hundId}`);
|
||||
if (!wrap) return;
|
||||
wrap.style.display = '';
|
||||
wrap.classList.remove('hidden');
|
||||
wrap.innerHTML = `<p style="color:var(--c-text-muted);font-size:var(--text-sm);padding:var(--space-2)">Lädt…</p>`;
|
||||
if (section === 'health') _loadHealthSection(hundId, wrap);
|
||||
if (section === 'genetic') _loadGeneticSection(hundId, wrap);
|
||||
|
|
@ -427,8 +427,8 @@ window.Page_zuchthunde = (() => {
|
|||
${t.untersuch_am ? `<span style="color:var(--c-text-muted);font-size:var(--text-xs)">${_fmtDate(t.untersuch_am)}</span>` : ''}
|
||||
${t.labor ? `<span style="color:var(--c-text-muted);font-size:var(--text-xs)">${UI.escape(t.labor)}</span>` : ''}
|
||||
</div>
|
||||
<button class="btn btn-ghost btn-xs zh-health-del-btn" data-tid="${t.id}" title="Löschen"
|
||||
class="text-danger">${UI.icon('trash')}</button>
|
||||
<button class="btn btn-ghost btn-xs zh-health-del-btn text-danger" data-tid="${t.id}" title="Löschen"
|
||||
>${UI.icon('trash')}</button>
|
||||
</div>`).join('')
|
||||
: `<p class="text-sm-muted">Noch keine Gesundheitstests eingetragen.</p>`;
|
||||
|
||||
|
|
@ -490,8 +490,8 @@ window.Page_zuchthunde = (() => {
|
|||
${t.getestet_am ? `<span style="color:var(--c-text-muted);font-size:var(--text-xs)">${_fmtDate(t.getestet_am)}</span>` : ''}
|
||||
${t.labor ? `<span style="color:var(--c-text-muted);font-size:var(--text-xs)">${UI.escape(t.labor)}</span>` : ''}
|
||||
</div>
|
||||
<button class="btn btn-ghost btn-xs zh-genetic-del-btn" data-tid="${t.id}" title="Löschen"
|
||||
class="text-danger">${UI.icon('trash')}</button>
|
||||
<button class="btn btn-ghost btn-xs zh-genetic-del-btn text-danger" data-tid="${t.id}" title="Löschen"
|
||||
>${UI.icon('trash')}</button>
|
||||
</div>`).join('')
|
||||
: `<p class="text-sm-muted">Noch keine Gentests eingetragen.</p>`;
|
||||
|
||||
|
|
@ -555,8 +555,8 @@ window.Page_zuchthunde = (() => {
|
|||
${t.richter ? `<span style="color:var(--c-text-muted);font-size:var(--text-xs)">${UI.escape(t.richter)}</span>` : ''}
|
||||
${t.formwert ? `<span class="zh-badge" style="background:#3B82F6">${UI.escape(t.formwert)}</span>` : ''}
|
||||
</div>
|
||||
<button class="btn btn-ghost btn-xs zh-title-del-btn" data-tid="${t.id}" title="Löschen"
|
||||
class="text-danger">${UI.icon('trash')}</button>
|
||||
<button class="btn btn-ghost btn-xs zh-title-del-btn text-danger" data-tid="${t.id}" title="Löschen"
|
||||
>${UI.icon('trash')}</button>
|
||||
</div>`).join('')
|
||||
: `<p class="text-sm-muted">Noch keine Titel eingetragen.</p>`;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<script src="/js/landing-init.js?v=1251"></script>
|
||||
<script src="/js/landing-init.js?v=1252"></script>
|
||||
<title>Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz</title>
|
||||
<meta name="description" content="Ban Yaro: Die kostenlose All-in-One Hunde-App für DACH. Tagebuch, Giftköder-Alarm, Training mit KI, Forum, Wurfbörse, Stammbaum, Inzucht-Check — DSGVO-konform, offline-fähig, direkt im Browser.">
|
||||
<meta name="keywords" content="Hunde App, Hunde Community, Wurfbörse, Züchter, Welpen kaufen, Stammbaum Hund, Inzuchtkoeffizient, Hundezucht, Impfpass Hund, Giftköder Alarm, Gassi Community, Hundetraining App, Hunde Forum, Hunde KI, Hundefilm Datenbank, Welpen Marktplatz">
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
============================================================ */
|
||||
|
||||
// ← EINZIGE Stelle für die Version — STATIC_ASSETS und CACHE_VERSION leiten sich ab
|
||||
const VER = '1251';
|
||||
const VER = '1252';
|
||||
const CACHE_VERSION = `by-v${VER}`;
|
||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue