diff --git a/make_post_sell/static/js/auction.js b/make_post_sell/static/js/auction.js index ff8c1d9..f81c6ae 100644 --- a/make_post_sell/static/js/auction.js +++ b/make_post_sell/static/js/auction.js @@ -114,9 +114,36 @@ }); } + // Pay-by countdown (post-end): same fmtRemaining; written into + // #auction-pay-countdown if present. The human deadline string is + // also resolved locally from the same data attribute so the user + // sees a consistent wall-clock + countdown in their own timezone. + const payCountdownEl = document.getElementById("auction-pay-countdown"); + const payDeadlineHumanEl = document.getElementById( + "auction-pay-deadline-human" + ); + + function tickPayCountdown() { + if (!payCountdownEl) return; + const raw = payCountdownEl.getAttribute("data-pay-deadline"); + if (!raw) return; + const deadline = parseInt(raw, 10); + if (isNaN(deadline)) return; + payCountdownEl.textContent = fmtRemaining(deadline - Date.now()); + if (payDeadlineHumanEl && payDeadlineHumanEl.textContent === "computing…") { + try { + payDeadlineHumanEl.textContent = new Date(deadline).toLocaleString(); + } catch (e) { + /* leave the placeholder */ + } + } + } + // Countdown ticks locally every second. setInterval(tickCountdown, 1000); + setInterval(tickPayCountdown, 1000); tickCountdown(); + tickPayCountdown(); // Live state: prefer a bounded SSE feed (the server closes it after // ~25s; EventSource reconnects on its own), and fall back to polling diff --git a/make_post_sell/static/js/offer.js b/make_post_sell/static/js/offer.js index e0c6cc3..69bcbb9 100644 --- a/make_post_sell/static/js/offer.js +++ b/make_post_sell/static/js/offer.js @@ -118,9 +118,46 @@ }); } + /* Pay-by deadline countdown. + * + * Any element carrying [data-pay-deadline] (an absolute ms timestamp) + * with a child .offer-pay-countdown-value will tick once a second + * showing how long the buyer has left to pay. When the window + * elapses the offer auto-expires server-side; we reflect that + * locally as "expired — refresh to update." + */ + function fmtRemaining(ms) { + if (ms <= 0) return "expired"; + var totalSeconds = Math.floor(ms / 1000); + var days = Math.floor(totalSeconds / 86400); + var hours = Math.floor((totalSeconds % 86400) / 3600); + var minutes = Math.floor((totalSeconds % 3600) / 60); + var seconds = totalSeconds % 60; + if (days > 0) return days + "d " + hours + "h " + minutes + "m"; + if (hours > 0) return hours + "h " + minutes + "m " + seconds + "s"; + if (minutes > 0) return minutes + "m " + seconds + "s"; + return seconds + "s"; + } + + function tickPayCountdown() { + var nodes = document.querySelectorAll("[data-pay-deadline]"); + if (!nodes.length) return; + var now = Date.now(); + Array.prototype.forEach.call(nodes, function (node) { + var raw = node.getAttribute("data-pay-deadline"); + var deadline = parseInt(raw, 10); + if (isNaN(deadline)) return; + var value = node.querySelector(".offer-pay-countdown-value"); + if (!value) return; + value.textContent = fmtRemaining(deadline - now); + }); + } + function init() { wire(); watchOfferState(); + tickPayCountdown(); + setInterval(tickPayCountdown, 1000); } if (document.readyState === "loading") { diff --git a/make_post_sell/templates/auction.j2 b/make_post_sell/templates/auction.j2 index 06c2267..6d975a0 100644 --- a/make_post_sell/templates/auction.j2 +++ b/make_post_sell/templates/auction.j2 @@ -40,6 +40,20 @@ {% endif %} + {% if is_ended and user_is_winner and not is_settled and payment_deadline_timestamp %} +
+

You won this auction!

+

+ Complete payment by computing… + · computing… remaining, + or the auction will be released to the next-highest bidder. +

+
+ +
+
+ {% endif %} + {% if is_active %} {% if user_is_seller %}
diff --git a/make_post_sell/templates/offer.j2 b/make_post_sell/templates/offer.j2 index c4c97cf..37c4eb7 100644 --- a/make_post_sell/templates/offer.j2 +++ b/make_post_sell/templates/offer.j2 @@ -107,7 +107,11 @@ {% if pay_deadline_human %} -

You have until {{ pay_deadline_human }} to complete payment, after which this offer auto-expires.

+

You have until {{ pay_deadline_human }} to complete payment, after which this offer auto-expires. + {% if pay_deadline_timestamp_ms %} + · computing… remaining + {% endif %} +

{% endif %}
@@ -118,7 +122,11 @@

Awaiting payment

You accepted {{ buyer_name }}’s offer at ${{ "%.2f"|format(current_amount) }}. We emailed them a one-time checkout link — this offer can be redeemed only once.

{% if pay_deadline_human %} -

Buyer must pay by {{ pay_deadline_human }}; the offer auto-expires after that.

+

Buyer must pay by {{ pay_deadline_human }}; the offer auto-expires after that. + {% if pay_deadline_timestamp_ms %} + · computing… remaining + {% endif %} +

{% endif %}

If they need it again, share this same page: