price change while ordering2
This commit is contained in:
@@ -386,7 +386,13 @@ field-optional = optional
|
||||
checkout-place-order = Place order
|
||||
checkout-continue-payment = Continue
|
||||
checkout-back-info = Back to details
|
||||
checkout-price-changed = The price of an item in your basket has changed since you opened this page. Please review the updated total below before placing your order.
|
||||
checkout-price-changed-title = Price changed
|
||||
checkout-price-changed = The price changed while you were checking out. Please review the new total before continuing.
|
||||
checkout-price-old = Previous total
|
||||
checkout-price-new = New total
|
||||
checkout-price-diff = Difference
|
||||
checkout-return-basket = Return to basket
|
||||
checkout-accept-price = Continue with new price
|
||||
checkout-summary = Order summary
|
||||
profile-title = My profile
|
||||
profile-intro = We'll use these details to prefill checkout.
|
||||
|
||||
@@ -386,7 +386,13 @@ field-optional = nepovinné
|
||||
checkout-place-order = Odoslať objednávku
|
||||
checkout-continue-payment = Pokračovať
|
||||
checkout-back-info = Späť na údaje
|
||||
checkout-price-changed = Cena niektorej položky v košíku sa od otvorenia tejto stránky zmenila. Pred odoslaním objednávky si prosím skontrolujte aktualizovanú sumu nižšie.
|
||||
checkout-price-changed-title = Cena sa zmenila
|
||||
checkout-price-changed = Počas objednávania sa zmenila cena. Pred pokračovaním si prosím skontrolujte novú sumu.
|
||||
checkout-price-old = Pôvodná suma
|
||||
checkout-price-new = Nová suma
|
||||
checkout-price-diff = Rozdiel
|
||||
checkout-return-basket = Späť do košíka
|
||||
checkout-accept-price = Pokračovať s novou cenou
|
||||
checkout-summary = Súhrn objednávky
|
||||
profile-title = Môj profil
|
||||
profile-intro = Tieto údaje použijeme na predvyplnenie pokladne.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -13,9 +13,43 @@
|
||||
<h1 class="text-3xl font-bold text-on-surface-strong dark:text-on-surface-dark-strong">{{ t(key="checkout-title", lang=lang | default(value='sk')) }}</h1>
|
||||
|
||||
{% if price_changed %}
|
||||
<div role="alert" class="mt-4 flex items-start gap-3 rounded-radius border border-warning/40 bg-warning/10 p-4 text-sm text-on-surface dark:text-on-surface-dark">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="size-5 shrink-0 text-warning" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" /></svg>
|
||||
<span>{{ t(key="checkout-price-changed", lang=lang | default(value='sk')) }}</span>
|
||||
<div x-data="{ open: true }" x-show="open" x-cloak x-trap.noscroll="open"
|
||||
@keydown.escape.window="open = false"
|
||||
class="fixed inset-0 z-50 flex items-center justify-center p-4"
|
||||
role="dialog" aria-modal="true" aria-labelledby="price-changed-title">
|
||||
<div class="fixed inset-0 bg-black/50" @click="open = false" aria-hidden="true"></div>
|
||||
<div x-show="open" x-transition
|
||||
class="relative w-full max-w-md rounded-radius border border-outline bg-surface p-6 shadow-lg dark:border-outline-dark dark:bg-surface-dark-alt">
|
||||
<div class="flex items-start gap-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="size-6 shrink-0 text-warning" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" /></svg>
|
||||
<div class="space-y-1">
|
||||
<h2 id="price-changed-title" class="text-lg font-semibold text-on-surface-strong dark:text-on-surface-dark-strong">{{ t(key="checkout-price-changed-title", lang=lang | default(value='sk')) }}</h2>
|
||||
<p class="text-sm text-on-surface/80 dark:text-on-surface-dark/80">{{ t(key="checkout-price-changed", lang=lang | default(value='sk')) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if price_old and price_new %}
|
||||
<dl class="mt-4 space-y-1.5 rounded-radius border border-outline p-3 text-sm dark:border-outline-dark">
|
||||
<div class="flex justify-between">
|
||||
<dt class="text-on-surface/70 dark:text-on-surface-dark/70">{{ t(key="checkout-price-old", lang=lang | default(value='sk')) }}</dt>
|
||||
<dd class="tabular-nums text-on-surface/70 line-through dark:text-on-surface-dark/70">{{ price_old }} €</dd>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<dt class="text-on-surface-strong dark:text-on-surface-dark-strong">{{ t(key="checkout-price-new", lang=lang | default(value='sk')) }}</dt>
|
||||
<dd class="tabular-nums font-semibold text-on-surface-strong dark:text-on-surface-dark-strong">{{ price_new }} €</dd>
|
||||
</div>
|
||||
<div class="flex justify-between border-t border-outline pt-1.5 dark:border-outline-dark">
|
||||
<dt class="text-on-surface/70 dark:text-on-surface-dark/70">{{ t(key="checkout-price-diff", lang=lang | default(value='sk')) }}</dt>
|
||||
<dd class="tabular-nums font-semibold {% if price_increased %}text-danger{% else %}text-success{% endif %}">{% if price_increased %}+{% else %}−{% endif %}{{ price_diff_abs }} €</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{% endif %}
|
||||
|
||||
<div class="mt-6 flex flex-col gap-2 sm:flex-row sm:justify-end">
|
||||
<a href="/cart" class="inline-flex items-center justify-center rounded-radius border border-outline px-6 py-2.5 text-sm font-medium text-on-surface transition hover:bg-surface-alt dark:border-outline-dark dark:text-on-surface-dark dark:hover:bg-surface-dark-alt">{{ t(key="checkout-return-basket", lang=lang | default(value='sk')) }}</a>
|
||||
<button type="button" @click="open = false" class="inline-flex items-center justify-center rounded-radius bg-primary px-6 py-2.5 text-sm font-medium text-on-primary transition hover:opacity-90 dark:bg-primary-dark dark:text-on-primary-dark">{{ t(key="checkout-accept-price", lang=lang | default(value='sk')) }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -398,6 +398,15 @@ async fn payment_page(
|
||||
.as_ref()
|
||||
.is_some_and(|pr| pr.address.is_some() && pr.city.is_some() && pr.zip.is_some());
|
||||
|
||||
// The old/new order totals carried by the price-change bounce (display only;
|
||||
// the actual price is always re-verified server-side on submit).
|
||||
let price_old = params.get("old").and_then(|s| s.parse::<i64>().ok());
|
||||
let price_new = params.get("new").and_then(|s| s.parse::<i64>().ok());
|
||||
let price_delta = match (price_old, price_new) {
|
||||
(Some(o), Some(n)) => Some(n - o),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let response = format::view(
|
||||
&v,
|
||||
"shop/checkout_payment.html",
|
||||
@@ -416,8 +425,13 @@ async fn payment_page(
|
||||
"profile_filled": profile_filled,
|
||||
"can_create_account": user.is_none(),
|
||||
// Set when the buyer was bounced back because a price changed between
|
||||
// viewing this page and submitting; shows a re-confirm notice.
|
||||
// viewing this page and submitting; opens a dialog with the old/new
|
||||
// totals and the difference so they can accept or return to the basket.
|
||||
"price_changed": params.contains_key("price_changed"),
|
||||
"price_old": price_old.map(format_price),
|
||||
"price_new": price_new.map(format_price),
|
||||
"price_diff_abs": price_delta.map(|d| format_price(d.abs())),
|
||||
"price_increased": price_delta.map(|d| d > 0),
|
||||
"lang": current_lang(&jar),
|
||||
}),
|
||||
)?;
|
||||
@@ -514,8 +528,14 @@ async fn place_order(
|
||||
Some(shown) => quote.subtotal_cents + shown,
|
||||
None => return format::redirect("/checkout/payment?price_changed=1"),
|
||||
};
|
||||
if subtotal + method.price_cents != expected_total {
|
||||
return format::redirect("/checkout/payment?price_changed=1");
|
||||
let charge_total = subtotal + method.price_cents;
|
||||
if charge_total != expected_total {
|
||||
// Bounce back with the old/new totals so the payment page can show the
|
||||
// buyer a dialog with the difference and let them accept or return to the
|
||||
// basket.
|
||||
return format::redirect(&format!(
|
||||
"/checkout/payment?price_changed=1&old={expected_total}&new={charge_total}"
|
||||
));
|
||||
}
|
||||
|
||||
// The address/contact captured in the info step, ready to seed a profile (for
|
||||
|
||||
Reference in New Issue
Block a user