Max nur eine Frage offen, Farb Korrektur Schrift

feature/FAQ
Niels Yannick Tietze 2026-09-30 13:32:55 +00:00
parent 7c96a97ebf
commit f04b45bf16
41 changed files with 4611 additions and 4562 deletions

128
FAQ.html
View File

@ -23,6 +23,15 @@
summary::-webkit-details-marker {
display: none;
}
:root {
--eyebrow-color: #53d5cd;
}
.eyebrow {
color: var(--eyebrow-color);
}
li::marker {
color: var(--eyebrow-color);
}
</style>
<script type="application/ld+json">
{
@ -191,12 +200,11 @@
</head>
<body class="min-h-screen">
<div id="navbar-placeholder"></div>
<main>
<section class="container py-20">
<div class="mx-auto max-w-4xl">
<p class="eyebrow mb-5 text-[var(--accent-warm)]">
Ernährungsberatung · FAQ
</p>
<p class="eyebrow mb-5">Ernährungsberatung · FAQ</p>
<h1
class="mb-6 font-display text-4xl leading-tight sm:text-5xl lg:text-7xl"
>
@ -276,9 +284,7 @@
aria-labelledby="h-grundlagen"
>
<div class="mb-5">
<p class="eyebrow mb-3 text-[var(--accent-warm)]">
3 Fragen
</p>
<p class="eyebrow mb-3">3 Fragen</p>
<h2
id="h-grundlagen"
class="font-display text-2xl sm:text-3xl"
@ -431,9 +437,7 @@
aria-labelledby="h-ablauf"
>
<div class="mb-5">
<p class="eyebrow mb-3 text-[var(--accent-warm)]">
5 Fragen
</p>
<p class="eyebrow mb-3">5 Fragen</p>
<h2
id="h-ablauf"
class="font-display text-2xl sm:text-3xl"
@ -515,9 +519,7 @@
<div
class="space-y-3 border-t border-white/10 pt-4 leading-relaxed text-white/70"
>
<ul
class="list-disc pl-5 space-y-2 marker:text-[var(--accent-warm)]"
>
<ul class="list-disc pl-5 space-y-2">
<li>
ein Ernährungsprotokoll der
letzten 3 bis 7 Tage (falls
@ -676,9 +678,7 @@
aria-labelledby="h-training"
>
<div class="mb-5">
<p class="eyebrow mb-3 text-[var(--accent-warm)]">
4 Fragen
</p>
<p class="eyebrow mb-3">4 Fragen</p>
<h2
id="h-training"
class="font-display text-2xl sm:text-3xl"
@ -717,9 +717,7 @@
<div
class="space-y-3 border-t border-white/10 pt-4 leading-relaxed text-white/70"
>
<ul
class="list-disc pl-5 space-y-2 marker:text-[var(--accent-warm)]"
>
<ul class="list-disc pl-5 space-y-2">
<li>
<strong>Vorher:</strong> leicht
verdauliche Kohlenhydrate, wenig
@ -884,9 +882,7 @@
aria-labelledby="h-gesundheit"
>
<div class="mb-5">
<p class="eyebrow mb-3 text-[var(--accent-warm)]">
4 Fragen
</p>
<p class="eyebrow mb-3">4 Fragen</p>
<h2
id="h-gesundheit"
class="font-display text-2xl sm:text-3xl"
@ -1077,9 +1073,7 @@
aria-labelledby="h-gewicht"
>
<div class="mb-5">
<p class="eyebrow mb-3 text-[var(--accent-warm)]">
3 Fragen
</p>
<p class="eyebrow mb-3">3 Fragen</p>
<h2
id="h-gewicht"
class="font-display text-2xl sm:text-3xl"
@ -1234,9 +1228,7 @@
<div
class="card-premium mx-auto max-w-4xl rounded-[1.8rem] p-8 text-center sm:p-12"
>
<p class="eyebrow mb-4 text-[var(--accent-warm)]">
Noch Fragen?
</p>
<p class="eyebrow mb-4">Noch Fragen?</p>
<h2 class="mb-4 font-display text-3xl sm:text-4xl">
Deine Frage war nicht dabei?
</h2>
@ -1281,86 +1273,6 @@
</div>
</footer>
<script>
(function () {
var items = [].slice.call(
document.querySelectorAll(".faq-item"),
);
var sections = [].slice.call(
document.querySelectorAll(".faq-section"),
);
var chips = [].slice.call(document.querySelectorAll(".chip"));
var search = document.getElementById("search");
var empty = document.getElementById("empty");
var status = document.getElementById("status");
var filter = "all";
var ON = [
"bg-primary",
"text-primary-foreground",
"border-transparent",
];
var OFF = [
"bg-white/5",
"text-white/70",
"border-white/10",
"hover:bg-white/10",
];
document.getElementById("year").textContent =
new Date().getFullYear();
items.forEach(function (d) {
d.addEventListener("toggle", function () {
d.dataset.state = d.open ? "open" : "closed";
});
});
function paintChips() {
chips.forEach(function (c) {
var active = c.dataset.filter === filter;
ON.forEach(function (k) {
c.classList.toggle(k, active);
});
OFF.forEach(function (k) {
c.classList.toggle(k, !active);
});
c.setAttribute("aria-pressed", active);
});
}
function apply() {
var q = search.value.trim().toLowerCase(),
shown = 0;
sections.forEach(function (s) {
var visible = 0;
s.querySelectorAll(".faq-item").forEach(function (d) {
var ok =
(filter === "all" ||
s.dataset.cat === filter) &&
(!q ||
d.textContent.toLowerCase().indexOf(q) >
-1);
d.classList.toggle("hidden", !ok);
if (ok) visible++;
});
s.classList.toggle("hidden", visible === 0);
shown += visible;
});
empty.classList.toggle("hidden", shown > 0);
status.textContent = shown + " Fragen angezeigt";
}
chips.forEach(function (c) {
c.addEventListener("click", function () {
filter = c.dataset.filter;
paintChips();
apply();
});
});
search.addEventListener("input", apply);
paintChips();
apply();
})();
</script>
<script src="/src/features/faq/faq.js" defer></script>
</body>
</html>

View File

@ -0,0 +1,137 @@
/**
* Tri-hub FAQ
* Suche, Kategorien, Accordion und Footer-Jahr
*/
document.addEventListener("DOMContentLoaded", () => {
const searchInput = document.getElementById("search");
const chipsContainer = document.getElementById("chips");
const sections = Array.from(document.querySelectorAll(".faq-section"));
const faqItems = Array.from(document.querySelectorAll(".faq-item"));
const emptyMessage = document.getElementById("empty");
const status = document.getElementById("status");
const yearElement = document.getElementById("year");
// Aktuelles Jahr im Footer
if (yearElement) {
yearElement.textContent = new Date().getFullYear();
}
// Aktiver Kategorie-Filter
let activeFilter = "all";
// Text für die Suche vereinheitlichen
function normalizeText(text) {
return text
.toLocaleLowerCase("de")
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.trim();
}
// FAQ-Suche und Kategorie-Filter anwenden
function filterFAQs() {
const searchTerm = normalizeText(searchInput?.value || "");
let visibleCount = 0;
sections.forEach((section) => {
const category = section.dataset.cat;
const categoryMatches =
activeFilter === "all" || category === activeFilter;
const items = Array.from(section.querySelectorAll(".faq-item"));
let visibleInSection = 0;
items.forEach((item) => {
const searchableText = normalizeText(item.textContent);
const searchMatches =
searchTerm === "" || searchableText.includes(searchTerm);
const isVisible = categoryMatches && searchMatches;
item.hidden = !isVisible;
if (isVisible) {
visibleInSection++;
visibleCount++;
}
});
// Kategorie nur anzeigen, wenn Fragen passen
section.hidden = visibleInSection === 0;
});
// Hinweis anzeigen, wenn nichts gefunden wurde
if (emptyMessage) {
emptyMessage.classList.toggle("hidden", visibleCount > 0);
}
// Screenreader über das Suchergebnis informieren
if (status) {
status.textContent =
visibleCount === 1
? "Eine Frage gefunden."
: `${visibleCount} Fragen gefunden.`;
}
}
// Kategorie-Buttons initialisieren
if (chipsContainer) {
const chips = Array.from(
chipsContainer.querySelectorAll("[data-filter]"),
);
function updateActiveChip() {
chips.forEach((chip) => {
const isActive = chip.dataset.filter === activeFilter;
chip.classList.toggle("is-active", isActive);
chip.setAttribute("aria-pressed", String(isActive));
});
}
chips.forEach((chip) => {
chip.addEventListener("click", () => {
activeFilter = chip.dataset.filter;
updateActiveChip();
filterFAQs();
});
});
updateActiveChip();
}
// Suche bei jeder Eingabe aktualisieren
if (searchInput) {
searchInput.addEventListener("input", filterFAQs);
}
// Accordion: Immer nur eine Frage gleichzeitig öffnen
faqItems.forEach((item) => {
item.addEventListener("toggle", () => {
const isOpen = item.open;
item.dataset.state = isOpen ? "open" : "closed";
if (!isOpen) return;
faqItems.forEach((otherItem) => {
if (otherItem !== item && otherItem.open) {
otherItem.open = false;
}
});
});
});
// Initialzustand setzen
faqItems.forEach((item) => {
item.dataset.state = item.open ? "open" : "closed";
});
filterFAQs();
});