- Mediathek: Video-Vorschaubilder statt Icons (FFmpeg-Thumbnails + Backfill-Command), Kategorie "Sonstiges" - B2in Media-Picker zeigt alle Medientypen, Typ wird automatisch erkannt; Thumbnail-Preview vor allen Medien-URL-Feldern - B2in Marke/Footer: Footer ein/aus, Logo+Claim frei positionierbar (Ecken) mit Constraints, separate Anzeige-Schalter - Angebote-Modul dynamisch: kein Slide-Typ mehr, einheitliches Detail-Layout mit ein-/ausblendbaren Bloecken, Logo/Brand pro Slide, Streichpreis-Option - Player: leere Module stoppen Endlosschleife, dynamische Layout-Anpassung bei verstecktem Footer/Header - Fix: Script-Ladereihenfolge (Livewire vor Flux), entfernte stale public/flux/flux.js, Modal-Crash beim Aktualisieren behoben Co-authored-by: Cursor <cursoragent@cursor.com>
388 lines
22 KiB
PHP
388 lines
22 KiB
PHP
<!DOCTYPE html>
|
|
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
|
|
|
|
<head>
|
|
@include('partials.head')
|
|
</head>
|
|
|
|
<body class="min-h-screen bg-zinc-50 dark:bg-zinc-800 antialiased">
|
|
<flux:sidebar sticky stashable class="border-e border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
|
|
<flux:sidebar.toggle class="lg:hidden" icon="x-mark" />
|
|
<a href="{{ config('domains.domain_main_url') }}" class="me-5 flex items-center space-x-2 rtl:space-x-reverse">
|
|
<x-app-logo />
|
|
</a>
|
|
|
|
@if (session('impersonate_from'))
|
|
<div
|
|
class="mb-4 rounded-lg bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-800 p-3">
|
|
<div class="flex items-start gap-3 mb-2">
|
|
<flux:icon.exclamation-triangle
|
|
class="h-5 w-5 text-orange-600 dark:text-orange-400 flex-shrink-0 mt-0.5" />
|
|
<div class="flex-1 min-w-0">
|
|
<div class="text-sm font-semibold text-orange-900 dark:text-orange-100">
|
|
{{ __('Als :name eingeloggt', ['name' => Auth::user()->name]) }}
|
|
</div>
|
|
<div class="text-xs text-orange-700 dark:text-orange-300 mt-0.5">
|
|
{{ __('Sie sind temporär als dieser User angemeldet') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<form method="POST" action="{{ route('admin.impersonate.leave') }}" class="w-full">
|
|
@csrf
|
|
<flux:button type="submit" variant="primary" size="sm" icon="arrow-left-start-on-rectangle"
|
|
class="w-full">
|
|
{{ __('Zurück zum Admin') }}
|
|
</flux:button>
|
|
</form>
|
|
</div>
|
|
@endif
|
|
|
|
<flux:navlist variant="outline">
|
|
@hasrole('Customer')
|
|
<flux:navlist.group :heading="__('Customer')" class="grid mb-4">
|
|
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')"
|
|
wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
<flux:navlist.group :heading="__('Daten')" class="grid mb-4">
|
|
<flux:navlist.item icon="building-office" :href="route('partner.my-data')"
|
|
:current="request()->routeIs('partner.my-data')" wire:navigate>{{ __('Meine Daten') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
@endhasrole
|
|
@hasrole('Retailer')
|
|
<flux:navlist.group :heading="__('Retailer')" class="grid mb-4">
|
|
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')"
|
|
wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
<flux:navlist.group :heading="__('Produkte')" class="grid mb-4">
|
|
<flux:navlist.item icon="cube" :href="route('products.index')"
|
|
:current="request()->routeIs('products.index')" wire:navigate>{{ __('Produktliste') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="plus-circle" :href="route('products.create.teaser')"
|
|
:current="request()->routeIs('products.create.teaser')" wire:navigate>
|
|
{{ __('Neues Teaser-Produkt') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="plus-circle" :href="route('products.create.standard')"
|
|
:current="request()->routeIs('products.create.standard')" wire:navigate>
|
|
{{ __('Neues Standard-Produkt') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
<flux:navlist.group :heading="__('Daten')" class="grid mb-4">
|
|
<flux:navlist.item icon="building-office" :href="route('partner.my-data')"
|
|
:current="request()->routeIs('partner.my-data')" wire:navigate>{{ __('Meine Daten') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
@endhasrole
|
|
@hasrole('Manufacturer')
|
|
<flux:navlist.group :heading="__('Manufacturer')" class="grid mb-4">
|
|
<flux:navlist.item icon="home" :href="route('dashboard')"
|
|
:current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
<flux:navlist.group :heading="__('Produkte')" class="grid mb-4">
|
|
<flux:navlist.item icon="cube" :href="route('products.index')"
|
|
:current="request()->routeIs('products.index')" wire:navigate>{{ __('Produktliste') }}
|
|
</flux:navlist.item>
|
|
|
|
<flux:navlist.item icon="plus-circle" :href="route('products.create.teaser')"
|
|
:current="request()->routeIs('products.create.teaser')" wire:navigate>
|
|
{{ __('Neues Teaser-Produkt') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="plus-circle" :href="route('products.create.standard')"
|
|
:current="request()->routeIs('products.create.standard')" wire:navigate>
|
|
{{ __('Neues Standard-Produkt') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
<flux:navlist.group :heading="__('Daten')" class="grid mb-4">
|
|
<flux:navlist.item icon="building-office" :href="route('partner.my-data')"
|
|
:current="request()->routeIs('partner.my-data')" wire:navigate>{{ __('Meine Daten') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
@endhasrole
|
|
@hasrole('Broker')
|
|
<flux:navlist.group :heading="__('Broker')" class="grid mb-4">
|
|
<flux:navlist.item icon="home" :href="route('dashboard')"
|
|
:current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
<flux:navlist.group :heading="__('Daten')" class="grid mb-4">
|
|
<flux:navlist.item icon="building-office" :href="route('partner.my-data')"
|
|
:current="request()->routeIs('partner.my-data')" wire:navigate>{{ __('Meine Daten') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
@endhasrole
|
|
@hasrole('Admin|Super-Admin')
|
|
<flux:navlist.group :heading="__('Info')" class="grid mb-4">
|
|
<flux:navlist.item icon="home" :href="route('dashboard')"
|
|
:current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
@endhasrole
|
|
|
|
@hasrole('Super-Admin|Admin')
|
|
<flux:navlist.group :heading="__('Admin')" class="grid mb-4">
|
|
<flux:navlist.group expandable
|
|
:expanded="request()->routeIs(['admin.users', 'admin.users.permissions', 'admin.partners.invite', 'admin.partners.registration-codes'])"
|
|
heading="Partner" class="grid">
|
|
<flux:navlist.item icon="user-group" :href="route('admin.users')"
|
|
:current="request()->routeIs('admin.users')" wire:navigate>{{ __('Benutzer') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="envelope" :href="route('admin.partners.invite')"
|
|
:current="request()->routeIs('admin.partners.invite')" wire:navigate>
|
|
{{ __('Partner einladen') }}</flux:navlist.item>
|
|
<flux:navlist.item icon="key" :href="route('admin.partners.registration-codes')"
|
|
:current="request()->routeIs('admin.partners.registration-codes')" wire:navigate>
|
|
{{ __('Registrierungscodes') }}</flux:navlist.item>
|
|
<flux:navlist.item icon="shield-check" :href="route('admin.users.permissions')"
|
|
:current="request()->routeIs('admin.users.permissions')" wire:navigate>{{ __('Permissions') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
<flux:navlist.group expandable :expanded="request()->routeIs('testing')" heading="Testing"
|
|
class="hidden lg:grid mt-2">
|
|
<flux:navlist.item icon="user-group" :href="route('testing.landing')"
|
|
:current="request()->routeIs('testing.landing')" wire:navigate>{{ __('Register') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
</flux:navlist.group>
|
|
|
|
<flux:navlist.group :heading="__('Produkte')" class="grid mb-4">
|
|
<flux:navlist.item icon="clipboard-document-check" :href="route('admin.products.index')"
|
|
:current="request()->routeIs('admin.products.*')" wire:navigate>
|
|
{{ __('Produkt-Verwaltung') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="cube" :href="route('products.index')"
|
|
:current="request()->routeIs('products.index')" wire:navigate>
|
|
{{ __('Alle Produkte') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
|
|
<flux:navlist.group :heading="__('Regionen')" class="grid mb-4">
|
|
<flux:navlist.item icon="map" :href="route('admin.hubs.index')"
|
|
:current="request()->routeIs('admin.hubs.*')" wire:navigate>{{ __('Hub-Verwaltung') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
|
|
<flux:navlist.group :heading="__('CMS')" class="grid mb-4">
|
|
<flux:navlist.group expandable
|
|
:expanded="request()->routeIs(['cms.dashboard', 'cms.content.index', 'cms.projects.index', 'cms.articles.index', 'cms.media.index'])"
|
|
heading="Website-Inhalte" class="grid">
|
|
<flux:navlist.item icon="rectangle-group" :href="route('cms.dashboard')"
|
|
:current="request()->routeIs('cms.dashboard')" wire:navigate>{{ __('Übersicht') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="document-text" :href="route('cms.content.index')"
|
|
:current="request()->routeIs('cms.content.index')" wire:navigate>{{ __('Inhalte') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="building-office" :href="route('cms.projects.index')"
|
|
:current="request()->routeIs('cms.projects.index')" wire:navigate>{{ __('Projekte') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="newspaper" :href="route('cms.articles.index')"
|
|
:current="request()->routeIs('cms.articles.index')" wire:navigate>{{ __('Magazin') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="photo" :href="route('cms.media.index')"
|
|
:current="request()->routeIs('cms.media.index')" wire:navigate>{{ __('Medien') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
</flux:navlist.group>
|
|
|
|
<flux:navlist.group :heading="__('Cabinet')" class="grid mb-4">
|
|
<flux:navlist.group expandable
|
|
:expanded="request()->routeIs(['admin.cms.display-dashboard', 'admin.cms.display-media', 'admin.cms.display-modules', 'admin.cms.display-module-edit', 'admin.cms.displays', 'admin.cms.cabinet', 'admin.cms.cabinet-tablet'])"
|
|
heading="Store Displays" class="grid">
|
|
<flux:navlist.item icon="squares-2x2" :href="route('admin.cms.display-dashboard')"
|
|
:current="request()->routeIs('admin.cms.display-dashboard')" wire:navigate>{{ __('Übersicht') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="photo" :href="route('admin.cms.display-media')"
|
|
:current="request()->routeIs('admin.cms.display-media')" wire:navigate>{{ __('Mediathek') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="rectangle-group" :href="route('admin.cms.display-modules')"
|
|
:current="request()->routeIs(['admin.cms.display-modules', 'admin.cms.display-module-edit'])" wire:navigate>{{ __('Module') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="tv" :href="route('admin.cms.displays')"
|
|
:current="request()->routeIs('admin.cms.displays')" wire:navigate>{{ __('Displays') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="device-tablet" :href="route('admin.cms.cabinet-tablet')"
|
|
:current="request()->routeIs('admin.cms.cabinet-tablet')" wire:navigate>{{ __('Info-Tablet') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
</flux:navlist.group>
|
|
@endhasrole
|
|
|
|
@hasrole('Super-Admin')
|
|
<flux:navlist.group :heading="__('Superadmin')" class="grid mb-4">
|
|
<flux:navlist.item icon="home" :href="route('dashboard')"
|
|
:current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
@endhasrole
|
|
</flux:navlist>
|
|
|
|
<flux:spacer />
|
|
|
|
@hasrole('Super-Admin|Admin')
|
|
<flux:navlist.group :heading="__('Dokumentation')" class="grid mb-4">
|
|
<flux:navlist.item icon="document-text" :href="route('admin.documentation')"
|
|
:current="request()->routeIs('admin.documentation')" wire:navigate>{{ __('Projekt-Dokumentation') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
@endhasrole
|
|
@hasrole('Super-Admin')
|
|
<flux:navlist variant="outline">
|
|
<flux:navlist.group :heading="__('Resources')">
|
|
<flux:navlist.item icon="pencil" href="https://tailwindcss.com/docs/installation/using-vite"
|
|
target="_blank">
|
|
{{ __('Tailwind CSS') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="shield-check" href="https://heroicons.com" target="_blank">
|
|
{{ __('Hero Icons') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="bolt" href="https://fluxui.dev/docs/installation" target="_blank">
|
|
{{ __('Flux UI') }}
|
|
</flux:navlist.item>
|
|
<flux:navlist.item icon="folder-git-2" href="https://github.com/laravel/livewire-starter-kit"
|
|
target="_blank">
|
|
{{ __('Repository') }}
|
|
</flux:navlist.item>
|
|
|
|
<flux:navlist.item icon="book-open-text" href="https://laravel.com/docs/starter-kits" target="_blank">
|
|
{{ __('Documentation') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
</flux:navlist>
|
|
@endhasrole
|
|
|
|
<!-- Desktop User Menu -->
|
|
<flux:dropdown position="bottom" align="start">
|
|
<flux:profile :name="auth()->user()->name" :initials="auth()->user()->initials()"
|
|
icon-trailing="chevrons-up-down" />
|
|
|
|
<flux:menu class="w-[220px]">
|
|
<flux:menu.radio.group>
|
|
<div class="p-0 text-sm font-normal">
|
|
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
|
|
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
|
|
<span
|
|
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white">
|
|
{{ auth()->user()->initials() }}
|
|
</span>
|
|
</span>
|
|
|
|
<div class="grid flex-1 text-start text-sm leading-tight">
|
|
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
|
|
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</flux:menu.radio.group>
|
|
|
|
<flux:menu.separator />
|
|
|
|
<flux:menu.radio.group>
|
|
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>
|
|
{{ __('Settings') }}</flux:menu.item>
|
|
</flux:menu.radio.group>
|
|
<flux:menu.separator />
|
|
|
|
<flux:menu.radio.group>
|
|
<div x-data="{
|
|
toggle() {
|
|
$flux.appearance = $flux.appearance === 'dark' ? 'light' : 'dark';
|
|
}
|
|
}">
|
|
<flux:menu.item x-show="$flux.appearance !== 'dark'" @click="toggle()" icon="moon">
|
|
{{ __('Dunkel') }}
|
|
</flux:menu.item>
|
|
<flux:menu.item x-show="$flux.appearance === 'dark'" x-cloak @click="toggle()"
|
|
icon="sun">
|
|
{{ __('Hell') }}
|
|
</flux:menu.item>
|
|
</div>
|
|
</flux:menu.radio.group>
|
|
|
|
<flux:menu.separator />
|
|
|
|
<form method="POST" action="{{ route('auth.logout') }}" class="w-full">
|
|
@csrf
|
|
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle"
|
|
class="w-full">
|
|
{{ __('Log Out') }}
|
|
</flux:menu.item>
|
|
</form>
|
|
</flux:menu>
|
|
</flux:dropdown>
|
|
</flux:sidebar>
|
|
|
|
<!-- Mobile User Menu -->
|
|
<flux:header class="lg:hidden">
|
|
<flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left" />
|
|
|
|
<a href="{{ config('domains.domain_main_url') }}"
|
|
class="me-5 ml-2 flex items-center space-x-2 rtl:space-x-reverse">
|
|
<x-app-logo />
|
|
</a>
|
|
<flux:spacer />
|
|
|
|
<flux:dropdown position="top" align="end">
|
|
<flux:profile :initials="auth()->user()->initials()" icon-trailing="chevron-down" />
|
|
|
|
<flux:menu>
|
|
<flux:menu.radio.group>
|
|
<div class="p-0 text-sm font-normal">
|
|
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
|
|
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
|
|
<span
|
|
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white">
|
|
{{ auth()->user()->initials() }}
|
|
</span>
|
|
</span>
|
|
|
|
<div class="grid flex-1 text-start text-sm leading-tight">
|
|
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
|
|
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</flux:menu.radio.group>
|
|
|
|
<flux:menu.separator />
|
|
|
|
<flux:menu.radio.group>
|
|
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>
|
|
{{ __('Settings') }}</flux:menu.item>
|
|
</flux:menu.radio.group>
|
|
<flux:menu.separator />
|
|
|
|
<flux:menu.radio.group>
|
|
<div x-data="{
|
|
toggle() {
|
|
$flux.appearance = $flux.appearance === 'dark' ? 'light' : 'dark';
|
|
}
|
|
}">
|
|
<flux:menu.item x-show="$flux.appearance !== 'dark'" @click="toggle()" icon="moon">
|
|
{{ __('Dunkel') }}
|
|
</flux:menu.item>
|
|
<flux:menu.item x-show="$flux.appearance === 'dark'" x-cloak @click="toggle()"
|
|
icon="sun">
|
|
{{ __('Hell') }}
|
|
</flux:menu.item>
|
|
</div>
|
|
</flux:menu.radio.group>
|
|
|
|
<flux:menu.separator />
|
|
|
|
<form method="POST" action="{{ route('auth.logout') }}" class="w-full">
|
|
@csrf
|
|
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle"
|
|
class="w-full">
|
|
{{ __('Log Out') }}
|
|
</flux:menu.item>
|
|
</form>
|
|
</flux:menu>
|
|
</flux:dropdown>
|
|
</flux:header>
|
|
|
|
{{ $slot }}
|
|
|
|
<flux:toast />
|
|
|
|
{{-- Reihenfolge laut Flux-Doku: Livewire stellt das gebündelte Alpine bereit, danach registriert flux.js seine Alpine-Komponenten (fluxModal, …). --}}
|
|
@livewireScripts
|
|
@fluxScripts
|
|
</body>
|
|
|
|
</html>
|