parent
9b6cd32b0c
commit
258ebeff69
10 changed files with 191 additions and 208 deletions
@ -1,44 +0,0 @@ |
|||||||
<?php |
|
||||||
namespace App\Components\Permission; |
|
||||||
|
|
||||||
use Livewire\Component; |
|
||||||
use Spatie\Permission\Models\Permission; |
|
||||||
|
|
||||||
class Form extends Component |
|
||||||
{ |
|
||||||
public $permissionId; |
|
||||||
public $name; |
|
||||||
|
|
||||||
protected function rules() |
|
||||||
{ |
|
||||||
return [ |
|
||||||
'name' => 'required|string|unique:permissions,name' . |
|
||||||
($this->permissionId ? ",{$this->permissionId}" : ''), |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
public function mount($permissionId = null) |
|
||||||
{ |
|
||||||
$this->permissionId = $permissionId; |
|
||||||
if ($permissionId) { |
|
||||||
$perm = Permission::findOrFail($permissionId); |
|
||||||
$this->name = $perm->name; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public function save() |
|
||||||
{ |
|
||||||
$this->validate(); |
|
||||||
Permission::updateOrCreate( |
|
||||||
['id' => $this->permissionId], |
|
||||||
['name' => $this->name] |
|
||||||
); |
|
||||||
session()->flash('message', 'Permission saved.'); |
|
||||||
$this->emitUp('permissionSaved'); |
|
||||||
} |
|
||||||
|
|
||||||
public function render() |
|
||||||
{ |
|
||||||
return view('components.permission.form'); |
|
||||||
} |
|
||||||
} |
|
@ -1,31 +0,0 @@ |
|||||||
<?php |
|
||||||
namespace App\Components\Permission; |
|
||||||
|
|
||||||
use Livewire\Component; |
|
||||||
use Livewire\WithPagination; |
|
||||||
use Spatie\Permission\Models\Permission; |
|
||||||
|
|
||||||
class Index extends Component |
|
||||||
{ |
|
||||||
use WithPagination; |
|
||||||
protected string $paginationTheme = 'bootstrap'; |
|
||||||
public $search = ''; |
|
||||||
protected $listeners = ['permissionSaved' => '$refresh']; |
|
||||||
|
|
||||||
public function updatingSearch() { $this->resetPage(); } |
|
||||||
|
|
||||||
public function delete($id) |
|
||||||
{ |
|
||||||
Permission::findOrFail($id)->delete(); |
|
||||||
session()->flash('message', 'Permission deleted.'); |
|
||||||
} |
|
||||||
|
|
||||||
public function render() |
|
||||||
{ |
|
||||||
$permissions = Permission::where('name', 'like', "%{$this->search}%") |
|
||||||
->orderByDesc('id') |
|
||||||
->paginate(10); |
|
||||||
|
|
||||||
return view('components.permission.index', compact('permissions')); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,80 @@ |
|||||||
|
<?php |
||||||
|
namespace App\Components\Permission; |
||||||
|
|
||||||
|
use Livewire\Component; |
||||||
|
use Livewire\WithPagination; |
||||||
|
use Spatie\Permission\Models\Permission; |
||||||
|
|
||||||
|
class Manager extends Component |
||||||
|
{ |
||||||
|
use WithPagination; |
||||||
|
protected string $paginationTheme = 'bootstrap'; |
||||||
|
|
||||||
|
public string $mode = 'index'; // 'index' hoặc 'form' |
||||||
|
public ?int $editingId = null; // id đang edit |
||||||
|
public string $search = ''; // search query |
||||||
|
public string $name = ''; // dùng cho form |
||||||
|
|
||||||
|
protected $listeners = [ |
||||||
|
'permissionSaved' => 'showIndex', |
||||||
|
]; |
||||||
|
|
||||||
|
// Khi search thay đổi, reset pagination |
||||||
|
public function updatingSearch() |
||||||
|
{ |
||||||
|
$this->resetPage(); |
||||||
|
} |
||||||
|
|
||||||
|
// Chuyển sang form (create/edit) |
||||||
|
public function showForm(int $id = null) |
||||||
|
{ |
||||||
|
$this->mode = 'form'; |
||||||
|
$this->editingId = $id; |
||||||
|
$this->name = $id |
||||||
|
? Permission::findOrFail($id)->name |
||||||
|
: ''; |
||||||
|
} |
||||||
|
|
||||||
|
// Quay về index, refresh list |
||||||
|
public function showIndex() |
||||||
|
{ |
||||||
|
$this->mode = 'index'; |
||||||
|
$this->resetPage(); |
||||||
|
$this->name = ''; |
||||||
|
$this->editingId = null; |
||||||
|
} |
||||||
|
|
||||||
|
// Xóa |
||||||
|
public function delete(int $id) |
||||||
|
{ |
||||||
|
Permission::findOrFail($id)->delete(); |
||||||
|
session()->flash('message', 'Permission deleted.'); |
||||||
|
$this->resetPage(); |
||||||
|
} |
||||||
|
|
||||||
|
// Lưu form |
||||||
|
public function save() |
||||||
|
{ |
||||||
|
$rules = ['name' => 'required|string|unique:permissions,name' |
||||||
|
.($this->editingId ? ",{$this->editingId}" : '')]; |
||||||
|
|
||||||
|
$this->validate($rules); |
||||||
|
|
||||||
|
Permission::updateOrCreate( |
||||||
|
['id' => $this->editingId], |
||||||
|
['name' => $this->name] |
||||||
|
); |
||||||
|
|
||||||
|
session()->flash('message', 'Permission saved.'); |
||||||
|
$this->emit('permissionSaved'); |
||||||
|
} |
||||||
|
|
||||||
|
public function render() |
||||||
|
{ |
||||||
|
$permissions = Permission::where('name', 'like', "%{$this->search}%") |
||||||
|
->orderByDesc('id') |
||||||
|
->paginate(10); |
||||||
|
|
||||||
|
return view('components.permission.manager', compact('permissions')); |
||||||
|
} |
||||||
|
} |
@ -1,8 +0,0 @@ |
|||||||
@extends('layouts.app') |
|
||||||
|
|
||||||
@section('title', isset($permissionId) ? 'Edit Permission' : 'Create Permission') |
|
||||||
|
|
||||||
@section('content') |
|
||||||
{{-- truyền permissionId nếu có --}} |
|
||||||
<livewire:permission.form :permission-id="$permissionId ?? null" /> |
|
||||||
@endsection |
|
@ -1,40 +0,0 @@ |
|||||||
<div class="row justify-content-center"> |
|
||||||
<div class="col-lg col-md-8"> |
|
||||||
<div class="card mb-4"> |
|
||||||
{{-- Card Header --}} |
|
||||||
<div class="card-header pb-0"> |
|
||||||
<h6 class="mb-0"> |
|
||||||
{{ $permissionId ? 'Edit Permission' : 'Create Permission' }} |
|
||||||
</h6> |
|
||||||
</div> |
|
||||||
{{-- Card Body --}} |
|
||||||
<div class="card-body"> |
|
||||||
@if (session()->has('message')) |
|
||||||
<div class="alert alert-success mb-3"> |
|
||||||
{{ session('message') }} |
|
||||||
</div> |
|
||||||
@endif |
|
||||||
|
|
||||||
<form wire:submit.prevent="save"> |
|
||||||
<div class="mb-3"> |
|
||||||
<label for="name" class="form-label">Name</label> |
|
||||||
<input id="name" type="text" wire:model.defer="name" class="form-control" |
|
||||||
placeholder="Enter permission name"> |
|
||||||
@error('name') |
|
||||||
<div class="text-danger text-xs mt-1">{{ $message }}</div> |
|
||||||
@enderror |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="d-flex justify-content-end"> |
|
||||||
<a href="{{ route('permissions.index') }}" class="btn btn-secondary btn-sm me-2"> |
|
||||||
Cancel |
|
||||||
</a> |
|
||||||
<button type="submit" class="btn btn-primary btn-sm"> |
|
||||||
{{ $permissionId ? 'Update' : 'Create' }} |
|
||||||
</button> |
|
||||||
</div> |
|
||||||
</form> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
@ -1,65 +0,0 @@ |
|||||||
<div class="row"> |
|
||||||
<div class="col-12"> |
|
||||||
<div class="card mb-4"> |
|
||||||
<!-- Card Header --> |
|
||||||
<div class="card-header pb-0 d-flex justify-content-between align-items-center"> |
|
||||||
<h6 class="mb-0">Permissions</h6> |
|
||||||
<div class="d-flex align-items-center"> |
|
||||||
{{-- Search field with Soft UI outline style --}} |
|
||||||
<div class="input-group input-group-outline me-2"> |
|
||||||
<input type="text" wire:model.debounce.500ms="search" wire:keydown.enter="resetPage" |
|
||||||
class="form-control" placeholder="Search permissions..."> |
|
||||||
</div> |
|
||||||
{{-- Search button --}} |
|
||||||
<button wire:click="resetPage" class="btn btn-sm btn-outline-secondary m-0" type="button"> |
|
||||||
<i class="fa-solid fa-magnifying-glass"></i> |
|
||||||
</button> |
|
||||||
{{-- New Permission button --}} |
|
||||||
<a href="{{ route('permissions.create') }}" class="btn btn-sm btn-primary ms-2 m-0">Create</a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<!-- Card Body --> |
|
||||||
<div class="card-body p-3"> |
|
||||||
@if (session()->has('message')) |
|
||||||
<div class="alert alert-success">{{ session('message') }}</div> |
|
||||||
@endif |
|
||||||
|
|
||||||
<div class="table-responsive"> |
|
||||||
<table class="table align-items-center mb-0"> |
|
||||||
<thead> |
|
||||||
<tr> |
|
||||||
<th class="text-center">ID</th> |
|
||||||
<th>Name</th> |
|
||||||
<th class="text-center">Actions</th> |
|
||||||
</tr> |
|
||||||
</thead> |
|
||||||
<tbody> |
|
||||||
@forelse($permissions as $p) |
|
||||||
<tr> |
|
||||||
<td class="text-center">{{ $p->id }}</td> |
|
||||||
<td>{{ $p->name }}</td> |
|
||||||
<td class="text-center"> |
|
||||||
<a href="{{ route('permissions.edit', $p) }}" |
|
||||||
class="btn btn-sm btn-info me-1">Edit</a> |
|
||||||
<button wire:click="delete({{ $p->id }})" |
|
||||||
class="btn btn-sm btn-danger">Delete</button> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
@empty |
|
||||||
<tr> |
|
||||||
<td colspan="3" class="text-center">No permissions found.</td> |
|
||||||
</tr> |
|
||||||
@endforelse |
|
||||||
</tbody> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
{{-- Pagination --}} |
|
||||||
<div class="mt-3"> |
|
||||||
{{ $permissions->links('pagination::bootstrap-5') }} |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
@ -0,0 +1,104 @@ |
|||||||
|
<div class="row"> |
||||||
|
<div class="col-12"> |
||||||
|
<div class="card mb-4"> |
||||||
|
{{-- Header --}} |
||||||
|
<div class="card-header d-flex justify-content-between align-items-center pb-0"> |
||||||
|
<h6 class="mb-0">Permissions</h6> |
||||||
|
@if ($mode === 'index') |
||||||
|
<div class="d-flex align-items-center"> |
||||||
|
<div class="input-group input-group-outline me-2"> |
||||||
|
<input type="text" wire:model.debounce.500ms="search" wire:keydown.enter="resetPage" |
||||||
|
class="form-control" placeholder="Search..."> |
||||||
|
</div> |
||||||
|
<button wire:click="showForm" class="btn btn-sm btn-outline-secondary me-2"> |
||||||
|
+ New |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
@else |
||||||
|
<button wire:click="showIndex" class="btn btn-sm btn-secondary"> |
||||||
|
← Back to list |
||||||
|
</button> |
||||||
|
@endif |
||||||
|
</div> |
||||||
|
|
||||||
|
{{-- Body --}} |
||||||
|
<div class="card-body p-3"> |
||||||
|
@if (session()->has('message')) |
||||||
|
<div class="alert alert-success">{{ session('message') }}</div> |
||||||
|
@endif |
||||||
|
|
||||||
|
@if ($mode === 'index') |
||||||
|
<div class="table-responsive"> |
||||||
|
<table class="table align-items-center mb-0"> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th class="text-center">ID</th> |
||||||
|
<th>Name</th> |
||||||
|
<th class="text-center">Actions</th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
@forelse($permissions as $p) |
||||||
|
<tr> |
||||||
|
<td class="text-center">{{ $p->id }}</td> |
||||||
|
<td>{{ $p->name }}</td> |
||||||
|
<td class="text-center"> |
||||||
|
<button wire:click="showForm({{ $p->id }})" |
||||||
|
class="btn btn-sm btn-info me-1"> |
||||||
|
Edit |
||||||
|
</button> |
||||||
|
<button wire:click="delete({{ $p->id }})" |
||||||
|
class="btn btn-sm btn-danger"> |
||||||
|
Delete |
||||||
|
</button> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
@empty |
||||||
|
<tr> |
||||||
|
<td colspan="3" class="text-center">No permissions found.</td> |
||||||
|
</tr> |
||||||
|
@endforelse |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
</div> |
||||||
|
<div class="mt-3">{{ $permissions->links('pagination::bootstrap-5') }}</div> |
||||||
|
@else |
||||||
|
{{-- Form --}} |
||||||
|
<div class="row justify-content-center"> |
||||||
|
<div class="col-lg-6"> |
||||||
|
<div class="card"> |
||||||
|
<div class="card-header pb-0"> |
||||||
|
<h6 class="mb-0"> |
||||||
|
{{ $editingId ? 'Edit Permission' : 'Create Permission' }} |
||||||
|
</h6> |
||||||
|
</div> |
||||||
|
<div class="card-body"> |
||||||
|
<form wire:submit.prevent="save"> |
||||||
|
<div class="mb-3"> |
||||||
|
<label class="form-label">Name</label> |
||||||
|
<input type="text" wire:model.defer="name" class="form-control" |
||||||
|
placeholder="Enter permission name"> |
||||||
|
@error('name') |
||||||
|
<div class="text-danger text-xs mt-1">{{ $message }}</div> |
||||||
|
@enderror |
||||||
|
</div> |
||||||
|
<div class="d-flex justify-content-end"> |
||||||
|
<button wire:click="showIndex" type="button" |
||||||
|
class="btn btn-secondary btn-sm me-2"> |
||||||
|
Cancel |
||||||
|
</button> |
||||||
|
<button type="submit" class="btn btn-primary btn-sm"> |
||||||
|
{{ $editingId ? 'Update' : 'Create' }} |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
@endif |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
Loading…
Reference in new issue