Beraterkarten sowie Daten erstellt und in index.html eingebunden
parent
55e4904482
commit
370d54fb39
16
index.html
16
index.html
|
|
@ -920,6 +920,21 @@
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- User Story: Rezensionen -->
|
<!-- User Story: Rezensionen -->
|
||||||
|
<section class="section advisor-section" id="beraterteam" aria-labelledby="advisor-heading">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-heading">
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow">PERSÖNLICH FÜR DICH DA</p>
|
||||||
|
<h2 id="advisor-heading">Lerne deine Ernährungsberater kennen.</h2>
|
||||||
|
</div>
|
||||||
|
<p class="section-intro">Hinter einer guten Ernährungsstrategie stehen Menschen, die zuhören und ihre Erfahrung in deinen Alltag und dein Training einbringen.</p>
|
||||||
|
</div>
|
||||||
|
<div class="advisor-grid" id="advisor-profiles" aria-live="polite">
|
||||||
|
<p class="advisor-loading">Beraterprofile werden geladen …</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="section review-section" id="erfahrungen">
|
<section class="section review-section" id="erfahrungen">
|
||||||
<div class="container review-layout">
|
<div class="container review-layout">
|
||||||
<div class="review-copy">
|
<div class="review-copy">
|
||||||
|
|
@ -1118,6 +1133,7 @@
|
||||||
type="module"
|
type="module"
|
||||||
src="/src/components/navigationsbar/navigation.js"
|
src="/src/components/navigationsbar/navigation.js"
|
||||||
></script>
|
></script>
|
||||||
|
<script type="module" src="/src/features/berater/berater-entry.js"></script>
|
||||||
<script>
|
<script>
|
||||||
const form = document.getElementById("reviewForm");
|
const form = document.getElementById("reviewForm");
|
||||||
const status = document.getElementById("formStatus");
|
const status = document.getElementById("formStatus");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
import berater from "../../shared/berater-daten.json";
|
||||||
|
import "./berater.css";
|
||||||
|
|
||||||
|
const container = document.querySelector("#advisor-profiles");
|
||||||
|
|
||||||
|
function escapeHtml(value) {
|
||||||
|
return String(value).replace(/[&<>"']/g, (character) => ({
|
||||||
|
"&": "&",
|
||||||
|
"<": "<",
|
||||||
|
">": ">",
|
||||||
|
'"': """,
|
||||||
|
"'": "'",
|
||||||
|
})[character]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (container) {
|
||||||
|
if (!Array.isArray(berater) || berater.length === 0) {
|
||||||
|
container.innerHTML = '<p class="advisor-loading">Aktuell sind keine Beraterprofile verfügbar.</p>';
|
||||||
|
} else {
|
||||||
|
container.innerHTML = berater.map((person) => `
|
||||||
|
<article class="advisor-card">
|
||||||
|
<div class="advisor-card__topline"></div>
|
||||||
|
<h3>${escapeHtml(person.name)}</h3>
|
||||||
|
<p class="advisor-card__role">${escapeHtml(person.titel || "Ernährungsberatung")}</p>
|
||||||
|
<div class="advisor-card__details">
|
||||||
|
<h4>Kurzbiografie</h4>
|
||||||
|
<p>${escapeHtml(person.biographie)}</p>
|
||||||
|
<h4>Qualifikationen</h4>
|
||||||
|
<ul>${(person.qualifikationen || []).map((qualification) => `<li>${escapeHtml(qualification)}</li>`).join("")}</ul>
|
||||||
|
<h4>Schwerpunkte</h4>
|
||||||
|
<ul>${(person.schwerpunkte || []).map((focus) => `<li>${escapeHtml(focus)}</li>`).join("")}</ul>
|
||||||
|
</div>
|
||||||
|
<button class="advisor-contact" type="button" data-berater-id="${escapeHtml(person.id)}" aria-haspopup="dialog">Berater kontaktieren</button>
|
||||||
|
</article>
|
||||||
|
`).join("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("click", async (event) => {
|
||||||
|
const button = event.target.closest("button[data-berater-id]");
|
||||||
|
if (!button) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { openContactDialog } = await import(/* @vite-ignore */ "../contact/contact-dialog.js");
|
||||||
|
openContactDialog({ advisorId: button.dataset.beraterId });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Das Kontaktformular ist derzeit nicht verfügbar.", error);
|
||||||
|
button.insertAdjacentHTML("afterend", '<p class="advisor-contact-error" role="status">Das Kontaktformular ist momentan nicht verfügbar.</p>');
|
||||||
|
button.disabled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
.advisor-section {
|
||||||
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.018), rgba(255, 255, 255, 0.035));
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-loading {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 30px;
|
||||||
|
border: 1px solid rgba(248, 250, 252, 0.12);
|
||||||
|
border-radius: 28px;
|
||||||
|
background: linear-gradient(145deg, rgba(255, 255, 255, 0.075), rgba(255, 255, 255, 0.025));
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-card__topline {
|
||||||
|
height: 3px;
|
||||||
|
margin: -30px -30px 26px;
|
||||||
|
border-radius: 28px 28px 0 0;
|
||||||
|
background: #10b981;
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-card h3 {
|
||||||
|
color: #fff;
|
||||||
|
font-family: Inter, system-ui, sans-serif;
|
||||||
|
font-size: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-card__role {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: #10b981;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.14em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-card__details {
|
||||||
|
flex: 1;
|
||||||
|
margin-top: 24px;
|
||||||
|
padding: 22px;
|
||||||
|
border: 1px solid rgba(248, 250, 252, 0.1);
|
||||||
|
border-radius: 22px;
|
||||||
|
background: rgba(255, 255, 255, 0.045);
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-card__details h4 {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 0.94rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-card__details p,
|
||||||
|
.advisor-card__details li {
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 0.92rem;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-card__details h4:not(:first-child) {
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-card__details ul {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-contact {
|
||||||
|
min-height: 58px;
|
||||||
|
margin-top: 24px;
|
||||||
|
padding: 10px 22px;
|
||||||
|
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||||
|
border-radius: 999px;
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(255, 255, 255, 0.025);
|
||||||
|
font: inherit;
|
||||||
|
font-weight: 700;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-contact:hover,
|
||||||
|
.advisor-contact:focus-visible {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
border-color: rgba(16, 185, 129, 0.55);
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-contact:focus-visible {
|
||||||
|
outline: 3px solid rgba(16, 185, 129, 0.45);
|
||||||
|
outline-offset: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advisor-contact-error {
|
||||||
|
margin-top: 10px;
|
||||||
|
color: #fca5a5;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "anna-mueller",
|
||||||
|
"name": "Anna Müller",
|
||||||
|
"email": "anna.mueller@tri-hub.de",
|
||||||
|
"titel": "Ernährungsberaterin",
|
||||||
|
"biographie": "Anna begleitet Ausdauerathletinnen und -athleten dabei, eine alltagstaugliche Ernährungsweise zu entwickeln. Im Mittelpunkt stehen individuelle Bedürfnisse, praktikable Routinen und eine gute Versorgung rund um Training und Wettkampf.",
|
||||||
|
"qualifikationen": ["Ernährungsberatung", "Sporternährung"],
|
||||||
|
"schwerpunkte": ["Sporternährung", "Wettkampfverpflegung", "Hydration"],
|
||||||
|
"bildquelle": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
Loading…
Reference in New Issue