Add files via upload
This commit is contained in:
parent
eb4e4b47f2
commit
4f16ac7a44
55
ASAshop.html
55
ASAshop.html
|
|
@ -665,7 +665,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ===== Checkout ===== */
|
/* ===== Checkout ===== */
|
||||||
const API = "https://affiliated-lets-automatic-oak.trycloudflare.com";
|
|
||||||
|
|
||||||
async function checkout(cart) {
|
async function checkout(cart) {
|
||||||
// 1) reserve
|
// 1) reserve
|
||||||
|
|
@ -692,6 +692,17 @@
|
||||||
if (!j2.url) { alert(j2.error || 'create-checkout failed'); return; }
|
if (!j2.url) { alert(j2.error || 'create-checkout failed'); return; }
|
||||||
location.href = j2.url; // redirect to Stripe
|
location.href = j2.url; // redirect to Stripe
|
||||||
}
|
}
|
||||||
|
document.getElementById('checkoutBtn').addEventListener('click', async () => {
|
||||||
|
const entries = Object.entries(state.cart || {});
|
||||||
|
if (!entries.length) return alert('Your cart is empty.');
|
||||||
|
|
||||||
|
const items = entries.map(([id, qty]) => {
|
||||||
|
const p = products.find(p => p.id === id);
|
||||||
|
return { id, name: p?.name || id, qty: Number(qty || 1), price: p?.price || 0 };
|
||||||
|
});
|
||||||
|
|
||||||
|
await checkout(items);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -716,24 +727,30 @@
|
||||||
ctx.fillText(products.find(p => p.id === id)?.name || id, 12, cv.height - 12);
|
ctx.fillText(products.find(p => p.id === id)?.name || id, 12, cv.height - 12);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// client.js (in your existing
|
|
||||||
<script>
|
|
||||||
)
|
let remaining = 12;
|
||||||
let remaining = 12;
|
|
||||||
async function refreshRemaining() {
|
async function refreshRemaining() {
|
||||||
try {
|
try {
|
||||||
const r = await fetch(`${API}/api/inventory`, { credentials: 'include' })
|
const r = await fetch(`${API}/api/inventory`);
|
||||||
document.querySelectorAll('[data-remaining] .remN').forEach(s => s.textContent = remaining);
|
if (!r.ok) return;
|
||||||
// Disable all three server buttons if none left:
|
const j = await r.json();
|
||||||
if (remaining <= 0) {
|
if (typeof j.remaining === 'number') remaining = j.remaining;
|
||||||
document.querySelectorAll('[data-add="server1"],[data-add="server2"],[data-add="server3"]').forEach(btn => {
|
|
||||||
btn.disabled = true; btn.textContent = 'Sold out';
|
// update badges
|
||||||
});
|
document.querySelectorAll('[data-remaining] .remN')
|
||||||
}
|
.forEach(s => s.textContent = remaining);
|
||||||
} catch { }
|
|
||||||
}
|
// disable server buttons if sold out relative to what's already in cart
|
||||||
refreshRemaining();
|
const left = Math.max(0, remaining - serversInCart());
|
||||||
setInterval(refreshRemaining, 30_000); // stay “24/7” up-to-date
|
const disable = left <= 0;
|
||||||
|
document.querySelectorAll('[data-add="server1"],[data-add="server2"],[data-add="server3"]')
|
||||||
|
.forEach(btn => { btn.disabled = disable; btn.textContent = disable ? 'Sold out' : 'Add to cart'; });
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue