Compare commits

..

No commits in common. "main" and "US-03-01-Online-Terminbuchung" have entirely different histories.

12 changed files with 135 additions and 156 deletions

View File

@ -134,7 +134,7 @@
.beratung-bereich .btn-accent { .beratung-bereich .btn-accent {
background: var(--accent); background: var(--accent);
color: var(--text-primary); color: #03242b;
} }
.beratung-bereich .btn-accent:hover { .beratung-bereich .btn-accent:hover {

View File

@ -86,6 +86,7 @@
/* Empfehlung kommt aus der JSON-Datei; die Auswahlklasse setzt leistungen.js beim Klick. */ /* Empfehlung kommt aus der JSON-Datei; die Auswahlklasse setzt leistungen.js beim Klick. */
.pakete .paket-karte--empfohlen { .pakete .paket-karte--empfohlen {
border-color: 1px solid rgba(248, 250, 252, 0.08);
box-shadow: 0 0 0 1px var(--accent-soft); box-shadow: 0 0 0 1px var(--accent-soft);
} }
@ -203,17 +204,15 @@
/* ---------- Paketauswahl und Tastaturfokus ---------- */ /* ---------- Paketauswahl und Tastaturfokus ---------- */
.pakete .paket-karte__cta { .pakete .paket-karte__cta {
display: inline-block;
font-family: var(--font-body); font-family: var(--font-body);
font-weight: 600; font-weight: 600;
font-size: 0.95rem; font-size: 0.95rem;
color: var(--text-primary); color: var(--text-primary);
background: var(--accent); background: var(--background);
border: none; border: 1px solid rgba(248, 250, 252, 0.08);
border-radius: 8px; border-radius: 8px;
padding: 0.85rem 1rem; padding: 0.85rem 1rem;
cursor: pointer; cursor: pointer;
text-decoration: none;
transition: filter 0.15s ease; transition: filter 0.15s ease;
} }

View File

@ -37,10 +37,6 @@
position: relative; position: relative;
box-sizing: border-box; box-sizing: border-box;
width: min(560px, 100%); width: min(560px, 100%);
/* Bei kleinen Fenstern bleibt der gesamte Dialog erreichbar. */
max-height: calc(100dvh - 48px);
overflow-y: auto;
overscroll-behavior: contain;
background-color: #111a1e; background-color: #111a1e;
border: 2px solid rgb(255 255 255 / 9%); border: 2px solid rgb(255 255 255 / 9%);
border-radius: 16px; border-radius: 16px;
@ -1149,4 +1145,4 @@
.tb-overlay * { .tb-overlay * {
transition-duration: 0.01ms !important; transition-duration: 0.01ms !important;
} }
} }

View File

@ -146,7 +146,7 @@
</div> </div>
<div class="reveal"> <div class="reveal">
<h3 style="font-size: 1.25rem; margin-bottom: 24px; margin-top: 38px;">Kontaktinformationen</h3> <h3 style="font-size: 1.25rem; margin-bottom: 24px;">Kontaktinformationen</h3>
<div class="info-stack"> <div class="info-stack">
<div class="info-card"> <div class="info-card">
<div class="info-card__icon" aria-hidden="true">✉</div> <div class="info-card__icon" aria-hidden="true">✉</div>
@ -238,7 +238,7 @@
</div> </div>
<div class="footer-legal"> <div class="footer-legal">
<span>© 2026 TRI-HUB GmbH</span> <span>© 2026 Tri-hub GmbH</span>
<span> <span>
<a href="https://tri-hub.de/impressum">Impressum</a> · <a href="https://tri-hub.de/impressum">Impressum</a> ·
<a href="https://tri-hub.de/datenschutz">Datenschutz</a> · <a href="https://tri-hub.de/datenschutz">Datenschutz</a> ·

View File

@ -58,6 +58,7 @@
<p class="hero__description">Volle Betreuung für ambitionierte Athletinnen und Athleten ab 50. Wir stehen dir wöchentlich zur Seite, stimmen deine Nahrungsergänzung ab und begleiten dich direkt an deinem Wettkampftag.</p> <p class="hero__description">Volle Betreuung für ambitionierte Athletinnen und Athleten ab 50. Wir stehen dir wöchentlich zur Seite, stimmen deine Nahrungsergänzung ab und begleiten dich direkt an deinem Wettkampftag.</p>
<div class="paket-detail__actions"> <div class="paket-detail__actions">
<a class="btn btn-accent" href="#anfrage">Premium-Paket ansehen <span aria-hidden="true">↗</span></a> <a class="btn btn-accent" href="#anfrage">Premium-Paket ansehen <span aria-hidden="true">↗</span></a>
<a class="paket-detail__text-link" href="#leistungen">Was ist enthalten? <span aria-hidden="true">↓</span></a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -58,6 +58,7 @@
<p class="hero__description">Laufende Betreuung für Triathletinnen und Triathleten, die regelmäßig trainieren. Wir passen deine Ernährung flexibel an deine Trainingsphasen an und entwickeln deine Wettkampfstrategie.</p> <p class="hero__description">Laufende Betreuung für Triathletinnen und Triathleten, die regelmäßig trainieren. Wir passen deine Ernährung flexibel an deine Trainingsphasen an und entwickeln deine Wettkampfstrategie.</p>
<div class="paket-detail__actions"> <div class="paket-detail__actions">
<a class="btn btn-accent" href="#anfrage">Standard-Paket ansehen <span aria-hidden="true">↗</span></a> <a class="btn btn-accent" href="#anfrage">Standard-Paket ansehen <span aria-hidden="true">↗</span></a>
<a class="paket-detail__text-link" href="#leistungen">Was ist enthalten? <span aria-hidden="true">↓</span></a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -58,6 +58,7 @@
<p class="hero__description">Du möchtest deine Ernährung bewusster auf dein Training abstimmen? Wir begleiten deinen Einstieg – mit einem persönlichen Gespräch, einem Plan für dich und konkreten Ideen für deinen Alltag.</p> <p class="hero__description">Du möchtest deine Ernährung bewusster auf dein Training abstimmen? Wir begleiten deinen Einstieg – mit einem persönlichen Gespräch, einem Plan für dich und konkreten Ideen für deinen Alltag.</p>
<div class="paket-detail__actions"> <div class="paket-detail__actions">
<a class="btn btn-accent" href="#anfrage">Starter-Paket ansehen <span aria-hidden="true">↗</span></a> <a class="btn btn-accent" href="#anfrage">Starter-Paket ansehen <span aria-hidden="true">↗</span></a>
<a class="paket-detail__text-link" href="#leistungen">Was ist enthalten? <span aria-hidden="true">↓</span></a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -38,6 +38,8 @@
aria-label="Menü öffnen">☰</button> aria-label="Menü öffnen">☰</button>
<nav class="site-navigation__links" id="navigation-links" aria-label="Seitennavigation"> <nav class="site-navigation__links" id="navigation-links" aria-label="Seitennavigation">
<ul> <ul>
<li><a href="#termin">Termin</a></li>
<li><a href="#formular">Deine Angaben</a></li>
<li><a href="../index.html">Zurück zur Übersicht</a></li> <li><a href="../index.html">Zurück zur Übersicht</a></li>
</ul> </ul>
</nav> </nav>
@ -174,8 +176,8 @@
<div class="tb-review-actions"> <div class="tb-review-actions">
<button type="button" class="tb-review-button tb-review-button--secondary" <button type="button" class="tb-review-button tb-review-button--secondary"
id="anfrage-bearbeiten">Zurück und bearbeiten</button> id="anfrage-bearbeiten">Zurück und bearbeiten</button>
<button type="button" class="tb-review-button tb-review-button--primary" id="anfrage-senden" disabled>Anfrage <a class="tb-review-button tb-review-button--primary" id="anfrage-senden" href="#">Anfrage
senden</button> senden</a>
</div> </div>
</div> </div>
</div> </div>
@ -213,7 +215,7 @@
</div> </div>
<div class="footer-legal"> <div class="footer-legal">
<span>© 2026 TRI-HUB GmbH</span> <span>© 2026 Tri-hub GmbH</span>
<span> <span>
<a href="https://tri-hub.de/impressum">Impressum</a> · <a href="https://tri-hub.de/impressum">Impressum</a> ·
<a href="https://tri-hub.de/datenschutz">Datenschutz</a> · <a href="https://tri-hub.de/datenschutz">Datenschutz</a> ·
@ -226,12 +228,13 @@
<dialog class="tb-confirm-dialog" id="anfrage-bestaetigung" aria-labelledby="bestaetigung-titel" <dialog class="tb-confirm-dialog" id="anfrage-bestaetigung" aria-labelledby="bestaetigung-titel"
aria-describedby="bestaetigung-text"> aria-describedby="bestaetigung-text">
<span class="kicker">Termin gebucht</span> <span class="kicker">Anfrage vorbereitet</span>
<h2 id="bestaetigung-titel">Terminbestätigung</h2> <h2 id="bestaetigung-titel">Terminanfrage</h2>
<p id="bestaetigung-text">Dein Termin wurde erfolgreich gebucht. Eine Bestätigung wurde an die angegebene E-Mail-Adresse gesendet.</p> <p id="bestaetigung-text">Deine Terminanfrage wurde an dein E-Mail-Programm übergeben. Sende sie dort
bitte ab. Wir prüfen deinen Wunschtermin und schicken dir anschließend eine Bestätigung per E-Mail.</p>
<a class="tb-review-button tb-review-button--primary" href="../index.html">OK, zur Übersicht</a> <a class="tb-review-button tb-review-button--primary" href="../index.html">OK, zur Übersicht</a>
</dialog> </dialog>
</div> </div>
</body> </body>
</html> </html>

View File

@ -249,7 +249,7 @@
</div> </div>
<div class="footer-legal"> <div class="footer-legal">
<span>© 2026 TRI-HUB GmbH</span> <span>© 2026 Tri-hub GmbH</span>
<span> <span>
<a href="https://tri-hub.de/impressum">Impressum</a> · <a href="https://tri-hub.de/impressum">Impressum</a> ·
<a href="https://tri-hub.de/datenschutz">Datenschutz</a> · <a href="https://tri-hub.de/datenschutz">Datenschutz</a> ·

View File

@ -1,7 +1,7 @@
// Online-Terminbuchung – Buchungsseite (html/terminbuchung.html). // Online-Terminbuchung – Buchungsseite (html/terminbuchung.html).
// Liest den gewählten Termin aus der URL (berater, datum, zeit), füllt die // Liest den gewählten Termin aus der URL (berater, datum, zeit), füllt die
// Zusammenfassung, verwaltet die Anamnese-Tags und prüft das Formular. // Zusammenfassung, verwaltet die Anamnese-Tags und prüft das Formular.
// Die Bestätigung wird nur auf der Seite angezeigt; es wird keine E-Mail versendet. // Zum Absenden wird wie auf der Kontaktseite das E-Mail-Programm geöffnet.
// ----- Scroll-Reveal ----- // ----- Scroll-Reveal -----
(function () { (function () {
@ -34,6 +34,66 @@
}); });
})(); })();
// ----- Termin-Zusammenfassung aus der URL -----
(function () {
const params = new URLSearchParams(window.location.search);
const beraterId = params.get("berater");
const datum = params.get("datum");
const zeit = params.get("zeit");
const elBerater = document.getElementById("tb-berater");
const elDatum = document.getElementById("tb-datum");
const elZeit = document.getElementById("tb-zeit");
const zusammenfassung = document.getElementById("termin-zusammenfassung");
if (!zusammenfassung) return;
// Ohne Termin-Parameter (z. B. direkter Seitenaufruf): Hinweis statt Zusammenfassung.
if (!beraterId || !datum || !zeit) {
zusammenfassung.classList.add("tb-summary--fehlend");
zusammenfassung.innerHTML = `
<div class="tb-summary__item">
<span class="tb-summary__label">Kein Termin ausgewählt</span>
<p class="tb-summary__value" style="font-size: 0.95rem; font-weight: 400;">
Du hast noch keinen Termin im Kalender gewählt.
Gehe bitte zurück zur <a href="../index.html#berater">Startseite</a> und öffne dort über einen
Berater die Terminbuchung.
</p>
</div>
`;
return;
}
// Datum lesbar formatieren, z. B. "Montag, 05.10.2026"
const [jahr, monat, tag] = datum.split("-").map(Number);
if (!jahr || !monat || !tag) return;
const datumObjekt = new Date(jahr, monat - 1, tag);
const formatiert = new Intl.DateTimeFormat("de-DE", {
weekday: "long",
day: "2-digit",
month: "2-digit",
year: "numeric"
}).format(datumObjekt);
elDatum.textContent = formatiert;
elZeit.textContent = zeit.replace(":", ".") + " Uhr";
// Berater-Namen aus json/berater.json auflösen (ID stammt aus dem Kalender).
fetch("../json/berater.json")
.then(function (response) {
if (!response.ok) throw new Error("HTTP " + response.status);
return response.json();
})
.then(function (daten) {
const treffer = (daten.berater || []).find(function (b) {
return String(b.id) === String(beraterId);
});
elBerater.textContent = treffer ? String(treffer.name).trim() : "Unbekannter Berater";
})
.catch(function () {
elBerater.textContent = "Unbekannter Berater";
});
})();
// ----- Anamnese-Tags (Allergien & Unverträglichkeiten) ----- // ----- Anamnese-Tags (Allergien & Unverträglichkeiten) -----
(function () { (function () {
const input = document.getElementById("tag-input"); const input = document.getElementById("tag-input");
@ -115,6 +175,7 @@
const form = document.getElementById("terminbuchung-formular"); const form = document.getElementById("terminbuchung-formular");
if (!form) return; if (!form) return;
const EMAIL_TARGET = "info@trihub.de";
const bestaetigungDialog = document.getElementById("anfrage-bestaetigung"); const bestaetigungDialog = document.getElementById("anfrage-bestaetigung");
const fields = { const fields = {
@ -132,7 +193,7 @@
const pruefBereich = document.getElementById("anfrage-pruefen"); const pruefBereich = document.getElementById("anfrage-pruefen");
const pruefDetails = document.getElementById("anfrage-pruefen-details"); const pruefDetails = document.getElementById("anfrage-pruefen-details");
const bearbeitenButton = document.getElementById("anfrage-bearbeiten"); const bearbeitenButton = document.getElementById("anfrage-bearbeiten");
const sendenButton = document.getElementById("anfrage-senden"); const sendenLink = document.getElementById("anfrage-senden");
function wrap(el) { function wrap(el) {
return el.closest(".field"); return el.closest(".field");
@ -173,7 +234,6 @@
function allValid() { function allValid() {
return ( return (
terminIstGueltig() &&
fields.art.value !== "" && fields.art.value !== "" &&
fields.format.value !== "" && fields.format.value !== "" &&
fields.gespraech.value !== "" && fields.gespraech.value !== "" &&
@ -206,76 +266,26 @@
}); });
}); });
// Nur ein eingetragener, noch zukünftiger Termin darf angefragt werden. // Termin-Angaben aus der URL für das E-Mail übernehmen.
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
const beraterId = params.get("berater"); const datumRoh = params.get("datum") || "";
const datum = params.get("datum"); const zeitRoh = params.get("zeit") || "";
const zeit = params.get("zeit"); let terminText = "–";
let termin = null; if (datumRoh && zeitRoh) {
const [jahr, monat, tag] = datumRoh.split("-").map(Number);
function terminIstGueltig() { if (jahr && monat && tag) {
return termin !== null && termin.zeitpunkt > Date.now(); const formatiert = new Intl.DateTimeFormat("de-DE", {
} weekday: "long",
day: "2-digit",
function terminFehlerAnzeigen(text) { month: "2-digit",
termin = null; year: "numeric"
const zusammenfassung = document.getElementById("termin-zusammenfassung"); }).format(new Date(jahr, monat - 1, tag));
zusammenfassung.classList.add("tb-summary--fehlend"); terminText = formatiert + " um " + zeitRoh.replace(":", ".") + " Uhr";
zusammenfassung.innerHTML = `
<div class="tb-summary__item">
<span class="tb-summary__label">Bitte einen gültigen Termin wählen</span>
<p class="tb-summary__value" style="font-size: 0.95rem; font-weight: 400;">
Wähle auf der <a href="../index.html#berater">Startseite</a> einen Berater,
einen verfügbaren Tag und eine Uhrzeit.
</p>
</div>
`;
pruefBereich.hidden = true;
formularBereich.hidden = false;
sendenButton.disabled = true;
showStatus("error", text);
updateSubmitState();
}
async function terminLaden() {
if (!beraterId || !datum || !zeit) {
terminFehlerAnzeigen("Bitte wähle zuerst einen Termin im Kalender.");
return;
}
try {
const [beraterDaten, terminDaten] = await Promise.all(
["../json/berater.json", "../json/terminbuchung.json"].map(async function (url) {
const response = await fetch(url);
if (!response.ok) throw new Error("HTTP " + response.status);
return response.json();
})
);
const berater = beraterDaten.berater.find(function (eintrag) {
return String(eintrag.id) === beraterId;
});
const zeiten = terminDaten[beraterId]?.[datum];
const zeitpunkt = new Date(`${datum}T${zeit}:00`).getTime();
if (!berater || !Array.isArray(zeiten) || !zeiten.includes(zeit) || !(zeitpunkt > Date.now())) {
terminFehlerAnzeigen("Dieser Termin ist nicht verfügbar oder bereits vergangen. Bitte wähle einen neuen Termin.");
return;
}
const datumText = new Intl.DateTimeFormat("de-DE", {
weekday: "long", day: "2-digit", month: "2-digit", year: "numeric"
}).format(new Date(zeitpunkt));
termin = {
zeitpunkt,
berater: String(berater.name).trim(),
text: datumText + " um " + zeit.replace(":", ".") + " Uhr"
};
document.getElementById("tb-berater").textContent = termin.berater;
document.getElementById("tb-datum").textContent = datumText;
document.getElementById("tb-zeit").textContent = zeit.replace(":", ".") + " Uhr";
updateSubmitState();
} catch (error) {
terminFehlerAnzeigen("Der Termin konnte nicht geprüft werden. Bitte lade die Seite erneut.");
} }
} }
const elBerater = document.getElementById("tb-berater");
function labelVon(key) { function labelVon(key) {
const select = fields[key]; const select = fields[key];
return select.options[select.selectedIndex].text; return select.options[select.selectedIndex].text;
@ -298,22 +308,15 @@
formularBereich.scrollIntoView({ behavior: "smooth", block: "start" }); formularBereich.scrollIntoView({ behavior: "smooth", block: "start" });
}); });
sendenButton.addEventListener("click", function () { sendenLink.addEventListener("click", function (event) {
if (!terminIstGueltig()) { event.preventDefault();
terminFehlerAnzeigen("Der Termin ist nicht mehr gültig. Bitte wähle einen neuen Termin.");
formularBereich.scrollIntoView({ block: "start" });
return;
}
bestaetigungDialog.showModal(); bestaetigungDialog.showModal();
window.location.href = sendenLink.href;
}); });
form.addEventListener("submit", function (event) { form.addEventListener("submit", function (event) {
event.preventDefault(); event.preventDefault();
form.dataset.touched = "true"; form.dataset.touched = "true";
if (!terminIstGueltig()) {
terminFehlerAnzeigen("Bitte wähle zuerst einen verfügbaren, zukünftigen Termin.");
return;
}
const okArt = validateSelect("art"); const okArt = validateSelect("art");
const okFormat = validateSelect("format"); const okFormat = validateSelect("format");
@ -327,8 +330,7 @@
} }
const tagListe = window.TerminbuchungTags ? window.TerminbuchungTags.holen() : []; const tagListe = window.TerminbuchungTags ? window.TerminbuchungTags.holen() : [];
const beraterText = termin.berater; const beraterText = elBerater ? elBerater.textContent.trim() : "–";
const terminText = termin.text;
const anfrageDaten = [ const anfrageDaten = [
["Berater/in", beraterText], ["Berater/in", beraterText],
["Termin", terminText], ["Termin", terminText],
@ -342,8 +344,28 @@
["Telefon", fields.phone.value.trim() || "–"] ["Telefon", fields.phone.value.trim() || "–"]
]; ];
const body = [
"Terminanfrage – Trainingsplan & Beratung",
"",
"Termin: " + terminText,
"Berater/in: " + beraterText,
"Art der Ernährungsberatung: " + labelVon("art"),
"Beratungsformat: " + labelVon("format"),
"Gesprächsart: " + labelVon("gespraech"),
"",
"Kurzbeschreibung: " + (fields.beschreibung.value.trim() || "–"),
"Anamnese (Allergien & Unverträglichkeiten): " + (tagListe.length ? tagListe.join(", ") : "–"),
"",
"Name: " + fields.name.value.trim(),
"E-Mail: " + fields.email.value.trim(),
"Telefon: " + (fields.phone.value.trim() || "–")
].join("\n");
werteAnzeigen(anfrageDaten); werteAnzeigen(anfrageDaten);
sendenButton.disabled = false; sendenLink.href =
"mailto:" + EMAIL_TARGET +
"?subject=" + encodeURIComponent("Terminanfrage: " + terminText) +
"&body=" + encodeURIComponent(body);
formularBereich.hidden = true; formularBereich.hidden = true;
pruefBereich.hidden = false; pruefBereich.hidden = false;
pruefBereich.scrollIntoView({ behavior: "smooth", block: "start" }); pruefBereich.scrollIntoView({ behavior: "smooth", block: "start" });
@ -357,5 +379,4 @@
} }
updateSubmitState(); updateSubmitState();
terminLaden();
})(); })();

View File

@ -77,17 +77,18 @@
const tabelle = terminDaten[String(beraterId)]; const tabelle = terminDaten[String(beraterId)];
if (!tabelle || typeof tabelle !== "object") return []; if (!tabelle || typeof tabelle !== "object") return [];
const zeiten = tabelle[schluessel]; const zeiten = tabelle[schluessel];
// Auch bereits vergangene Uhrzeiten am heutigen Tag ausblenden. return Array.isArray(zeiten) ? zeiten : [];
return Array.isArray(zeiten)
? zeiten.filter((zeit) => new Date(`${schluessel}T${zeit}:00`).getTime() > Date.now())
: [];
} }
function hatFreieTermine(beraterId) { function hatFreieTermine(beraterId) {
const tabelle = terminDaten[String(beraterId)]; const tabelle = terminDaten[String(beraterId)];
if (!tabelle || typeof tabelle !== "object") return false; if (!tabelle || typeof tabelle !== "object") return false;
return Object.keys(tabelle).some((schluessel) => zeitenFuer(beraterId, schluessel).length > 0); return Object.entries(tabelle).some(([schluessel, zeiten]) => {
const datum = /^(\d{4})-(\d{2})-(\d{2})$/.exec(schluessel);
if (!datum || !Array.isArray(zeiten) || zeiten.length === 0) return false;
return !istVergangen(Number(datum[1]), Number(datum[2]) - 1, Number(datum[3]));
});
} }
function istVerfuegbar(jahr, monat, tag) { function istVerfuegbar(jahr, monat, tag) {
@ -120,7 +121,7 @@
<div class="tb-dialog" role="dialog" aria-modal="true" aria-labelledby="tb-title"> <div class="tb-dialog" role="dialog" aria-modal="true" aria-labelledby="tb-title">
<button type="button" class="tb-close" aria-label="Terminbuchung schließen">&times;</button> <button type="button" class="tb-close" aria-label="Terminbuchung schließen">&times;</button>
<span class="tb-kicker">Online-Terminbuchung</span> <span class="tb-kicker">Online-Terminbuchung</span>
<h2 class="tb-title" id="tb-title"> Termin wählen</h2> <h2 class="tb-title" id="tb-title">Trainingsplan &amp; Beratung – Termin wählen</h2>
<p class="tb-subtitle">Wähle deinen Berater, einen verfügbaren Tag und eine Uhrzeit.</p> <p class="tb-subtitle">Wähle deinen Berater, einen verfügbaren Tag und eine Uhrzeit.</p>
<span class="tb-trainer-label">Berater/in wählen:</span> <span class="tb-trainer-label">Berater/in wählen:</span>
@ -180,32 +181,7 @@
if (event.target === overlay) schliessen(); if (event.target === overlay) schliessen();
}); });
document.addEventListener("keydown", (event) => { document.addEventListener("keydown", (event) => {
if (!istGeoeffnet) return; if (istGeoeffnet && event.key === "Escape") schliessen();
if (event.key === "Escape") {
event.preventDefault();
schliessen();
return;
}
if (event.key !== "Tab") return;
// Tab und Shift+Tab bleiben zwischen den sichtbaren Dialog-Buttons.
const buttons = [...overlay.querySelectorAll("button:not(:disabled)")]
.filter((button) => button.getClientRects().length > 0);
const erster = buttons[0];
const letzter = buttons[buttons.length - 1];
const fokus = document.activeElement;
if (!overlay.contains(fokus) || (event.shiftKey && fokus === erster)) {
event.preventDefault();
(event.shiftKey ? letzter : erster).focus();
} else if (!event.shiftKey && fokus === letzter) {
event.preventDefault();
erster.focus();
}
});
document.addEventListener("focusin", (event) => {
if (istGeoeffnet && !overlay.contains(event.target)) {
overlay.querySelector(".tb-close").focus();
}
}); });
// Buchen // Buchen
@ -297,14 +273,9 @@
kalenderZeichnen(); kalenderZeichnen();
zeitenZeichnen(); zeitenZeichnen();
buchButtonAktualisieren(); buchButtonAktualisieren();
overlay.querySelector(".tb-day--ausgewaehlt")?.focus();
} }
function zeitKlicken(zeit) { function zeitKlicken(zeit) {
if (!zeitenFuer(zustand.beraterId, zustand.datum).includes(zeit)) {
auswahlAktualisieren();
return;
}
zustand.zeit = zeit; zustand.zeit = zeit;
overlay.querySelectorAll(".tb-time-chip").forEach((chip) => { overlay.querySelectorAll(".tb-time-chip").forEach((chip) => {
chip.classList.toggle("is-active", chip.dataset.zeit === zeit); chip.classList.toggle("is-active", chip.dataset.zeit === zeit);
@ -314,11 +285,6 @@
function buchen() { function buchen() {
if (!zustand.datum || !zustand.zeit || zustand.beraterId == null) return; if (!zustand.datum || !zustand.zeit || zustand.beraterId == null) return;
// Die Seite kann seit der Auswahl offen geblieben sein.
if (!zeitenFuer(zustand.beraterId, zustand.datum).includes(zustand.zeit)) {
auswahlAktualisieren();
return;
}
const ziel = const ziel =
ZIELSEITE + ZIELSEITE +
"?berater=" + encodeURIComponent(zustand.beraterId) + "?berater=" + encodeURIComponent(zustand.beraterId) +
@ -327,15 +293,6 @@
window.location.href = ziel; window.location.href = ziel;
} }
function auswahlAktualisieren() {
zustand.zeit = null;
kalenderZeichnen();
zeitenZeichnen();
legendeAktualisieren();
buchButtonAktualisieren();
overlay.querySelector(".tb-close").focus();
}
// ----- Zeichnen ----- // ----- Zeichnen -----
function kalenderZeichnen() { function kalenderZeichnen() {

View File

@ -21,7 +21,7 @@
"url": "https://instagram.com" "url": "https://instagram.com"
}, },
{ {
"text": "Termin buchen", "text": "Trainingsplan buchen",
"url": "https://tri-hub.de/booking", "url": "https://tri-hub.de/booking",
"aktion": "terminbuchung" "aktion": "terminbuchung"
} }
@ -44,7 +44,7 @@
"url": "https://instagram.com" "url": "https://instagram.com"
}, },
{ {
"text": "Termin buchen", "text": "Trainingsplan buchen",
"url": "https://tri-hub.de/booking", "url": "https://tri-hub.de/booking",
"aktion": "terminbuchung" "aktion": "terminbuchung"
} }