fix: confirm prompt on terminal offer actions (accept / decline / withdraw)
These end the negotiation, so the forms now carry onsubmit="return confirm(...)". offer.js bails when the prompt is cancelled — it checks event.defaultPrevented before firing the AJAX request — so the JS path respects the confirmation too, and the no-JS path gets the native dialog before the POST+redirect.
This commit is contained in:
parent
c43336925c
commit
87ac9d90ca
3 changed files with 27 additions and 3 deletions
|
|
@ -28,6 +28,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSubmit(e) {
|
function handleSubmit(e) {
|
||||||
|
// An inline onsubmit="return confirm(...)" on terminal-action forms
|
||||||
|
// runs before this listener. If the user cancelled, the event is
|
||||||
|
// already defaultPrevented — bail so we don't fire the AJAX request.
|
||||||
|
if (e.defaultPrevented) return;
|
||||||
var form = e.currentTarget;
|
var form = e.currentTarget;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var submitBtn = form.querySelector('[type="submit"]');
|
var submitBtn = form.querySelector('[type="submit"]');
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,11 @@
|
||||||
<section class="offer-actions well">
|
<section class="offer-actions well">
|
||||||
<h3 class="type-title">Your turn</h3>
|
<h3 class="type-title">Your turn</h3>
|
||||||
|
|
||||||
<form method="post" action="/o/{{ id }}/accept" class="offer-action-form">
|
{# Terminal actions (accept / decline / withdraw) carry a confirm
|
||||||
|
prompt. offer.js bails if the prompt was cancelled (it checks
|
||||||
|
event.defaultPrevented), so the AJAX path respects it too. #}
|
||||||
|
<form method="post" action="/o/{{ id }}/accept" class="offer-action-form"
|
||||||
|
onsubmit="return confirm('Accept this offer for ${{ "%.2f"|format(current_amount) }} and continue to checkout? This is final.');">
|
||||||
<input type="text" name="message" placeholder="Optional message" />
|
<input type="text" name="message" placeholder="Optional message" />
|
||||||
<input type="submit" class="mps-submit" value="Accept ${{ "%.2f"|format(current_amount) }}" />
|
<input type="submit" class="mps-submit" value="Accept ${{ "%.2f"|format(current_amount) }}" />
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -74,13 +78,15 @@
|
||||||
<input type="submit" class="mps-button" value="Counter" />
|
<input type="submit" class="mps-button" value="Counter" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form method="post" action="/o/{{ id }}/decline" class="offer-action-form" style="margin-top: var(--space-3);">
|
<form method="post" action="/o/{{ id }}/decline" class="offer-action-form" style="margin-top: var(--space-3);"
|
||||||
|
onsubmit="return confirm('Decline this offer? This ends the negotiation and cannot be undone.');">
|
||||||
<input type="text" name="message" placeholder="Reason (optional)" />
|
<input type="text" name="message" placeholder="Reason (optional)" />
|
||||||
<input type="submit" class="mps-button" value="Decline" />
|
<input type="submit" class="mps-button" value="Decline" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% if actor_party == 0 %}
|
{% if actor_party == 0 %}
|
||||||
<form method="post" action="/o/{{ id }}/withdraw" class="offer-action-form" style="margin-top: var(--space-3);">
|
<form method="post" action="/o/{{ id }}/withdraw" class="offer-action-form" style="margin-top: var(--space-3);"
|
||||||
|
onsubmit="return confirm('Withdraw your offer? This ends the negotiation.');">
|
||||||
<input type="submit" class="mps-button" value="Withdraw offer" />
|
<input type="submit" class="mps-button" value="Withdraw offer" />
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
||||||
|
|
@ -5971,6 +5971,20 @@ class TestOfferRoutes(_AuthenticatedBase):
|
||||||
)
|
)
|
||||||
self.assertEqual(res2.status_int, 403)
|
self.assertEqual(res2.status_int, 403)
|
||||||
|
|
||||||
|
def test_terminal_action_forms_have_confirm_prompt(self):
|
||||||
|
product_id = self._make_offer_product(list_price=10000)
|
||||||
|
self.testapp.get("/log-out")
|
||||||
|
self.log_in_user(self.user2_creds)
|
||||||
|
res = self._ajax_post(f"/p/{product_id}/offer", {"amount": "70.00"})
|
||||||
|
offer_id = res.json["offer_id"]
|
||||||
|
# Seller views the pending offer — accept/decline forms must carry
|
||||||
|
# an "are you sure" confirm.
|
||||||
|
self.testapp.get("/log-out")
|
||||||
|
self.log_in_user(self.user1_creds)
|
||||||
|
body = self.testapp.get(f"/o/{offer_id}", status=200).body.decode()
|
||||||
|
self.assertIn(f"/o/{offer_id}/accept", body)
|
||||||
|
self.assertIn('onsubmit="return confirm(', body)
|
||||||
|
|
||||||
def test_offers_disabled_on_fixed_price_product(self):
|
def test_offers_disabled_on_fixed_price_product(self):
|
||||||
from ..models.product import Product
|
from ..models.product import Product
|
||||||
shop = self._create_shop_helper()
|
shop = self._create_shop_helper()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue