Files
WitShop/resources/views/layouts/shop.blade.php
T
marcoandClaude Sonnet 4.6 5dad8b9324
Deploy to Production (witstore.wende.it) / deploy (push) Successful in 7s
Add email templates, page layouts, and shop themes (template system)
- E-Mail-Templates: DB-gespeicherte HTML-Templates mit {{placeholder}}-System,
  Admin-UI zum Bearbeiten von Betreff und Body, alle 4 Mailables aktualisiert
- Seiten-Layouts: 4 Layouts für CMS-Seiten (Standard, Sidebar, Volle Breite, Landing),
  Layout-Auswahl im Admin-Formular
- Shop-Themes: 5 Farbthemen via CSS-Variablen, Picker in Einstellungen
- Deployment: EmailTemplateSeeder wird automatisch beim Deploy ausgeführt

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

255 lines
13 KiB
PHP

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', \App\Models\Setting::get('shop_name', 'Shop'))</title>
<meta name="description" content="@yield('meta_description', '')">
@vite(['resources/css/app.css', 'resources/js/app.js'])
@php
$themes = config('themes');
$themeName = \App\Models\Setting::get('theme_name', 'default');
$theme = $themes[$themeName] ?? $themes['default'];
@endphp
<style>
:root {
--primary: {{ $theme['primary'] }};
--primary-dark: {{ $theme['dark'] }};
--primary-light: {{ $theme['light'] }};
--primary-text: {{ $theme['text'] }};
}
.btn-primary { background-color: var(--primary); color: #fff; }
.btn-primary:hover { background-color: var(--primary-dark); }
.text-primary { color: var(--primary); }
.bg-primary { background-color: var(--primary); }
.bg-primary-dark { background-color: var(--primary-dark); }
.bg-primary-light { background-color: var(--primary-light); }
.border-primary { border-color: var(--primary); }
.hover-primary:hover { background-color: var(--primary-light); color: var(--primary-text); }
.cat-bar { background-color: var(--primary); }
.cat-bar a { color: rgba(255,255,255,0.85); }
.cat-bar a:hover { background-color: var(--primary-dark); color: #fff; }
.cat-bar a.active { background-color: var(--primary-dark); color: #fff; }
.cart-badge { color: var(--primary); }
.shop-name-text { color: var(--primary); }
</style>
</head>
<body class="bg-gray-50 text-gray-800 flex flex-col min-h-screen">
{{-- Cookie-Consent Banner --}}
@if(\App\Models\Setting::get('cookie_consent') && !Cookie::has('cookie_consent'))
<div id="cookie-banner" class="fixed bottom-0 left-0 right-0 bg-gray-900 text-white p-4 z-50 flex flex-col sm:flex-row items-center justify-between gap-3">
<p class="text-sm">Wir verwenden Cookies, um Ihnen die bestmögliche Nutzererfahrung zu bieten. Mit dem Klick auf „Akzeptieren" stimmen Sie der Verwendung aller Cookies zu. <a href="{{ route('page', 'datenschutz') }}" class="underline">Mehr erfahren</a></p>
<div class="flex gap-2 shrink-0">
<button onclick="setCookieConsent(false)" class="px-4 py-2 text-sm border border-gray-500 rounded hover:bg-gray-700">Ablehnen</button>
<button onclick="setCookieConsent(true)" class="px-4 py-2 text-sm btn-primary rounded">Akzeptieren</button>
</div>
</div>
<script>
function setCookieConsent(accept) {
document.cookie = 'cookie_consent=' + (accept ? '1' : '0') + '; path=/; max-age=31536000';
document.getElementById('cookie-banner').remove();
}
</script>
@endif
@php
$legalSlugs = ['impressum','datenschutz','agb','widerrufsbelehrung'];
$navPages = \App\Models\Page::where('published', true)
->where('show_in_nav', true)
->orderBy('nav_sort')
->orderBy('title')
->get();
$navCategories = \App\Models\Category::whereNull('parent_id')
->where('active', true)
->where('show_in_nav', true)
->orderBy('sort_order')
->get();
@endphp
{{-- Header: Logo-Leiste --}}
<header class="bg-white border-b shadow-sm">
<div class="max-w-6xl mx-auto px-4 py-3 flex items-center justify-between gap-4">
{{-- Logo --}}
<a href="{{ url('/') }}" class="shrink-0 flex items-center">
@php $logo = \App\Models\Setting::get('shop_logo'); @endphp
@if($logo)
<img src="{{ asset('storage/'.$logo) }}" alt="{{ \App\Models\Setting::get('shop_name', 'Shop') }}" class="h-12 w-auto object-contain">
@else
<span class="text-2xl font-bold tracking-tight shop-name-text">
{{ \App\Models\Setting::get('shop_name', 'Shop') }}
</span>
@endif
</a>
{{-- Haupt-Navigation --}}
<nav class="flex items-center gap-1">
<a href="{{ route('shop.products.index') }}"
class="px-3 py-2 rounded-lg text-sm font-medium text-gray-700 hover-primary transition">
Alle Produkte
</a>
@foreach($navCategories as $navCat)
<a href="{{ route('shop.category', $navCat->slug) }}"
class="px-3 py-2 rounded-lg text-sm font-medium text-gray-700 hover-primary transition
{{ request()->route('slug') === $navCat->slug ? 'bg-primary-light text-primary-text' : '' }}">
{{ $navCat->name }}
</a>
@endforeach
@foreach($navPages as $navPage)
<a href="{{ route('page', $navPage->slug) }}"
class="px-3 py-2 rounded-lg text-sm font-medium text-gray-700 hover-primary transition
{{ request()->route('slug') === $navPage->slug ? 'bg-primary-light text-primary-text' : '' }}">
{{ $navPage->title }}
</a>
@endforeach
@auth
<a href="{{ route('account.index') }}"
class="px-3 py-2 rounded-lg text-sm font-medium text-gray-700 hover-primary transition">
Mein Konto
</a>
@if(auth()->user()->isAdmin())
<a href="{{ route('admin.dashboard') }}"
class="px-3 py-2 rounded-lg text-sm font-medium text-gray-700 hover-primary transition">
Admin
</a>
@endif
@else
<a href="{{ route('login') }}"
class="px-3 py-2 rounded-lg text-sm font-medium text-gray-700 hover-primary transition">
Anmelden
</a>
<a href="{{ route('register') }}"
class="px-3 py-2 rounded-lg text-sm font-medium text-gray-700 hover-primary transition">
Registrieren
</a>
@endauth
<a href="{{ route('widerruf') }}"
class="px-3 py-2 rounded-lg text-sm font-medium border border-red-400 text-red-600 hover:border-red-600 hover:text-red-700 hover:bg-red-50 transition flex items-center gap-1.5"
title="Widerrufsformular">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"/>
</svg>
Widerruf erklären
</a>
<a href="{{ route('cart.index') }}"
class="relative ml-2 px-3 py-2 rounded-lg text-sm font-medium btn-primary transition flex items-center gap-1.5">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"/>
</svg>
Warenkorb
@php $cartCount = array_sum(array_column(session('cart', []), 'qty')); @endphp
@if($cartCount > 0)
<span class="bg-white cart-badge text-xs font-bold rounded-full w-5 h-5 flex items-center justify-center leading-none">{{ $cartCount }}</span>
@endif
</a>
</nav>
</div>
{{-- Kategorien-Navigation --}}
@php $navCats = \App\Models\Category::whereNull('parent_id')->where('active', true)->orderBy('sort_order')->get(); @endphp
@if($navCats->count())
<div class="cat-bar">
<div class="max-w-6xl mx-auto px-4 flex gap-1 overflow-x-auto">
@foreach($navCats as $cat)
<a href="{{ route('shop.category', $cat->slug) }}"
class="whitespace-nowrap px-4 py-2.5 text-sm font-medium transition
{{ request()->route('slug') === $cat->slug ? 'active' : '' }}">
{{ $cat->name }}
</a>
@endforeach
</div>
</div>
@endif
</header>
{{-- Flash Messages --}}
<div class="max-w-6xl mx-auto px-4 mt-4 w-full">
@if(session('success'))
<div class="bg-green-100 border border-green-300 text-green-800 px-4 py-3 rounded-lg mb-3">{{ session('success') }}</div>
@endif
@if(session('error'))
<div class="bg-red-100 border border-red-300 text-red-800 px-4 py-3 rounded-lg mb-3">{{ session('error') }}</div>
@endif
</div>
<main class="flex-1 max-w-6xl mx-auto px-4 py-6 w-full">
@yield('content')
</main>
{{-- Footer --}}
@php
$footerPages = \App\Models\Page::where('published', true)
->where('type', 'static')
->where('show_in_footer', true)
->whereNotIn('slug', $legalSlugs)
->orderBy('title')
->get();
$legalPages = \App\Models\Page::where('published', true)
->where('type', 'static')
->whereIn('slug', $legalSlugs)
->get()
->sortBy(fn($p) => array_search($p->slug, $legalSlugs))
->values();
$hasBlog = \App\Models\Page::where('type','blog')->where('published', true)->exists();
$hasFaq = \App\Models\Faq::exists();
@endphp
<footer class="bg-gray-900 text-gray-400 text-sm mt-12">
<div class="max-w-6xl mx-auto px-4 py-8 grid grid-cols-2 md:grid-cols-4 gap-6">
<div>
@if($logo)
<img src="{{ asset('storage/'.$logo) }}" alt="{{ \App\Models\Setting::get('shop_name') }}" class="h-8 w-auto object-contain mb-2 brightness-0 invert opacity-70">
@else
<h3 class="text-white font-semibold mb-2">{{ \App\Models\Setting::get('shop_name') }}</h3>
@endif
<p class="text-xs leading-relaxed">{{ \App\Models\Setting::get('shop_address') }}</p>
</div>
<div>
<h3 class="text-white font-semibold mb-2">Service</h3>
<ul class="space-y-1">
@if($hasBlog)
<li><a href="{{ route('blog') }}" class="hover:text-white transition">Blog / News</a></li>
@endif
@if($hasFaq)
<li><a href="{{ route('faq') }}" class="hover:text-white transition">FAQ</a></li>
@endif
<li><a href="{{ route('widerruf') }}" class="hover:text-white transition">Widerruf</a></li>
<li><a href="{{ route('order.track') }}" class="hover:text-white transition">Bestellung verfolgen</a></li>
@foreach($footerPages as $fp)
<li><a href="{{ route('page', $fp->slug) }}" class="hover:text-white transition">{{ $fp->title }}</a></li>
@endforeach
</ul>
</div>
<div>
<h3 class="text-white font-semibold mb-2">Rechtliches</h3>
<ul class="space-y-1">
@forelse($legalPages as $lp)
<li><a href="{{ route('page', $lp->slug) }}" class="hover:text-white transition">{{ $lp->title }}</a></li>
@empty
<li class="text-gray-600 text-xs">Noch keine Seiten angelegt.</li>
@endforelse
</ul>
</div>
<div>
<h3 class="text-white font-semibold mb-2">Konto</h3>
<ul class="space-y-1">
@auth
<li><a href="{{ route('account.index') }}" class="hover:text-white transition">Mein Konto</a></li>
<li><a href="{{ route('account.orders') }}" class="hover:text-white transition">Bestellungen</a></li>
@else
<li><a href="{{ route('login') }}" class="hover:text-white transition">Anmelden</a></li>
<li><a href="{{ route('register') }}" class="hover:text-white transition">Registrieren</a></li>
@endauth
</ul>
</div>
</div>
<div class="border-t border-gray-700 text-center py-4 text-xs text-gray-500">
&copy; {{ date('Y') }} {{ \App\Models\Setting::get('shop_name') }}. Alle Rechte vorbehalten.
</div>
</footer>
@stack('scripts')
</body>
</html>