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 @@