Cart timer and modal
August 26, 2025 · AI Conversations
const DURATION = 5 * 60 * 1000; // 20 minutes
const DEADLINE_KEY = "cart_deadline"; // localStorage key
const ORDER_KEY = "fossettsOrderData"; // your order data key
// Get deadline from localStorage or set new
let deadline = localStorage.getItem(DEADLINE_KEY);
if (!deadline) {
deadline = Date.now() + DURATION;
localStorage.setItem(DEADLINE_KEY, deadline);
} else {
deadline = parseInt(deadline, 10);
}
function updateTimers() {
const now = Date.now();
let remaining = deadline – now;
if (remaining {
el.textContent = "00:00";
});
clearInterval(timerInterval);
// Clear storage after time up
localStorage.removeItem(DEADLINE_KEY);
localStorage.removeItem(ORDER_KEY);
console.log("⏰ Time's up — fossettsOrderData cleared");
window.location.href = "/";
return;
}
const minutes = Math.floor(remaining / 1000 / 60);
const seconds = Math.floor((remaining / 1000) % 60);
const formatted =
`Complete your order in ${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")} minutes`;
document.querySelectorAll(".order_timer").forEach(el => {
el.innerHTML = formatted;
});
}
// Start ticking
updateTimers();
const timerInterval = setInterval(updateTimers, 1000);
})();
also how a modal about when 2 min left that your cart is expring
<script>
(function () {
const DURATION = 20 * 60 * 1000; // 20 minutes
const DEADLINE_KEY = "cart_deadline"; // localStorage key for deadline
const ORDER_KEY = "fossettsOrderData"; // your order data key
const WARN_KEY = "cart_warning_shown"; // prevent multiple warnings
const WARNING_THRESHOLD = 2 * 60 * 1000; // show modal at 2 minutes left
// Ensure a deadline exists and persists across refresh/close
let deadline = parseInt(localStorage.getItem(DEADLINE_KEY), 10);
if (!deadline || Number.isNaN(deadline)) {
deadline = Date.now() + DURATION;
localStorage.setItem(DEADLINE_KEY, String(deadline));
}
// Create modal lazily when needed
function ensureWarningModal() {
if (document.getElementById('cart-expiry-modal')) return;
const styles = `
#cart-expiry-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:9998;display:none}
#cart-expiry-modal{position:fixed;inset:0;display:none;align-items:center;justify-content:center;z-index:9999}
#cart-expiry-box{max-width:520px;width:92%;background:#fff;border-radius:12px;box-shadow:0 10px 30px rgba(0,0,0,.25);padding:20px 22px;font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,'Helvetica Neue',Arial}
#cart-expiry-title{font-size:20px;font-weight:700;margin:0 0 6px}
#cart-expiry-msg{font-size:14px;line-height:1.5;margin:0 0 16px}
#cart-expiry-actions{display:flex;gap:10px;justify-content:flex-end}
.cart-expiry-btn{appearance:none;border:0;border-radius:8px;padding:10px 14px;font-weight:600;cursor:pointer}
.cart-expiry-btn.primary{background:#111;color:#fff}
.cart-expiry-btn.ghost{background:#f1f1f1}
@media (prefers-color-scheme: dark){
#cart-expiry-box{background:#1e1e1e;color:#f8f8f8}
.cart-expiry-btn.ghost{background:#2a2a2a;color:#f8f8f8}
.cart-expiry-btn.primary{background:#3a82f6}
}
`;
const styleEl = document.createElement('style');
styleEl.textContent = styles;
document.head.appendChild(styleEl);
const backdrop = document.createElement('div');
backdrop.id = 'cart-expiry-backdrop';
const modal = document.createElement('div');
modal.id = 'cart-expiry-modal';
modal.innerHTML = `
<div id="cart-expiry-box" role="dialog" aria-modal="true" aria-labelledby="cart-expiry-title">
<h3 id="cart-expiry-title">Your cart is expiring soon</h3>
<p id="cart-expiry-msg">You have less than 2 minutes left to complete your order. After that, your cart will be cleared.</p>
<div id="cart-expiry-actions">
<button type="button" class="cart-expiry-btn ghost" id="cart-expiry-dismiss">Keep Shopping</button>
<button type="button" class="cart-expiry-btn primary" id="cart-expiry-checkout">Go to Checkout</button>
</div>
</div>
`;
document.body.appendChild(backdrop);
document.body.appendChild(modal);
function closeModal() {
backdrop.style.display = 'none';
modal.style.display = 'none';
}
document.getElementById('cart-expiry-dismiss').addEventListener('click', closeModal);
document.getElementById('cart-expiry-checkout').addEventListener('click', function () {
// If you have a checkout URL, replace below:
closeModal();
const checkoutBtn = document.querySelector('.checkout-button, .go-to-checkout, a[href*="checkout"]');
if (checkoutBtn && checkoutBtn.click) {
checkoutBtn.click();
} else {
window.location.href = '/checkout';
}
});
// expose simple show
window.__showCartExpiryModal = function () {
backdrop.style.display = 'block';
modal.style.display = 'flex';
};
}
function maybeShowWarning(remaining) {
if (remaining <= WARNING_THRESHOLD) {
if (!localStorage.getItem(WARN_KEY)) {
localStorage.setItem(WARN_KEY, '1');
ensureWarningModal();
if (typeof window.__showCartExpiryModal === 'function') {
window.__showCartExpiryModal();
}
}
}
}
function updateTimers() {
const now = Date.now();
let remaining = deadline - now;
if (remaining <= 0) {
document.querySelectorAll(".order_timer").forEach(el => {
el.textContent = "00:00";
});
clearInterval(timerInterval);
// Clear storage after time up
localStorage.removeItem(DEADLINE_KEY);
localStorage.removeItem(WARN_KEY);
localStorage.removeItem(ORDER_KEY);
console.log("⏰ Time's up — fossettsOrderData cleared");
// Optional: add a message parameter to show "Cart expired" on home page
window.location.href = "/?cart=expired";
return;
}
// Show the 2-minute warning modal (once)
maybeShowWarning(remaining);
const minutes = Math.floor(remaining / 1000 / 60);
const seconds = Math.floor((remaining / 1000) % 60);
const formatted =
`<div style="font-weight:bold;font-size:24px">Complete your order in ${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")} minutes</div>`;
document.querySelectorAll(".order_timer").forEach(el => {
el.innerHTML = formatted;
});
}
// Start ticking
updateTimers();
const timerInterval = setInterval(updateTimers, 1000);
})();
</script>