305 lines
14 KiB
JavaScript
305 lines
14 KiB
JavaScript
/* ======================================================
|
||
components.js – Feuerwehr Stadt Wehlen (Modern Light)
|
||
------------------------------------------------------
|
||
Rendert alle wiederkehrenden Elemente und die Inhalte
|
||
aus den zentralen Daten-Dateien (data/).
|
||
|
||
Erwartet window.FFW_BASE (Pfad zum Projekt-Root).
|
||
Aktiver Navigationspunkt über <body data-page="...">.
|
||
====================================================== */
|
||
|
||
(function () {
|
||
const base = window.FFW_BASE || "";
|
||
const page = document.body.dataset.page || "";
|
||
|
||
/* ======================================================
|
||
NAVIGATION & FOOTER
|
||
====================================================== */
|
||
const NAV = `
|
||
<nav class="navbar navbar-expand-lg gl-navbar sticky-top">
|
||
<div class="container">
|
||
<a class="navbar-brand" href="index.html">
|
||
<img src="${base}bilder/ffw_transp_72.gif" alt="Logo Feuerwehr Stadt Wehlen">
|
||
<span>Feuerwehr Stadt Wehlen</span>
|
||
</a>
|
||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#glNav"
|
||
aria-controls="glNav" aria-expanded="false" aria-label="Menü öffnen">
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="glNav">
|
||
<ul class="navbar-nav ms-auto">
|
||
<li class="nav-item"><a class="nav-link" data-page="start" href="index.html">Startseite</a></li>
|
||
<li class="nav-item dropdown">
|
||
<a class="nav-link dropdown-toggle" href="#" data-page="ueber" role="button" data-bs-toggle="dropdown" aria-expanded="false">Über uns</a>
|
||
<ul class="dropdown-menu dropdown-menu-end">
|
||
<li><a class="dropdown-item" data-page="geschichte" href="geschichte.html">Geschichte</a></li>
|
||
<li><a class="dropdown-item" data-page="technik" href="technik.html">Technik</a></li>
|
||
<li><hr class="dropdown-divider"></li>
|
||
<li><a class="dropdown-item" data-page="mitglieder" href="mitglieder.html">Organigramm</a></li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-item"><a class="nav-link" data-page="dienstplan" href="dienstplan.html">Dienstplan</a></li>
|
||
<li class="nav-item"><a class="nav-link" data-page="veranstaltungen" href="veranstaltungen.html">Veranstaltungen</a></li>
|
||
<li class="nav-item"><a class="nav-link" data-page="kontakt" href="kontakt.html">Kontakt / Impressum</a></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</nav>`;
|
||
|
||
const FOOTER = `
|
||
<footer class="gl-footer">
|
||
<div class="container">
|
||
<div class="row g-4 text-center text-md-start align-items-start">
|
||
<div class="col-md-3">
|
||
<div class="footer-brand">
|
||
<img src="${base}bilder/ffw_transp_72.gif" alt="Logo Feuerwehr Stadt Wehlen">
|
||
<span>Feuerwehr<br>Stadt Wehlen</span>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<h6>Letzte Aktualisierung</h6>
|
||
<p>17. März 2026</p>
|
||
<small>(Version 1.2)</small>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<h6>Kleine Statistik der FFw Stadt Wehlen</h6>
|
||
<p><strong>Aktive:</strong> 22 | <strong>Jugend:</strong> 20 | <strong>Passive:</strong> 13 | <strong>Förderverein:</strong> 161</p>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<h6>Navigation</h6>
|
||
<ul class="footer-nav justify-content-center justify-content-md-start">
|
||
<li><a href="geschichte.html">Geschichte</a></li>
|
||
<li><a href="technik.html">Technik</a></li>
|
||
<li><a href="mitglieder.html">Organigramm</a></li>
|
||
<li><a href="dienstplan.html">Dienstplan</a></li>
|
||
<li><a href="veranstaltungen.html">Veranstaltungen</a></li>
|
||
<li><a href="kontakt.html">Kontakt / Impressum</a></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</footer>`;
|
||
|
||
const headerMount = document.getElementById("site-header");
|
||
if (headerMount) headerMount.innerHTML = NAV;
|
||
|
||
const footerMount = document.getElementById("site-footer");
|
||
if (footerMount) footerMount.innerHTML = FOOTER;
|
||
|
||
/* Aktiven Menüpunkt markieren */
|
||
document.querySelectorAll(`[data-page="${page}"]`).forEach(el => el.classList.add("active"));
|
||
|
||
/* ======================================================
|
||
HERO (Startseite) – helle Split-Karte + Statistik
|
||
====================================================== */
|
||
const heroMount = document.getElementById("site-hero");
|
||
if (heroMount) {
|
||
heroMount.innerHTML = `
|
||
<section class="gl-hero container">
|
||
<div class="gl-hero-karte">
|
||
<div class="row g-0">
|
||
<div class="col-lg-6 d-flex align-items-center">
|
||
<div class="gl-hero-text">
|
||
<span class="gl-hero-badge">Freiwillige Feuerwehr seit 1901</span>
|
||
<h1>Feuerwehr <span class="highlight">Stadt Wehlen</span></h1>
|
||
<p>Ehrenamtlich im Einsatz für Stadt Wehlen und Pötzscha bei Brand, Hilfeleistung und Wasserrettung auf der Elbe.</p>
|
||
<div class="gl-hero-cta">
|
||
<a class="btn-pill" href="technik.html">Unsere Technik</a>
|
||
<a class="btn-pill btn-pill-ghost" href="dienstplan.html">Dienstplan & Termine</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-6">
|
||
<div class="gl-hero-bild" style="--hero-bild: url('${base}bilder/geraetehaus.png')" role="img" aria-label="Gerätehaus der Feuerwehr Stadt Wehlen"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row g-3 mt-2">
|
||
<div class="col-6 col-md-3"><div class="stat-kachel"><div class="zahl">22</div><div class="label">Aktive</div></div></div>
|
||
<div class="col-6 col-md-3"><div class="stat-kachel"><div class="zahl">20</div><div class="label">Jugendfeuerwehr</div></div></div>
|
||
<div class="col-6 col-md-3"><div class="stat-kachel"><div class="zahl">13</div><div class="label">Passive</div></div></div>
|
||
<div class="col-6 col-md-3"><div class="stat-kachel"><div class="zahl">161</div><div class="label">Förderverein</div></div></div>
|
||
</div>
|
||
</section>`;
|
||
}
|
||
|
||
/* ======================================================
|
||
GESCHICHTE – Accordion
|
||
====================================================== */
|
||
const geschichteMount = document.getElementById("geschichte-inhalt");
|
||
if (geschichteMount && window.FFW_GESCHICHTE) {
|
||
const items = window.FFW_GESCHICHTE.map((epoche, i) => {
|
||
const inhalt = epoche.eintraege.map(e => {
|
||
const bildBtn = e.bild
|
||
? `<button type="button" class="btn-pill mt-3" data-bs-toggle="modal" data-bs-target="#modal1921">${window.FFW_GESCHICHTE_BILD.button}</button>`
|
||
: "";
|
||
return `${e.titel ? `<h2>${e.titel}</h2>` : ""}${e.html}${bildBtn}`;
|
||
}).join("");
|
||
|
||
return `
|
||
<div class="accordion-item">
|
||
<h2 class="accordion-header">
|
||
<button class="accordion-button${i === 0 ? "" : " collapsed"}" type="button"
|
||
data-bs-toggle="collapse" data-bs-target="#epoche${i}"
|
||
aria-expanded="${i === 0}" aria-controls="epoche${i}">
|
||
${epoche.zeitraum}
|
||
</button>
|
||
</h2>
|
||
<div id="epoche${i}" class="accordion-collapse collapse${i === 0 ? " show" : ""}" data-bs-parent="#geschichteAccordion">
|
||
<div class="accordion-body">${inhalt}</div>
|
||
</div>
|
||
</div>`;
|
||
}).join("");
|
||
|
||
geschichteMount.innerHTML = `
|
||
<div class="accordion gl-accordion" id="geschichteAccordion">${items}</div>`;
|
||
|
||
/* Modal für den Zeitungsartikel von 1921 */
|
||
document.body.insertAdjacentHTML("beforeend", `
|
||
<div class="modal fade" id="modal1921" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title">${window.FFW_GESCHICHTE_BILD.titel}</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Schließen"></button>
|
||
</div>
|
||
<div class="modal-body text-center">
|
||
<img src="${base}${window.FFW_GESCHICHTE_BILD.src}" alt="${window.FFW_GESCHICHTE_BILD.titel}" class="img-fluid rounded">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>`);
|
||
}
|
||
|
||
/* ======================================================
|
||
TECHNIK – Kartenraster mit Kategorie-Filter
|
||
====================================================== */
|
||
const technikMount = document.getElementById("technik-grid");
|
||
if (technikMount && window.FFW_FAHRZEUGE) {
|
||
const kategorien = [...new Set(window.FFW_FAHRZEUGE.map(f => f.kategorie))];
|
||
|
||
const filterBtns = [`<button class="filter-btn active" data-filter="alle">Alle</button>`]
|
||
.concat(kategorien.map(k => `<button class="filter-btn" data-filter="${k}">${k}</button>`))
|
||
.join("");
|
||
|
||
const karten = window.FFW_FAHRZEUGE.map(f => {
|
||
const inner = `
|
||
<div class="bild-wrap">
|
||
<img src="${base}${f.karte}" alt="${f.name}" loading="lazy">
|
||
<span class="kat-chip">${f.kategorie}</span>
|
||
${f.inArbeit ? `<span class="bald-chip">Demnächst</span>` : ""}
|
||
</div>
|
||
<div class="body"><h5>${f.name}</h5><span class="pfeil">→</span></div>`;
|
||
|
||
return `<div class="col-md-4 col-sm-6 tech-item" data-kategorie="${f.kategorie}">
|
||
${f.inArbeit
|
||
? `<div class="tech-card">${inner}</div>`
|
||
: `<a class="tech-card" href="fahrzeug.html?id=${f.id}">${inner}</a>`}
|
||
</div>`;
|
||
}).join("");
|
||
|
||
technikMount.innerHTML = `
|
||
<div class="filter-leiste">${filterBtns}</div>
|
||
<div class="row g-4">${karten}</div>`;
|
||
|
||
technikMount.querySelectorAll(".filter-btn").forEach(btn => {
|
||
btn.addEventListener("click", () => {
|
||
technikMount.querySelectorAll(".filter-btn").forEach(b => b.classList.remove("active"));
|
||
btn.classList.add("active");
|
||
const filter = btn.dataset.filter;
|
||
technikMount.querySelectorAll(".tech-item").forEach(item => {
|
||
item.classList.toggle("d-none", filter !== "alle" && item.dataset.kategorie !== filter);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
/* ======================================================
|
||
FAHRZEUG – Detailseite (datengetrieben via ?id=)
|
||
====================================================== */
|
||
const fzMount = document.getElementById("fahrzeug-detail");
|
||
if (fzMount && window.FFW_FAHRZEUGE) {
|
||
const id = new URLSearchParams(location.search).get("id");
|
||
const f = window.FFW_FAHRZEUGE.find(x => x.id === id);
|
||
|
||
if (!f || f.inArbeit) {
|
||
fzMount.innerHTML = `
|
||
<div class="fz-karte text-center">
|
||
<h3>Fahrzeug nicht gefunden</h3>
|
||
<p class="termin-beschr">Dieses Fahrzeug existiert nicht (mehr) oder die Seite befindet sich im Aufbau.</p>
|
||
<a class="btn-pill mt-3" href="technik.html">← Zurück zur Technik-Übersicht</a>
|
||
</div>`;
|
||
} else {
|
||
document.title = `${f.titel} | Feuerwehr Stadt Wehlen`;
|
||
|
||
const specs = f.daten.map(([label, wert]) =>
|
||
`<li><span class="spec-label">${label}</span><span>${wert}</span></li>`).join("");
|
||
|
||
const bereiche = (f.bereiche || []).map(b => `
|
||
<h3 class="fz-sektion">${b.titel}</h3>
|
||
<ul class="fz-punkte">${b.punkte.map(p => `<li>${p}</li>`).join("")}</ul>`).join("");
|
||
|
||
const galerie = f.bilder.length > 1
|
||
? `<div id="fahrzeugCarousel" class="carousel slide">
|
||
<div class="carousel-inner">
|
||
${f.bilder.map((b, i) => `<div class="carousel-item${i === 0 ? " active" : ""}"><img src="${base}${b.src}" class="d-block w-100" alt="${b.alt}" loading="lazy"></div>`).join("")}
|
||
</div>
|
||
<button class="carousel-control-prev" type="button" data-bs-target="#fahrzeugCarousel" data-bs-slide="prev"><span class="carousel-control-prev-icon"></span><span class="visually-hidden">Zurück</span></button>
|
||
<button class="carousel-control-next" type="button" data-bs-target="#fahrzeugCarousel" data-bs-slide="next"><span class="carousel-control-next-icon"></span><span class="visually-hidden">Weiter</span></button>
|
||
</div>`
|
||
: `<img src="${base}${f.bilder[0].src}" class="img-fluid w-100 fz-einzelbild" alt="${f.bilder[0].alt}" loading="lazy">`;
|
||
|
||
fzMount.innerHTML = `
|
||
<div class="row g-4">
|
||
<div class="col-lg-7">
|
||
<div class="fz-karte">
|
||
${f.standort ? `<span class="standort-chip">Standort: ${f.standort}</span>` : ""}
|
||
<h3>Fahrzeugdaten</h3>
|
||
<ul class="spec-list">${specs}</ul>
|
||
${bereiche}
|
||
${f.text ? `<p class="mt-4 mb-0">${f.text}</p>` : ""}
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-5">
|
||
${galerie}
|
||
${f.hinweis ? `<div class="fz-hinweis">${f.hinweis}</div>` : ""}
|
||
</div>
|
||
</div>`;
|
||
|
||
const carouselEl = fzMount.querySelector("#fahrzeugCarousel");
|
||
if (carouselEl && window.bootstrap) new bootstrap.Carousel(carouselEl, { interval: 5000 });
|
||
}
|
||
}
|
||
|
||
/* ======================================================
|
||
MITGLIEDER – Organigramm
|
||
====================================================== */
|
||
const orgMount = document.getElementById("mitglieder-inhalt");
|
||
if (orgMount && window.FFW_MITGLIEDER) {
|
||
const M = window.FFW_MITGLIEDER;
|
||
const box = (eintrag, klasse = "") => `
|
||
<div class="org-box ${klasse}">
|
||
<span class="rolle">${eintrag.rolle}</span>
|
||
<span class="name">${eintrag.namen.join("<br>")}</span>
|
||
</div>`;
|
||
|
||
const ebene = (eintraege, klasse = "") =>
|
||
`<div class="org-ebene">${eintraege.map(e => box(e, klasse)).join("")}</div>`;
|
||
|
||
const gruppen = M.gruppen.map(g => {
|
||
const inhalt = g.abschnitte
|
||
? g.abschnitte.map(a => `<span class="label">${a.label}</span><ul>${a.namen.map(n => `<li>${n}</li>`).join("")}</ul>`).join("")
|
||
: `<ul>${g.namen.map(n => `<li>${n}</li>`).join("")}</ul>`;
|
||
return `<div class="org-gruppe"><h3>${g.titel}</h3>${inhalt}</div>`;
|
||
}).join("");
|
||
|
||
orgMount.innerHTML = `
|
||
${ebene([M.fuehrung[0]], "fuehrung")}
|
||
${ebene([M.fuehrung[1]], "fuehrung")}
|
||
${ebene(M.stab)}
|
||
${ebene(M.fachwarte)}
|
||
<div class="org-gruppen">${gruppen}</div>`;
|
||
}
|
||
})();
|