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:
@@ -4,10 +4,14 @@ import type { Locale } from "../i18n/config";
|
||||
import { localePrefix } from "../i18n/config";
|
||||
import { useTranslations } from "../i18n/ui";
|
||||
import { formatPrice } from "../i18n/format";
|
||||
import { effektiverPreis, rabattLabel, hatAktivenRabatt } from "../data/rabatt";
|
||||
|
||||
interface Props { product: Product; lang: Locale }
|
||||
const { product, lang } = Astro.props;
|
||||
const t = useTranslations(lang);
|
||||
const finalPrice = effektiverPreis(product);
|
||||
const discountBadge = rabattLabel(product);
|
||||
const showOldAsPreis = !product.preisAlt && hatAktivenRabatt(product);
|
||||
|
||||
const badgeLabel: Record<string, string> = {
|
||||
neu: t.badge.neu,
|
||||
@@ -32,13 +36,15 @@ const desc = product.beschreibung[lang];
|
||||
<span class={`badge ${b === "sale" ? "badge-sale" : ""}`}>{badgeLabel[b]}</span>
|
||||
))}
|
||||
{product.bestand === 0 && <span class="badge badge-sold-out">{t.badge.ausverkauft}</span>}
|
||||
{discountBadge && <span class="badge badge-rabatt">{discountBadge}</span>}
|
||||
</div>
|
||||
</div>
|
||||
<h3>{name}</h3>
|
||||
<p class="small">{desc.slice(0, 78)}{desc.length > 78 ? "…" : ""}</p>
|
||||
<div class="price-row">
|
||||
{product.preisAlt && <span class="price-old">{formatPrice(product.preisAlt, lang)}</span>}
|
||||
<span class="price">{formatPrice(product.preis, lang)}</span>
|
||||
{showOldAsPreis && <span class="price-old">{formatPrice(product.preis, lang)}</span>}
|
||||
<span class="price">{formatPrice(finalPrice, lang)}</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -53,4 +59,5 @@ const desc = product.beschreibung[lang];
|
||||
.price-row { margin-top: auto; display: flex; align-items: baseline; gap: 0.6rem; }
|
||||
.price { color: var(--c-accent); font-weight: 700; font-size: 1.15rem; }
|
||||
.price-old { color: var(--c-text-muted); text-decoration: line-through; font-size: 0.9rem; }
|
||||
.badge-rabatt { background: #ff5f7e; color: #fff; border-color: #ff5f7e; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user