OMNI Access v1.3.0 Free ~20 min read

CRUD Example: Roles Management

Copy-paste ready Roles CRUD: controller with cache-aware filtering, Bootstrap 5 Blade views, routes, and JavaScript helpers.

A Administrator Oct 25, 2026 8 Steps 2,709 views
Discussion (0)
Step 1 of 8

Controller: app/Http/Controllers/Admin/RoleController.php

<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use RbacSuite\OmniAccess\Models\Role;
use RbacSuite\OmniAccess\Models\Permission;
use RbacSuite\OmniAccess\Models\Group;
use RbacSuite\OmniAccess\Services\CacheService;

class RoleController extends Controller
{
    protected $cacheService;

    public function __construct(CacheService $cacheService)
    {
        $this->cacheService = $cacheService;

        // Apply middleware
        $this->middleware('auth');
        $this->middleware('permission:roles.view')->only(['index', 'show']);
        $this->middleware('permission:roles.create')->only(['create', 'store']);
        $this->middleware('permission:roles.edit')->only(['edit', 'update']);
        $this->middleware('permission:roles.delete')->only('destroy');
    }

    /**
     * Display a listing of roles
     */
    public function index(Request $request)
    {
        $query = Role::withCount(['users', 'permissions']);

        // Search functionality
        if ($request->filled('search')) {
            $search = $request->get('search');
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('slug', 'like', "%{$search}%")
                  ->orWhere('description', 'like', "%{$search}%");
            });
        }

        // Sort functionality
        $sortField = $request->get('sort', 'name');
        $sortDirection = $request->get('direction', 'asc');

        if (in_array($sortField, ['name', 'slug', 'created_at', 'users_count', 'permissions_count'])) {
            $query->orderBy($sortField, $sortDirection);
        }

        $roles = $query->paginate(10)->withQueryString();

        return view('admin.roles.index', compact('roles'));
    }

    /**
     * Show the form for creating a new role
     */
    public function create()
    {
        $permissions = Permission::with('group')
            ->get()
            ->groupBy('group.name');

        return view('admin.roles.create', compact('permissions'));
    }

    /**
     * Store a newly created role
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:50',
            'slug' => 'required|string|max:50|unique:roles,slug|regex:/^[a-z0-9\-]+$/',
            'description' => 'nullable|string|max:255',
            'is_default' => 'boolean',
            'permissions' => 'nullable|array',
            'permissions.*' => 'exists:permissions,id'
        ]);

        // Create role
        $role = Role::create([
            'name' => $validated['name'],
            'slug' => $validated['slug'],
            'description' => $validated['description'],
            'is_default' => $request->boolean('is_default')
        ]);

        // Assign permissions
        if (!empty($validated['permissions'])) {
            $role->permissions()->sync($validated['permissions']);
        }

        // Clear cache
        $this->cacheService->forgetRole($role->id);

        return redirect()
            ->route('admin.roles.index')
            ->with('success', 'Role created successfully!');
    }

    /**
     * Display the specified role
     */
    public function show(Role $role)
    {
        $role->load(['permissions.group', 'users']);

        $groupedPermissions = $role->permissions
            ->groupBy('group.name');

        $recentUsers = $role->users()
            ->latest('role_user.created_at')
            ->limit(5)
            ->get();

        return view('admin.roles.show', compact('role', 'groupedPermissions', 'recentUsers'));
    }

    /**
     * Show the form for editing the specified role
     */
    public function edit(Role $role)
    {
        // Prevent editing super-admin role
        if ($role->slug === config('omni-access.super_admin_role')) {
            return redirect()
                ->route('admin.roles.index')
                ->with('error', 'Cannot edit super admin role!');
        }

        $permissions = Permission::with('group')
            ->get()
            ->groupBy('group.name');

        $rolePermissions = $role->permissions->pluck('id')->toArray();

        return view('admin.roles.edit', compact('role', 'permissions', 'rolePermissions'));
    }

    /**
     * Update the specified role
     */
    public function update(Request $request, Role $role)
    {
        // Prevent editing super-admin role
        if ($role->slug === config('omni-access.super_admin_role')) {
            return redirect()
                ->route('admin.roles.index')
                ->with('error', 'Cannot edit super admin role!');
        }

        $validated = $request->validate([
            'name' => 'required|string|max:50',
            'slug' => 'required|string|max:50|unique:roles,slug,' . $role->id . '|regex:/^[a-z0-9\-]+$/',
            'description' => 'nullable|string|max:255',
            'is_default' => 'boolean',
            'permissions' => 'nullable|array',
            'permissions.*' => 'exists:permissions,id'
        ]);

        // Update role
        $role->update([
            'name' => $validated['name'],
            'slug' => $validated['slug'],
            'description' => $validated['description'],
            'is_default' => $request->boolean('is_default')
        ]);

        // Sync permissions
        $role->permissions()->sync($validated['permissions'] ?? []);

        // Clear cache
        $this->cacheService->forgetRole($role->id);

        return redirect()
            ->route('admin.roles.show', $role)
            ->with('success', 'Role updated successfully!');
    }

    /**
     * Remove the specified role
     */
    public function destroy(Role $role)
    {
        // Prevent deleting super-admin role
        if ($role->slug === config('omni-access.super_admin_role')) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete super admin role!'
            ], 403);
        }

        // Prevent deleting default role
        if ($role->is_default) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete default role!'
            ], 403);
        }

        // Check if role has users
        if ($role->users()->count() > 0) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete role with assigned users!'
            ], 403);
        }

        $role->delete();

        // Clear cache
        $this->cacheService->forgetRole($role->id);

        if (request()->wantsJson()) {
            return response()->json([
                'success' => true,
                'message' => 'Role deleted successfully!'
            ]);
        }

        return redirect()
            ->route('admin.roles.index')
            ->with('success', 'Role deleted successfully!');
    }

    /**
     * Clone a role
     */
    public function clone(Role $role)
    {
        $newRole = $role->replicate();
        $newRole->name = $role->name . ' (Copy)';
        $newRole->slug = $role->slug . '-copy-' . time();
        $newRole->is_default = false;
        $newRole->save();

        // Clone permissions
        $newRole->permissions()->sync($role->permissions);

        return redirect()
            ->route('admin.roles.edit', $newRole)
            ->with('success', 'Role cloned successfully!');
    }
}
php
<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use RbacSuite\OmniAccess\Models\Role;
use RbacSuite\OmniAccess\Models\Permission;
use RbacSuite\OmniAccess\Models\Group;
use RbacSuite\OmniAccess\Services\CacheService;

class RoleController extends Controller
{
    protected $cacheService;

    public function __construct(CacheService $cacheService)
    {
        $this->cacheService = $cacheService;

        // Apply middleware
        $this->middleware('auth');
        $this->middleware('permission:roles.view')->only(['index', 'show']);
        $this->middleware('permission:roles.create')->only(['create', 'store']);
        $this->middleware('permission:roles.edit')->only(['edit', 'update']);
        $this->middleware('permission:roles.delete')->only('destroy');
    }

    /**
     * Display a listing of roles
     */
    public function index(Request $request)
    {
        $query = Role::withCount(['users', 'permissions']);

        // Search functionality
        if ($request->filled('search')) {
            $search = $request->get('search');
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('slug', 'like', "%{$search}%")
                  ->orWhere('description', 'like', "%{$search}%");
            });
        }

        // Sort functionality
        $sortField = $request->get('sort', 'name');
        $sortDirection = $request->get('direction', 'asc');

        if (in_array($sortField, ['name', 'slug', 'created_at', 'users_count', 'permissions_count'])) {
            $query->orderBy($sortField, $sortDirection);
        }

        $roles = $query->paginate(10)->withQueryString();

        return view('admin.roles.index', compact('roles'));
    }

    /**
     * Show the form for creating a new role
     */
    public function create()
    {
        $permissions = Permission::with('group')
            ->get()
            ->groupBy('group.name');

        return view('admin.roles.create', compact('permissions'));
    }

    /**
     * Store a newly created role
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:50',
            'slug' => 'required|string|max:50|unique:roles,slug|regex:/^[a-z0-9\-]+$/',
            'description' => 'nullable|string|max:255',
            'is_default' => 'boolean',
            'permissions' => 'nullable|array',
            'permissions.*' => 'exists:permissions,id'
        ]);

        // Create role
        $role = Role::create([
            'name' => $validated['name'],
            'slug' => $validated['slug'],
            'description' => $validated['description'],
            'is_default' => $request->boolean('is_default')
        ]);

        // Assign permissions
        if (!empty($validated['permissions'])) {
            $role->permissions()->sync($validated['permissions']);
        }

        // Clear cache
        $this->cacheService->forgetRole($role->id);

        return redirect()
            ->route('admin.roles.index')
            ->with('success', 'Role created successfully!');
    }

    /**
     * Display the specified role
     */
    public function show(Role $role)
    {
        $role->load(['permissions.group', 'users']);

        $groupedPermissions = $role->permissions
            ->groupBy('group.name');

        $recentUsers = $role->users()
            ->latest('role_user.created_at')
            ->limit(5)
            ->get();

        return view('admin.roles.show', compact('role', 'groupedPermissions', 'recentUsers'));
    }

    /**
     * Show the form for editing the specified role
     */
    public function edit(Role $role)
    {
        // Prevent editing super-admin role
        if ($role->slug === config('omni-access.super_admin_role')) {
            return redirect()
                ->route('admin.roles.index')
                ->with('error', 'Cannot edit super admin role!');
        }

        $permissions = Permission::with('group')
            ->get()
            ->groupBy('group.name');

        $rolePermissions = $role->permissions->pluck('id')->toArray();

        return view('admin.roles.edit', compact('role', 'permissions', 'rolePermissions'));
    }

    /**
     * Update the specified role
     */
    public function update(Request $request, Role $role)
    {
        // Prevent editing super-admin role
        if ($role->slug === config('omni-access.super_admin_role')) {
            return redirect()
                ->route('admin.roles.index')
                ->with('error', 'Cannot edit super admin role!');
        }

        $validated = $request->validate([
            'name' => 'required|string|max:50',
            'slug' => 'required|string|max:50|unique:roles,slug,' . $role->id . '|regex:/^[a-z0-9\-]+$/',
            'description' => 'nullable|string|max:255',
            'is_default' => 'boolean',
            'permissions' => 'nullable|array',
            'permissions.*' => 'exists:permissions,id'
        ]);

        // Update role
        $role->update([
            'name' => $validated['name'],
            'slug' => $validated['slug'],
            'description' => $validated['description'],
            'is_default' => $request->boolean('is_default')
        ]);

        // Sync permissions
        $role->permissions()->sync($validated['permissions'] ?? []);

        // Clear cache
        $this->cacheService->forgetRole($role->id);

        return redirect()
            ->route('admin.roles.show', $role)
            ->with('success', 'Role updated successfully!');
    }

    /**
     * Remove the specified role
     */
    public function destroy(Role $role)
    {
        // Prevent deleting super-admin role
        if ($role->slug === config('omni-access.super_admin_role')) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete super admin role!'
            ], 403);
        }

        // Prevent deleting default role
        if ($role->is_default) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete default role!'
            ], 403);
        }

        // Check if role has users
        if ($role->users()->count() > 0) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete role with assigned users!'
            ], 403);
        }

        $role->delete();

        // Clear cache
        $this->cacheService->forgetRole($role->id);

        if (request()->wantsJson()) {
            return response()->json([
                'success' => true,
                'message' => 'Role deleted successfully!'
            ]);
        }

        return redirect()
            ->route('admin.roles.index')
            ->with('success', 'Role deleted successfully!');
    }

    /**
     * Clone a role
     */
    public function clone(Role $role)
    {
        $newRole = $role->replicate();
        $newRole->name = $role->name . ' (Copy)';
        $newRole->slug = $role->slug . '-copy-' . time();
        $newRole->is_default = false;
        $newRole->save();

        // Clone permissions
        $newRole->permissions()->sync($role->permissions);

        return redirect()
            ->route('admin.roles.edit', $newRole)
            ->with('success', 'Role cloned successfully!');
    }
}
Step 2 of 8

View: resources/views/admin/roles/index.blade.php

@extends('layouts.admin')

@section('title', 'Roles Management')

@section('content')
<div class="container-fluid">
    <!-- Page Header -->
    <div class="row mb-4">
        <div class="col-12">
            <div class="page-header d-flex justify-content-between align-items-center">
                <div>
                    <h1 class="h3 mb-0 text-gray-800">Roles Management</h1>
                    <p class="text-muted mb-0">Manage system roles and their permissions</p>
                </div>
                <div>
                    @permission('roles.create')
                        <a href="{{ route('admin.roles.create') }}" class="btn btn-primary">
                            <i class="bi bi-plus-circle me-2"></i>Create New Role
                        </a>
                    @endpermission
                </div>
            </div>
        </div>
    </div>

    <!-- Statistics Cards -->
    <div class="row mb-4">
        <div class="col-xl-3 col-md-6 mb-3">
            <div class="card border-left-primary shadow-sm h-100">
                <div class="card-body">
                    <div class="row no-gutters align-items-center">
                        <div class="col mr-2">
                            <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
                                Total Roles
                            </div>
                            <div class="h5 mb-0 font-weight-bold">{{ \RbacSuite\OmniAccess\Models\Role::count() }}</div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-person-badge fs-2 text-primary"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="col-xl-3 col-md-6 mb-3">
            <div class="card border-left-success shadow-sm h-100">
                <div class="card-body">
                    <div class="row no-gutters align-items-center">
                        <div class="col mr-2">
                            <div class="text-xs font-weight-bold text-success text-uppercase mb-1">
                                Active Users
                            </div>
                            <div class="h5 mb-0 font-weight-bold">{{ \App\Models\User::count() }}</div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-people fs-2 text-success"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="col-xl-3 col-md-6 mb-3">
            <div class="card border-left-info shadow-sm h-100">
                <div class="card-body">
                    <div class="row no-gutters align-items-center">
                        <div class="col mr-2">
                            <div class="text-xs font-weight-bold text-info text-uppercase mb-1">
                                Total Permissions
                            </div>
                            <div class="h5 mb-0 font-weight-bold">{{ \RbacSuite\OmniAccess\Models\Permission::count() }}</div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-key fs-2 text-info"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="col-xl-3 col-md-6 mb-3">
            <div class="card border-left-warning shadow-sm h-100">
                <div class="card-body">
                    <div class="row no-gutters align-items-center">
                        <div class="col mr-2">
                            <div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
                                Default Role
                            </div>
                            <div class="h6 mb-0 font-weight-bold">
                                {{ \RbacSuite\OmniAccess\Models\Role::where('is_default', true)->first()->name ?? 'None' }}
                            </div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-star fs-2 text-warning"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Alerts -->
    @if(session('success'))
        <div class="alert alert-success alert-dismissible fade show" role="alert">
            <i class="bi bi-check-circle me-2"></i>{{ session('success') }}
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
        </div>
    @endif

    @if(session('error'))
        <div class="alert alert-danger alert-dismissible fade show" role="alert">
            <i class="bi bi-exclamation-triangle me-2"></i>{{ session('error') }}
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
        </div>
    @endif

    <!-- Main Card -->
    <div class="card shadow-sm">
        <div class="card-header bg-white py-3">
            <div class="row align-items-center">
                <div class="col-md-6">
                    <form action="{{ route('admin.roles.index') }}" method="GET" class="d-flex">
                        <div class="input-group">
                            <input type="text"
                                   name="search"
                                   class="form-control"
                                   placeholder="Search roles..."
                                   value="{{ request('search') }}">
                            <button class="btn btn-outline-secondary" type="submit">
                                <i class="bi bi-search"></i>
                            </button>
                            @if(request('search'))
                                <a href="{{ route('admin.roles.index') }}" class="btn btn-outline-secondary">
                                    <i class="bi bi-x-lg"></i>
                                </a>
                            @endif
                        </div>
                    </form>
                </div>
                <div class="col-md-6 text-end">
                    <div class="btn-group" role="group">
                        <button type="button" class="btn btn-outline-secondary" onclick="toggleBulkSelect()">
                            <i class="bi bi-check-square me-1"></i>Select
                        </button>
                        <button type="button" class="btn btn-outline-danger d-none" id="bulkDeleteBtn" onclick="bulkDelete()">
                            <i class="bi bi-trash me-1"></i>Delete Selected
                        </button>
                    </div>
                </div>
            </div>
        </div>
        <div class="card-body p-0">
            <div class="table-responsive">
                <table class="table table-hover mb-0">
                    <thead class="table-light">
                        <tr>
                            <th class="bulk-select-column d-none" style="width: 40px;">
                                <input type="checkbox" class="form-check-input" id="selectAll">
                            </th>
                            <th>Name</th>
                            <th>Slug</th>
                            <th>Description</th>
                            <th class="text-center">Users</th>
                            <th class="text-center">Permissions</th>
                            <th class="text-center">Status</th>
                            <th class="text-end">Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        @forelse($roles as $role)
                            <tr>
                                <td class="bulk-select-column d-none">
                                    @if($role->slug !== config('omni-access.super_admin_role') && !$role->is_default && $role->users_count == 0)
                                        <input type="checkbox" class="form-check-input role-checkbox" value="{{ $role->id }}">
                                    @endif
                                </td>
                                <td>
                                    <div class="d-flex align-items-center">
                                        <div class="avatar-sm bg-primary bg-opacity-10 rounded-circle me-2">
                                            <span class="text-primary fw-bold">{{ strtoupper(substr($role->name, 0, 2)) }}</span>
                                        </div>
                                        <div>
                                            <div class="fw-semibold">{{ $role->name }}</div>
                                            @if($role->slug === config('omni-access.super_admin_role'))
                                                <span class="badge bg-danger">Super Admin</span>
                                            @elseif($role->is_default)
                                                <span class="badge bg-info">Default</span>
                                            @endif
                                        </div>
                                    </div>
                                </td>
                                <td>
                                    <code class="text-primary">{{ $role->slug }}</code>
                                </td>
                                <td>
                                    <span class="text-muted">{{ $role->description ?: '-' }}</span>
                                </td>
                                <td class="text-center">
                                    <span class="badge bg-success">{{ $role->users_count }}</span>
                                </td>
                                <td class="text-center">
                                    <span class="badge bg-primary">{{ $role->permissions_count }}</span>
                                </td>
                                <td class="text-center">
                                    @if($role->deleted_at)
                                        <span class="badge bg-danger">Deleted</span>
                                    @else
                                        <span class="badge bg-success">Active</span>
                                    @endif
                                </td>
                                <td class="text-end">
                                    <div class="btn-group" role="group">
                                        <a href="{{ route('admin.roles.show', $role) }}"
                                           class="btn btn-sm btn-outline-info"
                                           title="View">
                                            <i class="bi bi-eye"></i>
                                        </a>
                                        @permission('roles.edit')
                                            @if($role->slug !== config('omni-access.super_admin_role'))
                                                <a href="{{ route('admin.roles.edit', $role) }}"
                                                   class="btn btn-sm btn-outline-primary"
                                                   title="Edit">
                                                    <i class="bi bi-pencil"></i>
                                                </a>
                                            @endif
                                        @endpermission
                                        @permission('roles.create')
                                            <button type="button"
                                                    class="btn btn-sm btn-outline-secondary"
                                                    onclick="cloneRole({{ $role->id }})"
                                                    title="Clone">
                                                <i class="bi bi-files"></i>
                                            </button>
                                        @endpermission
                                        @permission('roles.delete')
                                            @if($role->slug !== config('omni-access.super_admin_role') && !$role->is_default && $role->users_count == 0)
                                                <button type="button"
                                                        class="btn btn-sm btn-outline-danger"
                                                        onclick="deleteRole({{ $role->id }}, '{{ $role->name }}')"
                                                        title="Delete">
                                                    <i class="bi bi-trash"></i>
                                                </button>
                                            @endif
                                        @endpermission
                                    </div>
                                </td>
                            </tr>
                        @empty
                            <tr>
                                <td colspan="8" class="text-center py-4">
                                    <div class="text-muted">
                                        <i class="bi bi-inbox fs-1"></i>
                                        <p class="mt-2">No roles found</p>
                                    </div>
                                </td>
                            </tr>
                        @endforelse
                    </tbody>
                </table>
            </div>
        </div>
        @if($roles->hasPages())
            <div class="card-footer bg-white">
                <div class="d-flex justify-content-between align-items-center">
                    <div class="text-muted">
                        Showing {{ $roles->firstItem() }} to {{ $roles->lastItem() }} of {{ $roles->total() }} results
                    </div>
                    <div>
                        {{ $roles->links('pagination::bootstrap-5') }}
                    </div>
                </div>
            </div>
        @endif
    </div>
</div>
@endsection
blade
@extends('layouts.admin')

@section('title', 'Roles Management')

@section('content')
<div class="container-fluid">
    <!-- Page Header -->
    <div class="row mb-4">
        <div class="col-12">
            <div class="page-header d-flex justify-content-between align-items-center">
                <div>
                    <h1 class="h3 mb-0 text-gray-800">Roles Management</h1>
                    <p class="text-muted mb-0">Manage system roles and their permissions</p>
                </div>
                <div>
                    @permission('roles.create')
                        <a href="{{ route('admin.roles.create') }}" class="btn btn-primary">
                            <i class="bi bi-plus-circle me-2"></i>Create New Role
                        </a>
                    @endpermission
                </div>
            </div>
        </div>
    </div>

    <!-- Statistics Cards -->
    <div class="row mb-4">
        <div class="col-xl-3 col-md-6 mb-3">
            <div class="card border-left-primary shadow-sm h-100">
                <div class="card-body">
                    <div class="row no-gutters align-items-center">
                        <div class="col mr-2">
                            <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
                                Total Roles
                            </div>
                            <div class="h5 mb-0 font-weight-bold">{{ \RbacSuite\OmniAccess\Models\Role::count() }}</div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-person-badge fs-2 text-primary"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="col-xl-3 col-md-6 mb-3">
            <div class="card border-left-success shadow-sm h-100">
                <div class="card-body">
                    <div class="row no-gutters align-items-center">
                        <div class="col mr-2">
                            <div class="text-xs font-weight-bold text-success text-uppercase mb-1">
                                Active Users
                            </div>
                            <div class="h5 mb-0 font-weight-bold">{{ \App\Models\User::count() }}</div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-people fs-2 text-success"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="col-xl-3 col-md-6 mb-3">
            <div class="card border-left-info shadow-sm h-100">
                <div class="card-body">
                    <div class="row no-gutters align-items-center">
                        <div class="col mr-2">
                            <div class="text-xs font-weight-bold text-info text-uppercase mb-1">
                                Total Permissions
                            </div>
                            <div class="h5 mb-0 font-weight-bold">{{ \RbacSuite\OmniAccess\Models\Permission::count() }}</div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-key fs-2 text-info"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="col-xl-3 col-md-6 mb-3">
            <div class="card border-left-warning shadow-sm h-100">
                <div class="card-body">
                    <div class="row no-gutters align-items-center">
                        <div class="col mr-2">
                            <div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
                                Default Role
                            </div>
                            <div class="h6 mb-0 font-weight-bold">
                                {{ \RbacSuite\OmniAccess\Models\Role::where('is_default', true)->first()->name ?? 'None' }}
                            </div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-star fs-2 text-warning"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Alerts -->
    @if(session('success'))
        <div class="alert alert-success alert-dismissible fade show" role="alert">
            <i class="bi bi-check-circle me-2"></i>{{ session('success') }}
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
        </div>
    @endif

    @if(session('error'))
        <div class="alert alert-danger alert-dismissible fade show" role="alert">
            <i class="bi bi-exclamation-triangle me-2"></i>{{ session('error') }}
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
        </div>
    @endif

    <!-- Main Card -->
    <div class="card shadow-sm">
        <div class="card-header bg-white py-3">
            <div class="row align-items-center">
                <div class="col-md-6">
                    <form action="{{ route('admin.roles.index') }}" method="GET" class="d-flex">
                        <div class="input-group">
                            <input type="text"
                                   name="search"
                                   class="form-control"
                                   placeholder="Search roles..."
                                   value="{{ request('search') }}">
                            <button class="btn btn-outline-secondary" type="submit">
                                <i class="bi bi-search"></i>
                            </button>
                            @if(request('search'))
                                <a href="{{ route('admin.roles.index') }}" class="btn btn-outline-secondary">
                                    <i class="bi bi-x-lg"></i>
                                </a>
                            @endif
                        </div>
                    </form>
                </div>
                <div class="col-md-6 text-end">
                    <div class="btn-group" role="group">
                        <button type="button" class="btn btn-outline-secondary" onclick="toggleBulkSelect()">
                            <i class="bi bi-check-square me-1"></i>Select
                        </button>
                        <button type="button" class="btn btn-outline-danger d-none" id="bulkDeleteBtn" onclick="bulkDelete()">
                            <i class="bi bi-trash me-1"></i>Delete Selected
                        </button>
                    </div>
                </div>
            </div>
        </div>
        <div class="card-body p-0">
            <div class="table-responsive">
                <table class="table table-hover mb-0">
                    <thead class="table-light">
                        <tr>
                            <th class="bulk-select-column d-none" style="width: 40px;">
                                <input type="checkbox" class="form-check-input" id="selectAll">
                            </th>
                            <th>Name</th>
                            <th>Slug</th>
                            <th>Description</th>
                            <th class="text-center">Users</th>
                            <th class="text-center">Permissions</th>
                            <th class="text-center">Status</th>
                            <th class="text-end">Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        @forelse($roles as $role)
                            <tr>
                                <td class="bulk-select-column d-none">
                                    @if($role->slug !== config('omni-access.super_admin_role') && !$role->is_default && $role->users_count == 0)
                                        <input type="checkbox" class="form-check-input role-checkbox" value="{{ $role->id }}">
                                    @endif
                                </td>
                                <td>
                                    <div class="d-flex align-items-center">
                                        <div class="avatar-sm bg-primary bg-opacity-10 rounded-circle me-2">
                                            <span class="text-primary fw-bold">{{ strtoupper(substr($role->name, 0, 2)) }}</span>
                                        </div>
                                        <div>
                                            <div class="fw-semibold">{{ $role->name }}</div>
                                            @if($role->slug === config('omni-access.super_admin_role'))
                                                <span class="badge bg-danger">Super Admin</span>
                                            @elseif($role->is_default)
                                                <span class="badge bg-info">Default</span>
                                            @endif
                                        </div>
                                    </div>
                                </td>
                                <td>
                                    <code class="text-primary">{{ $role->slug }}</code>
                                </td>
                                <td>
                                    <span class="text-muted">{{ $role->description ?: '-' }}</span>
                                </td>
                                <td class="text-center">
                                    <span class="badge bg-success">{{ $role->users_count }}</span>
                                </td>
                                <td class="text-center">
                                    <span class="badge bg-primary">{{ $role->permissions_count }}</span>
                                </td>
                                <td class="text-center">
                                    @if($role->deleted_at)
                                        <span class="badge bg-danger">Deleted</span>
                                    @else
                                        <span class="badge bg-success">Active</span>
                                    @endif
                                </td>
                                <td class="text-end">
                                    <div class="btn-group" role="group">
                                        <a href="{{ route('admin.roles.show', $role) }}"
                                           class="btn btn-sm btn-outline-info"
                                           title="View">
                                            <i class="bi bi-eye"></i>
                                        </a>
                                        @permission('roles.edit')
                                            @if($role->slug !== config('omni-access.super_admin_role'))
                                                <a href="{{ route('admin.roles.edit', $role) }}"
                                                   class="btn btn-sm btn-outline-primary"
                                                   title="Edit">
                                                    <i class="bi bi-pencil"></i>
                                                </a>
                                            @endif
                                        @endpermission
                                        @permission('roles.create')
                                            <button type="button"
                                                    class="btn btn-sm btn-outline-secondary"
                                                    onclick="cloneRole({{ $role->id }})"
                                                    title="Clone">
                                                <i class="bi bi-files"></i>
                                            </button>
                                        @endpermission
                                        @permission('roles.delete')
                                            @if($role->slug !== config('omni-access.super_admin_role') && !$role->is_default && $role->users_count == 0)
                                                <button type="button"
                                                        class="btn btn-sm btn-outline-danger"
                                                        onclick="deleteRole({{ $role->id }}, '{{ $role->name }}')"
                                                        title="Delete">
                                                    <i class="bi bi-trash"></i>
                                                </button>
                                            @endif
                                        @endpermission
                                    </div>
                                </td>
                            </tr>
                        @empty
                            <tr>
                                <td colspan="8" class="text-center py-4">
                                    <div class="text-muted">
                                        <i class="bi bi-inbox fs-1"></i>
                                        <p class="mt-2">No roles found</p>
                                    </div>
                                </td>
                            </tr>
                        @endforelse
                    </tbody>
                </table>
            </div>
        </div>
        @if($roles->hasPages())
            <div class="card-footer bg-white">
                <div class="d-flex justify-content-between align-items-center">
                    <div class="text-muted">
                        Showing {{ $roles->firstItem() }} to {{ $roles->lastItem() }} of {{ $roles->total() }} results
                    </div>
                    <div>
                        {{ $roles->links('pagination::bootstrap-5') }}
                    </div>
                </div>
            </div>
        @endif
    </div>
</div>
@endsection
Step 3 of 8

View: resources/views/admin/roles/create.blade.php

@extends('layouts.admin')

@section('title', 'Create Role')

@section('content')
<div class="container-fluid">
    <!-- Page Header -->
    <div class="row mb-4">
        <div class="col-12">
            <nav aria-label="breadcrumb">
                <ol class="breadcrumb">
                    <li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
                    <li class="breadcrumb-item"><a href="{{ route('admin.roles.index') }}">Roles</a></li>
                    <li class="breadcrumb-item active">Create Role</li>
                </ol>
            </nav>
            <h1 class="h3 mb-0 text-gray-800">Create New Role</h1>
        </div>
    </div>

    <form action="{{ route('admin.roles.store') }}" method="POST" id="createRoleForm">
        @csrf

        <div class="row">
            <!-- Role Information -->
            <div class="col-lg-8">
                <div class="card shadow-sm mb-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Role Information</h5>
                    </div>
                    <div class="card-body">
                        <div class="mb-3">
                            <label for="name" class="form-label">Role Name <span class="text-danger">*</span></label>
                            <input type="text"
                                   class="form-control @error('name') is-invalid @enderror"
                                   id="name"
                                   name="name"
                                   value="{{ old('name') }}"
                                   placeholder="e.g., Content Manager"
                                   required>
                            @error('name')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Display name for the role</small>
                        </div>

                        <div class="mb-3">
                            <label for="slug" class="form-label">Slug <span class="text-danger">*</span></label>
                            <input type="text"
                                   class="form-control @error('slug') is-invalid @enderror"
                                   id="slug"
                                   name="slug"
                                   value="{{ old('slug') }}"
                                   placeholder="e.g., content-manager"
                                   pattern="[a-z0-9\-]+"
                                   required>
                            @error('slug')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Unique identifier (lowercase, no spaces)</small>
                        </div>

                        <div class="mb-3">
                            <label for="description" class="form-label">Description</label>
                            <textarea class="form-control @error('description') is-invalid @enderror"
                                      id="description"
                                      name="description"
                                      rows="3"
                                      placeholder="Brief description of this role...">{{ old('description') }}</textarea>
                            @error('description')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="form-check">
                            <input class="form-check-input"
                                   type="checkbox"
                                   id="is_default"
                                   name="is_default"
                                   value="1"
                                   {{ old('is_default') ? 'checked' : '' }}>
                            <label class="form-check-label" for="is_default">
                                Set as default role for new users
                            </label>
                        </div>
                    </div>
                </div>

                <!-- Permissions -->
                <div class="card shadow-sm">
                    <div class="card-header bg-white d-flex justify-content-between align-items-center">
                        <h5 class="mb-0"><i class="bi bi-key me-2"></i>Permissions</h5>
                        <div>
                            <button type="button" class="btn btn-sm btn-outline-primary" onclick="selectAll()">
                                Select All
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary" onclick="selectNone()">
                                Clear All
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        @forelse($permissions as $groupName => $groupPermissions)
                            <div class="permission-group mb-4">
                                <div class="d-flex align-items-center mb-2">
                                    <h6 class="mb-0 me-auto">{{ $groupName ?: 'Ungrouped' }}</h6>
                                    <button type="button"
                                            class="btn btn-sm btn-link text-decoration-none"
                                            onclick="toggleGroup('{{ Str::slug($groupName) }}')">
                                        Select Group
                                    </button>
                                </div>
                                <div class="row" data-group="{{ Str::slug($groupName) }}">
                                    @foreach($groupPermissions as $permission)
                                        <div class="col-md-6 col-lg-4 mb-2">
                                            <div class="form-check">
                                                <input class="form-check-input permission-checkbox"
                                                       type="checkbox"
                                                       name="permissions[]"
                                                       value="{{ $permission->id }}"
                                                       id="permission_{{ $permission->id }}"
                                                       {{ in_array($permission->id, old('permissions', [])) ? 'checked' : '' }}>
                                                <label class="form-check-label" for="permission_{{ $permission->id }}">
                                                    {{ $permission->name }}
                                                    <small class="text-muted d-block">{{ $permission->slug }}</small>
                                                </label>
                                            </div>
                                        </div>
                                    @endforeach
                                </div>
                            </div>
                            @if(!$loop->last)
                                <hr>
                            @endif
                        @empty
                            <div class="text-center text-muted py-4">
                                <i class="bi bi-shield-x fs-1"></i>
                                <p class="mt-2">No permissions available</p>
                            </div>
                        @endforelse
                    </div>
                </div>
            </div>

            <!-- Sidebar -->
            <div class="col-lg-4">
                <!-- Quick Actions -->
                <div class="card shadow-sm mb-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-lightning me-2"></i>Quick Actions</h5>
                    </div>
                    <div class="card-body">
                        <button type="submit" class="btn btn-primary w-100 mb-2">
                            <i class="bi bi-check-circle me-2"></i>Create Role
                        </button>
                        <button type="submit" name="create_another" value="1" class="btn btn-outline-primary w-100 mb-2">
                            <i class="bi bi-plus-circle me-2"></i>Create & Add Another
                        </button>
                        <a href="{{ route('admin.roles.index') }}" class="btn btn-outline-secondary w-100">
                            <i class="bi bi-x-circle me-2"></i>Cancel
                        </a>
                    </div>
                </div>

                <!-- Role Templates -->
                <div class="card shadow-sm">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-collection me-2"></i>Role Templates</h5>
                    </div>
                    <div class="card-body">
                        <p class="small text-muted">Quick permission presets:</p>
                        <button type="button" class="btn btn-sm btn-outline-info w-100 mb-2" onclick="applyTemplate('viewer')">
                            <i class="bi bi-eye me-1"></i>Viewer (Read Only)
                        </button>
                        <button type="button" class="btn btn-sm btn-outline-warning w-100 mb-2" onclick="applyTemplate('editor')">
                            <i class="bi bi-pencil me-1"></i>Editor (Create & Edit)
                        </button>
                        <button type="button" class="btn btn-sm btn-outline-success w-100 mb-2" onclick="applyTemplate('moderator')">
                            <i class="bi bi-shield-check me-1"></i>Moderator (All Content)
                        </button>
                        <button type="button" class="btn btn-sm btn-outline-danger w-100" onclick="applyTemplate('admin')">
                            <i class="bi bi-gear me-1"></i>Admin (Full Access)
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </form>
</div>
@endsection
blade
@extends('layouts.admin')

@section('title', 'Create Role')

@section('content')
<div class="container-fluid">
    <!-- Page Header -->
    <div class="row mb-4">
        <div class="col-12">
            <nav aria-label="breadcrumb">
                <ol class="breadcrumb">
                    <li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
                    <li class="breadcrumb-item"><a href="{{ route('admin.roles.index') }}">Roles</a></li>
                    <li class="breadcrumb-item active">Create Role</li>
                </ol>
            </nav>
            <h1 class="h3 mb-0 text-gray-800">Create New Role</h1>
        </div>
    </div>

    <form action="{{ route('admin.roles.store') }}" method="POST" id="createRoleForm">
        @csrf

        <div class="row">
            <!-- Role Information -->
            <div class="col-lg-8">
                <div class="card shadow-sm mb-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Role Information</h5>
                    </div>
                    <div class="card-body">
                        <div class="mb-3">
                            <label for="name" class="form-label">Role Name <span class="text-danger">*</span></label>
                            <input type="text"
                                   class="form-control @error('name') is-invalid @enderror"
                                   id="name"
                                   name="name"
                                   value="{{ old('name') }}"
                                   placeholder="e.g., Content Manager"
                                   required>
                            @error('name')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Display name for the role</small>
                        </div>

                        <div class="mb-3">
                            <label for="slug" class="form-label">Slug <span class="text-danger">*</span></label>
                            <input type="text"
                                   class="form-control @error('slug') is-invalid @enderror"
                                   id="slug"
                                   name="slug"
                                   value="{{ old('slug') }}"
                                   placeholder="e.g., content-manager"
                                   pattern="[a-z0-9\-]+"
                                   required>
                            @error('slug')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Unique identifier (lowercase, no spaces)</small>
                        </div>

                        <div class="mb-3">
                            <label for="description" class="form-label">Description</label>
                            <textarea class="form-control @error('description') is-invalid @enderror"
                                      id="description"
                                      name="description"
                                      rows="3"
                                      placeholder="Brief description of this role...">{{ old('description') }}</textarea>
                            @error('description')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="form-check">
                            <input class="form-check-input"
                                   type="checkbox"
                                   id="is_default"
                                   name="is_default"
                                   value="1"
                                   {{ old('is_default') ? 'checked' : '' }}>
                            <label class="form-check-label" for="is_default">
                                Set as default role for new users
                            </label>
                        </div>
                    </div>
                </div>

                <!-- Permissions -->
                <div class="card shadow-sm">
                    <div class="card-header bg-white d-flex justify-content-between align-items-center">
                        <h5 class="mb-0"><i class="bi bi-key me-2"></i>Permissions</h5>
                        <div>
                            <button type="button" class="btn btn-sm btn-outline-primary" onclick="selectAll()">
                                Select All
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary" onclick="selectNone()">
                                Clear All
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        @forelse($permissions as $groupName => $groupPermissions)
                            <div class="permission-group mb-4">
                                <div class="d-flex align-items-center mb-2">
                                    <h6 class="mb-0 me-auto">{{ $groupName ?: 'Ungrouped' }}</h6>
                                    <button type="button"
                                            class="btn btn-sm btn-link text-decoration-none"
                                            onclick="toggleGroup('{{ Str::slug($groupName) }}')">
                                        Select Group
                                    </button>
                                </div>
                                <div class="row" data-group="{{ Str::slug($groupName) }}">
                                    @foreach($groupPermissions as $permission)
                                        <div class="col-md-6 col-lg-4 mb-2">
                                            <div class="form-check">
                                                <input class="form-check-input permission-checkbox"
                                                       type="checkbox"
                                                       name="permissions[]"
                                                       value="{{ $permission->id }}"
                                                       id="permission_{{ $permission->id }}"
                                                       {{ in_array($permission->id, old('permissions', [])) ? 'checked' : '' }}>
                                                <label class="form-check-label" for="permission_{{ $permission->id }}">
                                                    {{ $permission->name }}
                                                    <small class="text-muted d-block">{{ $permission->slug }}</small>
                                                </label>
                                            </div>
                                        </div>
                                    @endforeach
                                </div>
                            </div>
                            @if(!$loop->last)
                                <hr>
                            @endif
                        @empty
                            <div class="text-center text-muted py-4">
                                <i class="bi bi-shield-x fs-1"></i>
                                <p class="mt-2">No permissions available</p>
                            </div>
                        @endforelse
                    </div>
                </div>
            </div>

            <!-- Sidebar -->
            <div class="col-lg-4">
                <!-- Quick Actions -->
                <div class="card shadow-sm mb-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-lightning me-2"></i>Quick Actions</h5>
                    </div>
                    <div class="card-body">
                        <button type="submit" class="btn btn-primary w-100 mb-2">
                            <i class="bi bi-check-circle me-2"></i>Create Role
                        </button>
                        <button type="submit" name="create_another" value="1" class="btn btn-outline-primary w-100 mb-2">
                            <i class="bi bi-plus-circle me-2"></i>Create & Add Another
                        </button>
                        <a href="{{ route('admin.roles.index') }}" class="btn btn-outline-secondary w-100">
                            <i class="bi bi-x-circle me-2"></i>Cancel
                        </a>
                    </div>
                </div>

                <!-- Role Templates -->
                <div class="card shadow-sm">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-collection me-2"></i>Role Templates</h5>
                    </div>
                    <div class="card-body">
                        <p class="small text-muted">Quick permission presets:</p>
                        <button type="button" class="btn btn-sm btn-outline-info w-100 mb-2" onclick="applyTemplate('viewer')">
                            <i class="bi bi-eye me-1"></i>Viewer (Read Only)
                        </button>
                        <button type="button" class="btn btn-sm btn-outline-warning w-100 mb-2" onclick="applyTemplate('editor')">
                            <i class="bi bi-pencil me-1"></i>Editor (Create & Edit)
                        </button>
                        <button type="button" class="btn btn-sm btn-outline-success w-100 mb-2" onclick="applyTemplate('moderator')">
                            <i class="bi bi-shield-check me-1"></i>Moderator (All Content)
                        </button>
                        <button type="button" class="btn btn-sm btn-outline-danger w-100" onclick="applyTemplate('admin')">
                            <i class="bi bi-gear me-1"></i>Admin (Full Access)
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </form>
</div>
@endsection
Step 4 of 8

View: resources/views/admin/roles/edit.blade.php

@extends('layouts.admin')

@section('title', 'Edit Role - ' . $role->name)

@section('content')
<div class="container-fluid">
    <!-- Page Header -->
    <div class="row mb-4">
        <div class="col-12">
            <nav aria-label="breadcrumb">
                <ol class="breadcrumb">
                    <li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
                    <li class="breadcrumb-item"><a href="{{ route('admin.roles.index') }}">Roles</a></li>
                    <li class="breadcrumb-item active">Edit Role</li>
                </ol>
            </nav>
            <div class="d-flex justify-content-between align-items-center">
                <h1 class="h3 mb-0 text-gray-800">Edit Role: {{ $role->name }}</h1>
                <a href="{{ route('admin.roles.show', $role) }}" class="btn btn-outline-info">
                    <i class="bi bi-eye me-2"></i>View Role
                </a>
            </div>
        </div>
    </div>

    <form action="{{ route('admin.roles.update', $role) }}" method="POST">
        @csrf
        @method('PUT')

        <div class="row">
            <!-- Role Information -->
            <div class="col-lg-8">
                <div class="card shadow-sm mb-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Role Information</h5>
                    </div>
                    <div class="card-body">
                        <div class="mb-3">
                            <label for="name" class="form-label">Role Name <span class="text-danger">*</span></label>
                            <input type="text"
                                   class="form-control @error('name') is-invalid @enderror"
                                   id="name"
                                   name="name"
                                   value="{{ old('name', $role->name) }}"
                                   required>
                            @error('name')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="slug" class="form-label">Slug <span class="text-danger">*</span></label>
                            <input type="text"
                                   class="form-control @error('slug') is-invalid @enderror"
                                   id="slug"
                                   name="slug"
                                   value="{{ old('slug', $role->slug) }}"
                                   pattern="[a-z0-9\-]+"
                                   required>
                            @error('slug')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Changing the slug may affect existing code references</small>
                        </div>

                        <div class="mb-3">
                            <label for="description" class="form-label">Description</label>
                            <textarea class="form-control @error('description') is-invalid @enderror"
                                      id="description"
                                      name="description"
                                      rows="3">{{ old('description', $role->description) }}</textarea>
                            @error('description')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="form-check">
                            <input class="form-check-input"
                                   type="checkbox"
                                   id="is_default"
                                   name="is_default"
                                   value="1"
                                   {{ old('is_default', $role->is_default) ? 'checked' : '' }}>
                            <label class="form-check-label" for="is_default">
                                Set as default role for new users
                            </label>
                        </div>
                    </div>
                </div>

                <!-- Permissions -->
                <div class="card shadow-sm">
                    <div class="card-header bg-white d-flex justify-content-between align-items-center">
                        <h5 class="mb-0"><i class="bi bi-key me-2"></i>Permissions</h5>
                        <div>
                            <span class="badge bg-primary me-2">
                                <span id="selectedCount">{{ count($rolePermissions) }}</span> selected
                            </span>
                            <button type="button" class="btn btn-sm btn-outline-primary" onclick="selectAll()">
                                Select All
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary" onclick="selectNone()">
                                Clear All
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        @forelse($permissions as $groupName => $groupPermissions)
                            <div class="permission-group mb-4">
                                <div class="d-flex align-items-center mb-2">
                                    <h6 class="mb-0 me-auto">{{ $groupName ?: 'Ungrouped' }}</h6>
                                    <button type="button"
                                            class="btn btn-sm btn-link text-decoration-none"
                                            onclick="toggleGroup('{{ Str::slug($groupName) }}')">
                                        Toggle Group
                                    </button>
                                </div>
                                <div class="row" data-group="{{ Str::slug($groupName) }}">
                                    @foreach($groupPermissions as $permission)
                                        <div class="col-md-6 col-lg-4 mb-2">
                                            <div class="form-check">
                                                <input class="form-check-input permission-checkbox"
                                                       type="checkbox"
                                                       name="permissions[]"
                                                       value="{{ $permission->id }}"
                                                       id="permission_{{ $permission->id }}"
                                                       {{ in_array($permission->id, old('permissions', $rolePermissions)) ? 'checked' : '' }}
                                                       onchange="updateCount()">
                                                <label class="form-check-label" for="permission_{{ $permission->id }}">
                                                    {{ $permission->name }}
                                                    <small class="text-muted d-block">{{ $permission->slug }}</small>
                                                </label>
                                            </div>
                                        </div>
                                    @endforeach
                                </div>
                            </div>
                            @if(!$loop->last)
                                <hr>
                            @endif
                        @empty
                            <div class="text-center text-muted py-4">
                                <i class="bi bi-shield-x fs-1"></i>
                                <p class="mt-2">No permissions available</p>
                            </div>
                        @endforelse
                    </div>
                </div>
            </div>

            <!-- Sidebar -->
            <div class="col-lg-4">
                <!-- Quick Actions -->
                <div class="card shadow-sm mb-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-lightning me-2"></i>Actions</h5>
                    </div>
                    <div class="card-body">
                        <button type="submit" class="btn btn-primary w-100 mb-2">
                            <i class="bi bi-save me-2"></i>Save Changes
                        </button>
                        <button type="submit" name="save_and_continue" value="1" class="btn btn-outline-primary w-100 mb-2">
                            <i class="bi bi-save me-2"></i>Save & Continue Editing
                        </button>
                        <a href="{{ route('admin.roles.index') }}" class="btn btn-outline-secondary w-100">
                            <i class="bi bi-x-circle me-2"></i>Cancel
                        </a>
                    </div>
                </div>

                <!-- Role Info -->
                <div class="card shadow-sm mb-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Role Details</h5>
                    </div>
                    <div class="card-body">
                        <dl class="row mb-0">
                            <dt class="col-5">Created:</dt>
                            <dd class="col-7">{{ $role->created_at->format('M d, Y') }}</dd>

                            <dt class="col-5">Updated:</dt>
                            <dd class="col-7">{{ $role->updated_at->format('M d, Y') }}</dd>

                            <dt class="col-5">Users:</dt>
                            <dd class="col-7">
                                <span class="badge bg-success">{{ $role->users()->count() }}</span>
                            </dd>

                            <dt class="col-5">Permissions:</dt>
                            <dd class="col-7">
                                <span class="badge bg-primary">{{ $role->permissions()->count() }}</span>
                            </dd>
                        </dl>
                    </div>
                </div>
            </div>
        </div>
    </form>
</div>
@endsection
blade
@extends('layouts.admin')

@section('title', 'Edit Role - ' . $role->name)

@section('content')
<div class="container-fluid">
    <!-- Page Header -->
    <div class="row mb-4">
        <div class="col-12">
            <nav aria-label="breadcrumb">
                <ol class="breadcrumb">
                    <li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
                    <li class="breadcrumb-item"><a href="{{ route('admin.roles.index') }}">Roles</a></li>
                    <li class="breadcrumb-item active">Edit Role</li>
                </ol>
            </nav>
            <div class="d-flex justify-content-between align-items-center">
                <h1 class="h3 mb-0 text-gray-800">Edit Role: {{ $role->name }}</h1>
                <a href="{{ route('admin.roles.show', $role) }}" class="btn btn-outline-info">
                    <i class="bi bi-eye me-2"></i>View Role
                </a>
            </div>
        </div>
    </div>

    <form action="{{ route('admin.roles.update', $role) }}" method="POST">
        @csrf
        @method('PUT')

        <div class="row">
            <!-- Role Information -->
            <div class="col-lg-8">
                <div class="card shadow-sm mb-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Role Information</h5>
                    </div>
                    <div class="card-body">
                        <div class="mb-3">
                            <label for="name" class="form-label">Role Name <span class="text-danger">*</span></label>
                            <input type="text"
                                   class="form-control @error('name') is-invalid @enderror"
                                   id="name"
                                   name="name"
                                   value="{{ old('name', $role->name) }}"
                                   required>
                            @error('name')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="slug" class="form-label">Slug <span class="text-danger">*</span></label>
                            <input type="text"
                                   class="form-control @error('slug') is-invalid @enderror"
                                   id="slug"
                                   name="slug"
                                   value="{{ old('slug', $role->slug) }}"
                                   pattern="[a-z0-9\-]+"
                                   required>
                            @error('slug')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Changing the slug may affect existing code references</small>
                        </div>

                        <div class="mb-3">
                            <label for="description" class="form-label">Description</label>
                            <textarea class="form-control @error('description') is-invalid @enderror"
                                      id="description"
                                      name="description"
                                      rows="3">{{ old('description', $role->description) }}</textarea>
                            @error('description')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="form-check">
                            <input class="form-check-input"
                                   type="checkbox"
                                   id="is_default"
                                   name="is_default"
                                   value="1"
                                   {{ old('is_default', $role->is_default) ? 'checked' : '' }}>
                            <label class="form-check-label" for="is_default">
                                Set as default role for new users
                            </label>
                        </div>
                    </div>
                </div>

                <!-- Permissions -->
                <div class="card shadow-sm">
                    <div class="card-header bg-white d-flex justify-content-between align-items-center">
                        <h5 class="mb-0"><i class="bi bi-key me-2"></i>Permissions</h5>
                        <div>
                            <span class="badge bg-primary me-2">
                                <span id="selectedCount">{{ count($rolePermissions) }}</span> selected
                            </span>
                            <button type="button" class="btn btn-sm btn-outline-primary" onclick="selectAll()">
                                Select All
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary" onclick="selectNone()">
                                Clear All
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        @forelse($permissions as $groupName => $groupPermissions)
                            <div class="permission-group mb-4">
                                <div class="d-flex align-items-center mb-2">
                                    <h6 class="mb-0 me-auto">{{ $groupName ?: 'Ungrouped' }}</h6>
                                    <button type="button"
                                            class="btn btn-sm btn-link text-decoration-none"
                                            onclick="toggleGroup('{{ Str::slug($groupName) }}')">
                                        Toggle Group
                                    </button>
                                </div>
                                <div class="row" data-group="{{ Str::slug($groupName) }}">
                                    @foreach($groupPermissions as $permission)
                                        <div class="col-md-6 col-lg-4 mb-2">
                                            <div class="form-check">
                                                <input class="form-check-input permission-checkbox"
                                                       type="checkbox"
                                                       name="permissions[]"
                                                       value="{{ $permission->id }}"
                                                       id="permission_{{ $permission->id }}"
                                                       {{ in_array($permission->id, old('permissions', $rolePermissions)) ? 'checked' : '' }}
                                                       onchange="updateCount()">
                                                <label class="form-check-label" for="permission_{{ $permission->id }}">
                                                    {{ $permission->name }}
                                                    <small class="text-muted d-block">{{ $permission->slug }}</small>
                                                </label>
                                            </div>
                                        </div>
                                    @endforeach
                                </div>
                            </div>
                            @if(!$loop->last)
                                <hr>
                            @endif
                        @empty
                            <div class="text-center text-muted py-4">
                                <i class="bi bi-shield-x fs-1"></i>
                                <p class="mt-2">No permissions available</p>
                            </div>
                        @endforelse
                    </div>
                </div>
            </div>

            <!-- Sidebar -->
            <div class="col-lg-4">
                <!-- Quick Actions -->
                <div class="card shadow-sm mb-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-lightning me-2"></i>Actions</h5>
                    </div>
                    <div class="card-body">
                        <button type="submit" class="btn btn-primary w-100 mb-2">
                            <i class="bi bi-save me-2"></i>Save Changes
                        </button>
                        <button type="submit" name="save_and_continue" value="1" class="btn btn-outline-primary w-100 mb-2">
                            <i class="bi bi-save me-2"></i>Save & Continue Editing
                        </button>
                        <a href="{{ route('admin.roles.index') }}" class="btn btn-outline-secondary w-100">
                            <i class="bi bi-x-circle me-2"></i>Cancel
                        </a>
                    </div>
                </div>

                <!-- Role Info -->
                <div class="card shadow-sm mb-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Role Details</h5>
                    </div>
                    <div class="card-body">
                        <dl class="row mb-0">
                            <dt class="col-5">Created:</dt>
                            <dd class="col-7">{{ $role->created_at->format('M d, Y') }}</dd>

                            <dt class="col-5">Updated:</dt>
                            <dd class="col-7">{{ $role->updated_at->format('M d, Y') }}</dd>

                            <dt class="col-5">Users:</dt>
                            <dd class="col-7">
                                <span class="badge bg-success">{{ $role->users()->count() }}</span>
                            </dd>

                            <dt class="col-5">Permissions:</dt>
                            <dd class="col-7">
                                <span class="badge bg-primary">{{ $role->permissions()->count() }}</span>
                            </dd>
                        </dl>
                    </div>
                </div>
            </div>
        </div>
    </form>
</div>
@endsection
Step 5 of 8

View: resources/views/admin/roles/show.blade.php

@extends('layouts.admin')

@section('title', 'Role Details - ' . $role->name)

@section('content')
<div class="container-fluid">
    <!-- Page Header -->
    <div class="row mb-4">
        <div class="col-12">
            <nav aria-label="breadcrumb">
                <ol class="breadcrumb">
                    <li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
                    <li class="breadcrumb-item"><a href="{{ route('admin.roles.index') }}">Roles</a></li>
                    <li class="breadcrumb-item active">{{ $role->name }}</li>
                </ol>
            </nav>
            <div class="d-flex justify-content-between align-items-center">
                <div>
                    <h1 class="h3 mb-2 text-gray-800">{{ $role->name }}</h1>
                    <div>
                        @if($role->slug === config('omni-access.super_admin_role'))
                            <span class="badge bg-danger">Super Admin</span>
                        @elseif($role->is_default)
                            <span class="badge bg-info">Default Role</span>
                        @endif
                        @if($role->deleted_at)
                            <span class="badge bg-danger">Deleted</span>
                        @else
                            <span class="badge bg-success">Active</span>
                        @endif
                    </div>
                </div>
                <div>
                    @permission('roles.edit')
                        @if($role->slug !== config('omni-access.super_admin_role'))
                            <a href="{{ route('admin.roles.edit', $role) }}" class="btn btn-primary">
                                <i class="bi bi-pencil me-2"></i>Edit Role
                            </a>
                        @endif
                    @endpermission
                </div>
            </div>
        </div>
    </div>

    <div class="row">
        <!-- Role Information -->
        <div class="col-lg-4 mb-4">
            <div class="card shadow-sm">
                <div class="card-header bg-white">
                    <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Role Information</h5>
                </div>
                <div class="card-body">
                    <dl class="row">
                        <dt class="col-sm-4">Name:</dt>
                        <dd class="col-sm-8">{{ $role->name }}</dd>

                        <dt class="col-sm-4">Slug:</dt>
                        <dd class="col-sm-8"><code>{{ $role->slug }}</code></dd>

                        <dt class="col-sm-4">Description:</dt>
                        <dd class="col-sm-8">{{ $role->description ?: 'No description' }}</dd>

                        <dt class="col-sm-4">Default Role:</dt>
                        <dd class="col-sm-8">
                            @if($role->is_default)
                                <span class="badge bg-success">Yes</span>
                            @else
                                <span class="badge bg-secondary">No</span>
                            @endif
                        </dd>

                        <dt class="col-sm-4">Created:</dt>
                        <dd class="col-sm-8">
                            {{ $role->created_at->format('M d, Y') }}
                            <small class="text-muted d-block">{{ $role->created_at->diffForHumans() }}</small>
                        </dd>

                        <dt class="col-sm-4">Updated:</dt>
                        <dd class="col-sm-8">
                            {{ $role->updated_at->format('M d, Y') }}
                            <small class="text-muted d-block">{{ $role->updated_at->diffForHumans() }}</small>
                        </dd>
                    </dl>

                    <hr>

                    <div class="row text-center">
                        <div class="col-6">
                            <h3 class="mb-0">{{ $role->users->count() }}</h3>
                            <p class="text-muted mb-0">Users</p>
                        </div>
                        <div class="col-6">
                            <h3 class="mb-0">{{ $role->permissions->count() }}</h3>
                            <p class="text-muted mb-0">Permissions</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Permissions -->
        <div class="col-lg-8 mb-4">
            <div class="card shadow-sm">
                <div class="card-header bg-white">
                    <h5 class="mb-0">
                        <i class="bi bi-key me-2"></i>
                        Permissions
                        <span class="badge bg-primary ms-2">{{ $role->permissions->count() }}</span>
                    </h5>
                </div>
                <div class="card-body">
                    @forelse($groupedPermissions as $groupName => $permissions)
                        <div class="mb-4">
                            <h6 class="text-uppercase text-muted mb-3">
                                {{ $groupName ?: 'Ungrouped' }}
                                <span class="badge bg-secondary ms-2">{{ $permissions->count() }}</span>
                            </h6>
                            <div class="row">
                                @foreach($permissions as $permission)
                                    <div class="col-md-6 col-lg-4 mb-3">
                                        <div class="d-flex align-items-start">
                                            <i class="bi bi-check-circle-fill text-success me-2 mt-1"></i>
                                            <div>
                                                <div class="fw-semibold">{{ $permission->name }}</div>
                                                <code class="small text-muted">{{ $permission->slug }}</code>
                                                @if($permission->description)
                                                    <p class="small text-muted mb-0 mt-1">{{ $permission->description }}</p>
                                                @endif
                                            </div>
                                        </div>
                                    </div>
                                @endforeach
                            </div>
                        </div>
                        @if(!$loop->last)
                            <hr>
                        @endif
                    @empty
                        <div class="text-center py-5">
                            <i class="bi bi-shield-x fs-1 text-muted"></i>
                            <p class="mt-2 text-muted">No permissions assigned to this role</p>
                            @permission('roles.edit')
                                @if($role->slug !== config('omni-access.super_admin_role'))
                                    <a href="{{ route('admin.roles.edit', $role) }}" class="btn btn-primary">
                                        <i class="bi bi-plus-circle me-2"></i>Add Permissions
                                    </a>
                                @endif
                            @endpermission
                        </div>
                    @endforelse
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
blade
@extends('layouts.admin')

@section('title', 'Role Details - ' . $role->name)

@section('content')
<div class="container-fluid">
    <!-- Page Header -->
    <div class="row mb-4">
        <div class="col-12">
            <nav aria-label="breadcrumb">
                <ol class="breadcrumb">
                    <li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
                    <li class="breadcrumb-item"><a href="{{ route('admin.roles.index') }}">Roles</a></li>
                    <li class="breadcrumb-item active">{{ $role->name }}</li>
                </ol>
            </nav>
            <div class="d-flex justify-content-between align-items-center">
                <div>
                    <h1 class="h3 mb-2 text-gray-800">{{ $role->name }}</h1>
                    <div>
                        @if($role->slug === config('omni-access.super_admin_role'))
                            <span class="badge bg-danger">Super Admin</span>
                        @elseif($role->is_default)
                            <span class="badge bg-info">Default Role</span>
                        @endif
                        @if($role->deleted_at)
                            <span class="badge bg-danger">Deleted</span>
                        @else
                            <span class="badge bg-success">Active</span>
                        @endif
                    </div>
                </div>
                <div>
                    @permission('roles.edit')
                        @if($role->slug !== config('omni-access.super_admin_role'))
                            <a href="{{ route('admin.roles.edit', $role) }}" class="btn btn-primary">
                                <i class="bi bi-pencil me-2"></i>Edit Role
                            </a>
                        @endif
                    @endpermission
                </div>
            </div>
        </div>
    </div>

    <div class="row">
        <!-- Role Information -->
        <div class="col-lg-4 mb-4">
            <div class="card shadow-sm">
                <div class="card-header bg-white">
                    <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Role Information</h5>
                </div>
                <div class="card-body">
                    <dl class="row">
                        <dt class="col-sm-4">Name:</dt>
                        <dd class="col-sm-8">{{ $role->name }}</dd>

                        <dt class="col-sm-4">Slug:</dt>
                        <dd class="col-sm-8"><code>{{ $role->slug }}</code></dd>

                        <dt class="col-sm-4">Description:</dt>
                        <dd class="col-sm-8">{{ $role->description ?: 'No description' }}</dd>

                        <dt class="col-sm-4">Default Role:</dt>
                        <dd class="col-sm-8">
                            @if($role->is_default)
                                <span class="badge bg-success">Yes</span>
                            @else
                                <span class="badge bg-secondary">No</span>
                            @endif
                        </dd>

                        <dt class="col-sm-4">Created:</dt>
                        <dd class="col-sm-8">
                            {{ $role->created_at->format('M d, Y') }}
                            <small class="text-muted d-block">{{ $role->created_at->diffForHumans() }}</small>
                        </dd>

                        <dt class="col-sm-4">Updated:</dt>
                        <dd class="col-sm-8">
                            {{ $role->updated_at->format('M d, Y') }}
                            <small class="text-muted d-block">{{ $role->updated_at->diffForHumans() }}</small>
                        </dd>
                    </dl>

                    <hr>

                    <div class="row text-center">
                        <div class="col-6">
                            <h3 class="mb-0">{{ $role->users->count() }}</h3>
                            <p class="text-muted mb-0">Users</p>
                        </div>
                        <div class="col-6">
                            <h3 class="mb-0">{{ $role->permissions->count() }}</h3>
                            <p class="text-muted mb-0">Permissions</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Permissions -->
        <div class="col-lg-8 mb-4">
            <div class="card shadow-sm">
                <div class="card-header bg-white">
                    <h5 class="mb-0">
                        <i class="bi bi-key me-2"></i>
                        Permissions
                        <span class="badge bg-primary ms-2">{{ $role->permissions->count() }}</span>
                    </h5>
                </div>
                <div class="card-body">
                    @forelse($groupedPermissions as $groupName => $permissions)
                        <div class="mb-4">
                            <h6 class="text-uppercase text-muted mb-3">
                                {{ $groupName ?: 'Ungrouped' }}
                                <span class="badge bg-secondary ms-2">{{ $permissions->count() }}</span>
                            </h6>
                            <div class="row">
                                @foreach($permissions as $permission)
                                    <div class="col-md-6 col-lg-4 mb-3">
                                        <div class="d-flex align-items-start">
                                            <i class="bi bi-check-circle-fill text-success me-2 mt-1"></i>
                                            <div>
                                                <div class="fw-semibold">{{ $permission->name }}</div>
                                                <code class="small text-muted">{{ $permission->slug }}</code>
                                                @if($permission->description)
                                                    <p class="small text-muted mb-0 mt-1">{{ $permission->description }}</p>
                                                @endif
                                            </div>
                                        </div>
                                    </div>
                                @endforeach
                            </div>
                        </div>
                        @if(!$loop->last)
                            <hr>
                        @endif
                    @empty
                        <div class="text-center py-5">
                            <i class="bi bi-shield-x fs-1 text-muted"></i>
                            <p class="mt-2 text-muted">No permissions assigned to this role</p>
                            @permission('roles.edit')
                                @if($role->slug !== config('omni-access.super_admin_role'))
                                    <a href="{{ route('admin.roles.edit', $role) }}" class="btn btn-primary">
                                        <i class="bi bi-plus-circle me-2"></i>Add Permissions
                                    </a>
                                @endif
                            @endpermission
                        </div>
                    @endforelse
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
Step 6 of 8

Routes Configuration

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Admin\RoleController;

// Admin Routes with OMNI Access
Route::prefix('admin')->name('admin.')->middleware(['auth'])->group(function () {

    // Dashboard
    Route::get('/', function () {
        return view('admin.dashboard');
    })->name('dashboard');

    // Roles Management
    Route::prefix('roles')->name('roles.')->group(function () {
        Route::get('/', [RoleController::class, 'index'])->name('index');
        Route::get('/create', [RoleController::class, 'create'])->name('create');
        Route::post('/', [RoleController::class, 'store'])->name('store');
        Route::get('/{role}', [RoleController::class, 'show'])->name('show');
        Route::get('/{role}/edit', [RoleController::class, 'edit'])->name('edit');
        Route::put('/{role}', [RoleController::class, 'update'])->name('update');
        Route::delete('/{role}', [RoleController::class, 'destroy'])->name('destroy');

        // Additional routes
        Route::post('/bulk-delete', [RoleController::class, 'bulkDelete'])->name('bulk-delete');
        Route::post('/{role}/clone', [RoleController::class, 'clone'])->name('clone');
    });
});
php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Admin\RoleController;

// Admin Routes with OMNI Access
Route::prefix('admin')->name('admin.')->middleware(['auth'])->group(function () {

    // Dashboard
    Route::get('/', function () {
        return view('admin.dashboard');
    })->name('dashboard');

    // Roles Management
    Route::prefix('roles')->name('roles.')->group(function () {
        Route::get('/', [RoleController::class, 'index'])->name('index');
        Route::get('/create', [RoleController::class, 'create'])->name('create');
        Route::post('/', [RoleController::class, 'store'])->name('store');
        Route::get('/{role}', [RoleController::class, 'show'])->name('show');
        Route::get('/{role}/edit', [RoleController::class, 'edit'])->name('edit');
        Route::put('/{role}', [RoleController::class, 'update'])->name('update');
        Route::delete('/{role}', [RoleController::class, 'destroy'])->name('destroy');

        // Additional routes
        Route::post('/bulk-delete', [RoleController::class, 'bulkDelete'])->name('bulk-delete');
        Route::post('/{role}/clone', [RoleController::class, 'clone'])->name('clone');
    });
});
Step 7 of 8

JavaScript Functions (Add to Views)

// Toggle bulk select
function toggleBulkSelect() {
    const columns = document.querySelectorAll('.bulk-select-column');
    const bulkBtn = document.getElementById('bulkDeleteBtn');

    columns.forEach(col => col.classList.toggle('d-none'));
    bulkBtn.classList.toggle('d-none');
}

// Select all checkboxes
document.getElementById('selectAll')?.addEventListener('change', function() {
    const checkboxes = document.querySelectorAll('.role-checkbox');
    checkboxes.forEach(cb => cb.checked = this.checked);
});

// Delete single role
function deleteRole(id, name) {
    if (!confirm(`Are you sure you want to delete the role "${name}"?`)) {
        return;
    }

    fetch(`/admin/roles/${id}`, {
        method: 'DELETE',
        headers: {
            'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        }
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            location.reload();
        } else {
            alert(data.message || 'Error deleting role');
        }
    })
    .catch(error => {
        console.error('Error:', error);
        alert('An error occurred while deleting the role');
    });
}

// Auto-generate slug from name
document.getElementById('name')?.addEventListener('input', function(e) {
    const slug = document.getElementById('slug');
    if (!slug.dataset.manual) {
        slug.value = e.target.value
            .toLowerCase()
            .replace(/[^\w\s-]/g, '')
            .replace(/\s+/g, '-')
            .replace(/-+/g, '-')
            .trim();
    }
});

// Mark slug as manually edited
document.getElementById('slug')?.addEventListener('input', function() {
    this.dataset.manual = true;
});

// Select all permissions
function selectAll() {
    document.querySelectorAll('.permission-checkbox').forEach(cb => cb.checked = true);
    updateCount?.();
}

// Clear all permissions
function selectNone() {
    document.querySelectorAll('.permission-checkbox').forEach(cb => cb.checked = false);
    updateCount?.();
}

// Toggle group permissions
function toggleGroup(group) {
    const checkboxes = document.querySelectorAll(`[data-group="${group}"] .permission-checkbox`);
    const allChecked = Array.from(checkboxes).every(cb => cb.checked);
    checkboxes.forEach(cb => cb.checked = !allChecked);
    updateCount?.();
}

// Update selected count
function updateCount() {
    const count = document.querySelectorAll('.permission-checkbox:checked').length;
    const counter = document.getElementById('selectedCount');
    if (counter) {
        counter.textContent = count;
    }
}

// Apply permission template
function applyTemplate(template) {
    selectNone();

    const templates = {
        viewer: ['view'],
        editor: ['view', 'create', 'edit'],
        moderator: ['view', 'create', 'edit', 'delete'],
        admin: ['view', 'create', 'edit', 'delete', 'manage', 'settings']
    };

    const keywords = templates[template] || [];

    document.querySelectorAll('.permission-checkbox').forEach(cb => {
        const label = cb.nextElementSibling.textContent.toLowerCase();
        cb.checked = keywords.some(keyword => label.includes(keyword));
    });

    updateCount?.();
}
javascript
// Toggle bulk select
function toggleBulkSelect() {
    const columns = document.querySelectorAll('.bulk-select-column');
    const bulkBtn = document.getElementById('bulkDeleteBtn');

    columns.forEach(col => col.classList.toggle('d-none'));
    bulkBtn.classList.toggle('d-none');
}

// Select all checkboxes
document.getElementById('selectAll')?.addEventListener('change', function() {
    const checkboxes = document.querySelectorAll('.role-checkbox');
    checkboxes.forEach(cb => cb.checked = this.checked);
});

// Delete single role
function deleteRole(id, name) {
    if (!confirm(`Are you sure you want to delete the role "${name}"?`)) {
        return;
    }

    fetch(`/admin/roles/${id}`, {
        method: 'DELETE',
        headers: {
            'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        }
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            location.reload();
        } else {
            alert(data.message || 'Error deleting role');
        }
    })
    .catch(error => {
        console.error('Error:', error);
        alert('An error occurred while deleting the role');
    });
}

// Auto-generate slug from name
document.getElementById('name')?.addEventListener('input', function(e) {
    const slug = document.getElementById('slug');
    if (!slug.dataset.manual) {
        slug.value = e.target.value
            .toLowerCase()
            .replace(/[^\w\s-]/g, '')
            .replace(/\s+/g, '-')
            .replace(/-+/g, '-')
            .trim();
    }
});

// Mark slug as manually edited
document.getElementById('slug')?.addEventListener('input', function() {
    this.dataset.manual = true;
});

// Select all permissions
function selectAll() {
    document.querySelectorAll('.permission-checkbox').forEach(cb => cb.checked = true);
    updateCount?.();
}

// Clear all permissions
function selectNone() {
    document.querySelectorAll('.permission-checkbox').forEach(cb => cb.checked = false);
    updateCount?.();
}

// Toggle group permissions
function toggleGroup(group) {
    const checkboxes = document.querySelectorAll(`[data-group="${group}"] .permission-checkbox`);
    const allChecked = Array.from(checkboxes).every(cb => cb.checked);
    checkboxes.forEach(cb => cb.checked = !allChecked);
    updateCount?.();
}

// Update selected count
function updateCount() {
    const count = document.querySelectorAll('.permission-checkbox:checked').length;
    const counter = document.getElementById('selectedCount');
    if (counter) {
        counter.textContent = count;
    }
}

// Apply permission template
function applyTemplate(template) {
    selectNone();

    const templates = {
        viewer: ['view'],
        editor: ['view', 'create', 'edit'],
        moderator: ['view', 'create', 'edit', 'delete'],
        admin: ['view', 'create', 'edit', 'delete', 'manage', 'settings']
    };

    const keywords = templates[template] || [];

    document.querySelectorAll('.permission-checkbox').forEach(cb => {
        const label = cb.nextElementSibling.textContent.toLowerCase();
        cb.checked = keywords.some(keyword => label.includes(keyword));
    });

    updateCount?.();
}
Step 8 of 8

Features Included in This Example

  • ✓Complete CRUD operations

  • ✓Search and filtering

  • ✓Sorting by columns

  • ✓Pagination with Bootstrap 5

  • ✓Bulk delete functionality

  • ✓Role cloning feature

  • ✓Permission templates

  • ✓Permission-based access control

  • ✓Form validation

  • ✓Responsive Bootstrap 5 UI

  • ✓AJAX operations

  • ✓User avatars with UI Avatars

  • ✓Statistics cards

  • ✓Breadcrumb navigation

Previous Step

Congratulations! You Completed This Guide

You've walked through all 8 steps for OMNI Access v1.3.0. Keep practicing and exploring more hands-on tutorials.

Community Discussions 0

Ask questions, share step solutions, or discuss software workflows with other professionals.

Moderated Community

Join the Community Discussion

Got stuck on a step or have a question about this configuration? Sign in to join the discussion and receive direct advice from instructors and peers.

No Discussions Yet

Have a question or found a clever tip for this guide? Start the conversation using the comment box above!

Promotional Ads Available Space
Place Your advertising ads Here

Promote your brand, product, or service directly to our active readers and community.

Contact Us