Add product categories + shop sidebar filters, fix CTA button alignment
Products now carry an optional categories relationship (backend: new product-categories collection mirroring the blog's categories pattern, migration applied and deployed). The shop page gains a left sidebar (styled like AccountNav) with a dual-handle price slider, category checkboxes, and an availability toggle — all instant-apply via searchParams, same union-filter semantics as the blog's category chips. Uncategorized products always match every category filter rather than disappearing. Also fixes CTA buttons sitting at different heights across sibling cards when one product's title wraps to two lines — MerklisteGrid.tsx and RelatedProducts.tsx get the same h-full/flex-1 spacer pattern ProductGrid.tsx already used.
This commit is contained in:
@@ -134,7 +134,7 @@ export function RelatedProducts({ defaultTaxRate, kleinunternehmer }: { defaultT
|
||||
<div
|
||||
key={product.id}
|
||||
className={
|
||||
"group sm:col-span-4 bg-bg-base border border-border rounded-md overflow-hidden flex flex-col gap-4 transition-transform duration-300 hover:-translate-y-1 " +
|
||||
"group sm:col-span-4 bg-bg-base border border-border rounded-md overflow-hidden flex flex-col h-full gap-4 transition-transform duration-300 hover:-translate-y-1 " +
|
||||
// Center the row when there are fewer than 3 cards to show
|
||||
// (e.g. only 1 active product left once the others are
|
||||
// already in the cart) — only the first card needs an
|
||||
@@ -176,7 +176,7 @@ export function RelatedProducts({ defaultTaxRate, kleinunternehmer }: { defaultT
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 items-start px-5 pb-5 pt-2 w-full">
|
||||
<div className="flex flex-col gap-4 items-start px-5 pb-5 pt-2 w-full flex-1">
|
||||
<p
|
||||
className="font-semibold text-h4 text-text-primary w-full"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
@@ -192,12 +192,16 @@ export function RelatedProducts({ defaultTaxRate, kleinunternehmer }: { defaultT
|
||||
</p>
|
||||
{/* Always rendered, text conditional — min-h reserves this
|
||||
line's height in both states so cards in the same row
|
||||
stay equal height regardless of low-stock status; this
|
||||
component has no h-full/flex-1 spacer trick like
|
||||
ProductGrid.tsx to absorb a variable-height line instead. */}
|
||||
stay equal height regardless of low-stock status. */}
|
||||
<p className="min-h-[1.05rem] text-label font-bold text-warning">
|
||||
{anyLowStock ? "Nur noch wenige verfügbar" : null}
|
||||
</p>
|
||||
|
||||
{/* flex-1 spacer — pins every card's button to the same Y
|
||||
regardless of whether `product.name` wraps to one or two
|
||||
lines (see ProductGrid.tsx's identical spacer). */}
|
||||
<div className="flex-1" />
|
||||
|
||||
<AddToCartInlineButton id={product.id} outOfStock={product.outOfStock} maxQty={product.maxQty} variants={product.variants} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user