23-01-2026
This commit is contained in:
parent
07959c0ba2
commit
854ce02bf6
166 changed files with 32909 additions and 1262 deletions
398
resources/views/livewire/products/index.blade.php
Normal file
398
resources/views/livewire/products/index.blade.php
Normal 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>
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue