Files
construprogress/resources/views/livewire/role-permission-manager.blade.php
T
javier 0120c4bfb8 feat(roles/users): add-user form on role view + per-user direct permissions form
1. Role view (Details tab): a small form to add users to the role (select of
   users not yet in the role + Add) and a per-row remove button. Uses
   assignRole/removeRole.
2. User view (Permissions tab): the same grouped, collapsible permissions form
   with switches — operating on the user's DIRECT permissions
   (givePermissionTo/revokePermissionTo). Permissions inherited from a role show
   as checked+disabled with a 'from role' tag; per-group All/None too.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 18:51:59 +02:00

88 lines
4.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div class="py-8 max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="mb-6">
<h2 class="text-2xl font-bold text-gray-800">{{ __('Permission management') }}</h2>
<p class="text-sm text-gray-500 mt-1">{{ __('Tick which permissions each role has. Changes are saved instantly.') }}</p>
</div>
{{-- Crear rol / permiso --}}
<div class="flex flex-wrap items-start gap-6 mb-6">
<form wire:submit.prevent="addRole" class="flex flex-col gap-1">
<div class="flex gap-2">
<input wire:model="newRole" class="input input-bordered input-sm w-48" placeholder="{{ __('New role') }}" />
<button class="btn btn-sm btn-primary gap-1">
<x-heroicon-o-plus class="w-4 h-4" /> {{ __('Role') }}
</button>
</div>
@error('newRole') <span class="text-error text-xs">{{ $message }}</span> @enderror
</form>
<form wire:submit.prevent="addPermission" class="flex flex-col gap-1">
<div class="flex gap-2">
<input wire:model="newPermission" class="input input-bordered input-sm w-48" placeholder="{{ __('New permission') }}" />
<button class="btn btn-sm btn-outline gap-1">
<x-heroicon-o-plus class="w-4 h-4" /> {{ __('Permission') }}
</button>
</div>
@error('newPermission') <span class="text-error text-xs">{{ $message }}</span> @enderror
</form>
</div>
{{-- Matriz Roles × Permisos --}}
<div class="overflow-x-auto border border-base-300 rounded-lg bg-white">
<table class="table table-sm">
<thead>
<tr>
<th class="bg-base-200">{{ __('Permission') }}</th>
@foreach($roles as $role)
<th class="bg-base-200 text-center align-bottom">
<div class="flex flex-col items-center gap-1">
<span class="font-semibold">{{ $role->name }}</span>
@unless(in_array($role->name, ['Admin'], true))
<button wire:click="deleteRole({{ $role->id }})"
wire:confirm="{{ __('Delete role') }} '{{ $role->name }}'?"
class="btn btn-ghost btn-xs text-error" title="{{ __('Delete role') }}">
<x-heroicon-o-trash class="w-3.5 h-3.5" />
</button>
@endunless
</div>
</th>
@endforeach
</tr>
</thead>
<tbody>
@forelse($permissions as $perm)
<tr wire:key="perm-row-{{ $perm->id }}" class="hover">
<td class="font-medium whitespace-nowrap">
<div class="flex items-center gap-2">
<span>{{ $perm->name }}</span>
@if($perm->name !== 'manage all')
<button wire:click="deletePermission({{ $perm->id }})"
wire:confirm="{{ __('Delete permission') }} '{{ $perm->name }}'?"
class="btn btn-ghost btn-xs text-error opacity-40 hover:opacity-100" title="{{ __('Delete permission') }}">
<x-heroicon-o-trash class="w-3.5 h-3.5" />
</button>
@endif
</div>
</td>
@foreach($roles as $role)
<td class="text-center" wire:key="cell-{{ $perm->id }}-{{ $role->id }}">
<input type="checkbox"
class="toggle toggle-sm toggle-primary"
@checked($role->permissions->contains('id', $perm->id))
wire:click="togglePermission({{ $role->id }}, '{{ $perm->name }}')" />
</td>
@endforeach
</tr>
@empty
<tr><td colspan="{{ $roles->count() + 1 }}" class="text-center text-gray-400 py-6">{{ __('No permissions') }}</td></tr>
@endforelse
</tbody>
</table>
</div>
<p class="text-xs text-gray-400 mt-3">
{{ __('The Admin role and the "manage all" permission are protected and cannot be removed.') }}
</p>
</div>