(function () { const boot = window.APP_BOOT || { steps: [], csrf: '' }; const state = { email: '', currentStep: 1, totalSteps: boot.steps.length, autosaveId: null, }; const startForm = document.getElementById('startForm'); const wizardSection = document.getElementById('wizardSection'); const blockedSection = document.getElementById('blockedSection'); const statusSection = document.getElementById('statusSection'); const statusMessage = document.getElementById('statusMessage'); const applicationForm = document.getElementById('applicationForm'); const applicationEmail = document.getElementById('applicationEmail'); const progress = document.getElementById('progress'); const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); const submitBtn = document.getElementById('submitBtn'); const uploadNowBtn = document.getElementById('uploadNowBtn'); const stepElements = Array.from(document.querySelectorAll('.step')); function showMessage(text) { statusSection.classList.remove('hidden'); statusMessage.textContent = text; } function clearErrors() { document.querySelectorAll('[data-error-for]').forEach((el) => { el.textContent = ''; }); } function showErrors(errors) { clearErrors(); Object.keys(errors || {}).forEach((key) => { const el = document.querySelector('[data-error-for="' + key + '"]'); if (el) { el.textContent = errors[key]; } }); } function updateProgress() { progress.textContent = 'Schritt ' + state.currentStep + ' von ' + state.totalSteps; stepElements.forEach((el) => { const step = Number(el.getAttribute('data-step')); el.classList.toggle('hidden', step !== state.currentStep); }); prevBtn.disabled = state.currentStep === 1; nextBtn.classList.toggle('hidden', state.currentStep === state.totalSteps); submitBtn.classList.toggle('hidden', state.currentStep !== state.totalSteps); } function fillFormData(data) { Object.keys(data || {}).forEach((key) => { const field = applicationForm.querySelector('[name="form_data[' + key + ']"]'); if (!field) return; if (field.type === 'checkbox') { field.checked = ['1', 'on', 'true', true].includes(data[key]); } else { field.value = data[key] || ''; } }); } function renderUploadInfo(uploads) { document.querySelectorAll('[data-upload-list]').forEach((el) => { el.innerHTML = ''; }); Object.keys(uploads || {}).forEach((field) => { const target = document.querySelector('[data-upload-list="' + field + '"]'); if (!target || !Array.isArray(uploads[field])) return; uploads[field].forEach((item) => { const div = document.createElement('div'); div.className = 'upload-item'; div.textContent = item.original_filename + ' (' + item.uploaded_at + ')'; target.appendChild(div); }); }); } async function postForm(url, formData) { const response = await fetch(url, { method: 'POST', body: formData, credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' }, }); const payload = await response.json(); if (!response.ok || payload.ok === false) { const err = new Error(payload.message || 'Anfrage fehlgeschlagen'); err.payload = payload; throw err; } return payload; } function collectPayload(includeFiles) { const fd = new FormData(); fd.append('csrf', boot.csrf); fd.append('email', state.email); fd.append('step', String(state.currentStep)); fd.append('website', ''); Array.from(applicationForm.elements).forEach((el) => { if (!el.name) return; if (!el.name.startsWith('form_data[')) return; if (el.type === 'checkbox') { fd.append(el.name, el.checked ? '1' : '0'); } else { fd.append(el.name, el.value || ''); } }); if (includeFiles) { Array.from(applicationForm.querySelectorAll('input[type="file"]')).forEach((input) => { if (input.files && input.files[0]) { fd.append(input.name, input.files[0]); } }); } return fd; } async function loadDraft(email) { const fd = new FormData(); fd.append('csrf', boot.csrf); fd.append('email', email); fd.append('website', ''); return postForm('/api/load-draft.php', fd); } async function saveDraft(includeFiles, showSavedText) { const payload = collectPayload(includeFiles); const response = await postForm('/api/save-draft.php', payload); if (response.upload_errors && Object.keys(response.upload_errors).length > 0) { showErrors(response.upload_errors); showMessage('Einige Dateien konnten nicht gespeichert werden.'); } else if (showSavedText) { showMessage('Entwurf gespeichert: ' + (response.updated_at || '')); } if (response.uploads) { renderUploadInfo(response.uploads); } if (includeFiles) { Array.from(applicationForm.querySelectorAll('input[type="file"]')).forEach((input) => { input.value = ''; }); } return response; } async function submitApplication() { const payload = collectPayload(true); const response = await postForm('/api/submit.php', payload); clearErrors(); showMessage('Antrag erfolgreich abgeschlossen. Vielen Dank.'); submitBtn.disabled = true; nextBtn.disabled = true; prevBtn.disabled = true; return response; } startForm.addEventListener('submit', async (event) => { event.preventDefault(); const emailInput = document.getElementById('startEmail'); const email = (emailInput.value || '').trim().toLowerCase(); if (!email) { showMessage('Bitte E-Mail eingeben.'); return; } try { const result = await loadDraft(email); state.email = email; applicationEmail.value = email; if (result.already_submitted) { wizardSection.classList.add('hidden'); blockedSection.classList.remove('hidden'); showMessage(result.message || 'Antrag bereits abgeschlossen.'); return; } blockedSection.classList.add('hidden'); wizardSection.classList.remove('hidden'); fillFormData(result.data || {}); renderUploadInfo(result.uploads || {}); state.currentStep = Math.min(Math.max(Number(result.step || 1), 1), state.totalSteps); updateProgress(); showMessage('Formular geladen. Entwurf wird automatisch gespeichert.'); if (state.autosaveId) { clearInterval(state.autosaveId); } state.autosaveId = setInterval(async () => { if (!state.email || wizardSection.classList.contains('hidden')) { return; } try { await saveDraft(false, false); } catch (_err) { // Autsave errors are visible on next manual action. } }, 15000); } catch (err) { const msg = (err.payload && err.payload.message) || err.message || 'Laden fehlgeschlagen.'; showMessage(msg); } }); prevBtn.addEventListener('click', async () => { if (state.currentStep <= 1) return; try { await saveDraft(false, true); state.currentStep -= 1; updateProgress(); } catch (err) { const msg = (err.payload && err.payload.message) || err.message; showMessage(msg); } }); nextBtn.addEventListener('click', async () => { if (state.currentStep >= state.totalSteps) return; try { await saveDraft(false, true); state.currentStep += 1; updateProgress(); } catch (err) { const msg = (err.payload && err.payload.message) || err.message; showMessage(msg); } }); if (uploadNowBtn) { uploadNowBtn.addEventListener('click', async () => { try { await saveDraft(true, true); } catch (err) { const msg = (err.payload && err.payload.message) || err.message; showMessage(msg); } }); } submitBtn.addEventListener('click', async () => { try { await submitApplication(); } catch (err) { const payload = err.payload || {}; if (payload.errors) { showErrors(payload.errors); } const msg = payload.message || err.message || 'Absenden fehlgeschlagen.'; showMessage(msg); if (payload.already_submitted) { blockedSection.classList.remove('hidden'); wizardSection.classList.add('hidden'); } } }); updateProgress(); })();