- Fix: Notifiable-Trait zum User-Model hinzugefuegt (behebt notify()-500er) - Installer: SMTP-Verbindungstest mit EsmtpTransport + Ueberspringen-Link - Admin: Neuer E-Mail-Tab mit SMTP-Konfiguration + Verbindungstest - Admin: Lazy Quill-Initialisierung (nur sichtbare Locale wird geladen) - Uebersetzungen: 17 neue Mail-Keys in allen 6 Sprachen Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
90 lines
6.0 KiB
PHP
90 lines
6.0 KiB
PHP
<x-layouts.admin :title="__('admin.files_title')">
|
||
<div class="flex justify-between items-center mb-6">
|
||
<h1 class="text-2xl font-bold">{{ __('admin.files_title') }}</h1>
|
||
<a href="{{ route('admin.files.create') }}" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 text-sm font-medium">
|
||
{{ __('admin.upload_file') }}
|
||
</a>
|
||
</div>
|
||
|
||
{{-- Kategorie-Tabs --}}
|
||
<div class="flex flex-wrap gap-2 mb-6">
|
||
<a href="{{ route('admin.files.index') }}"
|
||
class="px-3 py-1.5 rounded-md text-sm font-medium {{ !$activeCategory ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }}">
|
||
{{ __('ui.all') }} ({{ $categories->sum('files_count') }})
|
||
</a>
|
||
@foreach ($categories as $category)
|
||
<a href="{{ route('admin.files.index', ['category' => $category->slug]) }}"
|
||
class="px-3 py-1.5 rounded-md text-sm font-medium {{ $activeCategory === $category->slug ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }} {{ !$category->is_active ? 'opacity-50' : '' }}">
|
||
{{ $category->name }} ({{ $category->files_count }})
|
||
</a>
|
||
@endforeach
|
||
</div>
|
||
|
||
{{-- Datei-Liste --}}
|
||
@if ($files->isEmpty())
|
||
<div class="bg-white rounded-lg shadow p-8 text-center">
|
||
<svg class="mx-auto h-12 w-12 text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m6.75 12H9.75m3 0h3m-1.5-3H12m-3 3V18m0-3h.008v.008H9v-.008zm0 3h.008v.008H9V18z" />
|
||
</svg>
|
||
<p class="mt-3 text-sm text-gray-500">{{ $activeCategory ? __('admin.no_files_yet') : __('admin.no_files_at_all') }}</p>
|
||
</div>
|
||
@else
|
||
<div class="grid gap-3" x-data>
|
||
@foreach ($files as $file)
|
||
<div class="bg-white rounded-lg shadow px-4 sm:px-5 py-4 flex items-center gap-3 sm:gap-4 min-w-0">
|
||
{{-- Clickable file area --}}
|
||
<div @click="$dispatch('open-file-preview', @js($file->previewData()))"
|
||
class="flex items-center gap-3 min-w-0 flex-1 cursor-pointer hover:opacity-80 transition-opacity">
|
||
{{-- Thumbnail oder Icon --}}
|
||
@if ($file->isImage())
|
||
<img src="{{ route('files.preview', $file) }}" alt="" class="flex-shrink-0 w-10 h-10 rounded-lg object-cover bg-gray-100" loading="lazy">
|
||
@else
|
||
<div class="flex-shrink-0 w-10 h-10 rounded-lg flex items-center justify-center
|
||
{{ match($file->iconType()) {
|
||
'pdf' => 'bg-red-100 text-red-600',
|
||
'word' => 'bg-blue-100 text-blue-600',
|
||
'excel' => 'bg-green-100 text-green-600',
|
||
default => 'bg-gray-100 text-gray-600',
|
||
} }}">
|
||
@if ($file->iconType() === 'pdf')
|
||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8l-6-6zm-1 2l5 5h-5V4z"/></svg>
|
||
@elseif ($file->iconType() === 'word')
|
||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8l-6-6zm-1 2l5 5h-5V4zM9 13h6v1H9v-1zm0 2h6v1H9v-1zm0 2h4v1H9v-1z"/></svg>
|
||
@elseif ($file->iconType() === 'excel')
|
||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8l-6-6zm-1 2l5 5h-5V4zM9 13h2v2H9v-2zm0 3h2v2H9v-2zm3-3h2v2h-2v-2zm0 3h2v2h-2v-2z"/></svg>
|
||
@else
|
||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8l-6-6zm-1 2l5 5h-5V4z"/></svg>
|
||
@endif
|
||
</div>
|
||
@endif
|
||
|
||
<div class="min-w-0">
|
||
<p class="text-sm font-medium text-gray-900 truncate">{{ $file->original_name }}</p>
|
||
<div class="flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-gray-500 mt-0.5">
|
||
<span class="inline-flex items-center px-1.5 py-0.5 rounded bg-gray-100 text-gray-600 font-medium">{{ $file->category->name }}</span>
|
||
<span>{{ $file->humanSize() }}</span>
|
||
<span class="hidden sm:inline">{{ $file->uploader->name ?? '–' }}</span>
|
||
<span class="hidden sm:inline">{{ $file->created_at->translatedFormat(__('ui.date_format_short')) }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Admin Actions --}}
|
||
<div class="flex items-center gap-2 flex-shrink-0">
|
||
<a href="{{ route('files.download', $file) }}" class="text-xs text-blue-600 hover:text-blue-800 font-medium">{{ __('ui.download') }}</a>
|
||
<form method="POST" action="{{ route('admin.files.destroy', $file) }}" class="inline" onsubmit="return confirm(@js(__('admin.confirm_delete_file')))">
|
||
@csrf
|
||
@method('DELETE')
|
||
<button type="submit" class="text-xs text-red-600 hover:text-red-800">{{ __('ui.delete') }}</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
@endforeach
|
||
</div>
|
||
|
||
<div class="mt-4">{{ $files->links() }}</div>
|
||
@endif
|
||
|
||
<x-file-preview-modal />
|
||
</x-layouts.admin>
|