Beraterkarten sowie Daten erstellt und in index.html eingebunden
parent
55e4904482
commit
370d54fb39
16
index.html
16
index.html
|
|
@ -920,6 +920,21 @@
|
|||
</section>
|
||||
|
||||
<!-- 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">
|
||||
<div class="container review-layout">
|
||||
<div class="review-copy">
|
||||
|
|
@ -1118,6 +1133,7 @@
|
|||
type="module"
|
||||
src="/src/components/navigationsbar/navigation.js"
|
||||
></script>
|
||||
<script type="module" src="/src/features/berater/berater-entry.js"></script>
|
||||
<script>
|
||||
const form = document.getElementById("reviewForm");
|
||||
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