presseportale/resources/views/livewire/admin/roles/create.blade.php
Kevin Adametz 036a53499f Responsive-Härtung: Seiten-Header, Kontextleiste, Stat-Cards
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 14:08:08 +00:00

154 lines
5.6 KiB
PHP

<?php
use App\Services\Admin\AdminPerformanceCache;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Volt\Component;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
new #[Layout('components.layouts.app'), Title('Neue Rolle')] class extends Component
{
public string $name = '';
public array $permissions = [];
public string $guardName = 'web';
public function save(): void
{
$validated = $this->validate([
'name' => [
'required',
'min:3',
'max:50',
Rule::unique('roles', 'name')
->where(fn (Builder $query) => $query->where('guard_name', $this->guardName)),
],
'permissions' => ['array'],
'permissions.*' => [
'string',
Rule::exists('permissions', 'name')
->where(fn (Builder $query) => $query->where('guard_name', $this->guardName)),
],
]);
$role = Role::query()->create([
'name' => $validated['name'],
'guard_name' => $this->guardName,
]);
$role->syncPermissions($validated['permissions'] ?? []);
session()->flash('success', 'Rolle erfolgreich erstellt.');
$this->redirect(route('admin.roles.index'), navigate: true);
}
public function with(): array
{
return [
'permissionGroups' => $this->permissionGroups(),
];
}
private function permissionGroups(): Collection
{
$cache = app(AdminPerformanceCache::class);
return $cache->remember($cache->permissionGroupsKey($this->guardName), AdminPerformanceCache::OptionsTtl, fn () => Permission::query()
->where('guard_name', $this->guardName)
->orderBy('name')
->get(['name'])
->groupBy(function (Permission $permission): string {
$prefix = Str::contains($permission->name, ':')
? Str::before($permission->name, ':')
: $permission->name;
return Str::headline(str_replace(['-', '_'], ' ', $prefix));
})
->map(fn ($group) => $group->values())
->sortKeys());
}
}; ?>
<form wire:submit="save" class="space-y-8">
{{-- ============== PAGE HEADER ============== --}}
<header class="page-header">
<div class="min-w-0">
<div class="flex items-center gap-3 mb-3 flex-wrap">
<span class="badge hub dot">{{ __('Admin Backend') }}</span>
<span class="eyebrow muted">{{ __('Administration · Sicherheit · Rollen') }}</span>
<span class="badge hub">{{ __('Guard') }}: {{ $guardName }}</span>
</div>
<h1 class="text-[30px] font-bold tracking-[-0.6px] leading-[1.15] m-0 text-[color:var(--color-ink)]">
{{ __('Neue Rolle') }}
</h1>
</div>
<div class="flex items-center gap-2 flex-shrink-0">
<flux:button variant="filled" icon="arrow-left" href="{{ route('admin.roles.index') }}" wire:navigate>
{{ __('Zurück') }}
</flux:button>
</div>
</header>
<article class="panel">
<div class="panel-head">
<span class="section-eyebrow">{{ __('Basis-Informationen') }}</span>
</div>
<div class="p-5">
<flux:field>
<flux:label>
{{ __('Technischer Name') }}
<span class="text-[color:var(--color-err)]">*</span>
</flux:label>
<flux:input wire:model="name" placeholder="{{ __('z.B. editor') }}" />
<flux:description>{{ __('Kleinbuchstaben, keine Leerzeichen. Wird intern verwendet.') }}</flux:description>
<flux:error name="name" />
</flux:field>
</div>
</article>
<article class="panel">
<div class="panel-head">
<span class="section-eyebrow">{{ __('Berechtigungen') }}</span>
</div>
<div class="p-5 space-y-6">
@forelse ($permissionGroups as $groupName => $permissionsInGroup)
<div>
<div class="text-[11px] uppercase tracking-[0.6px] text-[color:var(--color-ink-3)] font-semibold mb-3">
{{ $groupName }}
</div>
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
@foreach ($permissionsInGroup as $permission)
<flux:checkbox
wire:model="permissions"
value="{{ $permission['name'] }}"
label="{{ $permission['name'] }}"
/>
@endforeach
</div>
</div>
@empty
<p class="text-[12.5px] text-[color:var(--color-ink-3)] m-0">{{ __('Keine Berechtigungen fuer diesen Guard vorhanden.') }}</p>
@endforelse
<flux:error name="permissions" />
</div>
</article>
<article class="panel">
<div class="p-5 flex justify-end gap-3">
<flux:button variant="filled" href="{{ route('admin.roles.index') }}" wire:navigate>
{{ __('Abbrechen') }}
</flux:button>
<flux:button type="submit" variant="primary">
{{ __('Rolle erstellen') }}
</flux:button>
</div>
</article>
</form>