PHASE 1 — Sofort-Cleanup ohne Risiko: - Neue Datei utilities.css mit ~25 Klassen für häufige Kombinationen: * text-xs-muted, text-xs-secondary, text-sm-muted, text-sm-secondary * flex-gap-2/3, flex-col-gap-2/3/4, flex-center-gap-1/2/3 * flex-between, flex-1-min, mb-1/3, mt-1/3 * icon-xs/sm/md/lg, label-block, caption - index.html bindet utilities.css ein - mb-3/mt-3 ergänzt (waren in design-system.css unvollständig) PHASE 2 — .by-tab Modifier für Vereinheitlichung: - .by-tabs.grid (mit --tab-cols Variable für Admin/Health/etc.) - .by-tabs.sticky (Desktop vertikale Tabs für Admin) - .by-tabs.wrap (Zuchthunde, flex-wrap statt scroll) - .by-tabs.separated (Sitting, mit eigenem Hintergrund + Border) PHASE 3 — Inline-Style → Klassen-Migration (Python-Script): - 948 Inline-Styles entfernt (5101 → 4153, -18%) - 962 Migrationen über 47 Page-Dateien - Top-Treffer: admin.js (180), health.js (67), dog-profile.js (67), litters.js (62), settings.js (61), zuchthunde.js (51) - Patterns: text-muted, text-secondary, text-danger, text-xs-muted, text-sm-muted, grid-2 (Duplikat-Bug behoben!), flex-col-gap-3, p-3/4, mb-2/3/4, hidden, w-full, flex-1, ... - Bewahrt bestehende class-Attribute (mergt korrekt) Alle 19 Tests grün. Kein visueller Diff erwartet (gleiche Property-Werte).
496 lines
20 KiB
JavaScript
496 lines
20 KiB
JavaScript
/* ============================================================
|
||
BAN YARO — Reise mit Hund
|
||
Tabs: Checkliste | EU-Länder | Notfälle
|
||
============================================================ */
|
||
|
||
window.Page_reise = (() => {
|
||
|
||
let _container = null;
|
||
let _appState = null;
|
||
let _activeTab = 'checkliste';
|
||
|
||
const TABS = [
|
||
{ key: 'checkliste', label: 'Checkliste', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#check-square"></use></svg>' },
|
||
{ key: 'laender', label: 'EU-Länder', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#globe"></use></svg>' },
|
||
];
|
||
|
||
const CHECKLIST = [
|
||
{
|
||
key: 'dokumente',
|
||
label: 'Dokumente',
|
||
icon: 'file-text',
|
||
items: [
|
||
'EU-Heimtierausweis (Pflicht innerhalb EU)',
|
||
'Impfpass (Tollwut mind. 21 Tage alt)',
|
||
'Krankenkassen-Notfallkarte Tierarzt',
|
||
'Foto des Hundes (für Vermisst-Fall)',
|
||
'Chip-Nummer notiert',
|
||
],
|
||
},
|
||
{
|
||
key: 'gesundheit',
|
||
label: 'Gesundheit',
|
||
icon: 'heartbeat',
|
||
items: [
|
||
'Zecken-/Flohschutz aufgefrischt',
|
||
'Reisekrankheit-Mittel (falls nötig)',
|
||
'Medikamente ausreichend eingepackt',
|
||
'Tierarzt-Kontakt am Zielort recherchiert',
|
||
'Verbandszeug für Hunde',
|
||
],
|
||
},
|
||
{
|
||
key: 'ausruestung',
|
||
label: 'Ausrüstung',
|
||
icon: 'backpack',
|
||
items: [
|
||
'Leine + Ersatzleine',
|
||
'Halsband mit Adressanhänger',
|
||
'Transportbox/Reisekorb',
|
||
'Lieblingsdecke/Schlafplatz',
|
||
'Spielzeug (2–3 Stück)',
|
||
],
|
||
},
|
||
{
|
||
key: 'futter',
|
||
label: 'Futter & Wasser',
|
||
icon: 'bowl-food',
|
||
items: [
|
||
'Genug Futter (+ Reserve)',
|
||
'Wassernapf + Flasche',
|
||
'Futternapf',
|
||
'Bekannte Leckerlis',
|
||
],
|
||
},
|
||
{
|
||
key: 'auto',
|
||
label: 'Im Auto',
|
||
icon: 'car',
|
||
items: [
|
||
'Sicherheitsgurt-Adapter oder Box gesichert',
|
||
'Sonnenschutz-Netz für Fenster',
|
||
'Pausen alle 2h eingeplant',
|
||
],
|
||
},
|
||
];
|
||
|
||
const LAENDER = [
|
||
{ flag: '🇩🇪', name: 'Deutschland', regel: 'Keine Einschränkungen bei EU-Pass + Chip' },
|
||
{ flag: '🇦🇹', name: 'Österreich', regel: 'Gleiche Regeln wie DE, Leinenpflicht in Bergbahnen' },
|
||
{ flag: '🇨🇭', name: 'Schweiz', regel: 'Nicht-EU → eigene Einfuhrregeln, Tollwut-Titer-Test', warn: true },
|
||
{ flag: '🇮🇹', name: 'Italien', regel: 'Leinenpflicht öffentlich, Maulkorb in öffentlichen Verkehrsmitteln' },
|
||
{ flag: '🇫🇷', name: 'Frankreich', regel: 'Manche Strände im Sommer hundeverboten' },
|
||
{ flag: '🇬🇷', name: 'Griechenland', regel: 'Hunde erlaubt, kaum Einschränkungen' },
|
||
{ flag: '🇭🇷', name: 'Kroatien', regel: 'Viele Strände hundefreundlich, EU-Pass genügt' },
|
||
{ flag: '🇬🇧', name: 'Großbritannien', regel: 'Strenge Einreise! PETS-Zertifikat + Tollwut-Impfung + Bandwurm-Behandlung nötig', warn: true },
|
||
];
|
||
|
||
const SOFORTMASSNAHMEN = [
|
||
{ icon: 'thermometer-hot', text: 'Hitzschlag: Sofort Schatten, kühlen mit lauwarmem Wasser, Tierarzt rufen' },
|
||
{ icon: 'skull', text: 'Vergiftung: Ruhig halten, NICHT erbrechen lassen, sofort Tiergift-Notfall anrufen' },
|
||
{ icon: 'drop', text: 'Starke Blutung: Druckverband anlegen, Druck halten, Tierarzt aufsuchen' },
|
||
{ icon: 'bone', text: 'Knochenbruch: Ruhigstellen, nicht bewegen, Tierarzt aufsuchen' },
|
||
{ icon: 'heartbeat', text: 'Bewusstlosigkeit: Atemwege freihalten, stabile Seitenlage, 112 rufen' },
|
||
];
|
||
|
||
const LS_KEY = 'banyaro_reise_checkliste';
|
||
const LS_CUSTOM_KEY = 'banyaro_reise_custom'; // {catKey: ["custom item",...]}
|
||
const LS_HIDDEN_KEY = 'banyaro_reise_hidden'; // {itemKey: true} — gelöschte Standard-Items
|
||
let _editMode = false;
|
||
|
||
function _loadCustom() { try { return JSON.parse(localStorage.getItem(LS_CUSTOM_KEY) || '{}'); } catch { return {}; } }
|
||
function _saveCustom(d) { try { localStorage.setItem(LS_CUSTOM_KEY, JSON.stringify(d)); } catch {} }
|
||
function _loadHidden() { try { return JSON.parse(localStorage.getItem(LS_HIDDEN_KEY) || '{}'); } catch { return {}; } }
|
||
function _saveHidden(d) { try { localStorage.setItem(LS_HIDDEN_KEY, JSON.stringify(d)); } catch {} }
|
||
|
||
// ------------------------------------------------------------------
|
||
// Helpers
|
||
// ------------------------------------------------------------------
|
||
function _esc(s) {
|
||
if (s == null) return '';
|
||
return String(s)
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/"/g, '"');
|
||
}
|
||
|
||
function _loadChecked() {
|
||
try { return JSON.parse(localStorage.getItem(LS_KEY) || '{}'); }
|
||
catch { return {}; }
|
||
}
|
||
|
||
function _saveChecked(state) {
|
||
try { localStorage.setItem(LS_KEY, JSON.stringify(state)); }
|
||
catch {}
|
||
}
|
||
|
||
function _itemKey(catKey, idx) { return `${catKey}__${idx}`; }
|
||
|
||
// ------------------------------------------------------------------
|
||
// LIFECYCLE
|
||
// ------------------------------------------------------------------
|
||
function init(container, appState, params = {}) {
|
||
_container = container;
|
||
_appState = appState;
|
||
if (params?.tab && TABS.some(t => t.key === params.tab)) {
|
||
_activeTab = params.tab;
|
||
}
|
||
_render();
|
||
}
|
||
|
||
function refresh() { _renderTabContent(); }
|
||
function onDogChange() {}
|
||
|
||
// ------------------------------------------------------------------
|
||
// RENDER
|
||
// ------------------------------------------------------------------
|
||
function _render() {
|
||
_container.innerHTML = `
|
||
<div class="by-tabs" id="reise-tabs"></div>
|
||
<div id="reise-content"></div>
|
||
`;
|
||
_renderTabBar();
|
||
_renderTabContent();
|
||
}
|
||
|
||
function _renderTabBar() {
|
||
const el = _container.querySelector('#reise-tabs');
|
||
if (!el) return;
|
||
el.innerHTML = TABS.map(t => `
|
||
<button class="by-tab${t.key === _activeTab ? ' active' : ''}" data-tab="${t.key}">
|
||
${t.icon} ${t.label}
|
||
</button>`).join('');
|
||
el.querySelectorAll('.by-tab').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
_activeTab = btn.dataset.tab;
|
||
el.querySelectorAll('.by-tab').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
_renderTabContent();
|
||
});
|
||
});
|
||
}
|
||
|
||
function _renderTabContent() {
|
||
const el = _container.querySelector('#reise-content');
|
||
if (!el) return;
|
||
if (_activeTab === 'checkliste') _renderCheckliste(el);
|
||
else if (_activeTab === 'laender') _renderLaender(el);
|
||
else if (_activeTab === 'notfall') _renderNotfall(el);
|
||
}
|
||
|
||
// ------------------------------------------------------------------
|
||
// TAB 1: CHECKLISTE
|
||
// ------------------------------------------------------------------
|
||
function _renderCheckliste(el) {
|
||
const checked = _loadChecked();
|
||
const custom = _loadCustom();
|
||
const hidden = _loadHidden();
|
||
|
||
// Alle sichtbaren Items zählen
|
||
let totalItems = 0, doneItems = 0;
|
||
CHECKLIST.forEach(cat => {
|
||
cat.items.forEach((_, idx) => {
|
||
if (!hidden[_itemKey(cat.key, idx)]) {
|
||
totalItems++;
|
||
if (checked[_itemKey(cat.key, idx)]) doneItems++;
|
||
}
|
||
});
|
||
(custom[cat.key] || []).forEach((_, i) => {
|
||
totalItems++;
|
||
if (checked[`${cat.key}__custom__${i}`]) doneItems++;
|
||
});
|
||
});
|
||
const pct = totalItems > 0 ? Math.round((doneItems / totalItems) * 100) : 0;
|
||
|
||
const cats = CHECKLIST.map(cat => {
|
||
const customItems = custom[cat.key] || [];
|
||
|
||
const stdRows = cat.items.map((item, idx) => {
|
||
if (hidden[_itemKey(cat.key, idx)]) return '';
|
||
const key = _itemKey(cat.key, idx);
|
||
const done = !!checked[key];
|
||
if (_editMode) {
|
||
return `<div class="reise-check-row" style="justify-content:space-between">
|
||
<span style="flex:1;color:var(--c-text)">${_esc(item)}</span>
|
||
<button class="reise-del-btn" data-hide="${_esc(key)}"
|
||
style="background:none;border:none;color:#EF4444;cursor:pointer;padding:4px;flex-shrink:0">
|
||
<svg class="ph-icon" style="width:1rem;height:1rem"><use href="/icons/phosphor.svg#trash"></use></svg>
|
||
</button>
|
||
</div>`;
|
||
}
|
||
return `<label class="reise-check-row${done ? ' done' : ''}">
|
||
<input type="checkbox" class="reise-cb" data-key="${_esc(key)}" ${done ? 'checked' : ''}>
|
||
<span>${_esc(item)}</span>
|
||
</label>`;
|
||
}).join('');
|
||
|
||
const customRows = customItems.map((item, i) => {
|
||
const key = `${cat.key}__custom__${i}`;
|
||
const done = !!checked[key];
|
||
if (_editMode) {
|
||
return `<div class="reise-check-row" style="justify-content:space-between">
|
||
<span style="flex:1;color:var(--c-primary)">${_esc(item)}</span>
|
||
<button class="reise-del-custom-btn" data-cat="${_esc(cat.key)}" data-idx="${i}"
|
||
style="background:none;border:none;color:#EF4444;cursor:pointer;padding:4px;flex-shrink:0">
|
||
<svg class="ph-icon" style="width:1rem;height:1rem"><use href="/icons/phosphor.svg#trash"></use></svg>
|
||
</button>
|
||
</div>`;
|
||
}
|
||
return `<label class="reise-check-row${done ? ' done' : ''}">
|
||
<input type="checkbox" class="reise-cb" data-key="${_esc(key)}" ${done ? 'checked' : ''}>
|
||
<span class="text-primary">${_esc(item)}</span>
|
||
</label>`;
|
||
}).join('');
|
||
|
||
const addRow = _editMode ? `
|
||
<div style="padding:var(--space-2) 0;border-top:1px dashed var(--c-border);margin-top:4px">
|
||
<div style="display:flex;gap:8px;align-items:center">
|
||
<input class="reise-add-input" data-cat="${_esc(cat.key)}"
|
||
style="flex:1;padding:8px 10px;border-radius:8px;border:1px solid var(--c-border);
|
||
background:var(--c-bg-card);color:var(--c-text);font-size:var(--text-sm)"
|
||
placeholder="Eigenes Item hinzufügen…">
|
||
<button class="reise-add-btn btn btn-primary" data-cat="${_esc(cat.key)}"
|
||
style="padding:8px 12px;flex-shrink:0;font-size:var(--text-sm)">
|
||
<svg class="ph-icon" style="width:1rem;height:1rem"><use href="/icons/phosphor.svg#plus"></use></svg>
|
||
</button>
|
||
</div>
|
||
</div>` : '';
|
||
|
||
return `<div class="card mb-4">
|
||
<div style="padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--c-border);
|
||
display:flex;align-items:center;gap:var(--space-2)">
|
||
<svg class="ph-icon text-primary" aria-hidden="true">
|
||
<use href="/icons/phosphor.svg#${_esc(cat.icon)}"></use>
|
||
</svg>
|
||
<span style="font-weight:var(--weight-semibold)">${_esc(cat.label)}</span>
|
||
</div>
|
||
<div style="padding:var(--space-2) var(--space-4)">
|
||
${stdRows}${customRows}${addRow}
|
||
</div>
|
||
</div>`;
|
||
}).join('');
|
||
|
||
el.innerHTML = `
|
||
<style>
|
||
.reise-check-row {
|
||
display:flex;align-items:flex-start;gap:var(--space-3);
|
||
padding:var(--space-2) 0;cursor:pointer;
|
||
border-bottom:1px solid var(--c-surface-2);
|
||
font-size:var(--text-sm);color:var(--c-text);line-height:1.5;
|
||
}
|
||
.reise-check-row:last-child { border-bottom:none; }
|
||
.reise-check-row.done span { text-decoration:line-through;color:var(--c-text-secondary); }
|
||
.reise-check-row input[type=checkbox] {
|
||
flex-shrink:0;margin-top:2px;width:18px;height:18px;
|
||
accent-color:var(--c-primary);cursor:pointer;
|
||
}
|
||
</style>
|
||
<!-- Fortschritt + Buttons -->
|
||
<div style="margin-bottom:var(--space-5)">
|
||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--space-2)">
|
||
<span class="text-sm-secondary">${doneItems} von ${totalItems} erledigt</span>
|
||
<div style="display:flex;gap:8px;align-items:center">
|
||
<span style="font-size:var(--text-sm);font-weight:700;color:var(--c-primary)">${pct}%</span>
|
||
<button id="reise-edit-toggle" style="background:${_editMode ? 'var(--c-primary)' : 'var(--c-bg-card)'};
|
||
color:${_editMode ? '#fff' : 'var(--c-text-secondary)'};border:1.5px solid var(--c-border);
|
||
border-radius:8px;padding:5px 10px;cursor:pointer;font-size:var(--text-xs);font-weight:600;
|
||
display:flex;align-items:center;gap:4px">
|
||
<svg class="ph-icon" style="width:.9rem;height:.9rem"><use href="/icons/phosphor.svg#pencil-simple"></use></svg>
|
||
${_editMode ? 'Fertig' : 'Bearbeiten'}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div style="height:8px;background:var(--c-surface-2);border-radius:var(--radius-full);overflow:hidden">
|
||
<div style="height:100%;width:${pct}%;background:var(--c-primary);border-radius:var(--radius-full);transition:width .3s"></div>
|
||
</div>
|
||
</div>
|
||
${cats}
|
||
${!_editMode ? `<div style="text-align:center;margin-bottom:var(--space-6)">
|
||
<button class="btn btn-secondary" id="reise-reset-btn">
|
||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#arrow-counter-clockwise"></use></svg>
|
||
Abhaken zurücksetzen
|
||
</button>
|
||
</div>` : ''}
|
||
`;
|
||
|
||
// Checkbox events
|
||
el.querySelectorAll('.reise-cb').forEach(cb => {
|
||
cb.addEventListener('change', () => {
|
||
const key = cb.dataset.key;
|
||
const cur = _loadChecked();
|
||
cur[key] = cb.checked;
|
||
_saveChecked(cur);
|
||
_renderTabContent();
|
||
});
|
||
});
|
||
|
||
// Edit-Toggle
|
||
el.querySelector('#reise-edit-toggle')?.addEventListener('click', () => {
|
||
_editMode = !_editMode;
|
||
_renderTabContent();
|
||
});
|
||
|
||
// Standard-Item löschen (verstecken)
|
||
el.querySelectorAll('.reise-del-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
const h = _loadHidden();
|
||
h[btn.dataset.hide] = true;
|
||
_saveHidden(h);
|
||
_renderTabContent();
|
||
});
|
||
});
|
||
|
||
// Custom-Item löschen
|
||
el.querySelectorAll('.reise-del-custom-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
const c = _loadCustom();
|
||
c[btn.dataset.cat] = (c[btn.dataset.cat] || []).filter((_, i) => i !== parseInt(btn.dataset.idx));
|
||
_saveCustom(c);
|
||
_renderTabContent();
|
||
});
|
||
});
|
||
|
||
// Custom-Item hinzufügen
|
||
el.querySelectorAll('.reise-add-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
const cat = btn.dataset.cat;
|
||
const input = el.querySelector(`.reise-add-input[data-cat="${cat}"]`);
|
||
const val = (input?.value || '').trim();
|
||
if (!val) return;
|
||
const c = _loadCustom();
|
||
if (!c[cat]) c[cat] = [];
|
||
c[cat].push(val);
|
||
_saveCustom(c);
|
||
_renderTabContent();
|
||
});
|
||
});
|
||
|
||
// Enter in Add-Input
|
||
el.querySelectorAll('.reise-add-input').forEach(input => {
|
||
input.addEventListener('keydown', e => {
|
||
if (e.key === 'Enter') el.querySelector(`.reise-add-btn[data-cat="${input.dataset.cat}"]`)?.click();
|
||
});
|
||
});
|
||
|
||
el.querySelector('#reise-reset-btn')?.addEventListener('click', () => {
|
||
_saveChecked({});
|
||
_renderTabContent();
|
||
});
|
||
}
|
||
|
||
// ------------------------------------------------------------------
|
||
// TAB 2: EU-LÄNDER
|
||
// ------------------------------------------------------------------
|
||
function _renderLaender(el) {
|
||
const cards = LAENDER.map(l => `
|
||
<div class="card" style="margin-bottom:var(--space-3);padding:var(--space-4)">
|
||
<div style="display:flex;align-items:flex-start;gap:var(--space-3)">
|
||
<span style="font-size:2rem;line-height:1">${l.flag}</span>
|
||
<div class="flex-1-min">
|
||
<div style="font-weight:var(--weight-semibold);margin-bottom:var(--space-1)">
|
||
${_esc(l.name)}
|
||
</div>
|
||
<div class="text-sm-secondary">
|
||
${_esc(l.regel)}
|
||
</div>
|
||
</div>
|
||
${l.warn ? `<svg class="ph-icon" style="color:var(--c-warning,#f59e0b);flex-shrink:0;width:20px;height:20px" aria-hidden="true">
|
||
<use href="/icons/phosphor.svg#warning"></use>
|
||
</svg>` : ''}
|
||
</div>
|
||
</div>`).join('');
|
||
|
||
el.innerHTML = `
|
||
<div style="margin-bottom:var(--space-4);padding:var(--space-3) var(--space-4);
|
||
background:var(--c-surface-2);border-radius:var(--radius-md);
|
||
font-size:var(--text-sm);color:var(--c-text-secondary);
|
||
display:flex;gap:var(--space-2);align-items:flex-start">
|
||
<svg class="ph-icon" style="flex-shrink:0;margin-top:1px" aria-hidden="true">
|
||
<use href="/icons/phosphor.svg#info"></use>
|
||
</svg>
|
||
<span>EU-Heimtierausweis + Mikrochip + gültige Tollwut-Impfung (mindestens 21 Tage alt)
|
||
sind Pflicht für alle EU-Reisen. Informationen können sich ändern — immer beim
|
||
Zielland-Konsulat oder Tierarzt aktuell prüfen.</span>
|
||
</div>
|
||
${cards}
|
||
`;
|
||
}
|
||
|
||
// ------------------------------------------------------------------
|
||
// TAB 3: NOTFÄLLE
|
||
// ------------------------------------------------------------------
|
||
function _renderNotfall(el) {
|
||
const massnahmen = SOFORTMASSNAHMEN.map(m => `
|
||
<div style="display:flex;align-items:flex-start;gap:var(--space-3);
|
||
padding:var(--space-3) 0;border-bottom:1px solid var(--c-surface-2)">
|
||
<svg class="ph-icon" style="color:var(--c-danger,#ef4444);flex-shrink:0;margin-top:1px" aria-hidden="true">
|
||
<use href="/icons/phosphor.svg#${_esc(m.icon)}"></use>
|
||
</svg>
|
||
<span style="font-size:var(--text-sm);color:var(--c-text)">${_esc(m.text)}</span>
|
||
</div>`).join('');
|
||
|
||
el.innerHTML = `
|
||
<div class="card mb-4">
|
||
<div style="padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--c-border);
|
||
font-weight:var(--weight-semibold);display:flex;align-items:center;gap:var(--space-2)">
|
||
<svg class="ph-icon" style="color:var(--c-danger,#ef4444)" aria-hidden="true">
|
||
<use href="/icons/phosphor.svg#phone"></use>
|
||
</svg>
|
||
Notrufnummern
|
||
</div>
|
||
<div class="p-4">
|
||
<a href="tel:112" class="btn btn-danger w-full"
|
||
style="margin-bottom:var(--space-3);display:flex;align-items:center;
|
||
justify-content:center;gap:var(--space-2)">
|
||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#phone-call"></use></svg>
|
||
112 — EU-Notruf
|
||
</a>
|
||
<a href="tel:+498919240" class="btn btn-secondary w-full"
|
||
style="margin-bottom:var(--space-2);display:flex;align-items:center;
|
||
justify-content:center;gap:var(--space-2)">
|
||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#phone"></use></svg>
|
||
Tiergift-Notruf München
|
||
</a>
|
||
<div style="text-align:center;font-size:var(--text-xs);color:var(--c-text-secondary)">
|
||
+49 89 19240 (Tierärztliche Hochschule)
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card mb-4">
|
||
<div style="padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--c-border);
|
||
font-weight:var(--weight-semibold)">Tierarzt finden</div>
|
||
<div class="p-4">
|
||
<button class="btn btn-primary w-full" id="reise-map-btn"
|
||
style="display:flex;align-items:center;justify-content:center;gap:var(--space-2)">
|
||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#map-pin"></use></svg>
|
||
Tierarzt in der Nähe suchen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card mb-4">
|
||
<div style="padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--c-border);
|
||
font-weight:var(--weight-semibold);display:flex;align-items:center;gap:var(--space-2)">
|
||
<svg class="ph-icon" style="color:var(--c-warning,#f59e0b)" aria-hidden="true">
|
||
<use href="/icons/phosphor.svg#warning"></use>
|
||
</svg>
|
||
Sofortmaßnahmen
|
||
</div>
|
||
<div style="padding:var(--space-2) var(--space-4)">
|
||
${massnahmen}
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
el.querySelector('#reise-map-btn')?.addEventListener('click', () => {
|
||
App.navigate('map');
|
||
});
|
||
}
|
||
|
||
// ------------------------------------------------------------------
|
||
// PUBLIC
|
||
// ------------------------------------------------------------------
|
||
return { init, refresh, onDogChange };
|
||
})();
|