restore deleted categories

This commit is contained in:
punkfairie 2025-02-23 17:41:50 -08:00
parent 5f97900e30
commit 9385a4b7f1
Signed by: punkfairie
GPG key ID: B3C5488E9A1A7CA6
11 changed files with 145 additions and 59 deletions

View file

@ -17,8 +17,10 @@ public function index()
{ {
$this->authorize('viewAny', Category::class); $this->authorize('viewAny', Category::class);
return View::make('categories.index', return View::make('categories.index', [
['categories' => Category::all()]); 'categories' => Category::all(),
'trashedCategories' => Category::onlyTrashed()->get()
]);
} }
public function create() public function create()
@ -42,6 +44,8 @@ public function show(Category $category)
{ {
$this->authorize('view', $category); $this->authorize('view', $category);
$category->load('programs');
return View::make('categories.show', ['category' => $category]); return View::make('categories.show', ['category' => $category]);
} }
@ -54,11 +58,18 @@ public function edit(Category $category)
public function update(CategoryRequest $request, Category $category) public function update(CategoryRequest $request, Category $category)
{ {
$this->authorize('update', $category); if ($request->has('restore')) {
$this->authorize('restore', $category);
$category->update($request->validated()); $category->restore();
$request->session()->flash('status', 'Category restored!');
} else {
$this->authorize('update', $category);
$category->update($request->validated());
$request->session()->flash('status', 'Category updated!');
}
$request->session()->flash('status', 'Category updated!');
return Redirect::route('categories.index'); return Redirect::route('categories.index');
} }

View file

@ -5,6 +5,7 @@
use App\Http\Requests\ProgramRequest; use App\Http\Requests\ProgramRequest;
use App\Models\Program; use App\Models\Program;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Facades\View;
class ProgramController extends Controller class ProgramController extends Controller
{ {
@ -14,7 +15,7 @@ public function index()
{ {
$this->authorize('viewAny', Program::class); $this->authorize('viewAny', Program::class);
return Program::all(); return View::make('programs.index', ['programs' => Program::all()]);
} }
public function store(ProgramRequest $request) public function store(ProgramRequest $request)

View file

@ -10,15 +10,22 @@ class CategoryRequest extends FormRequest
public function rules(): array public function rules(): array
{ {
return [ return [
'name' => ['required'], 'name' => ['sometimes', 'required', 'string'],
'restore' => ['sometimes', 'required', 'boolean']
]; ];
} }
public function authorize(): bool public function authorize(): bool
{ {
if ($this->request->has('restore')) {
return $this->user()->can('restore', $this->route('category'));
}
if ($this->routeIs('categories.store')) { if ($this->routeIs('categories.store')) {
return $this->user()->can('create', Category::class); return $this->user()->can('create', Category::class);
} elseif ($this->routeIs('categories.update')) { }
if ($this->routeIs('categories.update')) {
return $this->user()->can('update', $this->route('category')); return $this->user()->can('update', $this->route('category'));
} }

View file

@ -11,12 +11,12 @@ class CategoryPolicy
{ {
use HandlesAuthorization; use HandlesAuthorization;
public function viewAny(User $user): bool public function viewAny(?User $user): bool
{ {
return true; return true;
} }
public function view(User $user, Category $category): bool public function view(?User $user, Category $category): bool
{ {
return true; return true;
} }

View file

@ -1,64 +1,112 @@
<x-layout title="Categories"> <x-layout title="Categories">
<x-window> <x-window x-data="{ tab: 'active' }">
<div class="sunken-panel"> @auth
<table class="interactive"> <x-tablist class="mt-3">
<thead> <x-tablist.tab id="active">Active</x-tablist.tab>
<tr> <x-tablist.tab id="deleted">Deleted</x-tablist.tab>
<th>Category</th> </x-tablist>
<th>Actions</th> @endauth
</tr>
</thead>
<tbody
x-data="{ hovered: null }"
x-on:mouseleave="hovered = null"
>
@foreach ($categories as $category)
<tr
id="{{ $category->id }}"
x-on:mouseenter="hovered = $event.target.id"
x-bind:class="{ 'highlighted': hovered === $el.id }"
>
<td>{{ $category->name }}</td>
<td>
<a href="{{ route('categories.show', $category->id) }}">
View
</a>
@auth <div class="window" role="tabpanel" x-show="tab === 'active'">
<div class="sunken-panel">
<table class="interactive">
<thead>
<tr>
<th>Category</th>
@auth
<th>Actions</th>
@endauth
</tr>
</thead>
<tbody
x-data="{ hovered: null }"
x-on:mouseleave="hovered = null"
>
@foreach ($categories as $category)
<tr
id="{{ $category->id }}"
x-on:mouseenter="hovered = $event.target.id"
x-bind:class="{ 'highlighted': hovered === $el.id }"
>
<td>
<a <a
href="{{ route('categories.edit', $category->id) }}" href="{{ route('categories.show', $category->id) }}"
class="ml-1" class="text-inherit no-underline"
> >
Edit {{ $category->name }}
</a> </a>
</td>
@auth
<td>
<a
href="{{ route('categories.edit', $category->id) }}"
class="ml-1"
>
Edit
</a>
<form
action="{{ route('categories.destroy', $category->id) }}"
method="POST"
class="ml-1 inline-block"
>
@csrf
@method('DELETE')
<a
href="#"
x-data
x-on:click.prevent="$el.closest('form').submit()"
>
Delete
</a>
</form>
</td>
@endauth
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="window" role="tabpanel" x-show="tab === 'deleted'">
<div class="sunken-panel">
<table class="interactive">
<thead>
<tr>
<td>Category</td>
<td>Actions</td>
</tr>
</thead>
<tbody>
@foreach ($trashedCategories as $category)
<tr>
<td>{{ $category->name }}</td>
<td>
<form <form
action="{{ route('categories.destroy', $category->id) }}" action="{{ route('categories.update', $category->id) }}"
method="POST" method="POST"
class="ml-1 inline-block"
> >
@csrf @csrf
@method('DELETE') @method('PATCH')
<input type="hidden" name="restore" value="1" />
<a <a
href="#" href="#"
x-data x-on:click.prevent="$el.closest('form').submit()"
x-on:click="
$event.preventDefault()
$el.closest('form').submit()
"
> >
Delete Restore
</a> </a>
</form> </form>
@endauth </td>
</td> </tr>
</tr> @endforeach
@endforeach </tbody>
</tbody> </table>
</table> </div>
</div> </div>
@auth @auth
<a href="{{ route('categories.create') }}" class="button">New</a> <a href="{{ route('categories.create') }}" class="button">New</a>
@endauth @endauth

View file

@ -1,5 +1,9 @@
<x-layout :title="'Category: '. $category->name"> <x-layout :title="'Category: '. $category->name">
<x-window> <x-window>
@foreach ($category->programs as $program)
{{ $program->name }}
@endforeach
<a href="{{ route('categories.index') }}">All</a> <a href="{{ route('categories.index') }}">All</a>
</x-window> </x-window>
</x-layout> </x-layout>

View file

@ -46,10 +46,7 @@ class="window"
<a <a
href="#" href="#"
x-on:click=" x-on:click.prevent="$el.closest('form').submit()"
$event.preventDefault()
$el.closest('form').submit()
"
> >
<img <img
src="{{ Vite::asset('resources/images/startmenu/key.png') }}" src="{{ Vite::asset('resources/images/startmenu/key.png') }}"

View file

@ -0,0 +1,15 @@
@props([
'id',
'tabVarName' => 'tab',
])
<li
role="tab"
x-bind:aria-selected="{{ $tabVarName }} === $el.id"
id="{{ $id }}"
{{ $attributes }}
>
<a href="#" x-on:click.prevent="{{ $tabVarName }} = $el.parentElement.id">
{{ $slot }}
</a>
</li>

View file

@ -0,0 +1,3 @@
<menu role="tablist" {{ $attributes }}>
{{ $slot }}
</menu>

View file

View file

@ -27,4 +27,4 @@
Route::resources([ Route::resources([
'categories' => CategoryController::class, 'categories' => CategoryController::class,
'programs' => ProgramController::class 'programs' => ProgramController::class
]); ], ['trashed' => []]);