Anpassungen am bestehenden Webshop laut PDF-Vorgabe

- Persönliche Vorstellung jedes DIY-Plushies-Charakters auf der jeweiligen
  Unterkategorie-Seite (dezente Box im Kartenstil), inkl. eigener HasiDog-Seite
  mit "Mehr über HasiDog"-Button
- Beschreibungstexte "DIY Plushies" und "Häkelzubehör" angepasst (Startseite +
  Kategorieseiten, gemeinsame Datenquelle)
- Shop-Filter erweitert: Unterkategorien jetzt gruppiert unter ihrer Hauptkategorie
  wählbar, inkl. Filterlogik
- Shop-Bannerbild jetzt auch auf allen Kategorie- und Unterkategorie-Seiten,
  gleiche Größe/Abstände/Responsivität wie im Shop
- Keine Design-Änderung: bestehende Farben, Typografie, Karten, Buttons, Abstände
  vollständig erhalten, alles fügt sich nahtlos ins bestehende Layout ein
- Alle Änderungen in DE/EN/CH/FR umgesetzt, Link-Audit durchgeführt
This commit is contained in:
qcigano
2026-08-02 15:08:49 +02:00
parent c5f6d37367
commit 63dd57d529
23 changed files with 387 additions and 93 deletions
+34
View File
@@ -0,0 +1,34 @@
---
import Layout from "../../../layouts/Layout.astro";
import { getCategory, getSubcategory } from "../../../data/categories";
import type { Locale } from "../../../i18n/config";
import { useTranslations } from "../../../i18n/ui";
const lang: Locale = "ch";
const t = useTranslations(lang);
const category = getCategory("diy-plushies")!;
const sub = getSubcategory("diy-plushies", "hase-hasidog")!;
---
<Layout title={sub.name[lang]} description="Lern dr HasiDog kenne dr chlii, wuschelig Abentürer vo Van's DIY & Bastelbedarf." lang={lang} path="/hasidog/">
<section class="section-tight">
<div class="container grid grid-2 intro">
<div class="portrait-frame portrait">
<img src="/img/hero-plushie-bunny.webp" alt="Ghäklets Hase-Plushie HasiDog i blaue Latzhose, im Gras" width="900" height="1200" loading="eager" />
<span class="portrait-badge">{t.common.handmadeBadge}</span>
</div>
<div>
<span class="eyebrow">{category.icon} {category.name[lang]}</span>
<h1>{sub.name[lang]}</h1>
{sub.vorstellung && (
<div class="character-intro">
{sub.vorstellung[lang].split("\n").map((line) => <p>{line}</p>)}
</div>
)}
<div class="btn-row">
<a class="btn btn-outline" href={`/ch/shop/${category.slug}/${sub.slug}/`}>← {sub.name[lang]}</a>
<a class="btn btn-primary" href="/ch/shop/">{t.common.toShop}</a>
</div>
</div>
</div>
</section>
</Layout>
+10 -8
View File
@@ -17,14 +17,16 @@ const category = getCategory(kategorie!)!;
const items = productsByCategory(category.slug);
---
<Layout title={category.name[lang]} description={category.description[lang]} lang={lang} path={`/shop/${category.slug}/`}>
<section class="section-tight">
<div class="container">
<p class="small breadcrumb"><a href="/ch/shop/">{t.shop.breadcrumbShop}</a> / {category.name[lang]}</p>
<span class="eyebrow" aria-hidden="true">{category.icon}</span>
<h1>{category.name[lang]}</h1>
<p class="lead">{category.description[lang]}</p>
</div>
</section>
<div class="container">
<p class="small breadcrumb" style="margin-top:1.5rem;"><a href="/ch/shop/">{t.shop.breadcrumbShop}</a> / {category.name[lang]}</p>
<section class="page-banner" style="background-image:url('/img/banner-shop.webp'); --banner-ratio: 1600 / 729;">
<div class="page-banner-content">
<span class="eyebrow" aria-hidden="true">{category.icon} {t.shop.breadcrumbShop}</span>
<h1>{category.name[lang]}</h1>
<p class="lead">{category.description[lang]}</p>
</div>
</section>
</div>
<section class="section-tight">
<div class="container">
@@ -17,22 +17,30 @@ const category = getCategory(kategorie!)!;
const sub = getSubcategory(kategorie!, unterkategorie!)!;
---
<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}/`}>
<section class="section-tight">
<div class="container">
<p class="small breadcrumb">
<a href="/ch/shop/">{t.shop.breadcrumbShop}</a> / <a href={`/ch/shop/${category.slug}/`}>{category.name[lang]}</a> / {sub.name[lang]}
</p>
<span class="eyebrow" aria-hidden="true">{category.icon}</span>
<h1>{sub.name[lang]}</h1>
</div>
</section>
<div class="container">
<p class="small breadcrumb" style="margin-top:1.5rem;">
<a href="/ch/shop/">{t.shop.breadcrumbShop}</a> / <a href={`/ch/shop/${category.slug}/`}>{category.name[lang]}</a> / {sub.name[lang]}
</p>
<section class="page-banner" style="background-image:url('/img/banner-shop.webp'); --banner-ratio: 1600 / 729;">
<div class="page-banner-content">
<span class="eyebrow" aria-hidden="true">{category.icon} {category.name[lang]}</span>
<h1>{sub.name[lang]}</h1>
</div>
</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>)}
</div>
)}
<p class="small">{t.shop.subcategoryEmpty}</p>
<div class="btn-row">
{sub.mehrLink && <a class="btn btn-primary" href={`/ch${sub.mehrLink}`}>{t.shop.moreAbout} {sub.name[lang]} →</a>}
<a class="btn btn-outline" href={`/ch/shop/${category.slug}/`}>← {category.name[lang]}</a>
<a class="btn btn-primary" href="/ch/shop/">{t.common.toShop}</a>
<a class="btn btn-outline" href="/ch/shop/">{t.common.toShop}</a>
</div>
</div>
</section>
+16 -2
View File
@@ -28,7 +28,16 @@ const t = useTranslations(lang);
<label for="f-kategorie">{t.shop.categoryLabel}</label>
<select id="f-kategorie">
<option value="">{t.shop.allCategories}</option>
{categories.map((c) => <option value={c.slug}>{c.name[lang]}</option>)}
{categories.map((c) => (
c.subcategories && c.subcategories.length > 0 ? (
<optgroup label={c.name[lang]}>
<option value={c.slug}>{c.name[lang]} ({t.shop.allCategories})</option>
{c.subcategories.map((s) => <option value={`sub:${s.slug}`}>— {s.name[lang]}</option>)}
</optgroup>
) : (
<option value={c.slug}>{c.name[lang]}</option>
)
))}
</select>
</div>
<div class="filter-group">
@@ -58,6 +67,7 @@ const t = useTranslations(lang);
<div
class="product-slot"
data-kategorie={p.kategorie}
data-unterkategorie={p.unterkategorie ?? ""}
data-preis={p.preis}
data-bestand={p.bestand}
data-neu={p.badges.includes("neu") ? 1 : 0}
@@ -98,7 +108,11 @@ const t = useTranslations(lang);
let visible = 0;
slots.forEach((slot) => {
const matchKat = !kat || slot.dataset.kategorie === kat;
const matchKat = !kat
? true
: kat.startsWith("sub:")
? slot.dataset.unterkategorie === kat.slice(4)
: slot.dataset.kategorie === kat;
const matchPreis = Number(slot.dataset.preis) <= maxPreis;
const matchVerfuegbar = !nurVerfuegbar || Number(slot.dataset.bestand) > 0;
const show = matchKat && matchPreis && matchVerfuegbar;
+34
View File
@@ -0,0 +1,34 @@
---
import Layout from "../../../layouts/Layout.astro";
import { getCategory, getSubcategory } from "../../../data/categories";
import type { Locale } from "../../../i18n/config";
import { useTranslations } from "../../../i18n/ui";
const lang: Locale = "en";
const t = useTranslations(lang);
const category = getCategory("diy-plushies")!;
const sub = getSubcategory("diy-plushies", "hase-hasidog")!;
---
<Layout title={sub.name[lang]} description="Meet HasiDog the small, fluffy adventurer from Van's DIY & Bastelbedarf." lang={lang} path="/hasidog/">
<section class="section-tight">
<div class="container grid grid-2 intro">
<div class="portrait-frame portrait">
<img src="/img/hero-plushie-bunny.webp" alt="Crocheted bunny plushie HasiDog in blue overalls, in the grass" width="900" height="1200" loading="eager" />
<span class="portrait-badge">{t.common.handmadeBadge}</span>
</div>
<div>
<span class="eyebrow">{category.icon} {category.name[lang]}</span>
<h1>{sub.name[lang]}</h1>
{sub.vorstellung && (
<div class="character-intro">
{sub.vorstellung[lang].split("\n").map((line) => <p>{line}</p>)}
</div>
)}
<div class="btn-row">
<a class="btn btn-outline" href={`/en/shop/${category.slug}/${sub.slug}/`}>← {sub.name[lang]}</a>
<a class="btn btn-primary" href="/en/shop/">{t.common.toShop}</a>
</div>
</div>
</div>
</section>
</Layout>
+10 -8
View File
@@ -17,14 +17,16 @@ const category = getCategory(kategorie!)!;
const items = productsByCategory(category.slug);
---
<Layout title={category.name[lang]} description={category.description[lang]} lang={lang} path={`/shop/${category.slug}/`}>
<section class="section-tight">
<div class="container">
<p class="small breadcrumb"><a href="/en/shop/">{t.shop.breadcrumbShop}</a> / {category.name[lang]}</p>
<span class="eyebrow" aria-hidden="true">{category.icon}</span>
<h1>{category.name[lang]}</h1>
<p class="lead">{category.description[lang]}</p>
</div>
</section>
<div class="container">
<p class="small breadcrumb" style="margin-top:1.5rem;"><a href="/en/shop/">{t.shop.breadcrumbShop}</a> / {category.name[lang]}</p>
<section class="page-banner" style="background-image:url('/img/banner-shop.webp'); --banner-ratio: 1600 / 729;">
<div class="page-banner-content">
<span class="eyebrow" aria-hidden="true">{category.icon} {t.shop.breadcrumbShop}</span>
<h1>{category.name[lang]}</h1>
<p class="lead">{category.description[lang]}</p>
</div>
</section>
</div>
<section class="section-tight">
<div class="container">
@@ -17,22 +17,30 @@ const category = getCategory(kategorie!)!;
const sub = getSubcategory(kategorie!, unterkategorie!)!;
---
<Layout title={`${sub.name[lang]} ${category.name[lang]}`} description={`${sub.name[lang]} at Van's DIY & Bastelbedarf.`} lang={lang} path={`/shop/${category.slug}/${sub.slug}/`}>
<section class="section-tight">
<div class="container">
<p class="small breadcrumb">
<a href="/en/shop/">{t.shop.breadcrumbShop}</a> / <a href={`/en/shop/${category.slug}/`}>{category.name[lang]}</a> / {sub.name[lang]}
</p>
<span class="eyebrow" aria-hidden="true">{category.icon}</span>
<h1>{sub.name[lang]}</h1>
</div>
</section>
<div class="container">
<p class="small breadcrumb" style="margin-top:1.5rem;">
<a href="/en/shop/">{t.shop.breadcrumbShop}</a> / <a href={`/en/shop/${category.slug}/`}>{category.name[lang]}</a> / {sub.name[lang]}
</p>
<section class="page-banner" style="background-image:url('/img/banner-shop.webp'); --banner-ratio: 1600 / 729;">
<div class="page-banner-content">
<span class="eyebrow" aria-hidden="true">{category.icon} {category.name[lang]}</span>
<h1>{sub.name[lang]}</h1>
</div>
</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>)}
</div>
)}
<p class="small">{t.shop.subcategoryEmpty}</p>
<div class="btn-row">
{sub.mehrLink && <a class="btn btn-primary" href={`/en${sub.mehrLink}`}>{t.shop.moreAbout} {sub.name[lang]} →</a>}
<a class="btn btn-outline" href={`/en/shop/${category.slug}/`}>← {category.name[lang]}</a>
<a class="btn btn-primary" href="/en/shop/">{t.common.toShop}</a>
<a class="btn btn-outline" href="/en/shop/">{t.common.toShop}</a>
</div>
</div>
</section>
+16 -2
View File
@@ -28,7 +28,16 @@ const t = useTranslations(lang);
<label for="f-kategorie">{t.shop.categoryLabel}</label>
<select id="f-kategorie">
<option value="">{t.shop.allCategories}</option>
{categories.map((c) => <option value={c.slug}>{c.name[lang]}</option>)}
{categories.map((c) => (
c.subcategories && c.subcategories.length > 0 ? (
<optgroup label={c.name[lang]}>
<option value={c.slug}>{c.name[lang]} ({t.shop.allCategories})</option>
{c.subcategories.map((s) => <option value={`sub:${s.slug}`}>— {s.name[lang]}</option>)}
</optgroup>
) : (
<option value={c.slug}>{c.name[lang]}</option>
)
))}
</select>
</div>
<div class="filter-group">
@@ -58,6 +67,7 @@ const t = useTranslations(lang);
<div
class="product-slot"
data-kategorie={p.kategorie}
data-unterkategorie={p.unterkategorie ?? ""}
data-preis={p.preis}
data-bestand={p.bestand}
data-neu={p.badges.includes("neu") ? 1 : 0}
@@ -98,7 +108,11 @@ const t = useTranslations(lang);
let visible = 0;
slots.forEach((slot) => {
const matchKat = !kat || slot.dataset.kategorie === kat;
const matchKat = !kat
? true
: kat.startsWith("sub:")
? slot.dataset.unterkategorie === kat.slice(4)
: slot.dataset.kategorie === kat;
const matchPreis = Number(slot.dataset.preis) <= maxPreis;
const matchVerfuegbar = !nurVerfuegbar || Number(slot.dataset.bestand) > 0;
const show = matchKat && matchPreis && matchVerfuegbar;
+34
View File
@@ -0,0 +1,34 @@
---
import Layout from "../../../layouts/Layout.astro";
import { getCategory, getSubcategory } from "../../../data/categories";
import type { Locale } from "../../../i18n/config";
import { useTranslations } from "../../../i18n/ui";
const lang: Locale = "fr";
const t = useTranslations(lang);
const category = getCategory("diy-plushies")!;
const sub = getSubcategory("diy-plushies", "hase-hasidog")!;
---
<Layout title={sub.name[lang]} description="Découvre HasiDog le petit aventurier tout doux de Van's DIY & Bastelbedarf." lang={lang} path="/hasidog/">
<section class="section-tight">
<div class="container grid grid-2 intro">
<div class="portrait-frame portrait">
<img src="/img/hero-plushie-bunny.webp" alt="Peluche lapin au crochet HasiDog en salopette bleue, dans l'herbe" width="900" height="1200" loading="eager" />
<span class="portrait-badge">{t.common.handmadeBadge}</span>
</div>
<div>
<span class="eyebrow">{category.icon} {category.name[lang]}</span>
<h1>{sub.name[lang]}</h1>
{sub.vorstellung && (
<div class="character-intro">
{sub.vorstellung[lang].split("\n").map((line) => <p>{line}</p>)}
</div>
)}
<div class="btn-row">
<a class="btn btn-outline" href={`/fr/shop/${category.slug}/${sub.slug}/`}>← {sub.name[lang]}</a>
<a class="btn btn-primary" href="/fr/shop/">{t.common.toShop}</a>
</div>
</div>
</div>
</section>
</Layout>
+10 -8
View File
@@ -17,14 +17,16 @@ const category = getCategory(kategorie!)!;
const items = productsByCategory(category.slug);
---
<Layout title={category.name[lang]} description={category.description[lang]} lang={lang} path={`/shop/${category.slug}/`}>
<section class="section-tight">
<div class="container">
<p class="small breadcrumb"><a href="/fr/shop/">{t.shop.breadcrumbShop}</a> / {category.name[lang]}</p>
<span class="eyebrow" aria-hidden="true">{category.icon}</span>
<h1>{category.name[lang]}</h1>
<p class="lead">{category.description[lang]}</p>
</div>
</section>
<div class="container">
<p class="small breadcrumb" style="margin-top:1.5rem;"><a href="/fr/shop/">{t.shop.breadcrumbShop}</a> / {category.name[lang]}</p>
<section class="page-banner" style="background-image:url('/img/banner-shop.webp'); --banner-ratio: 1600 / 729;">
<div class="page-banner-content">
<span class="eyebrow" aria-hidden="true">{category.icon} {t.shop.breadcrumbShop}</span>
<h1>{category.name[lang]}</h1>
<p class="lead">{category.description[lang]}</p>
</div>
</section>
</div>
<section class="section-tight">
<div class="container">
@@ -17,22 +17,30 @@ const category = getCategory(kategorie!)!;
const sub = getSubcategory(kategorie!, unterkategorie!)!;
---
<Layout title={`${sub.name[lang]} ${category.name[lang]}`} description={`${sub.name[lang]} chez Van's DIY & Bastelbedarf.`} lang={lang} path={`/shop/${category.slug}/${sub.slug}/`}>
<section class="section-tight">
<div class="container">
<p class="small breadcrumb">
<a href="/fr/shop/">{t.shop.breadcrumbShop}</a> / <a href={`/fr/shop/${category.slug}/`}>{category.name[lang]}</a> / {sub.name[lang]}
</p>
<span class="eyebrow" aria-hidden="true">{category.icon}</span>
<h1>{sub.name[lang]}</h1>
</div>
</section>
<div class="container">
<p class="small breadcrumb" style="margin-top:1.5rem;">
<a href="/fr/shop/">{t.shop.breadcrumbShop}</a> / <a href={`/fr/shop/${category.slug}/`}>{category.name[lang]}</a> / {sub.name[lang]}
</p>
<section class="page-banner" style="background-image:url('/img/banner-shop.webp'); --banner-ratio: 1600 / 729;">
<div class="page-banner-content">
<span class="eyebrow" aria-hidden="true">{category.icon} {category.name[lang]}</span>
<h1>{sub.name[lang]}</h1>
</div>
</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>)}
</div>
)}
<p class="small">{t.shop.subcategoryEmpty}</p>
<div class="btn-row">
{sub.mehrLink && <a class="btn btn-primary" href={`/fr${sub.mehrLink}`}>{t.shop.moreAbout} {sub.name[lang]} →</a>}
<a class="btn btn-outline" href={`/fr/shop/${category.slug}/`}>← {category.name[lang]}</a>
<a class="btn btn-primary" href="/fr/shop/">{t.common.toShop}</a>
<a class="btn btn-outline" href="/fr/shop/">{t.common.toShop}</a>
</div>
</div>
</section>
+16 -2
View File
@@ -28,7 +28,16 @@ const t = useTranslations(lang);
<label for="f-kategorie">{t.shop.categoryLabel}</label>
<select id="f-kategorie">
<option value="">{t.shop.allCategories}</option>
{categories.map((c) => <option value={c.slug}>{c.name[lang]}</option>)}
{categories.map((c) => (
c.subcategories && c.subcategories.length > 0 ? (
<optgroup label={c.name[lang]}>
<option value={c.slug}>{c.name[lang]} ({t.shop.allCategories})</option>
{c.subcategories.map((s) => <option value={`sub:${s.slug}`}>— {s.name[lang]}</option>)}
</optgroup>
) : (
<option value={c.slug}>{c.name[lang]}</option>
)
))}
</select>
</div>
<div class="filter-group">
@@ -58,6 +67,7 @@ const t = useTranslations(lang);
<div
class="product-slot"
data-kategorie={p.kategorie}
data-unterkategorie={p.unterkategorie ?? ""}
data-preis={p.preis}
data-bestand={p.bestand}
data-neu={p.badges.includes("neu") ? 1 : 0}
@@ -98,7 +108,11 @@ const t = useTranslations(lang);
let visible = 0;
slots.forEach((slot) => {
const matchKat = !kat || slot.dataset.kategorie === kat;
const matchKat = !kat
? true
: kat.startsWith("sub:")
? slot.dataset.unterkategorie === kat.slice(4)
: slot.dataset.kategorie === kat;
const matchPreis = Number(slot.dataset.preis) <= maxPreis;
const matchVerfuegbar = !nurVerfuegbar || Number(slot.dataset.bestand) > 0;
const show = matchKat && matchPreis && matchVerfuegbar;
+34
View File
@@ -0,0 +1,34 @@
---
import Layout from "../../layouts/Layout.astro";
import { getCategory, getSubcategory } from "../../data/categories";
import type { Locale } from "../../i18n/config";
import { useTranslations } from "../../i18n/ui";
const lang: Locale = "de";
const t = useTranslations(lang);
const category = getCategory("diy-plushies")!;
const sub = getSubcategory("diy-plushies", "hase-hasidog")!;
---
<Layout title={sub.name[lang]} description="Lerne HasiDog kennen den kleinen, wuscheligen Abenteurer von Van's DIY & Bastelbedarf." lang={lang} path="/hasidog/">
<section class="section-tight">
<div class="container grid grid-2 intro">
<div class="portrait-frame portrait">
<img src="/img/hero-plushie-bunny.webp" alt="Gehäkeltes Hasen-Plushie HasiDog in blauer Latzhose, im Gras" width="900" height="1200" loading="eager" />
<span class="portrait-badge">{t.common.handmadeBadge}</span>
</div>
<div>
<span class="eyebrow">{category.icon} {category.name[lang]}</span>
<h1>{sub.name[lang]}</h1>
{sub.vorstellung && (
<div class="character-intro">
{sub.vorstellung[lang].split("\n").map((line) => <p>{line}</p>)}
</div>
)}
<div class="btn-row">
<a class="btn btn-outline" href={`/shop/${category.slug}/${sub.slug}/`}>← {sub.name[lang]}</a>
<a class="btn btn-primary" href="/shop/">{t.common.toShop}</a>
</div>
</div>
</div>
</section>
</Layout>
+10 -8
View File
@@ -17,14 +17,16 @@ const category = getCategory(kategorie!)!;
const items = productsByCategory(category.slug);
---
<Layout title={category.name[lang]} description={category.description[lang]} lang={lang} path={`/shop/${category.slug}/`}>
<section class="section-tight">
<div class="container">
<p class="small breadcrumb"><a href="/shop/">{t.shop.breadcrumbShop}</a> / {category.name[lang]}</p>
<span class="eyebrow" aria-hidden="true">{category.icon}</span>
<h1>{category.name[lang]}</h1>
<p class="lead">{category.description[lang]}</p>
</div>
</section>
<div class="container">
<p class="small breadcrumb" style="margin-top:1.5rem;"><a href="/shop/">{t.shop.breadcrumbShop}</a> / {category.name[lang]}</p>
<section class="page-banner" style="background-image:url('/img/banner-shop.webp'); --banner-ratio: 1600 / 729;">
<div class="page-banner-content">
<span class="eyebrow" aria-hidden="true">{category.icon} {t.shop.breadcrumbShop}</span>
<h1>{category.name[lang]}</h1>
<p class="lead">{category.description[lang]}</p>
</div>
</section>
</div>
<section class="section-tight">
<div class="container">
@@ -17,22 +17,30 @@ const category = getCategory(kategorie!)!;
const sub = getSubcategory(kategorie!, unterkategorie!)!;
---
<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}/`}>
<section class="section-tight">
<div class="container">
<p class="small breadcrumb">
<a href="/shop/">{t.shop.breadcrumbShop}</a> / <a href={`/shop/${category.slug}/`}>{category.name[lang]}</a> / {sub.name[lang]}
</p>
<span class="eyebrow" aria-hidden="true">{category.icon}</span>
<h1>{sub.name[lang]}</h1>
</div>
</section>
<div class="container">
<p class="small breadcrumb" style="margin-top:1.5rem;">
<a href="/shop/">{t.shop.breadcrumbShop}</a> / <a href={`/shop/${category.slug}/`}>{category.name[lang]}</a> / {sub.name[lang]}
</p>
<section class="page-banner" style="background-image:url('/img/banner-shop.webp'); --banner-ratio: 1600 / 729;">
<div class="page-banner-content">
<span class="eyebrow" aria-hidden="true">{category.icon} {category.name[lang]}</span>
<h1>{sub.name[lang]}</h1>
</div>
</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>)}
</div>
)}
<p class="small">{t.shop.subcategoryEmpty}</p>
<div class="btn-row">
{sub.mehrLink && <a class="btn btn-primary" href={sub.mehrLink}>{t.shop.moreAbout} {sub.name[lang]} →</a>}
<a class="btn btn-outline" href={`/shop/${category.slug}/`}>← {category.name[lang]}</a>
<a class="btn btn-primary" href="/shop/">{t.common.toShop}</a>
<a class="btn btn-outline" href="/shop/">{t.common.toShop}</a>
</div>
</div>
</section>
+16 -2
View File
@@ -28,7 +28,16 @@ const t = useTranslations(lang);
<label for="f-kategorie">{t.shop.categoryLabel}</label>
<select id="f-kategorie">
<option value="">{t.shop.allCategories}</option>
{categories.map((c) => <option value={c.slug}>{c.name[lang]}</option>)}
{categories.map((c) => (
c.subcategories && c.subcategories.length > 0 ? (
<optgroup label={c.name[lang]}>
<option value={c.slug}>{c.name[lang]} ({t.shop.allCategories})</option>
{c.subcategories.map((s) => <option value={`sub:${s.slug}`}>— {s.name[lang]}</option>)}
</optgroup>
) : (
<option value={c.slug}>{c.name[lang]}</option>
)
))}
</select>
</div>
<div class="filter-group">
@@ -58,6 +67,7 @@ const t = useTranslations(lang);
<div
class="product-slot"
data-kategorie={p.kategorie}
data-unterkategorie={p.unterkategorie ?? ""}
data-preis={p.preis}
data-bestand={p.bestand}
data-neu={p.badges.includes("neu") ? 1 : 0}
@@ -98,7 +108,11 @@ const t = useTranslations(lang);
let visible = 0;
slots.forEach((slot) => {
const matchKat = !kat || slot.dataset.kategorie === kat;
const matchKat = !kat
? true
: kat.startsWith("sub:")
? slot.dataset.unterkategorie === kat.slice(4)
: slot.dataset.kategorie === kat;
const matchPreis = Number(slot.dataset.preis) <= maxPreis;
const matchVerfuegbar = !nurVerfuegbar || Number(slot.dataset.bestand) > 0;
const show = matchKat && matchPreis && matchVerfuegbar;