US2.1: Datenstruktur, Komponenten-Aufbau, Styling, Testing
parent
5851668bd8
commit
ef0745e59d
|
|
@ -0,0 +1,11 @@
|
|||
<section class="packages-section" id="angebotsuebersicht-section">
|
||||
<div class="packages-header">
|
||||
<!-- Hier könnte noch eine Überschrift hin, falls gewünscht -->
|
||||
<h2>Unsere Ernährungs-Pakete</h2>
|
||||
</div>
|
||||
|
||||
<!-- Das ist der Container, den unser JS mit den Karten füllt -->
|
||||
<div class="packages-container" id="packages-container">
|
||||
<!-- Karten werden hier dynamisch von angebotsuebersicht.js injiziert -->
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { packages } from "../../shared/packages.js";
|
||||
|
||||
export function renderAngebotsuebersicht() {
|
||||
// Wir suchen den Container, der in der angebotsuebersicht.html definiert wurde
|
||||
const container = document.getElementById("packages-container");
|
||||
|
||||
// Sicherheitscheck: Wenn der Container nicht da ist, brechen wir ab
|
||||
if (!container) {
|
||||
console.warn("Container für Angebotsübersicht nicht gefunden.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Container leeren (falls die Funktion mehrfach aufgerufen wird)
|
||||
container.innerHTML = "";
|
||||
|
||||
// Durch jedes Paket iterieren und das HTML generieren
|
||||
packages.forEach((pkg) => {
|
||||
// Highlight-Badge nur anzeigen, wenn es eins gibt
|
||||
const highlightHtml = pkg.highlight
|
||||
? `<span class="package-highlight">${pkg.highlight}</span>`
|
||||
: "";
|
||||
|
||||
const cardHtml = `
|
||||
<div class="package-card">
|
||||
|
||||
<div class="package-type-container">
|
||||
<span class="package-type">${pkg.type}</span>
|
||||
${highlightHtml}
|
||||
</div>
|
||||
|
||||
<h3 class="package-title">${pkg.title}</h3>
|
||||
<p class="package-desc">${pkg.description}</p>
|
||||
|
||||
<div class="package-details-box">
|
||||
<div class="detail-item">
|
||||
<div class="detail-title">Fokus</div>
|
||||
<div class="detail-text">${pkg.fokus}</div>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<div class="detail-title">Anamnese</div>
|
||||
<div class="detail-text">${pkg.anamnese}</div>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<div class="detail-title">Begleitung</div>
|
||||
<div class="detail-text">${pkg.begleitung}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- HIER ist der wichtige Link für deinen Kollegen: -->
|
||||
<a href="buchung.html?id=${pkg.id}" class="package-btn">${pkg.buttonText}</a>
|
||||
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Das generierte HTML dem Container hinzufügen
|
||||
container.innerHTML += cardHtml;
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
export const packages = [
|
||||
{
|
||||
id: "ernaehrung-starter",
|
||||
type: "STARTER",
|
||||
title: "Für den sicheren Einstieg in die Sporternährung",
|
||||
description:
|
||||
"Für Menschen 50+, die mit Triathlon beginnen und ihre Ernährung an die neue Belastung anpassen möchten.",
|
||||
fokus: "Grundlagen der Makronährstoffe, Hydration im Training und Gewichtsmanagement.",
|
||||
anamnese:
|
||||
"Zu Beginn gehört eine ausführliche gemeinsame Anamnese dazu, damit deine Essgewohnheiten und Ziele sauber eingeordnet werden.",
|
||||
begleitung:
|
||||
"Ein individueller Basis-Ernährungsplan und regelmäßige Check-ins im ersten Monat.",
|
||||
buttonText: "Starter-Paket ansehen",
|
||||
highlight: null,
|
||||
},
|
||||
{
|
||||
id: "ernaehrung-standard",
|
||||
type: "STANDARD",
|
||||
title: "Für Best Ager mit ersten Erfahrungen und klaren Zielen",
|
||||
description:
|
||||
"Für Athletinnen und Athleten, die ihre Ernährung für die Kurzdistanz und im Alltag gezielt weiterentwickeln wollen.",
|
||||
fokus: "Carb-Loading, Pacing-Strategien für den Magen und Timing der Nahrungsaufnahme.",
|
||||
anamnese:
|
||||
"Auch hier startet das Coaching mit einer ausführlichen gemeinsamen Anamnese, damit Trainingsrealität, Erfahrung und Verträglichkeit präzise erfasst werden.",
|
||||
begleitung:
|
||||
"Monatliche Anpassung des Plans und enger Austausch bei Magen-Darm-Herausforderungen.",
|
||||
buttonText: "Standard-Paket ansehen",
|
||||
highlight: "BESONDERS PASSEND",
|
||||
},
|
||||
{
|
||||
id: "ernaehrung-premium",
|
||||
type: "PREMIUM",
|
||||
title: "Für maximale Individualität mit klarem Fokus",
|
||||
description:
|
||||
"Für Menschen, die sich eine besonders enge Coaching-Beziehung und laufende Anpassung ihrer Ernährung wünschen.",
|
||||
fokus: "Individuelle Stoffwechselanalyse, Mikronährstoff-Optimierung und Raceday-Nutrition.",
|
||||
anamnese:
|
||||
"Wie in allen Paketen ist eine ausführliche gemeinsame Anamnese enthalten, damit Betreuung, Regeneration und Zielbild von Beginn an abgestimmt werden.",
|
||||
begleitung:
|
||||
"Wöchentliche Anpassungen, direkte Feedback-Schleifen und passgenaue Einkaufslisten.",
|
||||
buttonText: "Premium-Paket ansehen",
|
||||
highlight: null,
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
export async function renderAngebotsuebersicht() {
|
||||
const container = document.getElementById("packages-container");
|
||||
if (!container) return;
|
||||
|
||||
try {
|
||||
// 1. Daten vom Backend des Kollegen abfragen
|
||||
const response = await fetch("/api/angebote"); // Die genaue URL musst du den Kollegen fragen
|
||||
const backendPackages = await response.json();
|
||||
|
||||
container.innerHTML = "";
|
||||
|
||||
// 2. Mit den echten Daten die Karten generieren
|
||||
backendPackages.forEach((pkg) => {
|
||||
const highlightHtml = pkg.highlight
|
||||
? `<span class="package-highlight">${pkg.highlight}</span>`
|
||||
: "";
|
||||
|
||||
const cardHtml = `
|
||||
<div class="package-card">
|
||||
<div class="package-type-container">
|
||||
<span class="package-type">${pkg.type}</span>
|
||||
${highlightHtml}
|
||||
</div>
|
||||
<h3 class="package-title">${pkg.title}</h3>
|
||||
<p class="package-desc">${pkg.description}</p>
|
||||
<!-- ... Rest des HTMLs wie gehabt ... -->
|
||||
<a href="buchung.html?id=${pkg.id}" class="package-btn">${pkg.buttonText}</a>
|
||||
</div>
|
||||
`;
|
||||
container.innerHTML += cardHtml;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden der Angebote vom Backend:", error);
|
||||
container.innerHTML = "<p>Angebote konnten nicht geladen werden.</p>";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import { packages } from "../shared/packages.js";
|
||||
|
||||
describe("Angebots-Daten (packages.js)", () => {
|
||||
test("sollte ein Array mit Angeboten exportieren", () => {
|
||||
expect(Array.isArray(nutritionPackages)).toBe(true);
|
||||
expect(nutritionPackages.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test("jedes Paket muss eine ID und einen Titel für das Routing besitzen", () => {
|
||||
nutritionPackages.forEach((pkg) => {
|
||||
expect(pkg).toHaveProperty("id");
|
||||
expect(pkg).toHaveProperty("title");
|
||||
expect(pkg).toHaveProperty("buttonText");
|
||||
// Prüft, ob die ID das korrekte Format für die URLs hat
|
||||
expect(typeof pkg.id).toBe("string");
|
||||
expect(pkg.id.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue