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:
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user