Wartungs-Abo v2: Rechtsrunde umgesetzt

- Bestellseite: Pflichtangaben direkt ueber dem Button, Zahlungsarten,
  Wahl des Leistungsbeginns (sofort / nach Widerrufsfrist via 15 Tage
  Stripe-Probezeit), keine Vorauswahl
- Zustimmungsnachweis: Zeitpunkt, Version, Wahl, IP, Browser in Stripe-
  Metadaten und Appwrite (neue Attribute, Setup-Skript ergaenzt)
- Checkout: Karte + SEPA (Fallback nur Karte), korrigierter Hinweistext
- Vertragsbestaetigung mit PDF der Vertragsunterlagen statt HTML
- Kuendigen/Widerrufen: Formular direkt (keine Zwischenseite), Wunsch-
  termin, Druck/PDF der Bestaetigung, Vorbefuellung bei Login
- Widerrufsbutton im Abo waehrend der Frist, 'beginnt am'-Status
- Pilotbetrieb per ABO_PILOT_EMAILS
- Vertragsbedingungen v2, Datenschutzerklaerung, Kalkulator ohne MwSt
  und mit 100/80 EUR

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-09-25 14:10:21 +00:00
1 parent c0214725c0
commit 4ab154bfa2
18 files changed
+354 -163

No files matched your search

+29 -32
View File
@@ -3,62 +3,59 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Verträge hier kündigen – Webklar</title>
<title>Verträge hier kündigen – WEBklar</title>
<link rel="stylesheet" href="/legal-form.css">
</head>
<body>
<main>
<nav><a href="/dashboard.html">← Kundenportal</a> · <a href="/abo-bedingungen.html">Abo-Bedingungen</a></nav>
<div class="brandline">WEBKLAR</div>
<h1>Verträge hier kündigen</h1>
<div id="intro">
<p>Hier können Sie Ihr Webklar Wartungs-Abo kündigen, auch ohne Anmeldung. Eine ordentliche Kündigung wirkt zum Ende des bereits bezahlten Monats.</p>
<button type="button" class="big-btn primary" id="start-btn">Verträge hier kündigen</button>
<p class="muted">Alternativ im Kundenportal unter „Abo verwalten" oder formlos per E-Mail an kenso.gri@gmail.com.</p>
</div>
<form id="decl-form" class="card hidden" novalidate>
<label for="name" data-label-for="name" data-label="Name">Name <small>(Pflicht)</small></label>
<input id="name" name="name" autocomplete="name" required maxlength="200">
<label for="email" data-label-for="email" data-label="E-Mail">E-Mail-Adresse, mit der Sie das Abo abgeschlossen haben <small>(Pflicht)</small></label>
<input id="email" name="email" type="email" autocomplete="email" required maxlength="255">
<label for="customerNumber" data-label-for="customerNumber" data-label="Kundennummer">Kundennummer <small>(optional, hilft bei der Zuordnung)</small></label>
<input id="customerNumber" name="customerNumber" maxlength="50">
<label>Vertrag</label>
<input value="Webklar Wartungs-Abo" disabled>
<label data-label-for="kind" data-label="Art der Kündigung">Art der Kündigung</label>
<label class="radio"><input type="radio" name="kind" value="ordentlich" data-text="Ordentliche Kündigung" checked> Ordentliche Kündigung</label>
<label class="radio"><input type="radio" name="kind" value="ausserordentlich" data-text="Außerordentliche Kündigung"> Außerordentliche Kündigung aus wichtigem Grund</label>
<form id="decl-form" class="card" novalidate>
<fieldset>
<legend data-label-for="kind" data-label="Art der Kündigung">Art der Kündigung</legend>
<label class="radio"><input type="radio" name="kind" value="ordentlich" data-text="Ordentliche Kündigung" checked> Ordentliche Kündigung</label>
<label class="radio"><input type="radio" name="kind" value="ausserordentlich" data-text="Außerordentliche Kündigung"> Außerordentliche Kündigung aus wichtigem Grund</label>
</fieldset>
<div id="reason-wrap" class="hidden">
<label for="reason" data-label-for="reason" data-label="Kündigungsgrund">Kündigungsgrund</label>
<textarea id="reason" name="reason" maxlength="2000"></textarea>
</div>
<label for="effective" data-label-for="effective" data-label="Gewünschter Zeitpunkt">Zeitpunkt</label>
<select id="effective" name="effective">
<option value="nächstmöglicher Zeitpunkt">zum nächstmöglichen Zeitpunkt</option>
</select>
<label for="name" data-label-for="name" data-label="Name">Name</label>
<input id="name" name="name" autocomplete="name" required maxlength="200">
<label for="email" data-label-for="email" data-label="E-Mail für die Bestätigung">E-Mail-Adresse <small>(dorthin schicken wir die Bestätigung)</small></label>
<input id="email" name="email" type="email" autocomplete="email" required maxlength="255">
<label for="customerNumber" data-label-for="customerNumber" data-label="Kundennummer">Kundennummer <small>(optional)</small></label>
<input id="customerNumber" name="customerNumber" maxlength="50">
<label>Vertrag</label>
<input value="WEBklar Wartungs-Abo" disabled>
<fieldset>
<legend>Zeitpunkt</legend>
<label class="radio"><input type="radio" name="when" value="naechstmoeglich" checked> zum nächstmöglichen Zeitpunkt</label>
<label class="radio"><input type="radio" name="when" value="datum"> zu einem bestimmten Datum</label>
<input type="date" id="effective-date" class="hidden">
</fieldset>
<p class="error hidden" id="form-error"></p>
<button type="submit" class="big-btn">Jetzt kündigen</button>
<p class="muted">Sie erhalten sofort eine Eingangsbestätigung per E-Mail mit Datum und Uhrzeit sowie dem Zeitpunkt, zu dem der Vertrag endet.</p>
</form>
<div id="done" class="card ok hidden">
<h2 style="margin-top:0">Ihre Kündigung ist eingegangen</h2>
<p>Eingang: <strong id="done-at"></strong></p>
<dl id="done-list"></dl>
<p>Eine Bestätigung mit dem Vertragsende haben wir an Ihre E-Mail-Adresse geschickt. Bitte speichern oder drucken Sie diese Seite für Ihre Unterlagen.</p>
<p>Die Bestätigung mit dem Zeitpunkt, zu dem Ihr Vertrag endet, haben wir an Ihre E-Mail-Adresse geschickt.</p>
<button type="button" class="print-btn" id="print-btn">Diese Bestätigung drucken oder als PDF speichern</button>
</div>
</main>
<script src="/legal-form.js"></script>
<script>
initLegalForm({ endpoint: '/api/abo/public/cancel', fields: ['name', 'email', 'customerNumber', 'kind', 'reason', 'effective'] })
initLegalForm({ endpoint: '/api/abo/public/cancel', fields: ['kind', 'reason', 'name', 'email', 'customerNumber', 'effective'] })
</script>
</body>
</html>