diff --git a/backend/static/js/pages/reise.js b/backend/static/js/pages/reise.js new file mode 100644 index 0000000..e890dbc --- /dev/null +++ b/backend/static/js/pages/reise.js @@ -0,0 +1,381 @@ +/* ============================================================ + 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: '' }, + { key: 'laender', label: 'EU-Länder', icon: '' }, + { key: 'notfall', label: 'Notfälle', icon: '' }, + ]; + + 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'; + + // ------------------------------------------------------------------ + // Helpers + // ------------------------------------------------------------------ + function _esc(s) { + if (s == null) return ''; + return String(s) + .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 = ` +
+ + `; + _renderTabBar(); + _renderTabContent(); + } + + function _renderTabBar() { + const el = _container.querySelector('#reise-tabs'); + if (!el) return; + el.innerHTML = TABS.map(t => ` + `).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 totalItems = CHECKLIST.reduce((s, c) => s + c.items.length, 0); + const doneItems = Object.values(checked).filter(Boolean).length; + const pct = totalItems > 0 ? Math.round((doneItems / totalItems) * 100) : 0; + + const progressBar = ` +