Warenkorb: Versandkosten werden jetzt sofort berechnet und angezeigt (Länderauswahl direkt im Warenkorb, reagiert live auf Wechsel), statt erst im Checkout
This commit is contained in:
@@ -26,6 +26,15 @@ const t = useTranslations(lang);
|
|||||||
<aside class="card cart-summary">
|
<aside class="card cart-summary">
|
||||||
<h3>🧾 {t.cart.subtotal}</h3>
|
<h3>🧾 {t.cart.subtotal}</h3>
|
||||||
<div class="summary-row"><span>{t.cart.subtotal}</span><span id="sum-subtotal">0,00 €</span></div>
|
<div class="summary-row"><span>{t.cart.subtotal}</span><span id="sum-subtotal">0,00 €</span></div>
|
||||||
|
<div class="ship-country-row">
|
||||||
|
<label for="cart-land">📦 {t.checkout.country}</label>
|
||||||
|
<select id="cart-land">
|
||||||
|
<option value="ch" selected>Schwiz</option>
|
||||||
|
<option value="de">Dütschland</option>
|
||||||
|
<option value="at">Öschterrych</option>
|
||||||
|
<option value="lu">Luxemburg</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="summary-row"><span>{t.cart.shipping}</span><span id="sum-shipping">{t.cart.shippingCalculated}</span></div>
|
<div class="summary-row"><span>{t.cart.shipping}</span><span id="sum-shipping">{t.cart.shippingCalculated}</span></div>
|
||||||
<p class="free-shipping-badge" id="shipping-hint"></p>
|
<p class="free-shipping-badge" id="shipping-hint"></p>
|
||||||
<hr class="divider" />
|
<hr class="divider" />
|
||||||
@@ -38,16 +47,18 @@ const t = useTranslations(lang);
|
|||||||
</section>
|
</section>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<script define:vars={{ freeShipFrom: 75, removeLabel: t.cart.remove, perItemLabel: t.cart.perItem, remainingTemplate: t.cart.remaining("__V__"), freeShippingText: t.cart.freeShipping, cartLang: lang }}>
|
<script define:vars={{ freeShipFrom: 75, removeLabel: t.cart.remove, perItemLabel: t.cart.perItem, remainingTemplate: t.cart.remaining("__V__"), freeShippingText: t.cart.freeShipping, freeLabel: t.checkout.free, cartLang: lang }}>
|
||||||
// WICHTIG: define:vars-Skripte laufen als IIFE, keine "import"-Anweisungen möglich.
|
// WICHTIG: define:vars-Skripte laufen als IIFE, keine "import"-Anweisungen möglich.
|
||||||
window.__cartVars = { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, cartLang };
|
window.__cartVars = { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, freeLabel, cartLang };
|
||||||
</script>
|
</script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { getCart, updateQuantity, removeFromCart, cartTotal } from "../../../scripts/cart";
|
import { getCart, updateQuantity, removeFromCart, cartTotal } from "../../../scripts/cart";
|
||||||
import { formatPrice } from "../../../i18n/format";
|
import { formatPrice } from "../../../i18n/format";
|
||||||
import { getProduct } from "../../../data/products";
|
import { getProduct, products } from "../../../data/products";
|
||||||
|
import { berechneVersandkosten } from "../../../data/versand";
|
||||||
|
|
||||||
const { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, cartLang } = window.__cartVars;
|
const { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, freeLabel, cartLang } = window.__cartVars;
|
||||||
|
const landSelect = document.getElementById("cart-land");
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
const cart = getCart();
|
const cart = getCart();
|
||||||
@@ -89,8 +100,10 @@ const t = useTranslations(lang);
|
|||||||
|
|
||||||
const subtotal = cartTotal();
|
const subtotal = cartTotal();
|
||||||
const remaining = Math.max(0, freeShipFrom - subtotal);
|
const remaining = Math.max(0, freeShipFrom - subtotal);
|
||||||
|
const shipping = berechneVersandkosten(landSelect.value, cart.map((i) => ({ slug: i.slug, preis: i.preis, menge: i.menge })), products);
|
||||||
document.getElementById("sum-subtotal").textContent = formatPrice(subtotal, cartLang);
|
document.getElementById("sum-subtotal").textContent = formatPrice(subtotal, cartLang);
|
||||||
document.getElementById("sum-total").textContent = formatPrice(subtotal, cartLang);
|
document.getElementById("sum-shipping").textContent = shipping === 0 ? freeLabel : formatPrice(shipping, cartLang);
|
||||||
|
document.getElementById("sum-total").textContent = formatPrice(subtotal + shipping, cartLang);
|
||||||
document.getElementById("shipping-hint").textContent =
|
document.getElementById("shipping-hint").textContent =
|
||||||
remaining > 0 ? remainingTemplate.replace("__V__", formatPrice(remaining, cartLang)) : `🩵 ${freeShippingText}`;
|
remaining > 0 ? remainingTemplate.replace("__V__", formatPrice(remaining, cartLang)) : `🩵 ${freeShippingText}`;
|
||||||
|
|
||||||
@@ -112,4 +125,5 @@ const t = useTranslations(lang);
|
|||||||
|
|
||||||
render();
|
render();
|
||||||
window.addEventListener("cart:changed", render);
|
window.addEventListener("cart:changed", render);
|
||||||
|
landSelect.addEventListener("change", render);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -26,6 +26,15 @@ const t = useTranslations(lang);
|
|||||||
<aside class="card cart-summary">
|
<aside class="card cart-summary">
|
||||||
<h3>🧾 {t.cart.subtotal}</h3>
|
<h3>🧾 {t.cart.subtotal}</h3>
|
||||||
<div class="summary-row"><span>{t.cart.subtotal}</span><span id="sum-subtotal">0,00 €</span></div>
|
<div class="summary-row"><span>{t.cart.subtotal}</span><span id="sum-subtotal">0,00 €</span></div>
|
||||||
|
<div class="ship-country-row">
|
||||||
|
<label for="cart-land">📦 {t.checkout.country}</label>
|
||||||
|
<select id="cart-land">
|
||||||
|
<option value="de">Germany</option>
|
||||||
|
<option value="at">Austria</option>
|
||||||
|
<option value="ch">Switzerland</option>
|
||||||
|
<option value="lu">Luxembourg</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="summary-row"><span>{t.cart.shipping}</span><span id="sum-shipping">{t.cart.shippingCalculated}</span></div>
|
<div class="summary-row"><span>{t.cart.shipping}</span><span id="sum-shipping">{t.cart.shippingCalculated}</span></div>
|
||||||
<p class="free-shipping-badge" id="shipping-hint"></p>
|
<p class="free-shipping-badge" id="shipping-hint"></p>
|
||||||
<hr class="divider" />
|
<hr class="divider" />
|
||||||
@@ -38,16 +47,18 @@ const t = useTranslations(lang);
|
|||||||
</section>
|
</section>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<script define:vars={{ freeShipFrom: 75, removeLabel: t.cart.remove, perItemLabel: t.cart.perItem, remainingTemplate: t.cart.remaining("__V__"), freeShippingText: t.cart.freeShipping, cartLang: lang }}>
|
<script define:vars={{ freeShipFrom: 75, removeLabel: t.cart.remove, perItemLabel: t.cart.perItem, remainingTemplate: t.cart.remaining("__V__"), freeShippingText: t.cart.freeShipping, freeLabel: t.checkout.free, cartLang: lang }}>
|
||||||
// WICHTIG: define:vars-Skripte laufen als IIFE, keine "import"-Anweisungen möglich.
|
// WICHTIG: define:vars-Skripte laufen als IIFE, keine "import"-Anweisungen möglich.
|
||||||
window.__cartVars = { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, cartLang };
|
window.__cartVars = { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, freeLabel, cartLang };
|
||||||
</script>
|
</script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { getCart, updateQuantity, removeFromCart, cartTotal } from "../../../scripts/cart";
|
import { getCart, updateQuantity, removeFromCart, cartTotal } from "../../../scripts/cart";
|
||||||
import { formatPrice } from "../../../i18n/format";
|
import { formatPrice } from "../../../i18n/format";
|
||||||
import { getProduct } from "../../../data/products";
|
import { getProduct, products } from "../../../data/products";
|
||||||
|
import { berechneVersandkosten } from "../../../data/versand";
|
||||||
|
|
||||||
const { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, cartLang } = window.__cartVars;
|
const { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, freeLabel, cartLang } = window.__cartVars;
|
||||||
|
const landSelect = document.getElementById("cart-land");
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
const cart = getCart();
|
const cart = getCart();
|
||||||
@@ -89,8 +100,10 @@ const t = useTranslations(lang);
|
|||||||
|
|
||||||
const subtotal = cartTotal();
|
const subtotal = cartTotal();
|
||||||
const remaining = Math.max(0, freeShipFrom - subtotal);
|
const remaining = Math.max(0, freeShipFrom - subtotal);
|
||||||
|
const shipping = berechneVersandkosten(landSelect.value, cart.map((i) => ({ slug: i.slug, preis: i.preis, menge: i.menge })), products);
|
||||||
document.getElementById("sum-subtotal").textContent = formatPrice(subtotal, cartLang);
|
document.getElementById("sum-subtotal").textContent = formatPrice(subtotal, cartLang);
|
||||||
document.getElementById("sum-total").textContent = formatPrice(subtotal, cartLang);
|
document.getElementById("sum-shipping").textContent = shipping === 0 ? freeLabel : formatPrice(shipping, cartLang);
|
||||||
|
document.getElementById("sum-total").textContent = formatPrice(subtotal + shipping, cartLang);
|
||||||
document.getElementById("shipping-hint").textContent =
|
document.getElementById("shipping-hint").textContent =
|
||||||
remaining > 0 ? remainingTemplate.replace("__V__", formatPrice(remaining, cartLang)) : `🩵 ${freeShippingText}`;
|
remaining > 0 ? remainingTemplate.replace("__V__", formatPrice(remaining, cartLang)) : `🩵 ${freeShippingText}`;
|
||||||
|
|
||||||
@@ -112,4 +125,5 @@ const t = useTranslations(lang);
|
|||||||
|
|
||||||
render();
|
render();
|
||||||
window.addEventListener("cart:changed", render);
|
window.addEventListener("cart:changed", render);
|
||||||
|
landSelect.addEventListener("change", render);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -26,6 +26,15 @@ const t = useTranslations(lang);
|
|||||||
<aside class="card cart-summary">
|
<aside class="card cart-summary">
|
||||||
<h3>🧾 {t.cart.subtotal}</h3>
|
<h3>🧾 {t.cart.subtotal}</h3>
|
||||||
<div class="summary-row"><span>{t.cart.subtotal}</span><span id="sum-subtotal">0,00 €</span></div>
|
<div class="summary-row"><span>{t.cart.subtotal}</span><span id="sum-subtotal">0,00 €</span></div>
|
||||||
|
<div class="ship-country-row">
|
||||||
|
<label for="cart-land">📦 {t.checkout.country}</label>
|
||||||
|
<select id="cart-land">
|
||||||
|
<option value="de">Allemagne</option>
|
||||||
|
<option value="at">Autriche</option>
|
||||||
|
<option value="ch">Suisse</option>
|
||||||
|
<option value="lu">Luxembourg</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="summary-row"><span>{t.cart.shipping}</span><span id="sum-shipping">{t.cart.shippingCalculated}</span></div>
|
<div class="summary-row"><span>{t.cart.shipping}</span><span id="sum-shipping">{t.cart.shippingCalculated}</span></div>
|
||||||
<p class="free-shipping-badge" id="shipping-hint"></p>
|
<p class="free-shipping-badge" id="shipping-hint"></p>
|
||||||
<hr class="divider" />
|
<hr class="divider" />
|
||||||
@@ -38,16 +47,18 @@ const t = useTranslations(lang);
|
|||||||
</section>
|
</section>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<script define:vars={{ freeShipFrom: 75, removeLabel: t.cart.remove, perItemLabel: t.cart.perItem, remainingTemplate: t.cart.remaining("__V__"), freeShippingText: t.cart.freeShipping, cartLang: lang }}>
|
<script define:vars={{ freeShipFrom: 75, removeLabel: t.cart.remove, perItemLabel: t.cart.perItem, remainingTemplate: t.cart.remaining("__V__"), freeShippingText: t.cart.freeShipping, freeLabel: t.checkout.free, cartLang: lang }}>
|
||||||
// WICHTIG: define:vars-Skripte laufen als IIFE, keine "import"-Anweisungen möglich.
|
// WICHTIG: define:vars-Skripte laufen als IIFE, keine "import"-Anweisungen möglich.
|
||||||
window.__cartVars = { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, cartLang };
|
window.__cartVars = { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, freeLabel, cartLang };
|
||||||
</script>
|
</script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { getCart, updateQuantity, removeFromCart, cartTotal } from "../../../scripts/cart";
|
import { getCart, updateQuantity, removeFromCart, cartTotal } from "../../../scripts/cart";
|
||||||
import { formatPrice } from "../../../i18n/format";
|
import { formatPrice } from "../../../i18n/format";
|
||||||
import { getProduct } from "../../../data/products";
|
import { getProduct, products } from "../../../data/products";
|
||||||
|
import { berechneVersandkosten } from "../../../data/versand";
|
||||||
|
|
||||||
const { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, cartLang } = window.__cartVars;
|
const { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, freeLabel, cartLang } = window.__cartVars;
|
||||||
|
const landSelect = document.getElementById("cart-land");
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
const cart = getCart();
|
const cart = getCart();
|
||||||
@@ -89,8 +100,10 @@ const t = useTranslations(lang);
|
|||||||
|
|
||||||
const subtotal = cartTotal();
|
const subtotal = cartTotal();
|
||||||
const remaining = Math.max(0, freeShipFrom - subtotal);
|
const remaining = Math.max(0, freeShipFrom - subtotal);
|
||||||
|
const shipping = berechneVersandkosten(landSelect.value, cart.map((i) => ({ slug: i.slug, preis: i.preis, menge: i.menge })), products);
|
||||||
document.getElementById("sum-subtotal").textContent = formatPrice(subtotal, cartLang);
|
document.getElementById("sum-subtotal").textContent = formatPrice(subtotal, cartLang);
|
||||||
document.getElementById("sum-total").textContent = formatPrice(subtotal, cartLang);
|
document.getElementById("sum-shipping").textContent = shipping === 0 ? freeLabel : formatPrice(shipping, cartLang);
|
||||||
|
document.getElementById("sum-total").textContent = formatPrice(subtotal + shipping, cartLang);
|
||||||
document.getElementById("shipping-hint").textContent =
|
document.getElementById("shipping-hint").textContent =
|
||||||
remaining > 0 ? remainingTemplate.replace("__V__", formatPrice(remaining, cartLang)) : `🩵 ${freeShippingText}`;
|
remaining > 0 ? remainingTemplate.replace("__V__", formatPrice(remaining, cartLang)) : `🩵 ${freeShippingText}`;
|
||||||
|
|
||||||
@@ -112,4 +125,5 @@ const t = useTranslations(lang);
|
|||||||
|
|
||||||
render();
|
render();
|
||||||
window.addEventListener("cart:changed", render);
|
window.addEventListener("cart:changed", render);
|
||||||
|
landSelect.addEventListener("change", render);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -26,6 +26,15 @@ const t = useTranslations(lang);
|
|||||||
<aside class="card cart-summary">
|
<aside class="card cart-summary">
|
||||||
<h3>🧾 {t.cart.subtotal}</h3>
|
<h3>🧾 {t.cart.subtotal}</h3>
|
||||||
<div class="summary-row"><span>{t.cart.subtotal}</span><span id="sum-subtotal">0,00 €</span></div>
|
<div class="summary-row"><span>{t.cart.subtotal}</span><span id="sum-subtotal">0,00 €</span></div>
|
||||||
|
<div class="ship-country-row">
|
||||||
|
<label for="cart-land">📦 {t.checkout.country}</label>
|
||||||
|
<select id="cart-land">
|
||||||
|
<option value="de">Deutschland</option>
|
||||||
|
<option value="at">Österreich</option>
|
||||||
|
<option value="ch">Schweiz</option>
|
||||||
|
<option value="lu">Luxemburg</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="summary-row"><span>{t.cart.shipping}</span><span id="sum-shipping">{t.cart.shippingCalculated}</span></div>
|
<div class="summary-row"><span>{t.cart.shipping}</span><span id="sum-shipping">{t.cart.shippingCalculated}</span></div>
|
||||||
<p class="free-shipping-badge" id="shipping-hint"></p>
|
<p class="free-shipping-badge" id="shipping-hint"></p>
|
||||||
<hr class="divider" />
|
<hr class="divider" />
|
||||||
@@ -38,16 +47,18 @@ const t = useTranslations(lang);
|
|||||||
</section>
|
</section>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<script define:vars={{ freeShipFrom: 75, removeLabel: t.cart.remove, perItemLabel: t.cart.perItem, remainingTemplate: t.cart.remaining("__V__"), freeShippingText: t.cart.freeShipping, cartLang: lang }}>
|
<script define:vars={{ freeShipFrom: 75, removeLabel: t.cart.remove, perItemLabel: t.cart.perItem, remainingTemplate: t.cart.remaining("__V__"), freeShippingText: t.cart.freeShipping, freeLabel: t.checkout.free, cartLang: lang }}>
|
||||||
// WICHTIG: define:vars-Skripte laufen als IIFE, keine "import"-Anweisungen möglich.
|
// WICHTIG: define:vars-Skripte laufen als IIFE, keine "import"-Anweisungen möglich.
|
||||||
window.__cartVars = { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, cartLang };
|
window.__cartVars = { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, freeLabel, cartLang };
|
||||||
</script>
|
</script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { getCart, updateQuantity, removeFromCart, cartTotal } from "../../scripts/cart";
|
import { getCart, updateQuantity, removeFromCart, cartTotal } from "../../scripts/cart";
|
||||||
import { formatPrice } from "../../i18n/format";
|
import { formatPrice } from "../../i18n/format";
|
||||||
import { getProduct } from "../../data/products";
|
import { getProduct, products } from "../../data/products";
|
||||||
|
import { berechneVersandkosten } from "../../data/versand";
|
||||||
|
|
||||||
const { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, cartLang } = window.__cartVars;
|
const { freeShipFrom, removeLabel, perItemLabel, remainingTemplate, freeShippingText, freeLabel, cartLang } = window.__cartVars;
|
||||||
|
const landSelect = document.getElementById("cart-land");
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
const cart = getCart();
|
const cart = getCart();
|
||||||
@@ -89,8 +100,10 @@ const t = useTranslations(lang);
|
|||||||
|
|
||||||
const subtotal = cartTotal();
|
const subtotal = cartTotal();
|
||||||
const remaining = Math.max(0, freeShipFrom - subtotal);
|
const remaining = Math.max(0, freeShipFrom - subtotal);
|
||||||
|
const shipping = berechneVersandkosten(landSelect.value, cart.map((i) => ({ slug: i.slug, preis: i.preis, menge: i.menge })), products);
|
||||||
document.getElementById("sum-subtotal").textContent = formatPrice(subtotal, cartLang);
|
document.getElementById("sum-subtotal").textContent = formatPrice(subtotal, cartLang);
|
||||||
document.getElementById("sum-total").textContent = formatPrice(subtotal, cartLang);
|
document.getElementById("sum-shipping").textContent = shipping === 0 ? freeLabel : formatPrice(shipping, cartLang);
|
||||||
|
document.getElementById("sum-total").textContent = formatPrice(subtotal + shipping, cartLang);
|
||||||
document.getElementById("shipping-hint").textContent =
|
document.getElementById("shipping-hint").textContent =
|
||||||
remaining > 0 ? remainingTemplate.replace("__V__", formatPrice(remaining, cartLang)) : `🩵 ${freeShippingText}`;
|
remaining > 0 ? remainingTemplate.replace("__V__", formatPrice(remaining, cartLang)) : `🩵 ${freeShippingText}`;
|
||||||
|
|
||||||
@@ -112,4 +125,5 @@ const t = useTranslations(lang);
|
|||||||
|
|
||||||
render();
|
render();
|
||||||
window.addEventListener("cart:changed", render);
|
window.addEventListener("cart:changed", render);
|
||||||
|
landSelect.addEventListener("change", render);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -826,6 +826,18 @@ a:focus-visible, button:focus-visible {
|
|||||||
.summary-row { display: flex; justify-content: space-between; margin: 0.55rem 0; font-size: 0.92rem; color: var(--c-text-muted); }
|
.summary-row { display: flex; justify-content: space-between; margin: 0.55rem 0; font-size: 0.92rem; color: var(--c-text-muted); }
|
||||||
.summary-row.total { color: var(--c-text); font-weight: 700; font-size: 1.2rem; margin-top: 0.3rem; }
|
.summary-row.total { color: var(--c-text); font-weight: 700; font-size: 1.2rem; margin-top: 0.3rem; }
|
||||||
.cart-summary h3 { display: flex; align-items: center; gap: 0.5em; }
|
.cart-summary h3 { display: flex; align-items: center; gap: 0.5em; }
|
||||||
|
.ship-country-row { display: flex; align-items: center; justify-content: space-between; gap: 0.6em; margin: 0.6rem 0; font-size: 0.85rem; color: var(--c-text-muted); }
|
||||||
|
.ship-country-row label { display: flex; align-items: center; gap: 0.4em; white-space: nowrap; }
|
||||||
|
.ship-country-row select {
|
||||||
|
background: var(--c-anthracite);
|
||||||
|
color: var(--c-text);
|
||||||
|
border: 1px solid rgba(244, 241, 247, 0.16);
|
||||||
|
border-radius: var(--radius-s);
|
||||||
|
padding: 0.35em 0.6em;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.ship-country-row select:focus { outline: none; border-color: var(--c-accent); }
|
||||||
.free-shipping-badge {
|
.free-shipping-badge {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user