99 lines
4.9 KiB
JavaScript
99 lines
4.9 KiB
JavaScript
// Oeffentliche Erklaerungsseiten: Kuendigung (§ 312k BGB) und Widerruf (§ 356a BGB).
|
|
// Ohne Login erreichbar, Formular sofort sichtbar (keine Zwischenschritte).
|
|
// Der Kunde waehlt den Vertrag (Kuendigung: Abo oder nur der Zusatzspeicher, ganz oder mit Paketzahl) bzw. die
|
|
// Bestellung (Widerruf: Abschluss, Wechsel, Zusatzspeicher); die Auswahl geht in den Request und steht in der
|
|
// Bestaetigung. Nach dem Absenden: Bestaetigung mit Datum/Uhrzeit, speicher- und druckbar.
|
|
function initLegalForm({ endpoint, fields }) {
|
|
const form = document.getElementById('decl-form')
|
|
const done = document.getElementById('done')
|
|
const errEl = document.getElementById('form-error')
|
|
const esc = (s) => String(s || '').replace(/[&<>"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"' })[c])
|
|
|
|
// Angemeldete Kunden nicht erneut identifizieren lassen: Felder vorbefuellen
|
|
fetch('/api/auth/me', { credentials: 'same-origin' })
|
|
.then((r) => (r.ok ? r.json() : null))
|
|
.then((me) => {
|
|
const c = me?.customer
|
|
if (!c) return
|
|
if (form.elements.name && !form.elements.name.value) form.elements.name.value = c.name || ''
|
|
if (form.elements.email && !form.elements.email.value) form.elements.email.value = c.email || ''
|
|
if (form.elements.customerNumber && !form.elements.customerNumber.value) form.elements.customerNumber.value = c.code || ''
|
|
})
|
|
.catch(() => {})
|
|
|
|
const reasonWrap = document.getElementById('reason-wrap')
|
|
form.querySelectorAll('[name="kind"]').forEach((r) =>
|
|
r.addEventListener('change', () => reasonWrap?.classList.toggle('hidden', form.elements.kind.value !== 'ausserordentlich'))
|
|
)
|
|
const dateInput = document.getElementById('effective-date')
|
|
form.querySelectorAll('[name="when"]').forEach((r) =>
|
|
r.addEventListener('change', () => {
|
|
const onDate = form.elements.when.value === 'datum'
|
|
dateInput?.classList.toggle('hidden', !onDate)
|
|
if (onDate) dateInput?.focus()
|
|
})
|
|
)
|
|
// Nur der Zusatzspeicher: Paketzahl abfragen; der Zeitpunkt entfaellt (Ende des Abrechnungsmonats)
|
|
const storageOnly = () => form.elements.contract?.value === 'zusatzspeicher'
|
|
const packagesWrap = document.getElementById('packages-wrap')
|
|
const whenWrap = document.getElementById('when-wrap')
|
|
form.querySelectorAll('[name="contract"]').forEach((r) =>
|
|
r.addEventListener('change', () => {
|
|
packagesWrap?.classList.toggle('hidden', !storageOnly())
|
|
whenWrap?.classList.toggle('hidden', storageOnly())
|
|
})
|
|
)
|
|
|
|
form.addEventListener('submit', async (ev) => {
|
|
ev.preventDefault()
|
|
errEl.classList.add('hidden')
|
|
const payload = {}
|
|
for (const f of fields) payload[f] = String(form.elements[f]?.value ?? '').trim()
|
|
if (form.elements.when?.value === 'datum' && !storageOnly()) payload.effective = dateInput?.value || ''
|
|
if (form.elements.contract && !storageOnly()) delete payload.packages
|
|
const btn = form.querySelector('button[type="submit"]')
|
|
btn.disabled = true
|
|
try {
|
|
const res = await fetch(endpoint, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload),
|
|
})
|
|
const data = await res.json().catch(() => ({}))
|
|
if (!res.ok) throw new Error(data.error || `Fehler ${res.status}`)
|
|
const at = new Date(data.receivedAt).toLocaleString('de-DE', { dateStyle: 'full', timeStyle: 'medium' })
|
|
document.getElementById('done-at').textContent = at
|
|
// Zeile "Vertrag": die gewaehlte Beschriftung (data-text des Radioknopfs) statt eines festen Namens
|
|
const rows = []
|
|
for (const f of fields) {
|
|
if (f === 'effective') continue
|
|
if (f === 'packages') {
|
|
if (storageOnly()) rows.push(['Pakete', payload.packages ? `${payload.packages} Paket(e) zu je 5 GB` : 'alle gebuchten Pakete'])
|
|
continue
|
|
}
|
|
if (!payload[f]) continue
|
|
const label = form.querySelector(`[data-label-for="${f}"]`)?.dataset.label || f
|
|
const value = form.querySelector(`[name="${f}"]:checked`)?.dataset.text || payload[f]
|
|
rows.push([label, value])
|
|
}
|
|
if (form.elements.when) {
|
|
rows.push(['Zeitpunkt', storageOnly()
|
|
? 'zum Ende des laufenden Abrechnungsmonats'
|
|
: payload.effective
|
|
? `zum ${new Date(payload.effective + 'T12:00:00').toLocaleDateString('de-DE')} (Ende des dann laufenden Abrechnungsmonats)`
|
|
: 'zum nächstmöglichen Zeitpunkt'])
|
|
}
|
|
document.getElementById('done-list').innerHTML = rows.map(([k, v]) => `<dt>${esc(k)}</dt><dd>${esc(v)}</dd>`).join('')
|
|
form.classList.add('hidden')
|
|
done.classList.remove('hidden')
|
|
window.scrollTo({ top: 0, behavior: 'smooth' })
|
|
} catch (err) {
|
|
errEl.textContent = err.message
|
|
errEl.classList.remove('hidden')
|
|
btn.disabled = false
|
|
}
|
|
})
|
|
|
|
document.getElementById('print-btn')?.addEventListener('click', () => window.print())
|
|
}
|