presseportale/resources/views/components/web/hub/withdrawal-modal.blade.php
Kevin Adametz 268332c106 Recht (Web): Vertrag-widerrufen-Button + zweistufiges Widerrufs-Modal im Hub
Gut sichtbare Schaltflaeche "Vertrag widerrufen" im Footer; das Modal
fuehrt zweistufig durch den Widerruf: Schritt 1 nur Zuordnungsdaten,
Schritt 2 Kontrollansicht mit Bestaetigungsbutton "Jetzt widerrufen".
Erfolgs-/Fehlerzustand oeffnet automatisch (getrennter Error-Bag,
kollidiert nicht mit dem Kontakt-Modal).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:03:37 +00:00

154 lines
9.7 KiB
PHP

{{--
Gesetzlicher Widerrufsbutton (Online-Widerruf ohne Login), zweistufig:
Schritt 1 erfasst nur die Zuordnungsdaten (Name, E-Mail, optional
Bestellnummer — KEIN Widerrufsgrund, darf nicht verlangt werden),
Schritt 2 zeigt die Angaben zur Kontrolle und schließt mit dem
Bestätigungsbutton „Jetzt widerrufen" ab. Der Eingang wird sofort
automatisch per E-Mail bestätigt (WithdrawalController).
Öffnet auf das Window-Event `open-withdrawal-modal`.
--}}
@php($withdrawalErrors = $errors->getBag('withdrawal'))
<div
x-data="{
open: @js(session()->has('withdrawal-status') || $withdrawalErrors->any()),
step: @js($withdrawalErrors->any() ? 1 : 1),
name: @js(old('name', '')),
email: @js(old('email', '')),
reference: @js(old('order_reference', '')),
}"
@open-withdrawal-modal.window="open = true"
@keydown.escape.window="open = false"
>
<div x-show="open" x-cloak class="fixed inset-0 z-50 flex items-center justify-center p-4">
<div class="absolute inset-0 bg-black/50" @click="open = false" aria-hidden="true"></div>
<div class="relative bg-white border border-bg-rule rounded-[4px] w-full max-w-[520px] max-h-[90vh] overflow-y-auto p-7"
role="dialog" aria-modal="true" aria-label="Vertrag widerrufen">
<button type="button" @click="open = false" aria-label="Schließen"
class="absolute top-4 right-4 w-8 h-8 flex items-center justify-center text-ink-3 hover:text-ink transition-colors cursor-pointer">
<svg width="14" height="14" viewBox="0 0 16 16" fill="none">
<path d="M3 3l10 10M13 3L3 13" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
</svg>
</button>
@if (session('withdrawal-status'))
<div class="section-eyebrow mb-4">Widerruf</div>
<h3 class="text-[20px] font-bold text-ink tracking-[-0.4px] m-0 mb-3">Widerruf eingegangen</h3>
<p class="text-[13.5px] text-ink-2 leading-[1.6] m-0" role="status">
{{ session('withdrawal-status') }}
</p>
<button type="button" @click="open = false"
class="mt-6 inline-flex items-center justify-center px-5 py-2.5 text-[13px] font-semibold text-white bg-hub hover:bg-hub-2 rounded-[4px] transition-colors cursor-pointer">
Schließen
</button>
@else
<div class="section-eyebrow mb-4">Widerruf</div>
<h3 class="text-[20px] font-bold text-ink tracking-[-0.4px] m-0 mb-2">Vertrag widerrufen</h3>
<form method="POST" action="{{ route('widerruf.store') }}" novalidate
@submit="if (step !== 2) { $event.preventDefault(); }">
@csrf
{{-- Schritt 1: Zuordnungsdaten --}}
<div x-show="step === 1">
<p class="text-[12.5px] text-ink-3 leading-[1.55] m-0 mb-6">
Hier können Sie Ihren Vertrag ohne Anmeldung widerrufen. Wir benötigen nur
die Daten zur Zuordnung — eine Begründung ist nicht erforderlich.
</p>
<div class="space-y-4">
<div>
<label for="withdrawal-name" class="block text-[12px] font-semibold text-ink mb-1.5">Ihr Name</label>
<input id="withdrawal-name" type="text" name="name" x-model="name" required
autocomplete="name"
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub" />
@error('name', 'withdrawal')
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
@enderror
</div>
<div>
<label for="withdrawal-email" class="block text-[12px] font-semibold text-ink mb-1.5">E-Mail-Adresse</label>
<input id="withdrawal-email" type="email" name="email" x-model="email" required
autocomplete="email"
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub" />
@error('email', 'withdrawal')
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
@enderror
</div>
<div>
<label for="withdrawal-reference" class="block text-[12px] font-semibold text-ink mb-1.5">
Bestell-/Rechnungsnummer <span class="text-ink-3 font-normal">(falls zur Hand)</span>
</label>
<input id="withdrawal-reference" type="text" name="order_reference" x-model="reference"
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-hub" />
@error('order_reference', 'withdrawal')
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
@enderror
</div>
</div>
{{-- Bot-Schutz: versteckte Honeypot-Felder (siehe WithdrawalController). --}}
<div class="hidden" aria-hidden="true">
<label for="withdrawal-website">Website</label>
<input id="withdrawal-website" type="text" name="website" tabindex="-1" autocomplete="off" value="{{ old('website') }}" />
<label for="withdrawal-homepage">Homepage</label>
<input id="withdrawal-homepage" type="text" name="homepage" tabindex="-1" autocomplete="off" value="{{ old('homepage') }}" />
</div>
<div class="flex items-center justify-between gap-4 pt-5">
<p class="text-[11px] text-ink-3 leading-[1.5] m-0">
Ihre Angaben werden nur zur Bearbeitung des Widerrufs verarbeitet
(<a href="{{ route('datenschutz', ['edition' => 'de']) }}" class="underline hover:text-ink">Datenschutz</a>).
</p>
<button type="button" @click="if (name.trim() && email.trim()) { step = 2 }"
:disabled="! name.trim() || ! email.trim()"
:class="(! name.trim() || ! email.trim()) ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'"
class="inline-flex items-center justify-center px-5 py-2.5 text-[13px] font-semibold text-white bg-hub hover:bg-hub-2 rounded-[4px] whitespace-nowrap transition-colors">
Weiter zur Bestätigung
</button>
</div>
</div>
{{-- Schritt 2: Kontrolle + Bestätigungsbutton --}}
<div x-show="step === 2" x-cloak>
<p class="text-[12.5px] text-ink-3 leading-[1.55] m-0 mb-5">
Bitte prüfen Sie Ihre Angaben. Mit dem Klick auf „Jetzt widerrufen" geht Ihre
Widerrufserklärung bei uns ein — Sie erhalten sofort eine automatische
Eingangsbestätigung per E-Mail.
</p>
<dl class="border border-bg-rule divide-y divide-bg-rule text-[13px] m-0 mb-6">
<div class="flex items-baseline justify-between gap-4 px-4 py-3">
<dt class="text-ink-3">Name</dt>
<dd class="font-semibold text-ink m-0 text-right" x-text="name"></dd>
</div>
<div class="flex items-baseline justify-between gap-4 px-4 py-3">
<dt class="text-ink-3">E-Mail</dt>
<dd class="font-semibold text-ink m-0 text-right break-all" x-text="email"></dd>
</div>
<div class="flex items-baseline justify-between gap-4 px-4 py-3">
<dt class="text-ink-3">Bestell-/Rechnungsnummer</dt>
<dd class="font-semibold text-ink m-0 text-right" x-text="reference.trim() || '—'"></dd>
</div>
</dl>
<div class="flex items-center justify-between gap-4">
<button type="button" @click="step = 1"
class="inline-flex items-center justify-center px-4 py-2.5 text-[13px] font-semibold text-ink border border-bg-rule-strong hover:bg-bg rounded-[4px] transition-colors cursor-pointer">
Zurück
</button>
<button type="submit"
class="inline-flex items-center justify-center px-5 py-2.5 text-[13px] font-semibold text-white bg-hub hover:bg-hub-2 rounded-[4px] whitespace-nowrap transition-colors cursor-pointer">
Jetzt widerrufen
</button>
</div>
</div>
</form>
@endif
</div>
</div>
</div>