Tier-Familien-Seiten: nur noch Charaktere mit echtem Admin-Produkt sichtbar
Wichtige Verhaltensänderung: ein Charakter (aus dem Kategorien-Bereich im Admin) ist ab jetzt nur noch eine VORBEREITETE Definition. Er erscheint auf der Seite NUR, wenn ihm im Admin tatsächlich ein Produkt mit genau diesem Charakter-Code zugeordnet wurde (das Feld "Charakter" am Produkt = seine "Rolle"). Ohne zugeordnetes Produkt taucht er nirgends mehr auf — auch nicht mehr als Platzhalter-Karte mit seinem Namen. Konkret: HasiGott und Mama Hase verschwinden von der Hase-Seite, weil für sie (noch) keine Produkte im Admin angelegt wurden. Sobald VanVan ein Produkt mit charakter: hasigott anlegt, erscheint er automatisch. Familien ganz ohne Produkte (Kuh, Wal, Oktopus, Schildkröte, Pinguin) zeigen weiterhin die bereits vorbereiteten, namenlosen "Kommt bald"- Karten (unverändert) — nur die NAMENTLICHE Vorab-Anzeige einzelner Charaktere ohne Produkt entfällt. Zusätzlich: der "Mehr über mich"-Button in der Story-Box hatte keinen erklärenden Text — man wusste nicht, wohin/wozu er führt. Jetzt steht davor "Wenn du mehr über mich erfahren möchtest, dann klicke [hier →]" in allen 4 Sprachen. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b28475c26a
commit
8700e2c588
@@ -21,19 +21,18 @@ const sub = getSubcategory(kategorie!, unterkategorie!)!;
|
||||
// Alle Produkte dieser Unterkategorie (unabhängig davon, welchem Charakter sie zugeordnet sind).
|
||||
const alleProdukte = productsByUnterkategorie(category.slug, sub.slug);
|
||||
|
||||
// Jeder Charakter dieser Tier-Familie bekommt seine eigene kompakte Karte (wie die Produktkarten
|
||||
// im Shop-Grid), alle nebeneinander in einer Reihe. Sobald VanVan im Adminbereich neue
|
||||
// Charaktere UND passende Produkte ergänzt, wächst diese Reihe automatisch mit. Fehlt einem
|
||||
// Charakter noch ein echtes Produkt, zeigt seine Karte trotzdem schon den Charaktertext (nur ohne
|
||||
// Foto) — die Seite muss nicht auf das erste Foto warten, um zu existieren.
|
||||
// Ein Charakter (aus dem Kategorien-Bereich im Admin) ist erstmal nur eine VORBEREITETE
|
||||
// Definition — er erscheint auf der Seite NUR, wenn ihm im Admin auch wirklich ein Produkt mit
|
||||
// genau diesem Charakter-Code zugeordnet wurde (das Feld "Charakter" am Produkt = seine "Rolle").
|
||||
// Ohne zugeordnetes Produkt taucht er hier NICHT auf, auch nicht als Platzhalter — nur echte,
|
||||
// im Admin angelegte Artikel dürfen auf der Seite erscheinen.
|
||||
const characters = sub.characters ?? [];
|
||||
const characterEntries = characters.map((char) => ({
|
||||
char,
|
||||
product: alleProdukte.find((p) => p.charakter === char.slug),
|
||||
}));
|
||||
const characterEntries = characters
|
||||
.map((char) => ({ char, product: alleProdukte.find((p) => p.charakter === char.slug) }))
|
||||
.filter((e) => e.product);
|
||||
|
||||
// Produkte ohne (bekannte) Charakter-Zuordnung landen als "weitere Modelle" darunter.
|
||||
const zugeordneteSlugs = new Set(characterEntries.map((e) => e.product?.slug).filter(Boolean));
|
||||
const zugeordneteSlugs = new Set(characterEntries.map((e) => e.product!.slug));
|
||||
const weitere = alleProdukte.filter((p) => !zugeordneteSlugs.has(p.slug));
|
||||
const hatCharaktere = characterEntries.length > 0;
|
||||
const hatWeitere = weitere.length > 0;
|
||||
@@ -55,34 +54,23 @@ const komplettLeer = !hatCharaktere && !hatWeitere;
|
||||
{hatCharaktere && (
|
||||
<section class="section-tight">
|
||||
<div class="container">
|
||||
{characterEntries.some(({ product }) => product) && (
|
||||
<div class="character-stories">
|
||||
{characterEntries.filter(({ product }) => product).map(({ char }) => (
|
||||
<div class="card character-story">
|
||||
{char.vorstellung && <span class="eyebrow">{char.vorstellung[lang].split("\n")[0]}</span>}
|
||||
<p>{char.vorstellung ? char.vorstellung[lang].split("\n")[1] : ""}</p>
|
||||
{char.mehrLink && (
|
||||
<div class="character-stories">
|
||||
{characterEntries.map(({ char }) => (
|
||||
<div class="card character-story">
|
||||
{char.vorstellung && <span class="eyebrow">{char.vorstellung[lang].split("\n")[0]}</span>}
|
||||
<p>{char.vorstellung ? char.vorstellung[lang].split("\n")[1] : ""}</p>
|
||||
{char.mehrLink && (
|
||||
<p class="character-more-lead">
|
||||
{t.shop.moreAboutCharacterLead}{" "}
|
||||
<a class="btn btn-outline btn-sm" href={char.mehrLink} target="_blank" rel="noopener">da →</a>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="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>
|
||||
)
|
||||
)}
|
||||
{characterEntries.map(({ product }) => <ProductCard product={product!} lang={lang} />)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -21,19 +21,18 @@ const sub = getSubcategory(kategorie!, unterkategorie!)!;
|
||||
// Alle Produkte dieser Unterkategorie (unabhängig davon, welchem Charakter sie zugeordnet sind).
|
||||
const alleProdukte = productsByUnterkategorie(category.slug, sub.slug);
|
||||
|
||||
// Jeder Charakter dieser Tier-Familie bekommt seine eigene kompakte Karte (wie die Produktkarten
|
||||
// im Shop-Grid), alle nebeneinander in einer Reihe. Sobald VanVan im Adminbereich neue
|
||||
// Charaktere UND passende Produkte ergänzt, wächst diese Reihe automatisch mit. Fehlt einem
|
||||
// Charakter noch ein echtes Produkt, zeigt seine Karte trotzdem schon den Charaktertext (nur ohne
|
||||
// Foto) — die Seite muss nicht auf das erste Foto warten, um zu existieren.
|
||||
// Ein Charakter (aus dem Kategorien-Bereich im Admin) ist erstmal nur eine VORBEREITETE
|
||||
// Definition — er erscheint auf der Seite NUR, wenn ihm im Admin auch wirklich ein Produkt mit
|
||||
// genau diesem Charakter-Code zugeordnet wurde (das Feld "Charakter" am Produkt = seine "Rolle").
|
||||
// Ohne zugeordnetes Produkt taucht er hier NICHT auf, auch nicht als Platzhalter — nur echte,
|
||||
// im Admin angelegte Artikel dürfen auf der Seite erscheinen.
|
||||
const characters = sub.characters ?? [];
|
||||
const characterEntries = characters.map((char) => ({
|
||||
char,
|
||||
product: alleProdukte.find((p) => p.charakter === char.slug),
|
||||
}));
|
||||
const characterEntries = characters
|
||||
.map((char) => ({ char, product: alleProdukte.find((p) => p.charakter === char.slug) }))
|
||||
.filter((e) => e.product);
|
||||
|
||||
// Produkte ohne (bekannte) Charakter-Zuordnung landen als "weitere Modelle" darunter.
|
||||
const zugeordneteSlugs = new Set(characterEntries.map((e) => e.product?.slug).filter(Boolean));
|
||||
const zugeordneteSlugs = new Set(characterEntries.map((e) => e.product!.slug));
|
||||
const weitere = alleProdukte.filter((p) => !zugeordneteSlugs.has(p.slug));
|
||||
const hatCharaktere = characterEntries.length > 0;
|
||||
const hatWeitere = weitere.length > 0;
|
||||
@@ -55,34 +54,23 @@ const komplettLeer = !hatCharaktere && !hatWeitere;
|
||||
{hatCharaktere && (
|
||||
<section class="section-tight">
|
||||
<div class="container">
|
||||
{characterEntries.some(({ product }) => product) && (
|
||||
<div class="character-stories">
|
||||
{characterEntries.filter(({ product }) => product).map(({ char }) => (
|
||||
<div class="card character-story">
|
||||
{char.vorstellung && <span class="eyebrow">{char.vorstellung[lang].split("\n")[0]}</span>}
|
||||
<p>{char.vorstellung ? char.vorstellung[lang].split("\n")[1] : ""}</p>
|
||||
{char.mehrLink && (
|
||||
<div class="character-stories">
|
||||
{characterEntries.map(({ char }) => (
|
||||
<div class="card character-story">
|
||||
{char.vorstellung && <span class="eyebrow">{char.vorstellung[lang].split("\n")[0]}</span>}
|
||||
<p>{char.vorstellung ? char.vorstellung[lang].split("\n")[1] : ""}</p>
|
||||
{char.mehrLink && (
|
||||
<p class="character-more-lead">
|
||||
{t.shop.moreAboutCharacterLead}{" "}
|
||||
<a class="btn btn-outline btn-sm" href={char.mehrLink} target="_blank" rel="noopener">here →</a>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="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>
|
||||
)
|
||||
)}
|
||||
{characterEntries.map(({ product }) => <ProductCard product={product!} lang={lang} />)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -21,19 +21,18 @@ const sub = getSubcategory(kategorie!, unterkategorie!)!;
|
||||
// Alle Produkte dieser Unterkategorie (unabhängig davon, welchem Charakter sie zugeordnet sind).
|
||||
const alleProdukte = productsByUnterkategorie(category.slug, sub.slug);
|
||||
|
||||
// Jeder Charakter dieser Tier-Familie bekommt seine eigene kompakte Karte (wie die Produktkarten
|
||||
// im Shop-Grid), alle nebeneinander in einer Reihe. Sobald VanVan im Adminbereich neue
|
||||
// Charaktere UND passende Produkte ergänzt, wächst diese Reihe automatisch mit. Fehlt einem
|
||||
// Charakter noch ein echtes Produkt, zeigt seine Karte trotzdem schon den Charaktertext (nur ohne
|
||||
// Foto) — die Seite muss nicht auf das erste Foto warten, um zu existieren.
|
||||
// Ein Charakter (aus dem Kategorien-Bereich im Admin) ist erstmal nur eine VORBEREITETE
|
||||
// Definition — er erscheint auf der Seite NUR, wenn ihm im Admin auch wirklich ein Produkt mit
|
||||
// genau diesem Charakter-Code zugeordnet wurde (das Feld "Charakter" am Produkt = seine "Rolle").
|
||||
// Ohne zugeordnetes Produkt taucht er hier NICHT auf, auch nicht als Platzhalter — nur echte,
|
||||
// im Admin angelegte Artikel dürfen auf der Seite erscheinen.
|
||||
const characters = sub.characters ?? [];
|
||||
const characterEntries = characters.map((char) => ({
|
||||
char,
|
||||
product: alleProdukte.find((p) => p.charakter === char.slug),
|
||||
}));
|
||||
const characterEntries = characters
|
||||
.map((char) => ({ char, product: alleProdukte.find((p) => p.charakter === char.slug) }))
|
||||
.filter((e) => e.product);
|
||||
|
||||
// Produkte ohne (bekannte) Charakter-Zuordnung landen als "weitere Modelle" darunter.
|
||||
const zugeordneteSlugs = new Set(characterEntries.map((e) => e.product?.slug).filter(Boolean));
|
||||
const zugeordneteSlugs = new Set(characterEntries.map((e) => e.product!.slug));
|
||||
const weitere = alleProdukte.filter((p) => !zugeordneteSlugs.has(p.slug));
|
||||
const hatCharaktere = characterEntries.length > 0;
|
||||
const hatWeitere = weitere.length > 0;
|
||||
@@ -55,34 +54,23 @@ const komplettLeer = !hatCharaktere && !hatWeitere;
|
||||
{hatCharaktere && (
|
||||
<section class="section-tight">
|
||||
<div class="container">
|
||||
{characterEntries.some(({ product }) => product) && (
|
||||
<div class="character-stories">
|
||||
{characterEntries.filter(({ product }) => product).map(({ char }) => (
|
||||
<div class="card character-story">
|
||||
{char.vorstellung && <span class="eyebrow">{char.vorstellung[lang].split("\n")[0]}</span>}
|
||||
<p>{char.vorstellung ? char.vorstellung[lang].split("\n")[1] : ""}</p>
|
||||
{char.mehrLink && (
|
||||
<div class="character-stories">
|
||||
{characterEntries.map(({ char }) => (
|
||||
<div class="card character-story">
|
||||
{char.vorstellung && <span class="eyebrow">{char.vorstellung[lang].split("\n")[0]}</span>}
|
||||
<p>{char.vorstellung ? char.vorstellung[lang].split("\n")[1] : ""}</p>
|
||||
{char.mehrLink && (
|
||||
<p class="character-more-lead">
|
||||
{t.shop.moreAboutCharacterLead}{" "}
|
||||
<a class="btn btn-outline btn-sm" href={char.mehrLink} target="_blank" rel="noopener">ici →</a>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="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>
|
||||
)
|
||||
)}
|
||||
{characterEntries.map(({ product }) => <ProductCard product={product!} lang={lang} />)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -21,19 +21,18 @@ const sub = getSubcategory(kategorie!, unterkategorie!)!;
|
||||
// Alle Produkte dieser Unterkategorie (unabhängig davon, welchem Charakter sie zugeordnet sind).
|
||||
const alleProdukte = productsByUnterkategorie(category.slug, sub.slug);
|
||||
|
||||
// Jeder Charakter dieser Tier-Familie bekommt seine eigene kompakte Karte (wie die Produktkarten
|
||||
// im Shop-Grid), alle nebeneinander in einer Reihe. Sobald VanVan im Adminbereich neue
|
||||
// Charaktere UND passende Produkte ergänzt, wächst diese Reihe automatisch mit. Fehlt einem
|
||||
// Charakter noch ein echtes Produkt, zeigt seine Karte trotzdem schon den Charaktertext (nur ohne
|
||||
// Foto) — die Seite muss nicht auf das erste Foto warten, um zu existieren.
|
||||
// Ein Charakter (aus dem Kategorien-Bereich im Admin) ist erstmal nur eine VORBEREITETE
|
||||
// Definition — er erscheint auf der Seite NUR, wenn ihm im Admin auch wirklich ein Produkt mit
|
||||
// genau diesem Charakter-Code zugeordnet wurde (das Feld "Charakter" am Produkt = seine "Rolle").
|
||||
// Ohne zugeordnetes Produkt taucht er hier NICHT auf, auch nicht als Platzhalter — nur echte,
|
||||
// im Admin angelegte Artikel dürfen auf der Seite erscheinen.
|
||||
const characters = sub.characters ?? [];
|
||||
const characterEntries = characters.map((char) => ({
|
||||
char,
|
||||
product: alleProdukte.find((p) => p.charakter === char.slug),
|
||||
}));
|
||||
const characterEntries = characters
|
||||
.map((char) => ({ char, product: alleProdukte.find((p) => p.charakter === char.slug) }))
|
||||
.filter((e) => e.product);
|
||||
|
||||
// Produkte ohne (bekannte) Charakter-Zuordnung landen als "weitere Modelle" darunter.
|
||||
const zugeordneteSlugs = new Set(characterEntries.map((e) => e.product?.slug).filter(Boolean));
|
||||
const zugeordneteSlugs = new Set(characterEntries.map((e) => e.product!.slug));
|
||||
const weitere = alleProdukte.filter((p) => !zugeordneteSlugs.has(p.slug));
|
||||
const hatCharaktere = characterEntries.length > 0;
|
||||
const hatWeitere = weitere.length > 0;
|
||||
@@ -61,35 +60,24 @@ const komplettLeer = !hatCharaktere && !hatWeitere;
|
||||
<div class="container">
|
||||
{/* 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. */}
|
||||
{characterEntries.some(({ product }) => product) && (
|
||||
<div class="character-stories">
|
||||
{characterEntries.filter(({ product }) => product).map(({ char }) => (
|
||||
<div class="card character-story">
|
||||
{char.vorstellung && <span class="eyebrow">{char.vorstellung[lang].split("\n")[0]}</span>}
|
||||
<p>{char.vorstellung ? char.vorstellung[lang].split("\n")[1] : ""}</p>
|
||||
{char.mehrLink && (
|
||||
<div class="character-stories">
|
||||
{characterEntries.map(({ char }) => (
|
||||
<div class="card character-story">
|
||||
{char.vorstellung && <span class="eyebrow">{char.vorstellung[lang].split("\n")[0]}</span>}
|
||||
<p>{char.vorstellung ? char.vorstellung[lang].split("\n")[1] : ""}</p>
|
||||
{char.mehrLink && (
|
||||
<p class="character-more-lead">
|
||||
{t.shop.moreAboutCharacterLead}{" "}
|
||||
<a class="btn btn-outline btn-sm" href={char.mehrLink} target="_blank" rel="noopener">hier →</a>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Kartenreihe wie im Shop-Grid — nur Foto, Preis und Kaufinfos, keine Geschichten. */}
|
||||
<div class="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>
|
||||
)
|
||||
)}
|
||||
{characterEntries.map(({ product }) => <ProductCard product={product!} lang={lang} />)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user