OMNI Access v1.3.0 Free ~20 min read

CRUD Example: Permission Groups

Copy-paste ready Permission Groups CRUD: group controller, views, routes, and JavaScript helpers to organize permissions.

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

Introduction

Complete Permission Groups management for organizing permissions into logical categories.

Step 2 of 8

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

<?php

namespace App\Http\Controllers\Admin;

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

class GroupController extends Controller
{
    protected $cacheService;

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

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

    /**
     * Display a listing of groups
     */
    public function index(Request $request)
    {
        $query = Group::withCount('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', 'sort_order');
        $sortDirection = $request->get('direction', 'asc');

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

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

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

    /**
     * Show the form for creating a new group
     */
    public function create()
    {
        $maxSortOrder = Group::max('sort_order') ?? 0;
        $suggestedSortOrder = $maxSortOrder + 10;

        return view('admin.groups.create', compact('suggestedSortOrder'));
    }

    /**
     * Store a newly created group
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:50',
            'slug' => 'required|string|max:50|unique:permission_groups,slug|regex:/^[a-z0-9\-]+$/',
            'description' => 'nullable|string|max:255',
            'sort_order' => 'nullable|integer|min:0'
        ]);

        // Create group
        $group = Group::create([
            'name' => $validated['name'],
            'slug' => $validated['slug'],
            'description' => $validated['description'],
            'sort_order' => $validated['sort_order'] ?? 0
        ]);

        // Clear cache
        $this->cacheService->forget('groups.all');

        if ($request->input('create_another')) {
            return redirect()
                ->route('admin.groups.create')
                ->with('success', 'Group created successfully! You can add another.');
        }

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

    /**
     * Display the specified group
     */
    public function show(Group $group)
    {
        $group->load(['permissions' => function ($query) {
            $query->withCount('roles');
        }]);

        return view('admin.groups.show', compact('group'));
    }

    /**
     * Show the form for editing the specified group
     */
    public function edit(Group $group)
    {
        return view('admin.groups.edit', compact('group'));
    }

    /**
     * Update the specified group
     */
    public function update(Request $request, Group $group)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:50',
            'slug' => 'required|string|max:50|unique:permission_groups,slug,' . $group->id . '|regex:/^[a-z0-9\-]+$/',
            'description' => 'nullable|string|max:255',
            'sort_order' => 'nullable|integer|min:0'
        ]);

        // Update group
        $group->update([
            'name' => $validated['name'],
            'slug' => $validated['slug'],
            'description' => $validated['description'],
            'sort_order' => $validated['sort_order'] ?? 0
        ]);

        // Clear cache
        $this->cacheService->forget('groups.all');

        if ($request->input('save_and_continue')) {
            return redirect()
                ->route('admin.groups.edit', $group)
                ->with('success', 'Group updated successfully!');
        }

        return redirect()
            ->route('admin.groups.show', $group)
            ->with('success', 'Group updated successfully!');
    }

    /**
     * Remove the specified group
     */
    public function destroy(Group $group)
    {
        // Check if group has permissions
        if ($group->permissions()->count() > 0) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete group with permissions! Move permissions to another group first.'
            ], 403);
        }

        $group->delete();

        // Clear cache
        $this->cacheService->forget('groups.all');

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

        return redirect()
            ->route('admin.groups.index')
            ->with('success', 'Group deleted successfully!');
    }
php
<?php

namespace App\Http\Controllers\Admin;

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

class GroupController extends Controller
{
    protected $cacheService;

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

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

    /**
     * Display a listing of groups
     */
    public function index(Request $request)
    {
        $query = Group::withCount('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', 'sort_order');
        $sortDirection = $request->get('direction', 'asc');

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

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

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

    /**
     * Show the form for creating a new group
     */
    public function create()
    {
        $maxSortOrder = Group::max('sort_order') ?? 0;
        $suggestedSortOrder = $maxSortOrder + 10;

        return view('admin.groups.create', compact('suggestedSortOrder'));
    }

    /**
     * Store a newly created group
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:50',
            'slug' => 'required|string|max:50|unique:permission_groups,slug|regex:/^[a-z0-9\-]+$/',
            'description' => 'nullable|string|max:255',
            'sort_order' => 'nullable|integer|min:0'
        ]);

        // Create group
        $group = Group::create([
            'name' => $validated['name'],
            'slug' => $validated['slug'],
            'description' => $validated['description'],
            'sort_order' => $validated['sort_order'] ?? 0
        ]);

        // Clear cache
        $this->cacheService->forget('groups.all');

        if ($request->input('create_another')) {
            return redirect()
                ->route('admin.groups.create')
                ->with('success', 'Group created successfully! You can add another.');
        }

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

    /**
     * Display the specified group
     */
    public function show(Group $group)
    {
        $group->load(['permissions' => function ($query) {
            $query->withCount('roles');
        }]);

        return view('admin.groups.show', compact('group'));
    }

    /**
     * Show the form for editing the specified group
     */
    public function edit(Group $group)
    {
        return view('admin.groups.edit', compact('group'));
    }

    /**
     * Update the specified group
     */
    public function update(Request $request, Group $group)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:50',
            'slug' => 'required|string|max:50|unique:permission_groups,slug,' . $group->id . '|regex:/^[a-z0-9\-]+$/',
            'description' => 'nullable|string|max:255',
            'sort_order' => 'nullable|integer|min:0'
        ]);

        // Update group
        $group->update([
            'name' => $validated['name'],
            'slug' => $validated['slug'],
            'description' => $validated['description'],
            'sort_order' => $validated['sort_order'] ?? 0
        ]);

        // Clear cache
        $this->cacheService->forget('groups.all');

        if ($request->input('save_and_continue')) {
            return redirect()
                ->route('admin.groups.edit', $group)
                ->with('success', 'Group updated successfully!');
        }

        return redirect()
            ->route('admin.groups.show', $group)
            ->with('success', 'Group updated successfully!');
    }

    /**
     * Remove the specified group
     */
    public function destroy(Group $group)
    {
        // Check if group has permissions
        if ($group->permissions()->count() > 0) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete group with permissions! Move permissions to another group first.'
            ], 403);
        }

        $group->delete();

        // Clear cache
        $this->cacheService->forget('groups.all');

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

        return redirect()
            ->route('admin.groups.index')
            ->with('success', 'Group deleted successfully!');
    }
Step 3 of 8

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

@extends('layouts.admin')

@section('title', 'Permission Groups 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">Permission Groups</h1>
                    <p class="text-muted mb-0">Organize permissions into logical categories</p>
                </div>
                <div>
                    @permission('groups.create')
                        <a href="{{ route('admin.groups.create') }}" class="btn btn-primary">
                            <i class="bi bi-plus-circle me-2"></i>Create New Group
                        </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 Groups
                            </div>
                            <div class="h5 mb-0 font-weight-bold">{{ \RbacSuite\OmniAccess\Models\Group::count() }}</div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-collection 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">
                                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-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">
                                Grouped Permissions
                            </div>
                            <div class="h5 mb-0 font-weight-bold">
                                {{ \RbacSuite\OmniAccess\Models\Permission::whereNotNull('group_id')->count() }}
                            </div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-diagram-3 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">
                                Ungrouped
                            </div>
                            <div class="h5 mb-0 font-weight-bold">
                                {{ \RbacSuite\OmniAccess\Models\Permission::whereNull('group_id')->count() }}
                            </div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-exclamation-circle 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

    <!-- 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.groups.index') }}" method="GET" class="d-flex">
                        <div class="input-group">
                            <input type="text"
                                   name="search"
                                   class="form-control"
                                   placeholder="Search groups..."
                                   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.groups.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">
                    @permission('groups.edit')
                        <button type="button" class="btn btn-outline-primary" onclick="enableReorder()" id="reorderBtn">
                            <i class="bi bi-arrows-move me-1"></i>Reorder
                        </button>
                        <button type="button" class="btn btn-success d-none" onclick="saveOrder()" id="saveOrderBtn">
                            <i class="bi bi-save me-1"></i>Save Order
                        </button>
                        <button type="button" class="btn btn-secondary d-none" onclick="cancelReorder()" id="cancelOrderBtn">
                            <i class="bi bi-x me-1"></i>Cancel
                        </button>
                    @endpermission
                </div>
            </div>
        </div>
        <div class="card-body p-0">
            <div class="table-responsive">
                <table class="table table-hover mb-0" id="groupsTable">
                    <thead class="table-light">
                        <tr>
                            <th class="reorder-handle d-none" style="width: 40px;"></th>
                            <th>
                                <a href="{{ route('admin.groups.index', ['sort' => 'sort_order', 'direction' => request('direction') == 'asc' ? 'desc' : 'asc'] + request()->only('search')) }}"
                                   class="text-decoration-none text-dark">
                                    Order
                                    @if(request('sort') == 'sort_order')
                                        <i class="bi bi-chevron-{{ request('direction') == 'asc' ? 'up' : 'down' }} ms-1"></i>
                                    @endif
                                </a>
                            </th>
                            <th>Group Name</th>
                            <th>Slug</th>
                            <th>Description</th>
                            <th class="text-center">
                                <a href="{{ route('admin.groups.index', ['sort' => 'permissions_count', 'direction' => request('direction') == 'asc' ? 'desc' : 'asc'] + request()->only('search')) }}"
                                   class="text-decoration-none text-dark">
                                    Permissions
                                    @if(request('sort') == 'permissions_count')
                                        <i class="bi bi-chevron-{{ request('direction') == 'asc' ? 'up' : 'down' }} ms-1"></i>
                                    @endif
                                </a>
                            </th>
                            <th class="text-end">Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        @forelse($groups as $group)
                            <tr data-id="{{ $group->id }}" data-order="{{ $group->sort_order }}">
                                <td class="reorder-handle d-none">
                                    <i class="bi bi-grip-vertical text-muted"></i>
                                </td>
                                <td>
                                    <span class="badge bg-secondary">{{ $group->sort_order }}</span>
                                </td>
                                <td>
                                    <div class="d-flex align-items-center">
                                        <div class="avatar-sm bg-primary bg-opacity-10 rounded-circle me-2">
                                            <i class="bi bi-collection text-primary"></i>
                                        </div>
                                        <div>
                                            <div class="fw-semibold">{{ $group->name }}</div>
                                        </div>
                                    </div>
                                </td>
                                <td>
                                    <code class="text-primary">{{ $group->slug }}</code>
                                </td>
                                <td>
                                    <span class="text-muted small">{{ Str::limit($group->description, 50) ?: '-' }}</span>
                                </td>
                                <td class="text-center">
                                    @if($group->permissions_count > 0)
                                        <span class="badge bg-success">{{ $group->permissions_count }}</span>
                                    @else
                                        <span class="badge bg-secondary">0</span>
                                    @endif
                                </td>
                                <td class="text-end">
                                    <div class="btn-group" role="group">
                                        <a href="{{ route('admin.groups.show', $group) }}"
                                           class="btn btn-sm btn-outline-info"
                                           title="View">
                                            <i class="bi bi-eye"></i>
                                        </a>
                                        @permission('groups.edit')
                                            <a href="{{ route('admin.groups.edit', $group) }}"
                                               class="btn btn-sm btn-outline-primary"
                                               title="Edit">
                                                <i class="bi bi-pencil"></i>
                                            </a>
                                        @endpermission
                                        @permission('groups.delete')
                                            @if($group->permissions_count == 0)
                                                <button type="button"
                                                        class="btn btn-sm btn-outline-danger"
                                                        onclick="deleteGroup({{ $group->id }}, '{{ $group->name }}')"
                                                        title="Delete">
                                                    <i class="bi bi-trash"></i>
                                                </button>
                                            @else
                                                <button type="button"
                                                        class="btn btn-sm btn-outline-danger"
                                                        disabled
                                                        title="Has permissions">
                                                    <i class="bi bi-trash"></i>
                                                </button>
                                            @endif
                                        @endpermission
                                    </div>
                                </td>
                            </tr>
                        @empty
                            <tr>
                                <td colspan="7" class="text-center py-4">
                                    <div class="text-muted">
                                        <i class="bi bi-inbox fs-1"></i>
                                        <p class="mt-2">No groups found</p>
                                    </div>
                                </td>
                            </tr>
                        @endforelse
                    </tbody>
                </table>
            </div>
        </div>
        @if($groups->hasPages())
            <div class="card-footer bg-white">
                <div class="d-flex justify-content-between align-items-center">
                    <div class="text-muted">
                        Showing {{ $groups->firstItem() }} to {{ $groups->lastItem() }} of {{ $groups->total() }} results
                    </div>
                    <div>
                        {{ $groups->links('pagination::bootstrap-5') }}
                    </div>
                </div>
            </div>
        @endif
    </div>
</div>
@endsection
blade
@extends('layouts.admin')

@section('title', 'Permission Groups 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">Permission Groups</h1>
                    <p class="text-muted mb-0">Organize permissions into logical categories</p>
                </div>
                <div>
                    @permission('groups.create')
                        <a href="{{ route('admin.groups.create') }}" class="btn btn-primary">
                            <i class="bi bi-plus-circle me-2"></i>Create New Group
                        </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 Groups
                            </div>
                            <div class="h5 mb-0 font-weight-bold">{{ \RbacSuite\OmniAccess\Models\Group::count() }}</div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-collection 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">
                                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-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">
                                Grouped Permissions
                            </div>
                            <div class="h5 mb-0 font-weight-bold">
                                {{ \RbacSuite\OmniAccess\Models\Permission::whereNotNull('group_id')->count() }}
                            </div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-diagram-3 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">
                                Ungrouped
                            </div>
                            <div class="h5 mb-0 font-weight-bold">
                                {{ \RbacSuite\OmniAccess\Models\Permission::whereNull('group_id')->count() }}
                            </div>
                        </div>
                        <div class="col-auto">
                            <i class="bi bi-exclamation-circle 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

    <!-- 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.groups.index') }}" method="GET" class="d-flex">
                        <div class="input-group">
                            <input type="text"
                                   name="search"
                                   class="form-control"
                                   placeholder="Search groups..."
                                   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.groups.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">
                    @permission('groups.edit')
                        <button type="button" class="btn btn-outline-primary" onclick="enableReorder()" id="reorderBtn">
                            <i class="bi bi-arrows-move me-1"></i>Reorder
                        </button>
                        <button type="button" class="btn btn-success d-none" onclick="saveOrder()" id="saveOrderBtn">
                            <i class="bi bi-save me-1"></i>Save Order
                        </button>
                        <button type="button" class="btn btn-secondary d-none" onclick="cancelReorder()" id="cancelOrderBtn">
                            <i class="bi bi-x me-1"></i>Cancel
                        </button>
                    @endpermission
                </div>
            </div>
        </div>
        <div class="card-body p-0">
            <div class="table-responsive">
                <table class="table table-hover mb-0" id="groupsTable">
                    <thead class="table-light">
                        <tr>
                            <th class="reorder-handle d-none" style="width: 40px;"></th>
                            <th>
                                <a href="{{ route('admin.groups.index', ['sort' => 'sort_order', 'direction' => request('direction') == 'asc' ? 'desc' : 'asc'] + request()->only('search')) }}"
                                   class="text-decoration-none text-dark">
                                    Order
                                    @if(request('sort') == 'sort_order')
                                        <i class="bi bi-chevron-{{ request('direction') == 'asc' ? 'up' : 'down' }} ms-1"></i>
                                    @endif
                                </a>
                            </th>
                            <th>Group Name</th>
                            <th>Slug</th>
                            <th>Description</th>
                            <th class="text-center">
                                <a href="{{ route('admin.groups.index', ['sort' => 'permissions_count', 'direction' => request('direction') == 'asc' ? 'desc' : 'asc'] + request()->only('search')) }}"
                                   class="text-decoration-none text-dark">
                                    Permissions
                                    @if(request('sort') == 'permissions_count')
                                        <i class="bi bi-chevron-{{ request('direction') == 'asc' ? 'up' : 'down' }} ms-1"></i>
                                    @endif
                                </a>
                            </th>
                            <th class="text-end">Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        @forelse($groups as $group)
                            <tr data-id="{{ $group->id }}" data-order="{{ $group->sort_order }}">
                                <td class="reorder-handle d-none">
                                    <i class="bi bi-grip-vertical text-muted"></i>
                                </td>
                                <td>
                                    <span class="badge bg-secondary">{{ $group->sort_order }}</span>
                                </td>
                                <td>
                                    <div class="d-flex align-items-center">
                                        <div class="avatar-sm bg-primary bg-opacity-10 rounded-circle me-2">
                                            <i class="bi bi-collection text-primary"></i>
                                        </div>
                                        <div>
                                            <div class="fw-semibold">{{ $group->name }}</div>
                                        </div>
                                    </div>
                                </td>
                                <td>
                                    <code class="text-primary">{{ $group->slug }}</code>
                                </td>
                                <td>
                                    <span class="text-muted small">{{ Str::limit($group->description, 50) ?: '-' }}</span>
                                </td>
                                <td class="text-center">
                                    @if($group->permissions_count > 0)
                                        <span class="badge bg-success">{{ $group->permissions_count }}</span>
                                    @else
                                        <span class="badge bg-secondary">0</span>
                                    @endif
                                </td>
                                <td class="text-end">
                                    <div class="btn-group" role="group">
                                        <a href="{{ route('admin.groups.show', $group) }}"
                                           class="btn btn-sm btn-outline-info"
                                           title="View">
                                            <i class="bi bi-eye"></i>
                                        </a>
                                        @permission('groups.edit')
                                            <a href="{{ route('admin.groups.edit', $group) }}"
                                               class="btn btn-sm btn-outline-primary"
                                               title="Edit">
                                                <i class="bi bi-pencil"></i>
                                            </a>
                                        @endpermission
                                        @permission('groups.delete')
                                            @if($group->permissions_count == 0)
                                                <button type="button"
                                                        class="btn btn-sm btn-outline-danger"
                                                        onclick="deleteGroup({{ $group->id }}, '{{ $group->name }}')"
                                                        title="Delete">
                                                    <i class="bi bi-trash"></i>
                                                </button>
                                            @else
                                                <button type="button"
                                                        class="btn btn-sm btn-outline-danger"
                                                        disabled
                                                        title="Has permissions">
                                                    <i class="bi bi-trash"></i>
                                                </button>
                                            @endif
                                        @endpermission
                                    </div>
                                </td>
                            </tr>
                        @empty
                            <tr>
                                <td colspan="7" class="text-center py-4">
                                    <div class="text-muted">
                                        <i class="bi bi-inbox fs-1"></i>
                                        <p class="mt-2">No groups found</p>
                                    </div>
                                </td>
                            </tr>
                        @endforelse
                    </tbody>
                </table>
            </div>
        </div>
        @if($groups->hasPages())
            <div class="card-footer bg-white">
                <div class="d-flex justify-content-between align-items-center">
                    <div class="text-muted">
                        Showing {{ $groups->firstItem() }} to {{ $groups->lastItem() }} of {{ $groups->total() }} results
                    </div>
                    <div>
                        {{ $groups->links('pagination::bootstrap-5') }}
                    </div>
                </div>
            </div>
        @endif
    </div>
</div>
@endsection
Step 4 of 8

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

@extends('layouts.admin')

@section('title', 'Create Permission Group')

@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.groups.index') }}">Permission Groups</a></li>
                    <li class="breadcrumb-item active">Create Group</li>
                </ol>
            </nav>
            <h1 class="h3 mb-0 text-gray-800">Create New Permission Group</h1>
        </div>
    </div>

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

        <div class="row">
            <!-- Group Information -->
            <div class="col-lg-8">
                <div class="card shadow-sm">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Group Information</h5>
                    </div>
                    <div class="card-body">
                        <div class="mb-3">
                            <label for="name" class="form-label">Group 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., User Management"
                                   required>
                            @error('name')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Display name for the permission group</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., user-management"
                                   pattern="[a-z0-9\-]+"
                                   required>
                            @error('slug')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Unique identifier (lowercase, hyphens only)</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 what permissions in this group control...">{{ old('description') }}</textarea>
                            @error('description')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="sort_order" class="form-label">Sort Order</label>
                            <input type="number"
                                   class="form-control @error('sort_order') is-invalid @enderror"
                                   id="sort_order"
                                   name="sort_order"
                                   value="{{ old('sort_order', $suggestedSortOrder) }}"
                                   min="0"
                                   step="10">
                            @error('sort_order')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Lower numbers appear first (suggested: {{ $suggestedSortOrder }})</small>
                        </div>
                    </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 Group
                        </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.groups.index') }}" class="btn btn-outline-secondary w-100">
                            <i class="bi bi-x-circle me-2"></i>Cancel
                        </a>
                    </div>
                </div>

                <!-- Common Group Examples -->
                <div class="card shadow-sm">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-lightbulb me-2"></i>Common Groups</h5>
                    </div>
                    <div class="card-body">
                        <p class="small text-muted mb-3">Click to use these common group patterns:</p>
                        <div class="d-grid gap-2">
                            <button type="button" class="btn btn-sm btn-outline-secondary text-start"
                                    onclick="fillGroup('User Management', 'user-management', 'Permissions for managing users and roles')">
                                <i class="bi bi-people me-2"></i>User Management
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary text-start"
                                    onclick="fillGroup('Content Management', 'content-management', 'Permissions for managing content')">
                                <i class="bi bi-file-text me-2"></i>Content Management
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary text-start"
                                    onclick="fillGroup('System Settings', 'system-settings', 'Permissions for system configuration')">
                                <i class="bi bi-gear me-2"></i>System Settings
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary text-start"
                                    onclick="fillGroup('Reports', 'reports', 'Permissions for viewing and generating reports')">
                                <i class="bi bi-graph-up me-2"></i>Reports
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary text-start"
                                    onclick="fillGroup('API Access', 'api-access', 'Permissions for API endpoints')">
                                <i class="bi bi-plug me-2"></i>API Access
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </form>
</div>
@endsection
blade
@extends('layouts.admin')

@section('title', 'Create Permission Group')

@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.groups.index') }}">Permission Groups</a></li>
                    <li class="breadcrumb-item active">Create Group</li>
                </ol>
            </nav>
            <h1 class="h3 mb-0 text-gray-800">Create New Permission Group</h1>
        </div>
    </div>

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

        <div class="row">
            <!-- Group Information -->
            <div class="col-lg-8">
                <div class="card shadow-sm">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Group Information</h5>
                    </div>
                    <div class="card-body">
                        <div class="mb-3">
                            <label for="name" class="form-label">Group 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., User Management"
                                   required>
                            @error('name')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Display name for the permission group</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., user-management"
                                   pattern="[a-z0-9\-]+"
                                   required>
                            @error('slug')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Unique identifier (lowercase, hyphens only)</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 what permissions in this group control...">{{ old('description') }}</textarea>
                            @error('description')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="sort_order" class="form-label">Sort Order</label>
                            <input type="number"
                                   class="form-control @error('sort_order') is-invalid @enderror"
                                   id="sort_order"
                                   name="sort_order"
                                   value="{{ old('sort_order', $suggestedSortOrder) }}"
                                   min="0"
                                   step="10">
                            @error('sort_order')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Lower numbers appear first (suggested: {{ $suggestedSortOrder }})</small>
                        </div>
                    </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 Group
                        </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.groups.index') }}" class="btn btn-outline-secondary w-100">
                            <i class="bi bi-x-circle me-2"></i>Cancel
                        </a>
                    </div>
                </div>

                <!-- Common Group Examples -->
                <div class="card shadow-sm">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-lightbulb me-2"></i>Common Groups</h5>
                    </div>
                    <div class="card-body">
                        <p class="small text-muted mb-3">Click to use these common group patterns:</p>
                        <div class="d-grid gap-2">
                            <button type="button" class="btn btn-sm btn-outline-secondary text-start"
                                    onclick="fillGroup('User Management', 'user-management', 'Permissions for managing users and roles')">
                                <i class="bi bi-people me-2"></i>User Management
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary text-start"
                                    onclick="fillGroup('Content Management', 'content-management', 'Permissions for managing content')">
                                <i class="bi bi-file-text me-2"></i>Content Management
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary text-start"
                                    onclick="fillGroup('System Settings', 'system-settings', 'Permissions for system configuration')">
                                <i class="bi bi-gear me-2"></i>System Settings
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary text-start"
                                    onclick="fillGroup('Reports', 'reports', 'Permissions for viewing and generating reports')">
                                <i class="bi bi-graph-up me-2"></i>Reports
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary text-start"
                                    onclick="fillGroup('API Access', 'api-access', 'Permissions for API endpoints')">
                                <i class="bi bi-plug me-2"></i>API Access
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </form>
</div>
@endsection
Step 5 of 8

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

@extends('layouts.admin')

@section('title', 'Edit Group - ' . $group->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.groups.index') }}">Permission Groups</a></li>
                    <li class="breadcrumb-item active">Edit Group</li>
                </ol>
            </nav>
            <div class="d-flex justify-content-between align-items-center">
                <h1 class="h3 mb-0 text-gray-800">Edit Group: {{ $group->name }}</h1>
                <a href="{{ route('admin.groups.show', $group) }}" class="btn btn-outline-info">
                    <i class="bi bi-eye me-2"></i>View Group
                </a>
            </div>
        </div>
    </div>

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

        <div class="row">
            <!-- Group Information -->
            <div class="col-lg-8">
                <div class="card shadow-sm">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Group Information</h5>
                    </div>
                    <div class="card-body">
                        <div class="mb-3">
                            <label for="name" class="form-label">Group 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', $group->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', $group->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 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', $group->description) }}</textarea>
                            @error('description')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="sort_order" class="form-label">Sort Order</label>
                            <input type="number"
                                   class="form-control @error('sort_order') is-invalid @enderror"
                                   id="sort_order"
                                   name="sort_order"
                                   value="{{ old('sort_order', $group->sort_order) }}"
                                   min="0"
                                   step="10">
                            @error('sort_order')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Lower numbers appear first</small>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Sidebar -->
            <div class="col-lg-4">
                <!-- 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.groups.index') }}" class="btn btn-outline-secondary w-100">
                            <i class="bi bi-x-circle me-2"></i>Cancel
                        </a>
                    </div>
                </div>

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

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

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

@section('title', 'Edit Group - ' . $group->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.groups.index') }}">Permission Groups</a></li>
                    <li class="breadcrumb-item active">Edit Group</li>
                </ol>
            </nav>
            <div class="d-flex justify-content-between align-items-center">
                <h1 class="h3 mb-0 text-gray-800">Edit Group: {{ $group->name }}</h1>
                <a href="{{ route('admin.groups.show', $group) }}" class="btn btn-outline-info">
                    <i class="bi bi-eye me-2"></i>View Group
                </a>
            </div>
        </div>
    </div>

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

        <div class="row">
            <!-- Group Information -->
            <div class="col-lg-8">
                <div class="card shadow-sm">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Group Information</h5>
                    </div>
                    <div class="card-body">
                        <div class="mb-3">
                            <label for="name" class="form-label">Group 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', $group->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', $group->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 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', $group->description) }}</textarea>
                            @error('description')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="sort_order" class="form-label">Sort Order</label>
                            <input type="number"
                                   class="form-control @error('sort_order') is-invalid @enderror"
                                   id="sort_order"
                                   name="sort_order"
                                   value="{{ old('sort_order', $group->sort_order) }}"
                                   min="0"
                                   step="10">
                            @error('sort_order')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                            <small class="form-text text-muted">Lower numbers appear first</small>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Sidebar -->
            <div class="col-lg-4">
                <!-- 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.groups.index') }}" class="btn btn-outline-secondary w-100">
                            <i class="bi bi-x-circle me-2"></i>Cancel
                        </a>
                    </div>
                </div>

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

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

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

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

@extends('layouts.admin')

@section('title', 'Group Details - ' . $group->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.groups.index') }}">Permission Groups</a></li>
                    <li class="breadcrumb-item active">{{ $group->name }}</li>
                </ol>
            </nav>
            <div class="d-flex justify-content-between align-items-center">
                <div>
                    <h1 class="h3 mb-2 text-gray-800">{{ $group->name }}</h1>
                    <code class="fs-6 text-primary">{{ $group->slug }}</code>
                </div>
                <div>
                    @permission('groups.edit')
                        <a href="{{ route('admin.groups.edit', $group) }}" class="btn btn-primary">
                            <i class="bi bi-pencil me-2"></i>Edit Group
                        </a>
                    @endpermission
                </div>
            </div>
        </div>
    </div>

    <div class="row">
        <!-- Group 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>Group Information</h5>
                </div>
                <div class="card-body">
                    <dl class="row">
                        <dt class="col-sm-4">Name:</dt>
                        <dd class="col-sm-8">{{ $group->name }}</dd>

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

                        <dt class="col-sm-4">Sort Order:</dt>
                        <dd class="col-sm-8">
                            <span class="badge bg-secondary">{{ $group->sort_order }}</span>
                        </dd>

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

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

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

                    <hr>

                    <div class="text-center">
                        <h3 class="mb-0">{{ $group->permissions->count() }}</h3>
                        <p class="text-muted mb-0">Permissions in this group</p>
                    </div>
                </div>
            </div>

            <!-- Quick Actions -->
            <div class="card shadow-sm mt-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">
                    @permission('groups.edit')
                        <a href="{{ route('admin.groups.edit', $group) }}" class="btn btn-outline-primary w-100 mb-2">
                            <i class="bi bi-pencil me-2"></i>Edit Group
                        </a>
                    @endpermission

                    @permission('permissions.create')
                        <a href="{{ route('admin.permissions.create', ['group_id' => $group->id]) }}" class="btn btn-outline-success w-100 mb-2">
                            <i class="bi bi-plus-circle me-2"></i>Add Permission
                        </a>
                    @endpermission

                    @permission('groups.delete')
                        @if($group->permissions->isEmpty())
                            <button type="button"
                                    class="btn btn-outline-danger w-100"
                                    onclick="confirmDelete()">
                                <i class="bi bi-trash me-2"></i>Delete Group
                            </button>
                        @else
                            <button type="button" class="btn btn-outline-danger w-100" disabled>
                                <i class="bi bi-lock me-2"></i>Cannot Delete (Has Permissions)
                            </button>
                        @endif
                    @endpermission
                </div>
            </div>
        </div>

        <!-- Permissions in Group -->
        <div class="col-lg-8 mb-4">
            <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 in this Group
                        <span class="badge bg-primary ms-2">{{ $group->permissions->count() }}</span>
                    </h5>
                    @permission('permissions.create')
                        <a href="{{ route('admin.permissions.create', ['group_id' => $group->id]) }}" class="btn btn-sm btn-primary">
                            <i class="bi bi-plus-circle me-1"></i>Add Permission
                        </a>
                    @endpermission
                </div>
                <div class="card-body">
                    @forelse($group->permissions as $permission)
                        <div class="border-bottom pb-3 mb-3">
                            <div class="d-flex justify-content-between align-items-start">
                                <div>
                                    <h6 class="mb-1">
                                        {{ $permission->name }}
                                        @if($permission->roles_count > 0)
                                            <span class="badge bg-success ms-2">
                                                {{ $permission->roles_count }} roles
                                            </span>
                                        @else
                                            <span class="badge bg-warning ms-2">
                                                Unassigned
                                            </span>
                                        @endif
                                    </h6>
                                    <code class="text-primary">{{ $permission->slug }}</code>
                                    @if($permission->description)
                                        <p class="text-muted small mb-0 mt-1">{{ $permission->description }}</p>
                                    @endif
                                </div>
                                <div class="btn-group" role="group">
                                    <a href="{{ route('admin.permissions.show', $permission) }}"
                                       class="btn btn-sm btn-outline-info"
                                       title="View">
                                        <i class="bi bi-eye"></i>
                                    </a>
                                    @permission('permissions.edit')
                                        <a href="{{ route('admin.permissions.edit', $permission) }}"
                                           class="btn btn-sm btn-outline-primary"
                                           title="Edit">
                                            <i class="bi bi-pencil"></i>
                                        </a>
                                    @endpermission
                                </div>
                            </div>
                        </div>
                    @empty
                        <div class="text-center py-5">
                            <i class="bi bi-key-fill fs-1 text-muted"></i>
                            <p class="mt-2 text-muted">No permissions in this group</p>
                            @permission('permissions.create')
                                <a href="{{ route('admin.permissions.create', ['group_id' => $group->id]) }}" class="btn btn-primary">
                                    <i class="bi bi-plus-circle me-2"></i>Add First Permission
                                </a>
                            @endpermission
                        </div>
                    @endforelse
                </div>
            </div>

            @if($group->permissions->count() > 0)
                <!-- Permission Statistics -->
                <div class="card shadow-sm mt-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-bar-chart me-2"></i>Statistics</h5>
                    </div>
                    <div class="card-body">
                        <div class="row text-center">
                            <div class="col-4">
                                <h4>{{ $group->permissions->count() }}</h4>
                                <p class="text-muted mb-0">Total Permissions</p>
                            </div>
                            <div class="col-4">
                                <h4>{{ $group->permissions->sum('roles_count') }}</h4>
                                <p class="text-muted mb-0">Role Assignments</p>
                            </div>
                            <div class="col-4">
                                <h4>{{ $group->permissions->filter(fn($p) => $p->roles_count === 0)->count() }}</h4>
                                <p class="text-muted mb-0">Unassigned</p>
                            </div>
                        </div>
                    </div>
                </div>
            @endif
        </div>
    </div>
</div>

@push('scripts')
<script>
    function confirmDelete() {
        if (confirm('Are you sure you want to delete this group? This action cannot be undone.')) {
            fetch('{{ route("admin.groups.destroy", $group) }}', {
                method: 'DELETE',
                headers: {
                    'X-CSRF-TOKEN': '{{ csrf_token() }}',
                    'Accept': 'application/json'
                }
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    window.location.href = '{{ route("admin.groups.index") }}';
                } else {
                    alert(data.message || 'Error deleting group');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                alert('An error occurred');
            });
        }
    }
</script>
@endpush
@endsection
blade
@extends('layouts.admin')

@section('title', 'Group Details - ' . $group->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.groups.index') }}">Permission Groups</a></li>
                    <li class="breadcrumb-item active">{{ $group->name }}</li>
                </ol>
            </nav>
            <div class="d-flex justify-content-between align-items-center">
                <div>
                    <h1 class="h3 mb-2 text-gray-800">{{ $group->name }}</h1>
                    <code class="fs-6 text-primary">{{ $group->slug }}</code>
                </div>
                <div>
                    @permission('groups.edit')
                        <a href="{{ route('admin.groups.edit', $group) }}" class="btn btn-primary">
                            <i class="bi bi-pencil me-2"></i>Edit Group
                        </a>
                    @endpermission
                </div>
            </div>
        </div>
    </div>

    <div class="row">
        <!-- Group 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>Group Information</h5>
                </div>
                <div class="card-body">
                    <dl class="row">
                        <dt class="col-sm-4">Name:</dt>
                        <dd class="col-sm-8">{{ $group->name }}</dd>

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

                        <dt class="col-sm-4">Sort Order:</dt>
                        <dd class="col-sm-8">
                            <span class="badge bg-secondary">{{ $group->sort_order }}</span>
                        </dd>

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

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

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

                    <hr>

                    <div class="text-center">
                        <h3 class="mb-0">{{ $group->permissions->count() }}</h3>
                        <p class="text-muted mb-0">Permissions in this group</p>
                    </div>
                </div>
            </div>

            <!-- Quick Actions -->
            <div class="card shadow-sm mt-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">
                    @permission('groups.edit')
                        <a href="{{ route('admin.groups.edit', $group) }}" class="btn btn-outline-primary w-100 mb-2">
                            <i class="bi bi-pencil me-2"></i>Edit Group
                        </a>
                    @endpermission

                    @permission('permissions.create')
                        <a href="{{ route('admin.permissions.create', ['group_id' => $group->id]) }}" class="btn btn-outline-success w-100 mb-2">
                            <i class="bi bi-plus-circle me-2"></i>Add Permission
                        </a>
                    @endpermission

                    @permission('groups.delete')
                        @if($group->permissions->isEmpty())
                            <button type="button"
                                    class="btn btn-outline-danger w-100"
                                    onclick="confirmDelete()">
                                <i class="bi bi-trash me-2"></i>Delete Group
                            </button>
                        @else
                            <button type="button" class="btn btn-outline-danger w-100" disabled>
                                <i class="bi bi-lock me-2"></i>Cannot Delete (Has Permissions)
                            </button>
                        @endif
                    @endpermission
                </div>
            </div>
        </div>

        <!-- Permissions in Group -->
        <div class="col-lg-8 mb-4">
            <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 in this Group
                        <span class="badge bg-primary ms-2">{{ $group->permissions->count() }}</span>
                    </h5>
                    @permission('permissions.create')
                        <a href="{{ route('admin.permissions.create', ['group_id' => $group->id]) }}" class="btn btn-sm btn-primary">
                            <i class="bi bi-plus-circle me-1"></i>Add Permission
                        </a>
                    @endpermission
                </div>
                <div class="card-body">
                    @forelse($group->permissions as $permission)
                        <div class="border-bottom pb-3 mb-3">
                            <div class="d-flex justify-content-between align-items-start">
                                <div>
                                    <h6 class="mb-1">
                                        {{ $permission->name }}
                                        @if($permission->roles_count > 0)
                                            <span class="badge bg-success ms-2">
                                                {{ $permission->roles_count }} roles
                                            </span>
                                        @else
                                            <span class="badge bg-warning ms-2">
                                                Unassigned
                                            </span>
                                        @endif
                                    </h6>
                                    <code class="text-primary">{{ $permission->slug }}</code>
                                    @if($permission->description)
                                        <p class="text-muted small mb-0 mt-1">{{ $permission->description }}</p>
                                    @endif
                                </div>
                                <div class="btn-group" role="group">
                                    <a href="{{ route('admin.permissions.show', $permission) }}"
                                       class="btn btn-sm btn-outline-info"
                                       title="View">
                                        <i class="bi bi-eye"></i>
                                    </a>
                                    @permission('permissions.edit')
                                        <a href="{{ route('admin.permissions.edit', $permission) }}"
                                           class="btn btn-sm btn-outline-primary"
                                           title="Edit">
                                            <i class="bi bi-pencil"></i>
                                        </a>
                                    @endpermission
                                </div>
                            </div>
                        </div>
                    @empty
                        <div class="text-center py-5">
                            <i class="bi bi-key-fill fs-1 text-muted"></i>
                            <p class="mt-2 text-muted">No permissions in this group</p>
                            @permission('permissions.create')
                                <a href="{{ route('admin.permissions.create', ['group_id' => $group->id]) }}" class="btn btn-primary">
                                    <i class="bi bi-plus-circle me-2"></i>Add First Permission
                                </a>
                            @endpermission
                        </div>
                    @endforelse
                </div>
            </div>

            @if($group->permissions->count() > 0)
                <!-- Permission Statistics -->
                <div class="card shadow-sm mt-4">
                    <div class="card-header bg-white">
                        <h5 class="mb-0"><i class="bi bi-bar-chart me-2"></i>Statistics</h5>
                    </div>
                    <div class="card-body">
                        <div class="row text-center">
                            <div class="col-4">
                                <h4>{{ $group->permissions->count() }}</h4>
                                <p class="text-muted mb-0">Total Permissions</p>
                            </div>
                            <div class="col-4">
                                <h4>{{ $group->permissions->sum('roles_count') }}</h4>
                                <p class="text-muted mb-0">Role Assignments</p>
                            </div>
                            <div class="col-4">
                                <h4>{{ $group->permissions->filter(fn($p) => $p->roles_count === 0)->count() }}</h4>
                                <p class="text-muted mb-0">Unassigned</p>
                            </div>
                        </div>
                    </div>
                </div>
            @endif
        </div>
    </div>
</div>

@push('scripts')
<script>
    function confirmDelete() {
        if (confirm('Are you sure you want to delete this group? This action cannot be undone.')) {
            fetch('{{ route("admin.groups.destroy", $group) }}', {
                method: 'DELETE',
                headers: {
                    'X-CSRF-TOKEN': '{{ csrf_token() }}',
                    'Accept': 'application/json'
                }
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    window.location.href = '{{ route("admin.groups.index") }}';
                } else {
                    alert(data.message || 'Error deleting group');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                alert('An error occurred');
            });
        }
    }
</script>
@endpush
@endsection
Step 7 of 8

Routes Configuration

// Add to routes/web.php

Route::prefix('admin')->name('admin.')->middleware(['auth'])->group(function () {

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

        // Additional routes
        Route::post('/reorder', [GroupController::class, 'reorder'])->name('reorder');
        Route::post('/{group}/move-permissions', [GroupController::class, 'movePermissions'])->name('move-permissions');
    });
});
php
// Add to routes/web.php

Route::prefix('admin')->name('admin.')->middleware(['auth'])->group(function () {

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

        // Additional routes
        Route::post('/reorder', [GroupController::class, 'reorder'])->name('reorder');
        Route::post('/{group}/move-permissions', [GroupController::class, 'movePermissions'])->name('move-permissions');
    });
});
Step 8 of 8

JavaScript Functions for Group Views

// Group-specific JavaScript functions

// 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;
});

// Fill group form with template
function fillGroup(name, slug, description) {
    document.getElementById('name').value = name;
    document.getElementById('slug').value = slug;
    document.getElementById('description').value = description;
}

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

    fetch(`/admin/groups/${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 group');
        }
    })
    .catch(error => {
        console.error('Error:', error);
        alert('An error occurred while deleting the group');
    });
}

// Enable reordering
let originalOrder = [];

function enableReorder() {
    document.querySelectorAll('.reorder-handle').forEach(el => el.classList.remove('d-none'));
    document.getElementById('reorderBtn').classList.add('d-none');
    document.getElementById('saveOrderBtn').classList.remove('d-none');
    document.getElementById('cancelOrderBtn').classList.remove('d-none');

    // Store original order
    originalOrder = [];
    document.querySelectorAll('#groupsTable tbody tr').forEach(row => {
        originalOrder.push({
            id: row.dataset.id,
            order: row.dataset.order
        });
    });

    // Enable drag and drop
    enableDragAndDrop();
}

// Cancel reordering
function cancelReorder() {
    document.querySelectorAll('.reorder-handle').forEach(el => el.classList.add('d-none'));
    document.getElementById('reorderBtn').classList.remove('d-none');
    document.getElementById('saveOrderBtn').classList.add('d-none');
    document.getElementById('cancelOrderBtn').classList.add('d-none');

    // Restore original order if needed
    location.reload();
}

// Save new order
function saveOrder() {
    const groups = [];
    let sortOrder = 10;

    document.querySelectorAll('#groupsTable tbody tr').forEach(row => {
        if (row.dataset.id) {
            groups.push({
                id: parseInt(row.dataset.id),
                sort_order: sortOrder
            });
            sortOrder += 10;
        }
    });

    fetch('/admin/groups/reorder', {
        method: 'POST',
        headers: {
            'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ groups: groups })
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            location.reload();
        } else {
            alert('Error saving order');
        }
    })
    .catch(error => {
        console.error('Error:', error);
        alert('An error occurred');
    });
}

// Enable drag and drop for reordering
function enableDragAndDrop() {
    const tbody = document.querySelector('#groupsTable tbody');
    if (!tbody) return;

    let draggedElement = null;

    tbody.querySelectorAll('tr').forEach(row => {
        row.draggable = true;
        row.style.cursor = 'move';

        row.addEventListener('dragstart', function(e) {
            draggedElement = this;
            this.style.opacity = '0.5';
        });

        row.addEventListener('dragend', function(e) {
            this.style.opacity = '';
        });

        row.addEventListener('dragover', function(e) {
            e.preventDefault();
            this.style.backgroundColor = '#f0f0f0';
        });

        row.addEventListener('dragleave', function(e) {
            this.style.backgroundColor = '';
        });

        row.addEventListener('drop', function(e) {
            e.preventDefault();
            this.style.backgroundColor = '';

            if (this !== draggedElement) {
                if (this.parentNode) {
                    this.parentNode.insertBefore(draggedElement, this.nextSibling);
                }
            }
        });
    });
}

✓ Complete CRUD Package! You now have full CRUD examples for Roles, Permissions, and Permission Groups - all ready to copy and use in your Laravel application with OMNI Access.

Pro Tip: Add <meta name="csrf-token" content="{{ csrf_token() }}"> to your layout's head section for AJAX requests to work properly.

Note: Remember to create a base layout at resources/views/layouts/admin.blade.php with Bootstrap 5 CSS and JS included.

javascript
// Group-specific JavaScript functions

// 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;
});

// Fill group form with template
function fillGroup(name, slug, description) {
    document.getElementById('name').value = name;
    document.getElementById('slug').value = slug;
    document.getElementById('description').value = description;
}

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

    fetch(`/admin/groups/${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 group');
        }
    })
    .catch(error => {
        console.error('Error:', error);
        alert('An error occurred while deleting the group');
    });
}

// Enable reordering
let originalOrder = [];

function enableReorder() {
    document.querySelectorAll('.reorder-handle').forEach(el => el.classList.remove('d-none'));
    document.getElementById('reorderBtn').classList.add('d-none');
    document.getElementById('saveOrderBtn').classList.remove('d-none');
    document.getElementById('cancelOrderBtn').classList.remove('d-none');

    // Store original order
    originalOrder = [];
    document.querySelectorAll('#groupsTable tbody tr').forEach(row => {
        originalOrder.push({
            id: row.dataset.id,
            order: row.dataset.order
        });
    });

    // Enable drag and drop
    enableDragAndDrop();
}

// Cancel reordering
function cancelReorder() {
    document.querySelectorAll('.reorder-handle').forEach(el => el.classList.add('d-none'));
    document.getElementById('reorderBtn').classList.remove('d-none');
    document.getElementById('saveOrderBtn').classList.add('d-none');
    document.getElementById('cancelOrderBtn').classList.add('d-none');

    // Restore original order if needed
    location.reload();
}

// Save new order
function saveOrder() {
    const groups = [];
    let sortOrder = 10;

    document.querySelectorAll('#groupsTable tbody tr').forEach(row => {
        if (row.dataset.id) {
            groups.push({
                id: parseInt(row.dataset.id),
                sort_order: sortOrder
            });
            sortOrder += 10;
        }
    });

    fetch('/admin/groups/reorder', {
        method: 'POST',
        headers: {
            'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ groups: groups })
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            location.reload();
        } else {
            alert('Error saving order');
        }
    })
    .catch(error => {
        console.error('Error:', error);
        alert('An error occurred');
    });
}

// Enable drag and drop for reordering
function enableDragAndDrop() {
    const tbody = document.querySelector('#groupsTable tbody');
    if (!tbody) return;

    let draggedElement = null;

    tbody.querySelectorAll('tr').forEach(row => {
        row.draggable = true;
        row.style.cursor = 'move';

        row.addEventListener('dragstart', function(e) {
            draggedElement = this;
            this.style.opacity = '0.5';
        });

        row.addEventListener('dragend', function(e) {
            this.style.opacity = '';
        });

        row.addEventListener('dragover', function(e) {
            e.preventDefault();
            this.style.backgroundColor = '#f0f0f0';
        });

        row.addEventListener('dragleave', function(e) {
            this.style.backgroundColor = '';
        });

        row.addEventListener('drop', function(e) {
            e.preventDefault();
            this.style.backgroundColor = '';

            if (this !== draggedElement) {
                if (this.parentNode) {
                    this.parentNode.insertBefore(draggedElement, this.nextSibling);
                }
            }
        });
    });
}
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