diff --git a/app/Http/Controllers/Admin/AdminCategoryController.php b/app/Http/Controllers/Admin/AdminCategoryController.php index 61e33d16a..00b995642 100644 --- a/app/Http/Controllers/Admin/AdminCategoryController.php +++ b/app/Http/Controllers/Admin/AdminCategoryController.php @@ -135,4 +135,38 @@ class AdminCategoryController extends BasePageController return view('admin.categories.edit', $this->viewData); } + + /** + * Delete a category. + * + * @return \Illuminate\Http\RedirectResponse + * + * @throws \Exception + */ + public function destroy(Request $request) + { + $this->setAdminPrefs(); + + $id = $request->input('id'); + + if (! $id) { + return redirect()->to('admin/category-list')->with('error', 'No category ID provided.'); + } + + $category = Category::find($id); + + if (! $category) { + return redirect()->to('admin/category-list')->with('error', 'Category not found.'); + } + + // Check for child categories + if (Category::where('root_categories_id', $id)->exists()) { + return redirect()->to('admin/category-list')->with('error', 'Cannot delete category "'.$category->title.'" because it has child categories. Remove or reassign them first.'); + } + + $title = $category->title; + $category->delete(); + + return redirect()->to('admin/category-list')->with('success', 'Category "'.$title.'" deleted successfully.'); + } } diff --git a/resources/js/alpine/components/dismissible.js b/resources/js/alpine/components/dismissible.js index 4dc35c78d..821acd0ae 100644 --- a/resources/js/alpine/components/dismissible.js +++ b/resources/js/alpine/components/dismissible.js @@ -23,13 +23,21 @@ Alpine.data('commentDeleteModal', () => ({ init() { this._baseUrl = this.$el.dataset.deleteUrl || ''; + // Listen for delete button clicks via delegation (CSP-safe, no $dispatch with inline objects) + var self = this; + document.addEventListener('click', function(e) { + var btn = e.target.closest('.comment-delete-btn'); + if (btn) { + self.openModal(btn.dataset.commentId, btn.dataset.commentText); + } + }); }, openModal(id, text) { this.commentId = id; this.commentText = text; this.open = true; - const form = this.$refs.deleteForm; + var form = this.$refs.deleteForm; if (form) { form.action = this._baseUrl + '?id=' + id; } @@ -49,6 +57,14 @@ Alpine.data('categoryDeleteModal', () => ({ init() { this._baseUrl = this.$el.dataset.deleteUrl || ''; + // Listen for delete button clicks via delegation (CSP-safe, no $dispatch with inline objects) + var self = this; + document.addEventListener('click', function(e) { + var btn = e.target.closest('.category-delete-btn'); + if (btn) { + self.openModal(btn.dataset.categoryId); + } + }); }, openModal(id) { diff --git a/resources/views/admin/categories/index.blade.php b/resources/views/admin/categories/index.blade.php index c03e0d90a..22c0b23ba 100644 --- a/resources/views/admin/categories/index.blade.php +++ b/resources/views/admin/categories/index.blade.php @@ -118,9 +118,8 @@ @@ -159,7 +158,6 @@
@@ -190,7 +188,5 @@
- -{{-- Scripts moved to resources/js/csp-safe.js --}} @endsection diff --git a/resources/views/admin/comments/index.blade.php b/resources/views/admin/comments/index.blade.php index 201b0d9ae..8b7a37faf 100644 --- a/resources/views/admin/comments/index.blade.php +++ b/resources/views/admin/comments/index.blade.php @@ -121,11 +121,10 @@ @@ -151,7 +150,6 @@
diff --git a/routes/web.php b/routes/web.php index 298d31308..44e676fdf 100644 --- a/routes/web.php +++ b/routes/web.php @@ -203,6 +203,7 @@ Route::middleware(['role:Admin', '2fa'])->prefix('admin')->group(function () { Route::get('category-list', [AdminCategoryController::class, 'index'])->name('admin.category-list'); Route::match(['GET', 'POST'], 'category-add', [AdminCategoryController::class, 'create'])->name('admin.category-add'); Route::match(['GET', 'POST'], 'category-edit', [AdminCategoryController::class, 'edit'])->name('admin.category-edit'); + Route::get('category-delete', [AdminCategoryController::class, 'destroy'])->name('admin.category-delete'); Route::get('user-list', [AdminUserController::class, 'index'])->name('admin.user-list'); Route::match(['GET', 'POST'], 'user-edit', [AdminUserController::class, 'edit'])->name('admin.user-edit'); Route::post('user-delete', [AdminUserController::class, 'destroy'])->name('admin.user-delete');