Cart timer and modal

User
(function () {
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

Assistant
<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>

Leave a Comment

Your email address will not be published. Required fields are marked *