Files
WitShop/resources/views/shop/checkout/index.blade.php
T
marcoandClaude Sonnet 4.6 41078fdc08 Initial commit: WitShop Laravel Online-Shop
- Laravel 11, Blade, Alpine.js, Tailwind CSS
- Produkt- & Kategorieverwaltung mit Varianten
- Checkout (Vorkasse + Rechnung), Session-Warenkorb
- Admin-Backend (Dashboard, Bestellungen, Kunden, CMS)
- DSGVO-konform: Cookie-Consent, Impressum, Widerruf, AGB
- PDF-Rechnung via dompdf, SMTP-Mailversand
- Kundenverwaltung mit manueller Freischaltung

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 00:34:09 +02:00

239 lines
14 KiB
PHP

@extends('layouts.shop')
@section('title', 'Kasse')
@section('content')
<h1 class="text-2xl font-bold mb-6">Kasse</h1>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div class="md:col-span-2">
<form method="POST" action="{{ route('checkout.address') }}">
@csrf
{{-- Gastemail --}}
@guest
<div class="bg-white border rounded-lg p-6 mb-6">
<h2 class="font-semibold mb-4">Kontakt</h2>
<div>
<label class="block text-sm font-medium mb-1">E-Mail-Adresse *</label>
<input type="email" name="email" value="{{ old('email') }}" class="w-full border rounded px-3 py-2" required>
</div>
<p class="text-sm text-gray-500 mt-3">
Bereits Kunde? <a href="{{ route('login') }}" class="text-blue-600 hover:underline">Anmelden</a>
</p>
</div>
@endguest
{{-- Rechnungsadresse --}}
@php $defaultAddr = $userAddresses->firstWhere('is_default', true) ?? $userAddresses->first(); @endphp
<div class="bg-white border rounded-lg p-6 mb-6" x-data="addressForm({{ $userAddresses->toJson() }})">
<h2 class="font-semibold mb-4">Rechnungsadresse</h2>
{{-- Gespeicherte Adressen --}}
@if($userAddresses->count())
<div class="mb-5">
<p class="text-xs text-gray-500 mb-2">Gespeicherte Adressen:</p>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
@foreach($userAddresses as $addr)
<button type="button"
@click="fill({{ $addr->id }})"
:class="selected === {{ $addr->id }} ? 'border-blue-500 bg-blue-50 ring-1 ring-blue-500' : 'border-gray-200 hover:border-blue-300'"
class="text-left p-3 border rounded-lg text-sm transition">
<p class="font-medium">{{ $addr->first_name }} {{ $addr->last_name }}</p>
@if($addr->company)<p class="text-gray-400 text-xs">{{ $addr->company }}</p>@endif
<p class="text-gray-500 text-xs mt-0.5">{{ $addr->street }}, {{ $addr->zip }} {{ $addr->city }}</p>
</button>
@endforeach
<button type="button"
@click="clear()"
:class="selected === null ? 'border-blue-500 bg-blue-50 ring-1 ring-blue-500' : 'border-gray-200 hover:border-gray-300'"
class="text-left p-3 border rounded-lg text-sm transition text-gray-500">
+ Neue Adresse eingeben
</button>
</div>
</div>
@endif
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium mb-1">Vorname *</label>
<input type="text" name="billing[first_name]" x-model="form.first_name" value="{{ old('billing.first_name', $defaultAddr?->first_name) }}" class="w-full border rounded px-3 py-2 text-sm" required>
</div>
<div>
<label class="block text-sm font-medium mb-1">Nachname *</label>
<input type="text" name="billing[last_name]" x-model="form.last_name" value="{{ old('billing.last_name', $defaultAddr?->last_name) }}" class="w-full border rounded px-3 py-2 text-sm" required>
</div>
<div class="col-span-2">
<label class="block text-sm font-medium mb-1">Firma (optional)</label>
<input type="text" name="billing[company]" x-model="form.company" value="{{ old('billing.company', $defaultAddr?->company) }}" class="w-full border rounded px-3 py-2 text-sm">
</div>
<div class="col-span-2">
<label class="block text-sm font-medium mb-1">Straße und Hausnummer *</label>
<input type="text" name="billing[street]" x-model="form.street" value="{{ old('billing.street', $defaultAddr?->street) }}" class="w-full border rounded px-3 py-2 text-sm" required>
</div>
<div>
<label class="block text-sm font-medium mb-1">PLZ *</label>
<input type="text" name="billing[zip]" x-model="form.zip" value="{{ old('billing.zip', $defaultAddr?->zip) }}" class="w-full border rounded px-3 py-2 text-sm" required>
</div>
<div>
<label class="block text-sm font-medium mb-1">Stadt *</label>
<input type="text" name="billing[city]" x-model="form.city" value="{{ old('billing.city', $defaultAddr?->city) }}" class="w-full border rounded px-3 py-2 text-sm" required>
</div>
<div>
<label class="block text-sm font-medium mb-1">Land *</label>
<select name="billing[country]" x-model="form.country" class="w-full border rounded px-3 py-2 text-sm">
<option value="DE">Deutschland</option>
<option value="AT">Österreich</option>
<option value="CH">Schweiz</option>
</select>
</div>
<div>
<label class="block text-sm font-medium mb-1">Telefon</label>
<input type="tel" name="billing[phone]" x-model="form.phone" value="{{ old('billing.phone', $defaultAddr?->phone) }}" class="w-full border rounded px-3 py-2 text-sm">
</div>
</div>
</div>
{{-- Lieferadresse --}}
<div class="bg-white border rounded-lg p-6 mb-6" x-data="{ same: true }">
<div class="flex items-center justify-between mb-4">
<h2 class="font-semibold">Lieferadresse</h2>
<label class="flex items-center gap-2 text-sm cursor-pointer">
<input type="checkbox" name="shipping_same" value="1" x-model="same" checked>
Gleich wie Rechnungsadresse
</label>
</div>
<div x-show="!same" class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium mb-1">Vorname *</label>
<input type="text" name="shipping[first_name]" value="{{ old('shipping.first_name') }}" class="w-full border rounded px-3 py-2 text-sm">
</div>
<div>
<label class="block text-sm font-medium mb-1">Nachname *</label>
<input type="text" name="shipping[last_name]" value="{{ old('shipping.last_name') }}" class="w-full border rounded px-3 py-2 text-sm">
</div>
<div class="col-span-2">
<label class="block text-sm font-medium mb-1">Straße und Hausnummer *</label>
<input type="text" name="shipping[street]" value="{{ old('shipping.street') }}" class="w-full border rounded px-3 py-2 text-sm">
</div>
<div>
<label class="block text-sm font-medium mb-1">PLZ *</label>
<input type="text" name="shipping[zip]" value="{{ old('shipping.zip') }}" class="w-full border rounded px-3 py-2 text-sm">
</div>
<div>
<label class="block text-sm font-medium mb-1">Stadt *</label>
<input type="text" name="shipping[city]" value="{{ old('shipping.city') }}" class="w-full border rounded px-3 py-2 text-sm">
</div>
<div>
<label class="block text-sm font-medium mb-1">Land *</label>
<select name="shipping[country]" class="w-full border rounded px-3 py-2 text-sm">
<option value="DE" selected>Deutschland</option>
<option value="AT">Österreich</option>
<option value="CH">Schweiz</option>
</select>
</div>
</div>
</div>
{{-- Zahlungsart --}}
<div class="bg-white border rounded-lg p-6 mb-6">
<h2 class="font-semibold mb-4">Zahlungsart</h2>
<div class="space-y-3">
<label class="flex items-start gap-3 p-3 border rounded-lg cursor-pointer hover:bg-gray-50">
<input type="radio" name="payment_method" value="prepayment" class="mt-1" checked>
<div>
<div class="font-medium">Vorkasse (Überweisung)</div>
<div class="text-sm text-gray-500">Sie überweisen den Betrag auf unser Bankkonto. Wir versenden nach Zahlungseingang.</div>
</div>
</label>
<label class="flex items-start gap-3 p-3 border rounded-lg cursor-pointer hover:bg-gray-50">
<input type="radio" name="payment_method" value="invoice" class="mt-1">
<div>
<div class="font-medium">Kauf auf Rechnung</div>
<div class="text-sm text-gray-500">Sie erhalten die Rechnung per E-Mail. Zahlungsziel: {{ \App\Models\Setting::get('invoice_payment_days', 14) }} Tage.</div>
</div>
</label>
</div>
</div>
{{-- Rechtliches --}}
<div class="bg-white border rounded-lg p-6 mb-6 space-y-3">
<label class="flex items-start gap-3 cursor-pointer">
<input type="checkbox" name="agb" value="1" required class="mt-1">
<span class="text-sm">Ich habe die <a href="{{ route('page', 'agb') }}" class="text-blue-600 hover:underline" target="_blank">AGB</a> gelesen und akzeptiere sie. Ich habe die <a href="{{ route('page', 'widerrufsbelehrung') }}" class="text-blue-600 hover:underline" target="_blank">Widerrufsbelehrung</a> zur Kenntnis genommen. *</span>
</label>
<label class="flex items-start gap-3 cursor-pointer">
<input type="checkbox" name="privacy" value="1" required class="mt-1">
<span class="text-sm">Ich habe die <a href="{{ route('page', 'datenschutz') }}" class="text-blue-600 hover:underline" target="_blank">Datenschutzerklärung</a> gelesen. *</span>
</label>
</div>
@if($errors->any())
<div class="bg-red-50 border border-red-200 rounded-lg p-4 mb-4">
<ul class="text-sm text-red-700 space-y-1">
@foreach($errors->all() as $error)<li>• {{ $error }}</li>@endforeach
</ul>
</div>
@endif
<button type="submit" class="w-full bg-blue-600 text-white py-3 rounded-lg hover:bg-blue-700 font-semibold text-lg">
Bestellung prüfen →
</button>
</form>
</div>
{{-- Zusammenfassung --}}
<div>
<div class="bg-white border rounded-lg p-6 sticky top-4">
<h2 class="font-semibold mb-4">Zusammenfassung</h2>
<div class="space-y-2 text-sm mb-4 border-b pb-4">
<div class="flex justify-between"><span>Zwischensumme</span><span>{{ number_format($subtotal, 2, ',', '.') }} €</span></div>
<div class="flex justify-between"><span>Versand</span><span>{{ $shippingCost == 0 ? 'Kostenlos' : number_format($shippingCost, 2, ',', '.') . ' €' }}</span></div>
</div>
<div class="flex justify-between font-bold text-lg">
<span>Gesamt</span><span>{{ number_format($total, 2, ',', '.') }} €</span>
</div>
<p class="text-xs text-gray-400 mt-2">inkl. MwSt.</p>
</div>
</div>
</div>
@endsection
@push('scripts')
<script>
function addressForm(addresses) {
@php $defaultAddr = $userAddresses->firstWhere('is_default', true) ?? $userAddresses->first(); @endphp
const defaultId = {{ $defaultAddr?->id ?? 'null' }};
return {
addresses,
selected: defaultId,
form: {
first_name: '{{ old('billing.first_name', $defaultAddr?->first_name) }}',
last_name: '{{ old('billing.last_name', $defaultAddr?->last_name) }}',
company: '{{ old('billing.company', $defaultAddr?->company) }}',
street: '{{ old('billing.street', $defaultAddr?->street) }}',
zip: '{{ old('billing.zip', $defaultAddr?->zip) }}',
city: '{{ old('billing.city', $defaultAddr?->city) }}',
country: '{{ old('billing.country', $defaultAddr?->country ?? 'DE') }}',
phone: '{{ old('billing.phone', $defaultAddr?->phone) }}',
},
fill(id) {
const addr = this.addresses.find(a => a.id === id);
if (!addr) return;
this.selected = id;
this.form.first_name = addr.first_name ?? '';
this.form.last_name = addr.last_name ?? '';
this.form.company = addr.company ?? '';
this.form.street = addr.street ?? '';
this.form.zip = addr.zip ?? '';
this.form.city = addr.city ?? '';
this.form.country = addr.country ?? 'DE';
this.form.phone = addr.phone ?? '';
},
clear() {
this.selected = null;
Object.keys(this.form).forEach(k => this.form[k] = k === 'country' ? 'DE' : '');
}
}
}
</script>
@endpush