feat(shop): show sale badge and strikethrough price on discounted products

Products with compareAtPrice set now show a "-XX%" badge over the
image plus a struck-through original price, wherever price is
displayed (shop grid, homepage spotlight, cart line items). Also
switched the "inkl. MwSt. zzgl. Versand" rows on Pricing.tsx and
ProductSpotlight from items-center to items-baseline — with a large
price next to small disclosure text, center alignment left the
small text visibly floating above the price's bottom edge.
This commit is contained in:
Marco
2026-07-19 23:31:35 +00:00
parent 2a14e18aa1
commit 7b35b3e55b
5 changed files with 43 additions and 11 deletions
+10 -4
View File
@@ -3,7 +3,7 @@ import Link from "next/link";
import { AddToCartButton } from "./AddToCartButton";
import { Reveal } from "./Reveal";
import { getSpotlightProduct } from "../lib/payload";
import { formatPrice } from "../lib/format";
import { formatPrice, discountPercent } from "../lib/format";
/**
* Product teaser for whichever product is marked `spotlight` in Payload
@@ -26,6 +26,7 @@ export async function ProductSpotlight() {
if (!product) return null;
const image = product.spotlightImage || product.image;
const discount = discountPercent(product.price, product.compareAtPrice);
return (
<section className="w-full bg-bg-base py-12 md:py-16 px-[var(--layout-padding-x)]">
@@ -38,6 +39,11 @@ export async function ProductSpotlight() {
sizes="(min-width: 768px) 380px, 100vw"
className="object-cover transition-transform duration-500 group-hover:scale-105"
/>
{discount !== null && (
<span className="absolute top-3 left-3 rounded-full bg-brand px-2.5 py-1 text-label font-bold text-text-primary">
-{discount}%
</span>
)}
</div>
<div className="flex flex-col gap-4 items-start flex-1 min-w-0 w-full">
@@ -51,9 +57,9 @@ export async function ProductSpotlight() {
<p className="text-body text-text-body">
{product.spotlightText || product.description}
</p>
<div className="flex gap-2 items-center">
{product.compareAtPrice && product.compareAtPrice > product.price && (
<p className="text-body text-text-muted line-through">{formatPrice(product.compareAtPrice)}</p>
<div className="flex gap-2 items-baseline">
{discount !== null && (
<p className="text-body text-text-muted line-through">{formatPrice(product.compareAtPrice!)}</p>
)}
<p className="font-bold text-h3 text-text-primary">{formatPrice(product.price)}</p>
<p className="text-label text-text-muted">inkl. MwSt. zzgl. Versand</p>