- PlayerPosition Enum (7 Handball-Positionen) mit Label/ShortLabel - Spielerstatistik pro Spiel (Tore, Würfe, TW-Paraden, Bemerkung) - Position-Dropdown in Spieler-Editor und Event-Stats-Formular - Statistik-Seite: TW zuerst, Trennlinie, Feldspieler, Position-Badges - Spielfeld-SVG mit Ampel-Performance (grün/gelb/rot) - Anklickbare Spieler im Spielfeld öffnen Detail-Modal - Fahrgemeinschaften (Anbieten, Zuordnen, Zurückziehen) - Übersetzungen in allen 6 Sprachen (de, en, pl, ru, ar, tr) - .gitignore für Laravel hinzugefügt - Demo-Daten mit Positionen und Statistiken Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
203 lines
12 KiB
PHP
Executable File
203 lines
12 KiB
PHP
Executable File
<x-layouts.admin :title="__('admin.players_title')">
|
|
<h1 class="text-2xl font-bold mb-6">{{ __('admin.players_title') }}: {{ $player->full_name }}</h1>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
{{-- Spieler-Daten --}}
|
|
<div class="bg-white rounded-lg shadow p-6">
|
|
<h2 class="font-semibold mb-4">{{ __('admin.player_data') }}</h2>
|
|
<form method="POST" action="{{ route('admin.players.update', $player) }}" enctype="multipart/form-data">
|
|
@csrf
|
|
@method('PUT')
|
|
|
|
{{-- Profilbild --}}
|
|
<div class="mb-5" x-data="{ preview: null }">
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">{{ __('admin.profile_picture') }}</label>
|
|
<div class="flex items-center gap-4">
|
|
<div class="relative">
|
|
@if ($player->getAvatarUrl())
|
|
<img src="{{ $player->getAvatarUrl() }}" alt="{{ $player->full_name }}" class="w-14 h-14 rounded-full object-cover border-2 border-gray-200" x-show="!preview">
|
|
@else
|
|
<div class="w-14 h-14 rounded-full bg-gray-100 flex items-center justify-center text-gray-500 font-semibold border-2 border-gray-200" x-show="!preview">
|
|
{{ $player->getInitials() }}
|
|
</div>
|
|
@endif
|
|
<img :src="preview" x-show="preview" class="w-14 h-14 rounded-full object-cover border-2 border-blue-400" x-cloak>
|
|
</div>
|
|
<div class="flex flex-col gap-1">
|
|
<label class="cursor-pointer bg-gray-100 text-gray-700 px-3 py-1.5 rounded-md text-xs hover:bg-gray-200 inline-block">
|
|
{{ __('admin.upload_picture') }}
|
|
<input type="file" name="profile_picture" accept="image/jpeg,image/png,image/gif,image/webp" class="hidden"
|
|
@change="if ($event.target.files[0]) { preview = URL.createObjectURL($event.target.files[0]) }">
|
|
</label>
|
|
<span class="text-xs text-gray-400">{{ __('admin.max_picture_size') }}</span>
|
|
@error('profile_picture')
|
|
<p class="text-red-600 text-xs">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-4 mb-4">
|
|
<div>
|
|
<label for="first_name" class="block text-sm font-medium text-gray-700 mb-1">{{ __('admin.first_name') }} *</label>
|
|
<input type="text" name="first_name" id="first_name" value="{{ old('first_name', $player->first_name) }}" required
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md @error('first_name') border-red-500 @enderror">
|
|
@error('first_name')<p class="mt-1 text-sm text-red-600">{{ $message }}</p>@enderror
|
|
</div>
|
|
<div>
|
|
<label for="last_name" class="block text-sm font-medium text-gray-700 mb-1">{{ __('admin.last_name') }} *</label>
|
|
<input type="text" name="last_name" id="last_name" value="{{ old('last_name', $player->last_name) }}" required
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md @error('last_name') border-red-500 @enderror">
|
|
@error('last_name')<p class="mt-1 text-sm text-red-600">{{ $message }}</p>@enderror
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label for="team_id" class="block text-sm font-medium text-gray-700 mb-1">Team *</label>
|
|
<select name="team_id" id="team_id" required class="w-full px-3 py-2 border border-gray-300 rounded-md">
|
|
@foreach ($teams as $team)
|
|
<option value="{{ $team->id }}" {{ old('team_id', $player->team_id) == $team->id ? 'selected' : '' }}>{{ $team->name }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-4 mb-4">
|
|
<div>
|
|
<label for="birth_year" class="block text-sm font-medium text-gray-700 mb-1">{{ __('admin.birth_year') }}</label>
|
|
<input type="number" name="birth_year" id="birth_year" value="{{ old('birth_year', $player->birth_year) }}" min="2000" max="2030"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md">
|
|
</div>
|
|
<div>
|
|
<label for="jersey_number" class="block text-sm font-medium text-gray-700 mb-1">{{ __('admin.jersey_number') }}</label>
|
|
<input type="number" name="jersey_number" id="jersey_number" value="{{ old('jersey_number', $player->jersey_number) }}" min="1" max="99"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label for="position" class="block text-sm font-medium text-gray-700 mb-1">{{ __('admin.position') }}</label>
|
|
<select name="position" id="position" class="w-full px-3 py-2 border border-gray-300 rounded-md">
|
|
<option value="">{{ __('admin.please_select') }}</option>
|
|
@foreach (\App\Enums\PlayerPosition::cases() as $pos)
|
|
<option value="{{ $pos->value }}" {{ old('position', $player->position?->value) === $pos->value ? 'selected' : '' }}>{{ $pos->label() }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label class="flex items-center">
|
|
<input type="hidden" name="photo_permission" value="0">
|
|
<input type="checkbox" name="photo_permission" value="1" {{ old('photo_permission', $player->photo_permission) ? 'checked' : '' }} class="rounded border-gray-300 mr-2">
|
|
<span class="text-sm text-gray-700">{{ __('admin.photo_permission') }}</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label for="notes" class="block text-sm font-medium text-gray-700 mb-1">{{ __('admin.notes') }}</label>
|
|
<textarea name="notes" id="notes" rows="2" class="w-full px-3 py-2 border border-gray-300 rounded-md">{{ old('notes', $player->notes) }}</textarea>
|
|
</div>
|
|
|
|
<button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 text-sm font-medium">{{ __('ui.save') }}</button>
|
|
</form>
|
|
|
|
@if ($player->getAvatarUrl())
|
|
<div class="mt-3 pt-3 border-t">
|
|
<form method="POST" action="{{ route('admin.players.remove-picture', $player) }}" class="inline" onsubmit="return confirm(@js(__('admin.confirm_delete_file')))">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit" class="text-xs text-red-500 hover:text-red-700">{{ __('admin.remove_picture') }}</button>
|
|
</form>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
{{-- Eltern-Zuordnung --}}
|
|
<div class="bg-white rounded-lg shadow p-6">
|
|
<h2 class="font-semibold mb-4">{{ __('admin.parent_assignment') }}</h2>
|
|
|
|
@if ($player->parents->isNotEmpty())
|
|
<div class="mb-4 space-y-2">
|
|
@foreach ($player->parents as $parent)
|
|
<div class="flex items-center justify-between bg-gray-50 rounded px-3 py-2">
|
|
<div>
|
|
<span class="font-medium text-sm">{{ $parent->name }}</span>
|
|
@if ($parent->pivot->relationship_label)
|
|
<span class="text-xs text-gray-500">({{ $parent->pivot->relationship_label }})</span>
|
|
@endif
|
|
<span class="text-xs text-gray-400 block">{{ $parent->email }}</span>
|
|
</div>
|
|
<form method="POST" action="{{ route('admin.players.remove-parent', [$player, $parent]) }}" onsubmit="return confirm(@js(__('admin.confirm_remove_parent')))">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit" class="text-red-500 hover:text-red-700 text-xs">{{ __('admin.remove') }}</button>
|
|
</form>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@else
|
|
<p class="text-sm text-gray-500 mb-4">{{ __('admin.no_parents_yet') }}</p>
|
|
@endif
|
|
|
|
<form method="POST" action="{{ route('admin.players.assign-parent', $player) }}" class="border-t pt-4">
|
|
@csrf
|
|
<div class="mb-3">
|
|
<label for="parent_id" class="block text-sm font-medium text-gray-700 mb-1">{{ __('admin.add_parent') }}</label>
|
|
<select name="parent_id" id="parent_id" required class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm">
|
|
<option value="">{{ __('admin.select_user') }}</option>
|
|
@foreach ($users as $user)
|
|
<option value="{{ $user->id }}">{{ $user->name }} ({{ $user->email }})</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="relationship_label" class="block text-sm font-medium text-gray-700 mb-1">{{ __('admin.relationship_label') }}</label>
|
|
<input type="text" name="relationship_label" id="relationship_label" placeholder="{{ __('admin.relationship_placeholder') }}"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm">
|
|
</div>
|
|
<button type="submit" class="bg-gray-800 text-white px-3 py-1.5 rounded-md hover:bg-gray-900 text-sm">{{ __('admin.assign') }}</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Spieler deaktivieren / löschen --}}
|
|
<div class="mt-6 bg-white rounded-lg shadow p-6 border border-red-200">
|
|
<h2 class="font-semibold text-red-700 mb-2">{{ __('admin.danger_zone') }}</h2>
|
|
|
|
{{-- Deaktivieren / Aktivieren --}}
|
|
<div class="flex items-center justify-between py-3">
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900">{{ __('admin.player_status_label') }}</p>
|
|
<p class="text-xs text-gray-500">
|
|
{{ $player->is_active ? __('admin.deactivate_player_hint') : __('admin.activate_player_hint') }}
|
|
</p>
|
|
</div>
|
|
<form method="POST" action="{{ route('admin.players.toggle-active', $player) }}">
|
|
@csrf
|
|
@method('PUT')
|
|
<button type="submit" class="px-4 py-2 rounded-md text-sm font-medium {{ $player->is_active ? 'bg-yellow-500 text-white hover:bg-yellow-600' : 'bg-green-600 text-white hover:bg-green-700' }}">
|
|
{{ $player->is_active ? __('admin.deactivate') : __('admin.activate') }}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
{{-- Löschen --}}
|
|
<div class="flex items-center justify-between py-3 border-t border-red-100">
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900">{{ __('admin.delete_player') }}</p>
|
|
<p class="text-xs text-gray-500">{{ __('admin.delete_player_hint') }}</p>
|
|
</div>
|
|
<form method="POST" action="{{ route('admin.players.destroy', $player) }}" onsubmit="return confirm(@js(__('admin.confirm_delete_player')))">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit" class="bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700 text-sm font-medium">
|
|
{{ __('admin.delete') }}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<a href="{{ route('admin.players.index') }}" class="text-sm text-gray-600 hover:underline">{{ __('admin.back_to_list') }}</a>
|
|
</div>
|
|
</x-layouts.admin>
|