23-01-2026

This commit is contained in:
Kevin Adametz 2026-01-23 17:33:10 +01:00
parent 07959c0ba2
commit 854ce02bf6
166 changed files with 32909 additions and 1262 deletions

View file

@ -0,0 +1,398 @@
<?php
use function Livewire\Volt\{state, mount, computed};
state([
'search' => '',
'statusFilter' => 'all',
'categoryFilter' => 'all',
'sortBy' => 'created_at',
'sortDirection' => 'desc',
]);
// Dummy-Produkte für die Anzeige
$products = computed(function () {
return [
[
'id' => 1,
'b2in_number' => 'B2IN-000471',
'supplier_number' => 'SOFA-ALBA-3S-ANTHR',
'name' => 'Sofa ALBA 3-Sitzer',
'brand' => 'Möbelwerk Nord',
'category' => 'Wohnzimmer > Sofas',
'status' => 'active',
'price' => 1250.00,
'stock_status' => 'in_stock',
'created_at' => '2025-11-04',
'image' => null,
],
[
'id' => 2,
'b2in_number' => 'B2IN-000472',
'supplier_number' => 'CHAIR-NORDIC-OAK',
'name' => 'Stuhl Nordic Eiche',
'brand' => 'Design Studio',
'category' => 'Esszimmer > Stühle',
'status' => 'active',
'price' => 189.00,
'stock_status' => 'in_stock',
'created_at' => '2025-11-05',
'image' => null,
],
[
'id' => 3,
'b2in_number' => 'B2IN-000473',
'supplier_number' => 'BED-LUNA-180',
'name' => 'Bett Luna 180x200',
'brand' => 'Schlafwelt',
'category' => 'Schlafzimmer > Betten',
'status' => 'draft',
'price' => 899.00,
'stock_status' => 'on_order',
'created_at' => '2025-11-03',
'image' => null,
],
[
'id' => 4,
'b2in_number' => 'B2IN-000474',
'supplier_number' => 'TABLE-OAK-EXTEND',
'name' => 'Esstisch Eiche ausziehbar',
'brand' => 'Tischmanufaktur',
'category' => 'Esszimmer > Tische',
'status' => 'active',
'price' => 1450.00,
'stock_status' => 'in_stock',
'created_at' => '2025-10-28',
'image' => null,
],
[
'id' => 5,
'b2in_number' => 'B2IN-000475',
'supplier_number' => 'WARDROBE-CLASSIC',
'name' => 'Kleiderschrank Classic',
'brand' => 'Möbelwerk Nord',
'category' => 'Schlafzimmer > Schränke',
'status' => 'inactive',
'price' => 2100.00,
'stock_status' => 'out_of_stock',
'created_at' => '2025-10-15',
'image' => null,
],
[
'id' => 6,
'b2in_number' => 'B2IN-000476',
'supplier_number' => 'SIDEBOARD-MOD-120',
'name' => 'Sideboard Modern 120cm',
'brand' => 'Design Studio',
'category' => 'Wohnzimmer > Sideboards',
'status' => 'active',
'price' => 675.00,
'stock_status' => 'in_stock',
'created_at' => '2025-11-01',
'image' => null,
],
];
});
?>
<div class="space-y-6">
{{-- Header --}}
<div class="flex items-center justify-between">
<div>
<flux:heading size="xl">{{ __('Produkte') }} (in Entwicklung)</flux:heading>
<flux:subheading>{{ __('Verwalten Sie Ihre Produktliste') }}</flux:subheading>
</div>
<flux:button variant="primary" icon="plus" :href="route('products.create')" wire:navigate>
{{ __('Neues Produkt') }}
</flux:button>
</div>
{{-- Filter & Suche --}}
<flux:card class="p-6">
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
{{-- Suchfeld --}}
<div class="md:col-span-2">
<flux:input
wire:model.live.debounce.300ms="search"
placeholder="{{ __('Suche nach Name, Artikelnummer...') }}"
icon="magnifying-glass"
/>
</div>
{{-- Status Filter --}}
<flux:select wire:model.live="statusFilter">
<option value="all">{{ __('Alle Status') }}</option>
<option value="active">{{ __('Aktiv') }}</option>
<option value="draft">{{ __('Entwurf') }}</option>
<option value="inactive">{{ __('Inaktiv') }}</option>
</flux:select>
{{-- Kategorie Filter --}}
<flux:select wire:model.live="categoryFilter">
<option value="all">{{ __('Alle Kategorien') }}</option>
<option value="sofas">{{ __('Sofas') }}</option>
<option value="chairs">{{ __('Stühle') }}</option>
<option value="tables">{{ __('Tische') }}</option>
<option value="beds">{{ __('Betten') }}</option>
<option value="wardrobes">{{ __('Schränke') }}</option>
</flux:select>
</div>
{{-- Aktive Filter Anzeige --}}
@if($search || $statusFilter !== 'all' || $categoryFilter !== 'all')
<div class="flex items-center gap-2 mt-4 pt-4 border-t border-zinc-200 dark:border-zinc-700">
<span class="text-sm text-zinc-600 dark:text-zinc-400">{{ __('Aktive Filter:') }}</span>
@if($search)
<flux:badge color="blue">
{{ __('Suche: ') }}{{ $search }}
<button wire:click="$set('search', '')" class="ml-1">×</button>
</flux:badge>
@endif
@if($statusFilter !== 'all')
<flux:badge color="green">
{{ __('Status: ') }}{{ __($statusFilter) }}
<button wire:click="$set('statusFilter', 'all')" class="ml-1">×</button>
</flux:badge>
@endif
@if($categoryFilter !== 'all')
<flux:badge color="purple">
{{ __('Kategorie: ') }}{{ __($categoryFilter) }}
<button wire:click="$set('categoryFilter', 'all')" class="ml-1">×</button>
</flux:badge>
@endif
<button
wire:click="$set('search', ''); $set('statusFilter', 'all'); $set('categoryFilter', 'all')"
class="text-sm text-accent-600 hover:text-accent-700 dark:text-accent-400 ml-2"
>
{{ __('Alle Filter zurücksetzen') }}
</button>
</div>
@endif
</flux:card>
{{-- Produkttabelle --}}
<flux:card>
<flux:table>
<flux:table.columns>
<flux:table.column class="w-20">{{ __('Bild') }}</flux:table.column>
<flux:table.column>{{ __('Produkt') }}</flux:table.column>
<flux:table.column>{{ __('Marke') }}</flux:table.column>
<flux:table.column>{{ __('Kategorie') }}</flux:table.column>
<flux:table.column class="text-right">{{ __('Preis') }}</flux:table.column>
<flux:table.column class="text-center">{{ __('Status') }}</flux:table.column>
<flux:table.column class="text-center">{{ __('Lager') }}</flux:table.column>
<flux:table.column>{{ __('Erstellt') }}</flux:table.column>
<flux:table.column class="text-right w-32">{{ __('Aktionen') }}</flux:table.column>
</flux:table.columns>
<flux:table.rows>
@forelse($this->products as $product)
<flux:table.row :key="$product['id']" class="odd:bg-zinc-50 dark:odd:bg-zinc-800/30">
{{-- Bild --}}
<flux:table.cell>
<div class="w-12 h-12 bg-zinc-200 dark:bg-zinc-700 rounded flex items-center justify-center">
<flux:icon.photo class="w-6 h-6 text-zinc-400" />
</div>
</flux:table.cell>
{{-- Produkt --}}
<flux:table.cell>
<div>
<div class="font-semibold text-zinc-900 dark:text-zinc-100">
{{ $product['name'] }}
</div>
<div class="text-xs text-zinc-500 dark:text-zinc-400 space-y-0.5 mt-1">
<div>B2in: {{ $product['b2in_number'] }}</div>
<div>Art.-Nr.: {{ $product['supplier_number'] }}</div>
</div>
</div>
</flux:table.cell>
{{-- Marke --}}
<flux:table.cell>
<span class="text-sm text-zinc-700 dark:text-zinc-300">
{{ $product['brand'] }}
</span>
</flux:table.cell>
{{-- Kategorie --}}
<flux:table.cell>
<span class="text-sm text-zinc-600 dark:text-zinc-400">
{{ $product['category'] }}
</span>
</flux:table.cell>
{{-- Preis --}}
<flux:table.cell class="text-right">
<span class="font-semibold text-zinc-900 dark:text-zinc-100">
{{ number_format($product['price'], 2, ',', '.') }}
</span>
</flux:table.cell>
{{-- Status --}}
<flux:table.cell class="text-center">
@php
$statusColors = [
'active' => 'green',
'draft' => 'yellow',
'inactive' => 'zinc',
];
$statusLabels = [
'active' => __('Aktiv'),
'draft' => __('Entwurf'),
'inactive' => __('Inaktiv'),
];
@endphp
<flux:badge :color="$statusColors[$product['status']]" size="sm">
{{ $statusLabels[$product['status']] }}
</flux:badge>
</flux:table.cell>
{{-- Lagerstatus --}}
<flux:table.cell class="text-center">
@php
$stockColors = [
'in_stock' => 'green',
'on_order' => 'yellow',
'out_of_stock' => 'red',
];
$stockLabels = [
'in_stock' => __('Auf Lager'),
'on_order' => __('Bestellung'),
'out_of_stock' => __('Nicht verfügbar'),
];
@endphp
<flux:badge :color="$stockColors[$product['stock_status']]" size="sm" variant="outline">
{{ $stockLabels[$product['stock_status']] }}
</flux:badge>
</flux:table.cell>
{{-- Erstellt am --}}
<flux:table.cell>
<span class="text-sm text-zinc-600 dark:text-zinc-400">
{{ \Carbon\Carbon::parse($product['created_at'])->format('d.m.Y') }}
</span>
</flux:table.cell>
{{-- Aktionen --}}
<flux:table.cell class="text-right">
<div class="flex items-center justify-end gap-2">
<flux:button variant="ghost" size="sm" icon="eye">
{{ __('Ansehen') }}
</flux:button>
<flux:dropdown position="bottom" align="end">
<flux:button variant="ghost" size="sm" icon="ellipsis-horizontal" icon-trailing />
<flux:menu class="w-48">
<flux:menu.item icon="pencil">
{{ __('Bearbeiten') }}
</flux:menu.item>
<flux:menu.item icon="document-duplicate">
{{ __('Duplizieren') }}
</flux:menu.item>
<flux:menu.separator />
<flux:menu.item icon="archive-box">
{{ __('Archivieren') }}
</flux:menu.item>
<flux:menu.item icon="trash" variant="danger">
{{ __('Löschen') }}
</flux:menu.item>
</flux:menu>
</flux:dropdown>
</div>
</flux:table.cell>
</flux:table.row>
@empty
<flux:table.row>
<flux:table.cell colspan="9" class="text-center py-12">
<div class="flex flex-col items-center justify-center">
<flux:icon.cube class="w-16 h-16 text-zinc-400 mb-4" />
<flux:heading size="lg" class="mb-2">{{ __('Keine Produkte gefunden') }}</flux:heading>
<flux:subheading class="mb-4">
{{ __('Erstellen Sie Ihr erstes Produkt oder passen Sie Ihre Filter an.') }}
</flux:subheading>
<flux:button variant="primary" icon="plus" :href="route('products.create')" wire:navigate>
{{ __('Neues Produkt erstellen') }}
</flux:button>
</div>
</flux:table.cell>
</flux:table.row>
@endforelse
</flux:table.rows>
</flux:table>
{{-- Pagination / Stats --}}
<div class="px-6 py-4 border-t border-zinc-200 dark:border-zinc-700">
<div class="flex items-center justify-between">
<div class="text-sm text-zinc-600 dark:text-zinc-400">
{{ __('Zeige') }} <span class="font-semibold">{{ count($this->products) }}</span> {{ __('von') }} <span class="font-semibold">{{ count($this->products) }}</span> {{ __('Produkten') }}
</div>
{{-- Hier würde normalerweise die Pagination kommen --}}
<div class="flex items-center gap-2">
<flux:button variant="ghost" size="sm" icon="chevron-left" disabled>
{{ __('Zurück') }}
</flux:button>
<span class="text-sm text-zinc-600 dark:text-zinc-400">{{ __('Seite 1 von 1') }}</span>
<flux:button variant="ghost" size="sm" icon="chevron-right" icon-trailing disabled>
{{ __('Weiter') }}
</flux:button>
</div>
</div>
</div>
</flux:card>
{{-- Statistiken (Optional) --}}
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
<flux:card class="p-4">
<div class="flex items-center gap-3">
<div class="p-3 bg-green-100 dark:bg-green-900/20 rounded-lg">
<flux:icon.check-circle class="w-6 h-6 text-green-600 dark:text-green-400" />
</div>
<div>
<div class="text-2xl font-bold text-zinc-900 dark:text-zinc-100">4</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">{{ __('Aktive Produkte') }}</div>
</div>
</div>
</flux:card>
<flux:card class="p-4">
<div class="flex items-center gap-3">
<div class="p-3 bg-yellow-100 dark:bg-yellow-900/20 rounded-lg">
<flux:icon.document class="w-6 h-6 text-yellow-600 dark:text-yellow-400" />
</div>
<div>
<div class="text-2xl font-bold text-zinc-900 dark:text-zinc-100">1</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">{{ __('Entwürfe') }}</div>
</div>
</div>
</flux:card>
<flux:card class="p-4">
<div class="flex items-center gap-3">
<div class="p-3 bg-blue-100 dark:bg-blue-900/20 rounded-lg">
<flux:icon.cube class="w-6 h-6 text-blue-600 dark:text-blue-400" />
</div>
<div>
<div class="text-2xl font-bold text-zinc-900 dark:text-zinc-100">5</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">{{ __('Auf Lager') }}</div>
</div>
</div>
</flux:card>
<flux:card class="p-4">
<div class="flex items-center gap-3">
<div class="p-3 bg-zinc-100 dark:bg-zinc-700 rounded-lg">
<flux:icon.currency-euro class="w-6 h-6 text-zinc-600 dark:text-zinc-400" />
</div>
<div>
<div class="text-2xl font-bold text-zinc-900 dark:text-zinc-100">6.563 </div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">{{ __('Ø Preis') }}</div>
</div>
</div>
</flux:card>
</div>
</div>