352 lines
20 KiB
PHP
352 lines
20 KiB
PHP
@extends('layouts.vending')
|
|
|
|
@section('title', 'Produkt bearbeiten')
|
|
|
|
@section('content')
|
|
<div class="max-w-4xl mx-auto px-4">
|
|
<div class="mb-8">
|
|
<div class="flex items-center space-x-4 mb-4">
|
|
<a href="{{ route('products.index') }}" class="text-blue-600 hover:text-blue-800">
|
|
← Zurück zur Übersicht
|
|
</a>
|
|
</div>
|
|
<h1 class="text-3xl font-bold text-gray-900">Produkt bearbeiten</h1>
|
|
<p class="text-gray-600 mt-2">{{ $product->name }} - LMIV-konforme Produktdaten</p>
|
|
</div>
|
|
|
|
<form action="{{ route('products.update', $product) }}" method="POST" enctype="multipart/form-data" class="space-y-8">
|
|
@csrf
|
|
@method('PUT')
|
|
|
|
<!-- Grundinformationen -->
|
|
<div class="bg-white shadow rounded-lg p-6">
|
|
<h2 class="text-xl font-semibold text-gray-900 mb-6 border-b border-gray-200 pb-2">
|
|
Grundinformationen
|
|
</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div>
|
|
<label for="name" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Produktname *
|
|
</label>
|
|
<input type="text" id="name" name="name" value="{{ old('name', $product->name) }}" required
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('name') border-red-500 @enderror">
|
|
@error('name')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="price" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Preis (€) *
|
|
</label>
|
|
<input type="number" id="price" name="price" value="{{ old('price', $product->price) }}" step="0.01" min="0" required
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('price') border-red-500 @enderror">
|
|
@error('price')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div class="md:col-span-2">
|
|
<label for="description" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Beschreibung
|
|
</label>
|
|
<textarea id="description" name="description" rows="3"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('description') border-red-500 @enderror">{{ old('description', $product->description) }}</textarea>
|
|
@error('description')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="image" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Produktbild
|
|
</label>
|
|
@if($product->image)
|
|
<div class="mb-2">
|
|
<img src="{{ asset('storage/' . $product->image) }}" alt="{{ $product->name }}" class="h-20 w-20 object-cover rounded">
|
|
<p class="text-xs text-gray-500 mt-1">Aktuelles Bild (wird ersetzt wenn neues hochgeladen)</p>
|
|
</div>
|
|
@endif
|
|
<input type="file" id="image" name="image" accept="image/jpeg,image/jpg,image/png,image/gif,image/webp"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('image') border-red-500 @enderror">
|
|
<p class="text-xs text-gray-500 mt-1">Erlaubte Formate: JPEG, PNG, GIF, WebP (max. 2MB)</p>
|
|
@error('image')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="barcode" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Barcode
|
|
</label>
|
|
<input type="text" id="barcode" name="barcode" value="{{ old('barcode', $product->barcode) }}"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('barcode') border-red-500 @enderror">
|
|
@error('barcode')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- LMIV-Pflichtangaben -->
|
|
<div class="bg-white shadow rounded-lg p-6">
|
|
<h2 class="text-xl font-semibold text-gray-900 mb-6 border-b border-gray-200 pb-2">
|
|
LMIV-Pflichtangaben
|
|
</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div class="md:col-span-2">
|
|
<label for="ingredients" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Zutaten (in absteigender Reihenfolge)
|
|
</label>
|
|
<textarea id="ingredients" name="ingredients" rows="3"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('ingredients') border-red-500 @enderror">{{ old('ingredients', $product->ingredients) }}</textarea>
|
|
@error('ingredients')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div class="md:col-span-2">
|
|
<label for="allergens" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Allergene und Unverträglichkeiten
|
|
</label>
|
|
<textarea id="allergens" name="allergens" rows="3"
|
|
placeholder="z.B. Enthält Gluten, Milch, Nüsse..."
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('allergens') border-red-500 @enderror">{{ old('allergens', $product->allergens) }}</textarea>
|
|
@error('allergens')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="net_weight" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Nettofüllmenge (g)
|
|
</label>
|
|
<input type="number" id="net_weight" name="net_weight" value="{{ old('net_weight', $product->net_weight) }}" step="0.1"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('net_weight') border-red-500 @enderror">
|
|
@error('net_weight')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="origin_country" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Herkunftsland
|
|
</label>
|
|
<input type="text" id="origin_country" name="origin_country" value="{{ old('origin_country', $product->origin_country) }}"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('origin_country') border-red-500 @enderror">
|
|
@error('origin_country')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="manufacturer" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Hersteller
|
|
</label>
|
|
<input type="text" id="manufacturer" name="manufacturer" value="{{ old('manufacturer', $product->manufacturer) }}"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('manufacturer') border-red-500 @enderror">
|
|
@error('manufacturer')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="distributor" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Vertreiber
|
|
</label>
|
|
<input type="text" id="distributor" name="distributor" value="{{ old('distributor', $product->distributor) }}"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('distributor') border-red-500 @enderror">
|
|
@error('distributor')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Nährwertangaben -->
|
|
<div class="bg-white shadow rounded-lg p-6">
|
|
<h2 class="text-xl font-semibold text-gray-900 mb-6 border-b border-gray-200 pb-2">
|
|
Nährwertangaben (pro 100g)
|
|
</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
<!-- Erste Reihe -->
|
|
<div>
|
|
<label for="energy_kcal" class="block text-sm font-medium text-gray-700 mb-2 h-10 flex items-center">
|
|
Energie (kcal)
|
|
</label>
|
|
<input type="number" id="energy_kcal" name="energy_kcal" value="{{ old('energy_kcal', $product->energy_kcal) }}" step="0.1"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('energy_kcal') border-red-500 @enderror">
|
|
@error('energy_kcal')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="energy_kj" class="block text-sm font-medium text-gray-700 mb-2 h-10 flex items-center">
|
|
Energie (kJ)
|
|
</label>
|
|
<input type="number" id="energy_kj" name="energy_kj" value="{{ old('energy_kj', $product->energy_kj) }}" step="0.1"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('energy_kj') border-red-500 @enderror">
|
|
@error('energy_kj')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="fat" class="block text-sm font-medium text-gray-700 mb-2 h-10 flex items-center">
|
|
Fett (g)
|
|
</label>
|
|
<input type="number" id="fat" name="fat" value="{{ old('fat', $product->fat) }}" step="0.01"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('fat') border-red-500 @enderror">
|
|
@error('fat')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="saturated_fat" class="block text-sm font-medium text-gray-700 mb-2 h-10 flex items-center">
|
|
davon gesättigte Fettsäuren (g)
|
|
</label>
|
|
<input type="number" id="saturated_fat" name="saturated_fat" value="{{ old('saturated_fat', $product->saturated_fat) }}" step="0.01"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('saturated_fat') border-red-500 @enderror">
|
|
@error('saturated_fat')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<!-- Zweite Reihe -->
|
|
<div>
|
|
<label for="carbohydrates" class="block text-sm font-medium text-gray-700 mb-2 h-10 flex items-center">
|
|
Kohlenhydrate (g)
|
|
</label>
|
|
<input type="number" id="carbohydrates" name="carbohydrates" value="{{ old('carbohydrates', $product->carbohydrates) }}" step="0.01"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('carbohydrates') border-red-500 @enderror">
|
|
@error('carbohydrates')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="sugars" class="block text-sm font-medium text-gray-700 mb-2 h-10 flex items-center">
|
|
davon Zucker (g)
|
|
</label>
|
|
<input type="number" id="sugars" name="sugars" value="{{ old('sugars', $product->sugars) }}" step="0.01"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('sugars') border-red-500 @enderror">
|
|
@error('sugars')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="protein" class="block text-sm font-medium text-gray-700 mb-2 h-10 flex items-center">
|
|
Eiweiß (g)
|
|
</label>
|
|
<input type="number" id="protein" name="protein" value="{{ old('protein', $product->protein) }}" step="0.01"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('protein') border-red-500 @enderror">
|
|
@error('protein')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="salt" class="block text-sm font-medium text-gray-700 mb-2 h-10 flex items-center">
|
|
Salz (g)
|
|
</label>
|
|
<input type="number" id="salt" name="salt" value="{{ old('salt', $product->salt) }}" step="0.01" min="0"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('salt') border-red-500 @enderror">
|
|
@error('salt')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Zusätzliche Informationen -->
|
|
<div class="bg-white shadow rounded-lg p-6">
|
|
<h2 class="text-xl font-semibold text-gray-900 mb-6 border-b border-gray-200 pb-2">
|
|
Zusätzliche Informationen
|
|
</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div>
|
|
<label for="storage_instructions" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Aufbewahrungshinweise
|
|
</label>
|
|
<textarea id="storage_instructions" name="storage_instructions" rows="3"
|
|
placeholder="z.B. Kühl und trocken lagern..."
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('storage_instructions') border-red-500 @enderror">{{ old('storage_instructions', $product->storage_instructions) }}</textarea>
|
|
@error('storage_instructions')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="usage_instructions" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Verwendungshinweise
|
|
</label>
|
|
<textarea id="usage_instructions" name="usage_instructions" rows="3"
|
|
placeholder="z.B. Vor Verzehr gut schütteln..."
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('usage_instructions') border-red-500 @enderror">{{ old('usage_instructions', $product->usage_instructions) }}</textarea>
|
|
@error('usage_instructions')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="best_before_date" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Mindesthaltbarkeitsdatum
|
|
</label>
|
|
<input type="date" id="best_before_date" name="best_before_date" value="{{ old('best_before_date', $product->best_before_date?->format('Y-m-d')) }}"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('best_before_date') border-red-500 @enderror">
|
|
@error('best_before_date')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<div>
|
|
<label for="lot_number" class="block text-sm font-medium text-gray-700 mb-2">
|
|
Chargennummer
|
|
</label>
|
|
<input type="text" id="lot_number" name="lot_number" value="{{ old('lot_number', $product->lot_number) }}"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 @error('lot_number') border-red-500 @enderror">
|
|
@error('lot_number')
|
|
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Aktionsbuttons -->
|
|
<div class="flex justify-between items-center bg-gray-50 px-6 py-4 rounded-lg">
|
|
<a href="{{ route('products.index') }}"
|
|
class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
|
|
Abbrechen
|
|
</a>
|
|
|
|
<div class="flex space-x-3">
|
|
<a href="{{ route('products.show', $product) }}"
|
|
class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
|
|
Vorschau
|
|
</a>
|
|
<button type="submit"
|
|
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
|
|
Änderungen speichern
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<script>
|
|
// Automatische kJ-Berechnung basierend auf kcal
|
|
document.getElementById('energy_kcal').addEventListener('input', function() {
|
|
const kcal = parseFloat(this.value);
|
|
if (!isNaN(kcal)) {
|
|
document.getElementById('energy_kj').value = Math.round(kcal * 4.184);
|
|
}
|
|
});
|
|
</script>
|
|
@endsection |