Charaktergeschichten von den Shop-Karten getrennt: eigene volle-Breite Boxen oben, reine Foto/Preis-Karten darunter

Bisher stand die persönliche Charaktergeschichte (Hallo-ich-bin-Text)
direkt in derselben Karte wie Foto und Kaufinfos. Jetzt zweigeteilt:
- Oben: jede Geschichte in einer eigenen, vollen Breite Karte
  (character-stories/.character-story), übereinander gestapelt.
- Darunter: eine Kartenreihe wie im Shop-Grid, die für Charaktere mit
  echtem Produkt direkt die vorhandene ProductCard-Komponente wiederverwendet
  (Foto, Badges, Preis, Kurzbeschreibung — 1:1 wie überall sonst im Shop),
  für Charaktere ohne Produkt ein passender Platzhalter im gleichen
  Kartenstil. Keine Geschichten mehr in dieser Reihe.

Verifiziert per Puppeteer: alle drei Geschichten-Boxen ohne Preis, alle
drei Shop-Karten ohne Geschichtstext, HasiDog-Karte zeigt echten Preis
(42,00 € durchgestrichen, 25,00 €) über die wiederverwendete ProductCard-
Komponente.
This commit is contained in:
qcigano
2026-08-02 22:44:51 +02:00
parent bdb1b323c7
commit 8cd0145003
5 changed files with 150 additions and 82 deletions
@@ -50,27 +50,43 @@ const weitere = alleProdukte.filter((p) => !zugeordneteSlugs.has(p.slug));
</div>
{characterEntries.length > 0 ? (
<section class="section-tight">
<div class="container grid grid-3">
{characterEntries.map(({ char, product }) => (
<div class="card character-card">
<div class="product-media">
{product && product.bilder && product.bilder.length > 0 ? (
<img class="product-photo" src={product.bilder[0]} alt={product.name[lang]} loading="lazy" />
) : (
<div class="img-placeholder" role="img" aria-label={product ? product.name[lang] : char.name[lang]}></div>
<>
{/* Die persönlichen Charaktergeschichten stehen als eigene, volle Breite Boxen ÜBER der
Kartenreihe — getrennt von den "Shop"-Karten darunter, die nur Foto/Preis/Infos zeigen. */}
<section class="section-tight">
<div class="container character-stories">
{characterEntries.map(({ char }) => (
<div class="card character-story">
{char.vorstellung && <span class="eyebrow">{char.vorstellung[lang].split("\n")[0]}</span>}
<h3>{char.name[lang]}</h3>
<p>{char.vorstellung ? char.vorstellung[lang].split("\n")[1] : ""}</p>
{char.mehrLink && (
<a class="btn btn-outline btn-sm" href={char.mehrLink} target="_blank" rel="noopener">here →</a>
)}
</div>
{char.vorstellung && <span class="eyebrow">{char.vorstellung[lang].split("\n")[0]}</span>}
<h3>{product ? <a href={`/en/produkt/${product.slug}/`}>{product.name[lang]}</a> : char.name[lang]}</h3>
<p class="character-card-desc">{char.vorstellung ? char.vorstellung[lang].split("\n")[1] : (product ? product.beschreibung[lang] : t.shop.subcategoryEmpty)}</p>
{char.mehrLink && (
<a class="btn btn-outline btn-sm character-more-btn" href={char.mehrLink} target="_blank" rel="noopener">here →</a>
)}
</div>
))}
</div>
</section>
))}
</div>
</section>
{/* Kartenreihe wie im Shop-Grid — nur Foto, Preis und Kaufinfos, keine Geschichten. */}
<section class="section-tight">
<div class="container grid grid-3">
{characterEntries.map(({ char, product }) =>
product ? (
<ProductCard product={product} lang={lang} />
) : (
<div class="card character-card">
<div class="product-media">
<div class="img-placeholder" role="img" aria-label={char.name[lang]}></div>
</div>
<h3>{char.name[lang]}</h3>
<p class="character-card-desc">{t.shop.subcategoryEmpty}</p>
</div>
)
)}
</div>
</section>
</>
) : (
<section class="section-tight">
<div class="container">