Event-Thumbnails: Vorschaubilder mit Auto-Resize und Typ-Logos
- Migration: thumbnail-Spalte in events-Tabelle - Event-Model: imageUrl() liefert Custom-Thumbnail oder Standard-Logo je Event-Typ (Logo_Training.png, Logo_Heimspiel.png, etc.) - Thumbnail-Upload neben Typ-Auswahl bei Erstellen/Bearbeiten mit Live-Vorschau und Entfernen-Button - Automatische Skalierung auf max. FullHD (1920x1080) via GD und Speicherung als JPEG (Qualität 85) - Event-Listen (App + Admin): Logo/Thumbnail links im Terminblock - Übersetzungen in allen 6 Sprachen Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -99,6 +99,7 @@ class EventController extends Controller
|
||||
$event->updated_by = $request->user()->id;
|
||||
$event->save();
|
||||
|
||||
$this->handleThumbnail($request, $event);
|
||||
$this->createParticipantsForTeam($event);
|
||||
$this->syncAssignments($event, $request);
|
||||
$this->saveKnownLocation($validated, $request->input('location_name'));
|
||||
@@ -172,6 +173,7 @@ class EventController extends Controller
|
||||
$event->syncParticipants($request->user()->id);
|
||||
}
|
||||
|
||||
$this->handleThumbnail($request, $event);
|
||||
$this->syncAssignments($event, $request);
|
||||
$this->saveKnownLocation($validated, $request->input('location_name'));
|
||||
$this->syncEventFiles($event, $request);
|
||||
@@ -349,6 +351,7 @@ class EventController extends Controller
|
||||
'new_files.*' => ['file', 'max:10240', 'mimes:pdf,docx,xlsx,jpg,jpeg,png,gif,webp'],
|
||||
'new_file_categories' => ['nullable', 'array'],
|
||||
'new_file_categories.*' => ['integer', 'exists:file_categories,id'],
|
||||
'thumbnail' => ['nullable', 'image', 'max:10240', 'mimes:jpg,jpeg,png,gif,webp'],
|
||||
]);
|
||||
|
||||
$validated = $request->validate([
|
||||
@@ -666,4 +669,68 @@ class EventController extends Controller
|
||||
|
||||
return count($dates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Thumbnail hochladen, auf max. 1920x1080 skalieren und als JPEG speichern.
|
||||
*/
|
||||
private function handleThumbnail(Request $request, Event $event): void
|
||||
{
|
||||
// Thumbnail entfernen
|
||||
if ($request->boolean('remove_thumbnail') && $event->thumbnail) {
|
||||
Storage::disk('public')->delete('thumbnails/' . $event->thumbnail);
|
||||
$event->thumbnail = null;
|
||||
$event->save();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$request->hasFile('thumbnail')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Altes Thumbnail löschen
|
||||
if ($event->thumbnail) {
|
||||
Storage::disk('public')->delete('thumbnails/' . $event->thumbnail);
|
||||
}
|
||||
|
||||
$uploadedFile = $request->file('thumbnail');
|
||||
$storedName = Str::uuid() . '.jpg';
|
||||
|
||||
// Bild laden und auf max. FullHD skalieren
|
||||
$imageData = file_get_contents($uploadedFile->getRealPath());
|
||||
$source = @imagecreatefromstring($imageData);
|
||||
|
||||
if (!$source) {
|
||||
return;
|
||||
}
|
||||
|
||||
$origWidth = imagesx($source);
|
||||
$origHeight = imagesy($source);
|
||||
$maxWidth = 1920;
|
||||
$maxHeight = 1080;
|
||||
|
||||
// Nur verkleinern, nicht vergrößern
|
||||
if ($origWidth > $maxWidth || $origHeight > $maxHeight) {
|
||||
$ratio = min($maxWidth / $origWidth, $maxHeight / $origHeight);
|
||||
$newWidth = (int) round($origWidth * $ratio);
|
||||
$newHeight = (int) round($origHeight * $ratio);
|
||||
|
||||
$resized = imagecreatetruecolor($newWidth, $newHeight);
|
||||
imagecopyresampled($resized, $source, 0, 0, 0, 0, $newWidth, $newHeight, $origWidth, $origHeight);
|
||||
imagedestroy($source);
|
||||
$source = $resized;
|
||||
}
|
||||
|
||||
// Verzeichnis sicherstellen
|
||||
$dir = storage_path('app/public/thumbnails');
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0755, true);
|
||||
}
|
||||
|
||||
// Als JPEG speichern (Qualität 85)
|
||||
imagejpeg($source, $dir . '/' . $storedName, 85);
|
||||
imagedestroy($source);
|
||||
|
||||
$event->thumbnail = $storedName;
|
||||
$event->save();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user