Kündigung und Widerruf: Vertrag bzw. Bestellung auswählbar (§ 312k, § 356a BGB)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Fable 5.1 committed 2026-09-29 09:52:37 +00:00
1 parent f66a713531
commit 7ffe95f24a
10 files changed
+992 -87

No files matched your search

+31 -10
View File
@@ -1,6 +1,8 @@
// Oeffentliche Erklaerungsseiten: Kuendigung (§ 312k BGB) und Widerruf (§ 356a BGB).
// Ohne Login erreichbar, Formular sofort sichtbar (keine Zwischenschritte).
// Nach dem Absenden: Bestaetigung mit Datum/Uhrzeit, speicher- und druckbar.
// 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')
@@ -21,23 +23,34 @@ function initLegalForm({ endpoint, fields }) {
const reasonWrap = document.getElementById('reason-wrap')
form.querySelectorAll('[name="kind"]').forEach((r) =>
r.addEventListener('change', () => reasonWrap?.classList.toggle('hidden', form.kind.value !== 'ausserordentlich'))
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.when.value === 'datum'
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.when?.value === 'datum') payload.effective = dateInput?.value || ''
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 {
@@ -50,17 +63,25 @@ function initLegalForm({ endpoint, fields }) {
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
const rows = [['Vertrag', 'WEBklar Wartungs-Abo']]
// Zeile "Vertrag": die gewaehlte Beschriftung (data-text des Radioknopfs) statt eines festen Namens
const rows = []
for (const f of fields) {
if (!payload[f] || f === 'effective') continue
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.when) {
rows.push(['Zeitpunkt', payload.effective
? `zum ${new Date(payload.effective + 'T12:00:00').toLocaleDateString('de-DE')} (Ende des dann laufenden Abrechnungsmonats)`
: 'zum nächstmöglichen Zeitpunkt'])
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')