implementation for the warenkorb system

This commit is contained in:
2026-08-24 21:49:18 +02:00
parent 75c051a20d
commit 9d33e9c996
3 changed files with 415 additions and 424 deletions
+44 -7
View File
@@ -416,6 +416,7 @@
const form = document.getElementById('checkout-form');
const errorAlert = document.getElementById('form-error-alert');
const statusText = document.getElementById('loading-status-text');
const spinner = document.querySelector('.spinner'); // Referenz auf den Ladekreis
// Subdomain Live-Prüfung
const slugInput = document.getElementById('tenant_slug');
@@ -423,17 +424,23 @@
const submitBtn = document.getElementById('booking_submit');
let slugTimer = null;
// OPTIMIERT: Alles im 'input'-Event (fängt auch Maus-Paste und Autocomplete)
slugInput.addEventListener('input', (e) => {
// 1. Sanitization
e.target.value = e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, '');
});
slugInput.addEventListener('keyup', (e) => {
// 2. Debounced API Check
clearTimeout(slugTimer);
slugTimer = setTimeout(() => checkSubdomain(e.target.value), 600);
});
async function checkSubdomain(name) {
if (name.length < 3) return;
if (name.length < 3) {
feedback.textContent = 'Bitte mindestens 3 Zeichen eingeben.';
feedback.style.color = '#5e757d';
submitBtn.disabled = true;
return;
}
try {
const res = await fetch(`/instance_request/check_subdomain?slug=${name}`);
const j = await res.json();
@@ -448,6 +455,8 @@
}
} catch (e) {
console.error(e);
feedback.textContent = 'Prüfung fehlgeschlagen. Bitte erneut versuchen.';
feedback.style.color = '#b02a37';
}
}
@@ -457,7 +466,11 @@
form.addEventListener('submit', async (e) => {
e.preventDefault();
errorAlert.style.display = 'none';
// OPTIMIERT: Visuelles Feedback für den initialen Submit
const originalBtnText = submitBtn.textContent;
submitBtn.disabled = true;
submitBtn.textContent = "Wird verarbeitet...";
const formData = new FormData(form);
const tenantSlug = formData.get('tenant_slug');
@@ -486,6 +499,7 @@
errorAlert.textContent = error.message;
errorAlert.style.display = 'block';
submitBtn.disabled = false;
submitBtn.textContent = originalBtnText; // Button zurücksetzen
}
});
@@ -509,9 +523,22 @@
}
}, 3500);
let retryCount = 0;
const maxRetries = 30; // OPTIMIERT: Max 90 Sekunden Polling (30 * 3s)
const checkStatus = async () => {
retryCount++;
// Timeout-Abbruch
if (retryCount > maxRetries) {
handlePollingError("Zeitüberschreitung. Die Bereitstellung dauert ungewöhnlich lange. Sie werden per E-Mail informiert, sobald das System bereit ist.", msgInterval);
return;
}
try {
const res = await fetch(`/instance_request/status?slug=${slug}`);
if (!res.ok) throw new Error("Network response was not ok");
const data = await res.json();
if (data.status === 'ready') {
@@ -520,14 +547,13 @@
showSuccessState(data.url, data.username, data.password, data.invoice_url);
} else if (data.status === 'failed') {
// SETUP FEHLGESCHLAGEN
clearInterval(msgInterval);
statusText.textContent = "Fehler bei der Bereitstellung. Bitte Support kontaktieren.";
statusText.style.color = '#b02a37';
handlePollingError("Fehler bei der Bereitstellung. Bitte kontaktieren Sie unseren Support.", msgInterval);
} else {
// SETUP LÄUFT NOCH -> in 3 Sekunden erneut prüfen
setTimeout(checkStatus, 3000);
}
} catch (err) {
// Bei Netzwerkfehler weiter versuchen, solange maxRetries nicht erreicht ist
setTimeout(checkStatus, 3000);
}
};
@@ -535,6 +561,17 @@
// Starte den ersten Check nach 2 Sekunden
setTimeout(checkStatus, 2000);
}
// OPTIMIERT: Hilfsfunktion für Polling-Fehler (verhindert Sackgassen-UI)
function handlePollingError(message, intervalId) {
clearInterval(intervalId);
statusText.textContent = message;
statusText.style.color = '#b02a37';
if (spinner) spinner.style.display = 'none'; // Spinner ausblenden
// Optional: Einen Zurück/Support-Button einfügen
statusText.insertAdjacentHTML('afterend', '<br><a href="#" onclick="window.location.reload(); return false;" class="btn secondary" style="margin-top:1rem;">Seite neu laden</a>');
}
// ==========================================
// Erfolgs-Bildschirm anzeigen