live seat availability: fetch from server webhook, orange/red styling when <10/0 seats, disable sold-out locations
This commit is contained in:
@@ -299,6 +299,8 @@
|
||||
}
|
||||
.pricing-config-select:hover { border-color: var(--accent); }
|
||||
.pricing-config-select:focus { border-color: var(--accent); }
|
||||
.pricing-config-select.low-seats { border-color: var(--warning); box-shadow: 0 0 0 2px rgba(255, 170, 0, 0.2); }
|
||||
.pricing-config-select.no-seats { border-color: var(--danger); box-shadow: 0 0 0 2px rgba(255, 59, 59, 0.2); }
|
||||
.pricing-config-input {
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
@@ -363,7 +365,7 @@
|
||||
<option value="yearly">Yearly</option>
|
||||
</select>
|
||||
<select class="pricing-config-select" id="pricing-location">
|
||||
<option value="france">France</option>
|
||||
<option value="">Loading locations...</option>
|
||||
</select>
|
||||
<input type="email" class="pricing-config-input" id="pricing-email" placeholder="Email" autocomplete="email" />
|
||||
<input type="text" class="pricing-config-input" id="pricing-coupon" placeholder="Coupon code" />
|
||||
@@ -539,6 +541,51 @@
|
||||
<script>
|
||||
// ── Signup Webhook URLs (matching app.derez.ai) ──────────
|
||||
const ORDER_WEBHOOK = "https://n8n.derez.ai/webhook/payment";
|
||||
const SERVER_WEBHOOK = "https://n8n.derez.ai/webhook/server";
|
||||
|
||||
async function initServerLocations() {
|
||||
const sel = document.getElementById('pricing-location');
|
||||
if (!sel) return;
|
||||
try {
|
||||
const res = await fetch(SERVER_WEBHOOK);
|
||||
const data = await res.json();
|
||||
const servers = Array.isArray(data) ? data : [data];
|
||||
sel.innerHTML = '';
|
||||
servers.forEach(function(s) {
|
||||
const server = s.server || '';
|
||||
const available = parseInt(s['Seats Available'], 10) || 0;
|
||||
const label = server.charAt(0).toUpperCase() + server.slice(1);
|
||||
const opt = document.createElement('option');
|
||||
opt.value = server.toLowerCase().replace(/\s+/g, '-');
|
||||
if (available <= 0) {
|
||||
opt.textContent = label + ' (sold out)';
|
||||
opt.disabled = true;
|
||||
opt.style.color = '#ff4444';
|
||||
opt.style.fontWeight = '600';
|
||||
sel.classList.remove('low-seats');
|
||||
sel.classList.add('no-seats');
|
||||
} else if (available < 10) {
|
||||
opt.textContent = label + ' (available ' + available + ')';
|
||||
opt.style.color = '#ff9900';
|
||||
opt.style.fontWeight = '600';
|
||||
sel.classList.add('low-seats');
|
||||
sel.classList.remove('no-seats');
|
||||
} else {
|
||||
opt.textContent = label + ' (available ' + available + ')';
|
||||
opt.style.color = '';
|
||||
opt.style.fontWeight = '';
|
||||
sel.classList.remove('low-seats', 'no-seats');
|
||||
}
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
for (var i = 0; i < sel.options.length; i++) {
|
||||
if (!sel.options[i].disabled) { sel.selectedIndex = i; break; }
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load server locations:', err);
|
||||
sel.innerHTML = '<option value="france" style="color:#ff9900;font-weight:600">France (available ?)</option>';
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Period / billing update ──────────────────────────── */
|
||||
function updatePeriodDisplay() {
|
||||
@@ -553,6 +600,7 @@
|
||||
}
|
||||
document.getElementById('pricing-period').addEventListener('change', updatePeriodDisplay);
|
||||
updatePeriodDisplay();
|
||||
initServerLocations();
|
||||
|
||||
/* ── Capture UTM params from URL ──────────────────────── */
|
||||
(function () {
|
||||
|
||||
Reference in New Issue
Block a user