365 lines
16 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ======================================================
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><a class="dropdown-item" data-page="mitglieder" href="mitglieder.html">Organigramm</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" data-page="jugendfeuerwehr" href="jugendfeuerwehr.html">Jugendfeuerwehr</a></li>
<li><a class="dropdown-item" data-page="foerderverein" href="foerderverein.html">Förderverein</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="jugendfeuerwehr.html">Jugendfeuerwehr</a></li>
<li><a href="foerderverein.html">Förderverein</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>
<li><a href="datenschutz.html">Datenschutz</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 &amp; 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>`;
}
/* ======================================================
FÖRDERVEREIN Downloads & Sponsoren
====================================================== */
const dlMount = document.getElementById("foerderverein-downloads");
if (dlMount && window.FFW_FOERDERVEREIN) {
const F = window.FFW_FOERDERVEREIN;
dlMount.innerHTML = `<div class="row g-4">${F.downloads.map(d => `
<div class="col-md-6 col-lg-3">
<a class="gl-card text-center" href="${base}${d.datei}" target="_blank" rel="noopener">
<h3>${d.titel}</h3>
<p class="beschreibung">${d.beschr}</p>
<span class="mehr">PDF öffnen ↗</span>
</a>
</div>`).join("")}
</div>`;
}
const spMount = document.getElementById("sponsoren-inhalt");
if (spMount && window.FFW_FOERDERVEREIN) {
const F = window.FFW_FOERDERVEREIN;
const privat = Object.entries(F.sponsorenPrivat).map(([gruppe, namen]) => `
<div class="col-md-4">
<div class="org-gruppe h-100">
<h3>${gruppe}</h3>
<ul>${namen.map(n => `<li>${n}</li>`).join("")}</ul>
</div>
</div>`).join("");
const firmen = F.sponsorenFirmen.map(f => `
<div class="col-md-6 col-lg-4">
<div class="sponsor-firma">
<strong>${f.name}</strong>
<span>${f.ort}</span>
${f.tel ? `<span>Tel.: ${f.tel}</span>` : ""}
</div>
</div>`).join("");
spMount.innerHTML = `
<h2 class="abschnitt-titel mt-5">Unsere Sponsoren</h2>
<p class="abschnitt-sub">Herzlichen Dank für die Unterstützung!</p>
<h3 class="fz-sektion">Privatpersonen</h3>
<div class="row g-4 mb-4">${privat}</div>
<h3 class="fz-sektion">Vereine</h3>
<div class="org-gruppe mb-4" style="max-width: 420px;">
<ul>${F.sponsorenVereine.map(v => `<li>${v}</li>`).join("")}</ul>
</div>
<h3 class="fz-sektion">Firmen</h3>
<div class="row g-3">${firmen}</div>`;
}
})();