Honor Products.noShippingCost across cart, checkout, and product pages

- api/checkout/route.ts: authoritative shipping charge is 0 whenever
  every cart line opts out via noShippingCost, regardless of the
  free-shipping threshold.
- Cart/checkout order summaries: the whole "Versand" line (cost, free-
  shipping note, delivery time) is hidden entirely rather than showing
  "Kostenlos" — that's a different state from hitting the threshold.
- ProductSpotlight/Pricing/TodoKartenHero: "zzgl. Versand" and delivery-
  time hints drop for an exempted product's own page.
- /versand + its shared modal: one clarifying sentence that digital
  products are exempt.
- Widerrufsformular link: opens inline in a new tab (no forced download),
  arrow icon changed from a download glyph to a plain right arrow to
  match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-07-29 22:48:33 +00:00
parent bffc7d39a2
commit a3f843ad15
13 changed files with 145 additions and 70 deletions
+13 -4
View File
@@ -97,10 +97,19 @@ export async function Pricing() {
)}
<p className="font-bold text-h3 text-text-primary">{formatPrice(product.price)}</p>
</div>
<p className="text-label text-text-muted">{kleinunternehmer ? "zzgl. Versand" : `inkl. ${taxRate}% MwSt. zzgl. Versand`}</p>
<p className="text-label text-text-muted">
Lieferzeit: {shipping.totalDays.min}{shipping.totalDays.max} Werktage innerhalb Deutschlands
</p>
{(() => {
const priceHint = kleinunternehmer
? product.noShippingCost
? null
: "zzgl. Versand"
: `inkl. ${taxRate}% MwSt.${product.noShippingCost ? "" : " zzgl. Versand"}`;
return priceHint && <p className="text-label text-text-muted">{priceHint}</p>;
})()}
{!product.noShippingCost && (
<p className="text-label text-text-muted">
Lieferzeit: {shipping.totalDays.min}{shipping.totalDays.max} Werktage innerhalb Deutschlands
</p>
)}
</div>
{/* Single product, no grid siblings to stay equal-height with —
plain conditional line, same reasoning as ProductSpotlight.tsx. */}
+13 -4
View File
@@ -124,12 +124,21 @@ export async function TodoKartenHero() {
<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">{kleinunternehmer ? "zzgl. Versand" : `inkl. ${taxRate}% MwSt. zzgl. Versand`}</p>
{(() => {
const priceHint = kleinunternehmer
? product.noShippingCost
? null
: "zzgl. Versand"
: `inkl. ${taxRate}% MwSt.${product.noShippingCost ? "" : " zzgl. Versand"}`;
return priceHint && <p className="text-label text-text-muted">{priceHint}</p>;
})()}
</div>
)}
<p className="text-label text-text-muted">
Lieferzeit: {shipping.totalDays.min}{shipping.totalDays.max} Werktage innerhalb Deutschlands
</p>
{!product?.noShippingCost && (
<p className="text-label text-text-muted">
Lieferzeit: {shipping.totalDays.min}{shipping.totalDays.max} Werktage innerhalb Deutschlands
</p>
)}
{/* Single product, no grid siblings to stay equal-height with —
plain conditional line, same reasoning as ProductSpotlight.tsx/Pricing.tsx. */}
{anyLowStock && <p className="text-label font-bold text-warning">Nur noch wenige verfügbar</p>}