- Beispieldaten werden nicht mehr eingebettet (data/seed.js entfernt), sondern beim ersten Start per fetch(EventMap.config.SEED_DATA_URL) von einem externen, selbst gehosteten Server geladen (siehe ADR 0001, Revision 2026-07-28). - Neuer UI-Sprachumschalter (Deutsch/Englisch) für die Bedienoberfläche: js/i18n/strings.js + js/i18n/i18n.js, Sprachwahl im Menü, Persistenz über settings.language, Retranslation ohne Reload. - Neuer Menüpunkt "Ausflugsziel übersetzen (KI)": erzeugt einen Prompt, der eine externe KI bittet, Name/Beschreibungen eines bestehenden Ortes ins Englische, Spanische oder Französische zu übersetzen (js/ai/translatePromptBuilder.js, js/ui/translatePromptGenerator.js). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
182 lines
8.0 KiB
HTML
182 lines
8.0 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title data-i18n="documentTitle">EventMap – Familienfreundliche Ausflugsziele</title>
|
||
|
||
<link rel="stylesheet" href="vendor/leaflet/leaflet.css" />
|
||
<link rel="stylesheet" href="vendor/leaflet.markercluster/MarkerCluster.css" />
|
||
<link rel="stylesheet" href="vendor/leaflet.markercluster/MarkerCluster.Default.css" />
|
||
|
||
<link rel="stylesheet" href="css/reset.css" />
|
||
<link rel="stylesheet" href="css/variables.css" />
|
||
<link rel="stylesheet" href="css/layout.css" />
|
||
<link rel="stylesheet" href="css/components.css" />
|
||
<link rel="stylesheet" href="css/detail.css" />
|
||
<link rel="stylesheet" href="css/form.css" />
|
||
<link rel="stylesheet" href="css/filters.css" />
|
||
<link rel="stylesheet" href="css/promptGenerator.css" />
|
||
<link rel="stylesheet" href="css/manualLocation.css" />
|
||
<link rel="stylesheet" href="css/import.css" />
|
||
<link rel="stylesheet" href="css/responsive.css" />
|
||
</head>
|
||
<body>
|
||
<header class="app-header">
|
||
<div class="app-header__row">
|
||
<div>
|
||
<h1 class="app-header__title" data-i18n="header.title">EventMap</h1>
|
||
<p class="app-header__subtitle" data-i18n="header.subtitle">Familienfreundliche Ausflugsziele auf der Karte</p>
|
||
</div>
|
||
<button
|
||
id="menu-toggle-btn"
|
||
type="button"
|
||
class="app-header__menu-toggle"
|
||
aria-expanded="false"
|
||
aria-controls="app-menu"
|
||
data-i18n-aria-label="header.menuToggleLabel"
|
||
aria-label="Menü öffnen"
|
||
>
|
||
<span aria-hidden="true">☰</span>
|
||
</button>
|
||
</div>
|
||
|
||
<nav id="app-menu" class="app-menu" data-i18n-aria-label="menu.ariaLabel" aria-label="Aktionen" hidden>
|
||
<div class="app-menu__language">
|
||
<label class="app-menu__language-label" for="language-select" data-i18n="settings.languageLabel">
|
||
Anzeigesprache
|
||
</label>
|
||
<select id="language-select" class="app-menu__language-select">
|
||
<option value="de">Deutsch</option>
|
||
<option value="en">English</option>
|
||
</select>
|
||
</div>
|
||
<button id="locate-btn" type="button" class="btn btn--secondary" data-i18n="menu.locate">
|
||
Meinen Standort verwenden
|
||
</button>
|
||
<button id="manual-location-btn" type="button" class="btn btn--secondary" data-i18n="menu.manualLocation">
|
||
Standort manuell eingeben
|
||
</button>
|
||
<button id="pick-location-btn" type="button" class="btn btn--secondary" data-i18n="menu.pickLocation">
|
||
📍 Standort auf Karte wählen
|
||
</button>
|
||
<button id="add-place-btn" type="button" class="btn btn--primary" data-i18n="menu.addPlace">
|
||
+ Neues Ausflugsziel hinzufügen
|
||
</button>
|
||
<button id="open-prompt-generator-btn" type="button" class="btn btn--secondary" data-i18n="menu.promptGenerator">
|
||
🤖 Neue Ausflugsziele mit KI erstellen
|
||
</button>
|
||
<button id="open-translate-prompt-generator-btn" type="button" class="btn btn--secondary" data-i18n="menu.translatePlace">
|
||
🌐 Ausflugsziel übersetzen (KI)
|
||
</button>
|
||
<button id="open-import-btn" type="button" class="btn btn--secondary" data-i18n="menu.import">
|
||
📥 KI-Ausflugsziele importieren
|
||
</button>
|
||
<button id="open-backup-btn" type="button" class="btn btn--secondary" data-i18n="menu.backup">
|
||
💾 Daten sichern/wiederherstellen
|
||
</button>
|
||
</nav>
|
||
</header>
|
||
|
||
<div id="app-status" class="app-status" role="alert" hidden>
|
||
<p id="app-status-text" class="app-status__text"></p>
|
||
<button
|
||
id="app-status-close"
|
||
type="button"
|
||
class="app-status__close"
|
||
data-i18n-aria-label="status.closeLabel"
|
||
aria-label="Meldung schließen"
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
|
||
<main class="app-layout">
|
||
<section class="map-panel" data-i18n-aria-label="map.ariaLabel" aria-label="Karte">
|
||
<p id="map-picking-hint" class="map-picking-hint" hidden>
|
||
<span data-i18n="map.pickingHint">Klicke auf die Karte, um den Standort auszuwählen.</span>
|
||
<button id="map-picking-cancel-btn" type="button" class="map-picking-hint__cancel" data-i18n="map.pickingCancel">
|
||
Abbrechen
|
||
</button>
|
||
</p>
|
||
<div id="map" class="map-panel__map">
|
||
<p class="map-panel__loading" data-i18n="map.loading">Karte wird geladen…</p>
|
||
</div>
|
||
</section>
|
||
|
||
<div id="filter-panel" class="filter-panel" data-i18n-aria-label="filterPanel.ariaLabel" aria-label="Filter und Suche"></div>
|
||
|
||
<aside class="list-panel" data-i18n-aria-label="list.ariaLabel" aria-label="Ergebnisliste">
|
||
<h2 class="list-panel__title" data-i18n="list.title">Ausflugsziele</h2>
|
||
<div id="place-list" class="list-panel__content">
|
||
<p class="list-empty" data-i18n="list.loading">Lade Ausflugsziele…</p>
|
||
</div>
|
||
</aside>
|
||
</main>
|
||
|
||
<div id="detail-modal" class="detail-modal" hidden></div>
|
||
<div id="place-form-modal" class="place-form-modal" hidden></div>
|
||
<div id="manual-location-modal" class="manual-location-modal" hidden></div>
|
||
<div id="prompt-generator-modal" class="prompt-generator-modal" hidden></div>
|
||
<div id="translate-prompt-generator-modal" class="prompt-generator-modal" hidden></div>
|
||
<div id="import-modal" class="import-modal" hidden></div>
|
||
|
||
<script src="vendor/leaflet/leaflet.js"></script>
|
||
<script src="vendor/leaflet.markercluster/leaflet.markercluster.js"></script>
|
||
|
||
<!-- Klassische Scripts statt ES-Module (import/export), damit die App
|
||
auch per Doppelklick/file:// ohne lokalen Server funktioniert.
|
||
Reihenfolge folgt der Abhängigkeitskette; alle Dateien hängen ihre
|
||
öffentliche API an das globale window.EventMap-Namespace-Objekt an. -->
|
||
<script src="js/utils/dom.js"></script>
|
||
<script src="js/utils/geo.js"></script>
|
||
<script src="js/utils/id.js"></script>
|
||
<script src="js/utils/clipboard.js"></script>
|
||
<script src="js/utils/download.js"></script>
|
||
<script src="js/filters/filterEngine.js"></script>
|
||
<script src="js/config/constants.js"></script>
|
||
<script src="js/config/categories.js"></script>
|
||
<script src="js/models/schema.js"></script>
|
||
<script src="js/models/place.js"></script>
|
||
<script src="js/store/migrations.js"></script>
|
||
<script src="js/store/storage.js"></script>
|
||
<script src="js/store/store.js"></script>
|
||
|
||
<!-- UI-Sprachumschalter (ADR 0002): muss nach store.js (liest persistierte
|
||
Settings synchron beim Init) und vor allen UI-Modulen geladen werden. -->
|
||
<script src="js/i18n/strings.js"></script>
|
||
<script src="js/i18n/i18n.js"></script>
|
||
|
||
<script src="js/map/geolocation.js"></script>
|
||
<script src="js/map/markers.js"></script>
|
||
<script src="js/map/mapController.js"></script>
|
||
<script src="js/ui/list.js"></script>
|
||
<script src="js/ui/detail.js"></script>
|
||
<script src="js/ui/form.js"></script>
|
||
<script src="js/ui/manualLocation.js"></script>
|
||
<script src="js/filters/filterPanel.js"></script>
|
||
|
||
<!-- KI-Prompt-Generator (Phase 6): eigener Bereich, da js/ai/promptBuilder.js
|
||
auf EventMap.config.CATEGORIES angewiesen ist und js/ui/promptGenerator.js
|
||
wiederum promptBuilder.js voraussetzt. -->
|
||
<script src="js/ai/promptBuilder.js"></script>
|
||
<script src="js/ui/promptGenerator.js"></script>
|
||
|
||
<!-- "Ausflugsziel übersetzen (KI)": erzeugt einen Prompt zum Übersetzen
|
||
eines bestehenden Ortes (Name/Beschreibungen) in eine Zielsprache
|
||
(Englisch/Spanisch/Französisch), analog zum obigen Prompt-Generator. -->
|
||
<script src="js/ai/translatePromptBuilder.js"></script>
|
||
<script src="js/ui/translatePromptGenerator.js"></script>
|
||
|
||
<!-- KI-JSON-Import + Backup-Export/Import (Phase 7): js/import/*.js sind
|
||
reine Validierungs-/Datenfunktionen ohne DOM-Zugriff und setzen daher
|
||
nur EventMap.utils/models/config/store voraus (bereits geladen);
|
||
js/ui/import.js baut darauf auf. -->
|
||
<script src="js/import/importValidator.js"></script>
|
||
<script src="js/import/backup.js"></script>
|
||
<script src="js/ui/import.js"></script>
|
||
|
||
<script src="js/main.js"></script>
|
||
</body>
|
||
</html>
|