Add coupons, newsletter, country-based shipping, sale prices, USP bar
Deploy to Production (witstore.wende.it) / deploy (push) Successful in 8s

- Gutscheincodes: DB-Verwaltung (%, €-Rabatt, Mindestbestellwert, Ablauf),
  Eingabefeld im Checkout, Admin unter Marketing → Gutscheine
- Newsletter: Double-Opt-In per E-Mail, Formular im Footer,
  Admin-Liste mit CSV-Export
- Länderzonen-Versand: DE / DACH / EU / WORLD, Versandkosten nach
  Lieferland dynamisch berechnet, Coupon-Rabatt in Bestellung gespeichert
- Sale-Preise: sale_price auf Produkten, durchgestrichener UVP auf
  Produktkarte, Sonderangebote-Sektion auf Startseite
- USP-Leiste auf Startseite: Versand, Zahlung, Rückgabe, Service

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 11:07:14 +02:00
co-authored by Claude Sonnet 4.6
parent 5dad8b9324
commit 092dae6085
27 changed files with 782 additions and 51 deletions
@@ -48,6 +48,11 @@
<div class="bg-white border rounded-lg p-6 sticky top-4">
<div class="space-y-2 text-sm mb-3 border-b pb-3">
<div class="flex justify-between"><span>Zwischensumme</span><span>{{ number_format($subtotal, 2, ',', '.') }} €</span></div>
@if(($discount ?? 0) > 0)
<div class="flex justify-between text-green-600">
<span>Gutschein ({{ $couponCode }})</span><span>- {{ number_format($discount, 2, ',', '.') }} €</span>
</div>
@endif
<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">
+33 -2
View File
@@ -186,12 +186,43 @@
<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>
@if($discount > 0)
<div class="flex justify-between text-green-600">
<span>Gutschein ({{ $couponCode }})</span>
<span>- {{ number_format($discount, 2, ',', '.') }} €</span>
</div>
@endif
<div class="flex justify-between"><span>Versand</span><span id="shipping-display">{{ $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>
<span>Gesamt</span><span id="total-display">{{ number_format($total, 2, ',', '.') }} €</span>
</div>
<p class="text-xs text-gray-400 mt-2">inkl. MwSt.</p>
{{-- Gutscheincode --}}
<div class="mt-4 border-t pt-4">
@if(session('coupon_error'))
<p class="text-red-600 text-xs mb-2">{{ session('coupon_error') }}</p>
@endif
@if(session('coupon_success'))
<p class="text-green-600 text-xs mb-2">{{ session('coupon_success') }}</p>
@endif
@if($couponCode)
<div class="flex items-center justify-between text-sm mb-2">
<span class="font-mono bg-green-50 text-green-700 px-2 py-0.5 rounded">{{ $couponCode }}</span>
<form method="POST" action="{{ route('checkout.coupon.remove') }}">@csrf
<button class="text-red-500 text-xs hover:underline">Entfernen</button>
</form>
</div>
@else
<form method="POST" action="{{ route('checkout.coupon.apply') }}" class="flex gap-2">
@csrf
<input type="text" name="coupon_code" placeholder="Gutscheincode"
class="flex-1 border rounded px-3 py-1.5 text-sm uppercase" style="text-transform:uppercase">
<button class="bg-gray-700 text-white px-3 py-1.5 rounded text-sm hover:bg-gray-800">OK</button>
</form>
@endif
</div>
</div>
</div>
</div>
+40
View File
@@ -2,6 +2,30 @@
@section('title', \App\Models\Setting::get('shop_name', 'Shop'))
@section('content')
{{-- USP-Leiste --}}
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8 text-center">
<div class="bg-white rounded-lg p-4 border">
<div class="text-2xl mb-1">🚚</div>
<p class="text-sm font-semibold">Schnelle Lieferung</p>
<p class="text-xs text-gray-400">1-3 Werktage</p>
</div>
<div class="bg-white rounded-lg p-4 border">
<div class="text-2xl mb-1">🔒</div>
<p class="text-sm font-semibold">Sicher bezahlen</p>
<p class="text-xs text-gray-400">Vorkasse & Rechnung</p>
</div>
<div class="bg-white rounded-lg p-4 border">
<div class="text-2xl mb-1">↩️</div>
<p class="text-sm font-semibold">14 Tage Rückgabe</p>
<p class="text-xs text-gray-400">Widerrufsrecht</p>
</div>
<div class="bg-white rounded-lg p-4 border">
<div class="text-2xl mb-1">📞</div>
<p class="text-sm font-semibold">Persönlicher Service</p>
<p class="text-xs text-gray-400">{{ \App\Models\Setting::get('shop_phone', '') }}</p>
</div>
</div>
{{-- Banner --}}
@if($banners->count())
<div class="relative mb-10 -mx-4" x-data="{ current: 0 }">
@@ -65,6 +89,22 @@
</div>
@endif
{{-- Sonderangebote --}}
@if($saleProducts->count())
<div class="mb-12">
<div class="flex items-center gap-3 mb-6">
<span class="text-2xl">🏷️</span>
<h2 class="text-2xl font-bold">Sonderangebote</h2>
<span class="bg-red-100 text-red-700 text-xs font-bold px-2 py-0.5 rounded-full">SALE</span>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-6">
@foreach($saleProducts as $product)
@include('shop.products._card', ['product' => $product])
@endforeach
</div>
</div>
@endif
{{-- Neue Produkte --}}
@if($newProducts->count())
<div class="mb-12">
+16 -6
View File
@@ -4,17 +4,27 @@
@else
<div class="w-full h-48 bg-gray-100 flex items-center justify-center text-5xl">📦</div>
@endif
@if(isset($badge))
<span class="absolute top-2 left-2 bg-yellow-400 text-yellow-900 text-xs font-bold px-2 py-0.5 rounded-full">
★ {{ $badge }}
</span>
@if($product->isOnSale())
<span class="absolute top-2 left-2 bg-red-500 text-white text-xs font-bold px-2 py-0.5 rounded-full">SALE</span>
@elseif(isset($badge))
<span class="absolute top-2 left-2 bg-yellow-400 text-yellow-900 text-xs font-bold px-2 py-0.5 rounded-full">★ {{ $badge }}</span>
@endif
<div class="p-4">
<p class="text-xs text-gray-400 mb-1">{{ $product->category?->name }}</p>
<h3 class="font-semibold text-sm mb-2 group-hover:text-blue-600">{{ $product->name }}</h3>
<h3 class="font-semibold text-sm mb-2 group-hover:text-primary">{{ $product->name }}</h3>
<div class="flex items-baseline gap-2">
<span class="text-lg font-bold text-blue-700">{{ number_format($product->base_price, 2, ',', '.') }} €</span>
@if($product->isOnSale())
<span class="text-lg font-bold text-red-600">{{ number_format($product->sale_price, 2, ',', '.') }} €</span>
<span class="text-sm text-gray-400 line-through">{{ number_format($product->base_price, 2, ',', '.') }} €</span>
@else
<span class="text-lg font-bold text-primary">{{ number_format($product->base_price, 2, ',', '.') }} €</span>
@endif
<span class="text-xs text-gray-400">inkl. {{ number_format($product->tax_rate, 0) }}% MwSt.</span>
</div>
@if($product->track_stock && $product->variants->sum('stock') <= 0)
<p class="text-xs text-red-500 mt-1">Nicht vorrätig</p>
@endif
</div>
</a>