Rabatt-System, größerer Mengen-Stepper, Zahlungsart zuerst, echte HasiDog-Inhalte
- Neues Rabatt-System: Prozent-/Betrag-Rabatt mit optionalem Ablaufdatum, Mengenrabatt-Staffel pro Produkt, sowie site-weite Gutscheincodes. Wird live im Warenkorb/Checkout berechnet (src/data/rabatt.ts, src/data/gutscheine.ts, cart.ts) und ist im Adminbereich direkt unter dem Preis bearbeitbar (config.yml: "Rabatte" + neue Collection "Gutscheincodes"). Effektiver Preis + Rabatt-Badge auf Produktkarten und Produktseite sichtbar. - Mengen-Stepper auf der Produktseite vergrößert (bereits vorbereitet, jetzt mit Build/Test verifiziert). - Zahlungsart im Checkout auf Platz 1, mit markenfarbigen, fertig gestalteten Buttons (PayPal/Klarna/Banküberweisung). - Unterkategorie-Seiten zeigen jetzt VanVans eigene Produktbeschreibung und das echte Fotos des Produkts statt Platzhaltertext, mit kleinem Link zur HasiDog-Universum-Seite statt großem Button. Verifiziert per Puppeteer-Funktionstest gegen den echten Production-Build (Rabatt-Berechnung, Mengenrabatt, Gutschein-Einlösung, Checkout-Summary, keine Konsolenfehler).
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
---
|
||||
import Layout from "../../../layouts/Layout.astro";
|
||||
import ProductCard from "../../../components/ProductCard.astro";
|
||||
import { categories, getCategory, getSubcategory } from "../../../data/categories";
|
||||
import { productsByUnterkategorie } from "../../../data/products";
|
||||
import type { Locale } from "../../../i18n/config";
|
||||
import { useTranslations } from "../../../i18n/ui";
|
||||
|
||||
@@ -15,6 +17,13 @@ const t = useTranslations(lang);
|
||||
const { kategorie, unterkategorie } = Astro.params;
|
||||
const category = getCategory(kategorie!)!;
|
||||
const sub = getSubcategory(kategorie!, unterkategorie!)!;
|
||||
|
||||
// Sobald VanVan im Adminbereich ein echtes Produkt dieser Unterkategorie zuordnet, wird es
|
||||
// hier automatisch featured angezeigt (echtes Foto + ihr echter Text) statt des generischen
|
||||
// Platzhaltertexts.
|
||||
const echtProdukte = productsByUnterkategorie(category.slug, sub.slug);
|
||||
const featured = echtProdukte[0];
|
||||
const weitere = echtProdukte.slice(1);
|
||||
---
|
||||
<Layout title={`${sub.name[lang]} – ${category.name[lang]}`} description={`${sub.name[lang]} bei Van's DIY & Bastelbedarf.`} lang={lang} path={`/shop/${category.slug}/${sub.slug}/`}>
|
||||
<div class="container">
|
||||
@@ -29,11 +38,23 @@ const sub = getSubcategory(kategorie!, unterkategorie!)!;
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="section-tight">
|
||||
<div class="container">
|
||||
{sub.vorstellung && (
|
||||
<div class="character-intro">
|
||||
{sub.vorstellung[lang].split("\n").map((line) => <p>{line}</p>)}
|
||||
{featured ? (
|
||||
<section class="section-tight">
|
||||
<div class="container grid grid-2 intro">
|
||||
<div class="portrait-frame portrait">
|
||||
{featured.bilder && featured.bilder.length > 0 ? (
|
||||
<img class="product-photo" src={featured.bilder[0]} alt={featured.name[lang]} loading="lazy" />
|
||||
) : (
|
||||
<div class="img-placeholder" role="img" aria-label={featured.name[lang]}></div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
{sub.vorstellung && <span class="eyebrow">{sub.vorstellung[lang].split("\n")[0]}</span>}
|
||||
<h2>{featured.name[lang]}</h2>
|
||||
<p class="lead">{featured.beschreibung[lang]}</p>
|
||||
<div class="btn-row">
|
||||
<a class="btn btn-primary" href={`/produkt/${featured.slug}/`}>{t.common.discoverNow} →</a>
|
||||
</div>
|
||||
{sub.mehrLink && (
|
||||
<p class="character-more">
|
||||
Du willst mehr über {sub.name[lang]} erfahren, dann klicke hier:{" "}
|
||||
@@ -41,8 +62,37 @@ const sub = getSubcategory(kategorie!, unterkategorie!)!;
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<p class="small">{t.shop.subcategoryEmpty}</p>
|
||||
</div>
|
||||
</section>
|
||||
) : (
|
||||
<section class="section-tight">
|
||||
<div class="container">
|
||||
{sub.vorstellung && (
|
||||
<div class="character-intro">
|
||||
{sub.vorstellung[lang].split("\n").map((line) => <p>{line}</p>)}
|
||||
{sub.mehrLink && (
|
||||
<p class="character-more">
|
||||
Du willst mehr über {sub.name[lang]} erfahren, dann klicke hier:{" "}
|
||||
<a class="character-more-link" href={sub.mehrLink} target="_blank" rel="noopener">hier →</a>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<p class="small">{t.shop.subcategoryEmpty}</p>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{weitere.length > 0 && (
|
||||
<section class="section-tight">
|
||||
<div class="container">
|
||||
<div class="grid grid-3">{weitere.map((p) => <ProductCard product={p} lang={lang} />)}</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
<section class="section-tight">
|
||||
<div class="container">
|
||||
<div class="btn-row">
|
||||
<a class="btn btn-outline" href={`/shop/${category.slug}/`}>← {category.name[lang]}</a>
|
||||
<a class="btn btn-outline" href="/shop/">{t.common.toShop}</a>
|
||||
|
||||
Reference in New Issue
Block a user