diff --git a/app/Http/Controllers/Api/MenusController.php b/app/Http/Controllers/Api/MenusController.php
index 95913c6..eede7aa 100644
--- a/app/Http/Controllers/Api/MenusController.php
+++ b/app/Http/Controllers/Api/MenusController.php
@@ -3,8 +3,11 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
+use App\Http\Requests\MenuRequest;
+use App\Http\Resources\MenuResource;
use App\Models\Menu;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Log;
class MenusController extends Controller
{
@@ -13,7 +16,7 @@ class MenusController extends Controller
*/
public function index(Request $request)
{
- $query = Menu::query();
+ $query = Menu::query()->orderBy('id', 'desc');
if($request->has("search") && !empty($request->get("search"))){
$query = $query->where("name", "like", "%".$request->get("search")."%");
@@ -25,9 +28,15 @@ class MenusController extends Controller
/**
* Store a newly created resource in storage.
*/
- public function store(Request $request)
+ public function store(MenuRequest $request)
{
- //
+ try{
+ $menu = Menu::create($request->validated());
+ return response()->json(['message' => 'Menu created successfully', 'data' => new MenuResource($menu)]);
+ }catch(\Exception $e){
+ Log::error($e);
+ return response()->json(['message' => 'Error when creating menu'], 500);
+ }
}
/**
@@ -35,15 +44,37 @@ class MenusController extends Controller
*/
public function show(string $id)
{
- //
+ try{
+ $menu = Menu::find($id);
+ if($menu){
+ return response()->json(['message' => 'Menu found', 'data' => new MenuResource($menu)]);
+ } else {
+ return response()->json(['message' => 'Menu not found'], 404);
+ }
+ }catch(\Exception $e){
+ Log::error($e);
+ Log::error($e->getMessage());
+ return response()->json(['message' => 'Error when finding menu'], 500);
+ }
}
/**
* Update the specified resource in storage.
*/
- public function update(Request $request, string $id)
+ public function update(MenuRequest $request, string $id)
{
- //
+ try{
+ $menu = Menu::findOrFail($id);
+ if($menu){
+ $menu->update($request->validated());
+ return response()->json(['message' => 'Menu updated successfully', 'data' => new MenuResource($menu)]);
+ } else {
+ return response()->json(['message' => 'Menu not found'], 404);
+ }
+ }catch(\Exception $e){
+ Log::error($e);
+ return response()->json(['message' => 'Error when updating menu'], 500);
+ }
}
/**
@@ -51,6 +82,28 @@ class MenusController extends Controller
*/
public function destroy(string $id)
{
- //
+ try{
+ $menu = Menu::findOrFail($id);
+ if($menu){
+ $this->deleteChildren($menu);
+ $menu->roles()->detach();
+ $menu->delete();
+ return response()->json(['message' => 'Menu deleted successfully']);
+ } else {
+ return response()->json(['message' => 'Menu not found'], 404);
+ }
+ }catch(\Exception $e){
+ Log::error($e);
+ return response()->json(['message' => 'Error when deleting menu'], 500);
+ }
+ }
+
+ private function deleteChildren($menu)
+ {
+ foreach ($menu->children as $child) {
+ $this->deleteChildren($child); // Recursively delete its children
+ $child->roles()->detach(); // Detach roles before deleting
+ $child->delete();
+ }
}
}
diff --git a/app/Http/Requests/MenuRequest.php b/app/Http/Requests/MenuRequest.php
index a95e7e7..24bd50d 100644
--- a/app/Http/Requests/MenuRequest.php
+++ b/app/Http/Requests/MenuRequest.php
@@ -3,6 +3,7 @@
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Validation\Rule;
class MenuRequest extends FormRequest
{
@@ -21,12 +22,14 @@ class MenuRequest extends FormRequest
*/
public function rules(): array
{
+ $menuId = $this->route('menu_id'); // Get the menu ID if updating
+
return [
- 'name' => ['required','string','max:255'],
- 'url' => ['nullable','string','max:255'],
- 'icon' => ['nullable','string','max:255'],
- 'parent_id' => ['nullable','exists:menus,id'],
- 'sort_order' => ['required','integer'],
+ 'name' => ['required', 'string', 'max:255', Rule::unique('menus', 'name')->ignore($menuId)],
+ 'url' => ['nullable', 'string', 'max:255'],
+ 'icon' => ['nullable', 'string', 'max:255'],
+ 'parent_id' => ['nullable', 'exists:menus,id'],
+ 'sort_order' => ['required', 'integer'],
];
}
}
diff --git a/app/Http/Resources/MenuResource.php b/app/Http/Resources/MenuResource.php
new file mode 100644
index 0000000..7e67480
--- /dev/null
+++ b/app/Http/Resources/MenuResource.php
@@ -0,0 +1,19 @@
+
+ */
+ public function toArray(Request $request): array
+ {
+ return parent::toArray($request);
+ }
+}
diff --git a/resources/js/customers/index.js b/resources/js/customers/index.js
index 9141ae5..e2f5835 100644
--- a/resources/js/customers/index.js
+++ b/resources/js/customers/index.js
@@ -12,7 +12,7 @@ class Customers {
this.table = null;
// Initialize functions
- this.initTableSpatialPlannings();
+ this.initTableCustomers();
this.initEvents();
}
initEvents() {
@@ -25,7 +25,7 @@ class Customers {
});
}
- initTableSpatialPlannings() {
+ initTableCustomers() {
let tableContainer = document.getElementById("table-customers");
// Create a new Grid.js instance only if it doesn't exist
this.table = new Grid({
diff --git a/resources/js/menus/create.js b/resources/js/menus/create.js
index 8ab2a1d..129004e 100644
--- a/resources/js/menus/create.js
+++ b/resources/js/menus/create.js
@@ -1,55 +1,67 @@
-document.addEventListener("DOMContentLoaded", function (e) {
- const toastNotification = document.getElementById("toastNotification");
- const toast = new bootstrap.Toast(toastNotification);
- document
- .getElementById("btnCreateMenus")
- .addEventListener("click", async function () {
- let submitButton = this;
- let spinner = document.getElementById("spinner");
- let form = document.getElementById("formCreateMenus");
+class CreateMenu {
+ constructor() {
+ this.initCreateMenu();
+ }
- if (!form) {
- console.error("Form element not found!");
- return;
- }
- // Get form data
- let formData = new FormData(form);
+ initCreateMenu() {
+ const toastNotification = document.getElementById("toastNotification");
+ const toast = new bootstrap.Toast(toastNotification);
+ document
+ .getElementById("btnCreateMenus")
+ .addEventListener("click", async function () {
+ let submitButton = this;
+ let spinner = document.getElementById("spinner");
+ let form = document.getElementById("formCreateMenus");
- // Disable button and show spinner
- submitButton.disabled = true;
- spinner.classList.remove("d-none");
+ if (!form) {
+ console.error("Form element not found!");
+ return;
+ }
+ // Get form data
+ let formData = new FormData(form);
- try {
- let response = await fetch(form.action, {
- method: "POST",
- headers: {
- "X-CSRF-TOKEN": document
- .querySelector('meta[name="csrf-token"]')
- .getAttribute("content"),
- },
- body: formData,
- });
+ // Disable button and show spinner
+ submitButton.disabled = true;
+ spinner.classList.remove("d-none");
- if (response.ok) {
- let result = await response.json();
- document.getElementById("toast-message").innerText =
- result.message;
- toast.show();
- setTimeout(() => {
- window.location.href = "/menus";
- }, 2000);
- } else {
- let error = await response.json();
+ try {
+ let response = await fetch(form.action, {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${document
+ .querySelector('meta[name="api-token"]')
+ .getAttribute("content")}`,
+ },
+ body: formData,
+ });
+
+ if (response.ok) {
+ let result = await response.json();
+ document.getElementById("toast-message").innerText =
+ result.message;
+ toast.show();
+ setTimeout(() => {
+ window.location.href = "/menus";
+ }, 2000);
+ } else {
+ let error = await response.json();
+ document.getElementById("toast-message").innerText =
+ error.message;
+ toast.show();
+ console.error("Error:", error);
+ submitButton.disabled = false;
+ spinner.classList.add("d-none");
+ }
+ } catch (error) {
+ console.error("Request failed:", error);
document.getElementById("toast-message").innerText =
error.message;
toast.show();
- console.error("Error:", error);
}
- } catch (error) {
- console.error("Request failed:", error);
- document.getElementById("toast-message").innerText =
- error.message;
- toast.show();
- }
- });
+ });
+ }
+}
+
+document.addEventListener("DOMContentLoaded", function (e) {
+ new CreateMenu();
});
diff --git a/resources/js/menus/index.js b/resources/js/menus/index.js
index 9a12b31..a2797c6 100644
--- a/resources/js/menus/index.js
+++ b/resources/js/menus/index.js
@@ -2,13 +2,27 @@ import { Grid } from "gridjs/dist/gridjs.umd.js";
import gridjs from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js";
import GlobalConfig from "../global-config";
+import Swal from "sweetalert2";
class Menus {
constructor() {
+ this.toastMessage = document.getElementById("toast-message");
+ this.toastElement = document.getElementById("toastNotification");
+ this.toast = new bootstrap.Toast(this.toastElement);
this.table = null;
- }
- init() {
+
+ // Initialize functions
this.initTableMenus();
+ this.initEvents();
+ }
+ initEvents() {
+ document.body.addEventListener("click", async (event) => {
+ const deleteButton = event.target.closest(".btn-delete-menu");
+ if (deleteButton) {
+ event.preventDefault();
+ await this.handleDelete(deleteButton);
+ }
+ });
}
initTableMenus() {
@@ -19,7 +33,7 @@ class Menus {
this.table
.updateConfig({
server: {
- url: `${GlobalConfig.apiHost}/api/api-menus`,
+ url: `${GlobalConfig.apiHost}/api/menus`,
credentials: "include",
headers: {
Authorization: `Bearer ${document
@@ -60,7 +74,8 @@ class Menus {
-