Files
eventmap/js/models/place.js
T
dapelza ee55fb1cf9 Phase 0+1: Scaffold, Datenmodell, Karte und Liste
Reines HTML5/CSS3/JavaScript ohne Build-Tooling, lauffaehig direkt per
Doppelklick auf index.html (file://, kein Server noetig):

- Datenmodell fuer Ausflugsziele mit allen Feldern aus der Anforderung,
  15 feste Kategorien inkl. Farbe/Icon
- Zentraler Pub/Sub-Store mit LocalStorage-Persistenz und
  Migrations-Grundgeruest
- Interaktive Karte (Leaflet + Leaflet.markercluster, lokal vendored)
  mit kategoriefarbenen Markern, Clustering, Popups, Geolocation-Button
- Kartengrundlage ueber CARTO-Basemaps statt tile.openstreetmap.org, da
  dessen Referer-Pflicht file://-Aufrufe blockiert
- Seed-Daten als eingebettetes Script (data/seed.js) statt JSON-Datei,
  da fetch() auf lokale Dateien unter file:// nicht zuverlaessig
  funktioniert
- Ergebnisliste mit 10 Beispiel-Ausflugszielen, sicher gerendert ueber
  textContent/DOM-APIs statt innerHTML (Vorbereitung fuer spaeteren
  KI-JSON-Import mit Fremddaten)
- Responsives Layout (Desktop nebeneinander, Mobile gestapelt)
2026-07-24 11:24:47 +02:00

57 lines
2.0 KiB
JavaScript

// Internes Place-Objekt: bleibt nah am KI-Import-JSON-Format aus
// anforderung.md, ergänzt um intern generierte Felder (id, createdAt,
// updatedAt). Die Kategorie wird beim Normalisieren immer auf eine
// gültige Kategorie-id (Slug) aufgelöst, damit Styling (Farbe/Icon)
// überall per getCategoryById() funktioniert.
(function () {
const { generateId } = EventMap.utils;
const { CATEGORIES, getCategoryById, getCategoryByLabel } = EventMap.config;
const { createDefaultPlaceFields } = EventMap.models;
const CATEGORY_IDS = new Set(CATEGORIES.map((c) => c.id));
function resolveCategory(rawCategory) {
if (typeof rawCategory === 'string' && CATEGORY_IDS.has(rawCategory)) {
return rawCategory;
}
return getCategoryByLabel(rawCategory).id;
}
/**
* Normalisiert ein rohes Place-Objekt (z.B. aus data/seed.js oder einem
* späteren KI-Import) zu einem vollständigen internen Place-Objekt.
* Fehlende Felder werden mit Defaults aufgefüllt, id/createdAt/updatedAt
* werden übernommen falls vorhanden, sonst neu generiert.
*/
function normalizePlace(raw = {}) {
const defaults = createDefaultPlaceFields();
const now = new Date().toISOString();
return {
id: raw.id || generateId(),
...defaults,
...raw,
category: resolveCategory(raw.category),
ageRecommendation: { ...defaults.ageRecommendation, ...(raw.ageRecommendation || {}) },
cost: { ...defaults.cost, ...(raw.cost || {}) },
facilities: { ...defaults.facilities, ...(raw.facilities || {}) },
tags: Array.isArray(raw.tags) ? [...raw.tags] : [],
createdAt: raw.createdAt || now,
updatedAt: raw.updatedAt || now,
};
}
function getPlaceCategory(place) {
return getCategoryById(place.category);
}
function getPlaceLatLng(place) {
return { lat: place.latitude, lng: place.longitude };
}
EventMap.models.normalizePlace = normalizePlace;
EventMap.models.getPlaceCategory = getPlaceCategory;
EventMap.models.getPlaceLatLng = getPlaceLatLng;
})();