diff --git a/app/Http/Controllers/Api/RolesController.php b/app/Http/Controllers/Api/RolesController.php index 7a7774b..d005214 100644 --- a/app/Http/Controllers/Api/RolesController.php +++ b/app/Http/Controllers/Api/RolesController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; +use App\Http\Requests\RoleRequest; use App\Models\Role; use Illuminate\Http\Request; @@ -13,7 +14,7 @@ class RolesController extends Controller */ public function index(Request $request) { - $query = Role::query(); + $query = Role::query()->orderBy('id', 'desc'); if($request->has('search') && !empty($request->get('search'))){ $query = $query->where('name', 'like', '%'. $request->get('search') . '%'); @@ -25,9 +26,14 @@ class RolesController extends Controller /** * Store a newly created resource in storage. */ - public function store(Request $request) + public function store(RoleRequest $request) { - // + try{ + $role = Role::create($request->validated()); + return response()->json(['message' => 'Successfully created', 'data' => $role]); + }catch(\Exception $e){ + return response()->json(['message' => 'Error when creating role', 'error' => $e->getMessage()], 500); + } } /** @@ -35,15 +41,34 @@ class RolesController extends Controller */ public function show(string $id) { - // + try{ + $role = Role::find($id); + if($role){ + return response()->json(['data' => $role]); + } else { + return response()->json(['message' => 'Role not found'], 404); + } + }catch(\Exception $e){ + return response()->json(['message' => 'Error when getting role', 'error' => $e->getMessage()], 500); + } } /** * Update the specified resource in storage. */ - public function update(Request $request, string $id) + public function update(RoleRequest $request, string $id) { - // + try{ + $role = Role::find($id); + if($role){ + $role->update($request->validated()); + return response()->json(['message' => 'Successfully updated', 'data' => $role]); + } else { + return response()->json(['message' => 'Role not found'], 404); + } + }catch(\Exception $e){ + return response()->json(['message' => 'Error when updating role', 'error' => $e->getMessage()], 500); + } } /** @@ -51,6 +76,16 @@ class RolesController extends Controller */ public function destroy(string $id) { - // + try{ + $role = Role::find($id); + if($role){ + $role->delete(); + return response()->json(['message' => 'Successfully deleted']); + } else { + return response()->json(['message' => 'Role not found'], 404); + } + }catch(\Exception $e){ + return response()->json(['message' => 'Error when deleting role', 'error' => $e->getMessage()], 500); + } } } diff --git a/app/Http/Requests/RoleRequest.php b/app/Http/Requests/RoleRequest.php index 13c7130..ed26732 100644 --- a/app/Http/Requests/RoleRequest.php +++ b/app/Http/Requests/RoleRequest.php @@ -21,7 +21,7 @@ class RoleRequest extends FormRequest */ public function rules(): array { - $roleId = $this->route('role'); + $roleId = $this->route('role_id'); return [ 'name' => 'required|string|max:255|unique:roles,name,' . ($roleId ?? 'NULL') . ',id', 'description' => 'nullable|string', diff --git a/resources/js/customers/edit.js b/resources/js/customers/edit.js index b59b4b8..5e1df45 100644 --- a/resources/js/customers/edit.js +++ b/resources/js/customers/edit.js @@ -1,9 +1,9 @@ class UpdateCustomer { constructor() { - this.initUpdateSpatial(); + this.initUpdateCustomer(); } - initUpdateSpatial() { + initUpdateCustomer() { const toastNotification = document.getElementById("toastNotification"); const toast = new bootstrap.Toast(toastNotification); document diff --git a/resources/js/roles/create.js b/resources/js/roles/create.js index 243d0b0..db3333a 100644 --- a/resources/js/roles/create.js +++ b/resources/js/roles/create.js @@ -1,55 +1,67 @@ -document.addEventListener("DOMContentLoaded", function (e) { - const toastNotification = document.getElementById("toastNotification"); - const toast = new bootstrap.Toast(toastNotification); - document - .getElementById("btnCreateRole") - .addEventListener("click", async function () { - let submitButton = this; - let spinner = document.getElementById("spinner"); - let form = document.getElementById("formCreateRole"); +class CreateRoles { + constructor() { + this.initCreateRole(); + } - if (!form) { - console.error("Form element not found!"); - return; - } - // Get form data - let formData = new FormData(form); + initCreateRole() { + const toastNotification = document.getElementById("toastNotification"); + const toast = new bootstrap.Toast(toastNotification); + document + .getElementById("btnCreateRole") + .addEventListener("click", async function () { + let submitButton = this; + let spinner = document.getElementById("spinner"); + let form = document.getElementById("formCreateRole"); - // 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 = "/roles"; - }, 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 = "/roles"; + }, 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 CreateRoles(); }); diff --git a/resources/js/roles/index.js b/resources/js/roles/index.js index d05e808..a6bfc2a 100644 --- a/resources/js/roles/index.js +++ b/resources/js/roles/index.js @@ -2,46 +2,31 @@ 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 Roles { constructor() { - this.table = null; // Store Grid.js instance - } + 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.initTableRoles(); + this.initEvents(); + } + initEvents() { + document.body.addEventListener("click", async (event) => { + const deleteButton = event.target.closest(".btn-delete-role"); + if (deleteButton) { + event.preventDefault(); + await this.handleDelete(deleteButton); + } + }); } initTableRoles() { let tableContainer = document.getElementById("table-roles"); - - // If table instance already exists, update it instead of re-creating - if (this.table) { - this.table - .updateConfig({ - server: { - url: `${GlobalConfig.apiHost}/api/api-roles`, - credentials: "include", - headers: { - Authorization: `Bearer ${document - .querySelector('meta[name="api-token"]') - .getAttribute("content")}`, - "Content-Type": "application/json", - }, - then: (data) => - data.data.map((item) => [ - item.id, - item.name, - item.description, - item.id, - ]), - total: (data) => data.total, - }, - }) - .forceRender(); - return; - } - // Create a new Grid.js instance only if it doesn't exist this.table = new gridjs.Grid({ columns: [ @@ -82,7 +67,7 @@ class Roles { }, }, server: { - url: `${GlobalConfig.apiHost}/api/api-roles`, + url: `${GlobalConfig.apiHost}/api/roles`, credentials: "include", headers: { Authorization: `Bearer ${document @@ -100,116 +85,63 @@ class Roles { total: (data) => data.total, }, }).render(tableContainer); - - document.addEventListener("click", this.handleDelete.bind(this)); } - handleDelete(event) { - if (event.target.classList.contains("btn-delete-role")) { - event.preventDefault(); + async handleDelete(deleteButton) { + const id = deleteButton.getAttribute("data-id"); - const id = event.target.getAttribute("data-id"); - let modalElement = document.getElementById("modalConfirmation"); - let toastMessage = document.getElementById("toast-message"); + const result = await Swal.fire({ + title: "Are you sure?", + text: "You won't be able to revert this!", + icon: "warning", + showCancelButton: true, + confirmButtonColor: "#3085d6", + cancelButtonColor: "#d33", + confirmButtonText: "Yes, delete it!", + }); - if (!modalElement) { - console.error("Modal element not found!"); - return; - } - - let modal = new bootstrap.Modal(modalElement); - let btnSaveConfirmation = document.getElementById( - "btnSaveConfirmation" - ); - let toastElement = document.getElementById("toastNotification"); - let toast = new bootstrap.Toast(toastElement); - - // Remove previous event listeners to avoid multiple bindings - btnSaveConfirmation.replaceWith( - btnSaveConfirmation.cloneNode(true) - ); - btnSaveConfirmation = document.getElementById( - "btnSaveConfirmation" - ); - - // Set the role ID on the confirm button inside the modal - btnSaveConfirmation.setAttribute("data-role-id", id); - - // Show the modal - modal.show(); - - btnSaveConfirmation.addEventListener("click", async () => { - let roleId = btnSaveConfirmation.getAttribute("data-role-id"); - - try { - let response = await fetch(`/roles/${roleId}`, { + if (result.isConfirmed) { + try { + let response = await fetch( + `${GlobalConfig.apiHost}/api/roles/${id}`, + { method: "DELETE", credentials: "include", - headers: { - "X-CSRF-TOKEN": document - .querySelector('meta[name="csrf-token"]') - .getAttribute("content"), - "Content-Type": "application/json", - }, - }); - - if (response.ok) { - let result = await response.json(); - toastMessage.innerText = - result.message || "Deleted successfully!"; - toast.show(); - - // Hide modal - modal.hide(); - - // Refresh Grid.js table - this.refreshRolesTable(); - } else { - let error = await response.json(); - console.error("Delete failed:", error); - toastMessage.innerText = - error.message || "Delete failed!"; - toast.show(); - } - } catch (error) { - console.error("Error deleting item:", error); - toastMessage.innerText = "An error occurred!"; - toast.show(); - } - }); - } - } - - refreshRolesTable() { - if (this.table) { - this.table - .updateConfig({ - server: { - url: `${GlobalConfig.apiHost}/api/api-roles`, - credentials: "include", headers: { Authorization: `Bearer ${document .querySelector('meta[name="api-token"]') .getAttribute("content")}`, "Content-Type": "application/json", }, - then: (data) => - data.data.map((item) => [ - item.id, - item.name, - item.description, - item.id, - ]), - total: (data) => data.total, - }, - }) - .forceRender(); - } else { - this.initTableRoles(); // If the table is null, reinitialize + } + ); + + if (response.ok) { + let result = await response.json(); + this.toastMessage.innerText = + result.message || "Deleted successfully!"; + this.toast.show(); + + // Refresh Grid.js table + if (typeof this.table !== "undefined") { + this.table.updateConfig({}).forceRender(); + } + } else { + let error = await response.json(); + console.error("Delete failed:", error); + this.toastMessage.innerText = + error.message || "Delete failed!"; + this.toast.show(); + } + } catch (error) { + console.error("Error deleting item:", error); + this.toastMessage.innerText = "An error occurred!"; + this.toast.show(); + } } } } document.addEventListener("DOMContentLoaded", function (e) { - new Roles().init(); + new Roles(); }); diff --git a/resources/js/roles/update.js b/resources/js/roles/update.js index 5753448..3723f85 100644 --- a/resources/js/roles/update.js +++ b/resources/js/roles/update.js @@ -1,53 +1,67 @@ -document.addEventListener("DOMContentLoaded", function (e) { - let form = document.getElementById("formUpdateRole"); - let submitButton = document.getElementById("btnUpdateRole"); - let spinner = document.getElementById("spinner"); - let toastMessage = document.getElementById("toast-message"); - let toast = new bootstrap.Toast( - document.getElementById("toastNotification") - ); - submitButton.addEventListener("click", async function () { - let submitButton = this; +class UpdateRoles { + constructor() { + this.initUpdateRole(); + } - if (!form) { - console.error("Form element not found!"); - return; - } - // Get form data - let formData = new FormData(form); + initUpdateRole() { + const toastNotification = document.getElementById("toastNotification"); + const toast = new bootstrap.Toast(toastNotification); + document + .getElementById("btnUpdateRole") + .addEventListener("click", async function () { + let submitButton = this; + let spinner = document.getElementById("spinner"); + let form = document.getElementById("formUpdateRole"); - // 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"); + + 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 = "/roles"; + }, 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(); + } }); + } +} - if (response.ok) { - let result = await response.json(); - toastMessage.innerText = result.message; - toast.show(); - setTimeout(() => { - window.location.href = "/roles"; - }, 2000); - } else { - let error = await response.json(); - toastMessage.innerText = error.message; - toast.show(); - console.error("Error:", error); - } - } catch (error) { - console.error("Request failed:", error); - toastMessage.innerText = error.message; - toast.show(); - } - }); +document.addEventListener("DOMContentLoaded", function (e) { + new UpdateRoles(); }); diff --git a/resources/views/data-settings/create.blade.php b/resources/views/data-settings/create.blade.php index 226daa1..5ed3cb8 100644 --- a/resources/views/data-settings/create.blade.php +++ b/resources/views/data-settings/create.blade.php @@ -8,6 +8,9 @@
+
+ Back +
@csrf diff --git a/resources/views/data-settings/edit.blade.php b/resources/views/data-settings/edit.blade.php index 77357c3..659ec72 100644 --- a/resources/views/data-settings/edit.blade.php +++ b/resources/views/data-settings/edit.blade.php @@ -8,6 +8,9 @@
+
+ Back +
@csrf diff --git a/resources/views/menus/create.blade.php b/resources/views/menus/create.blade.php index 3786d66..83bf331 100644 --- a/resources/views/menus/create.blade.php +++ b/resources/views/menus/create.blade.php @@ -12,6 +12,9 @@
+
+ Back +
@csrf diff --git a/resources/views/menus/edit.blade.php b/resources/views/menus/edit.blade.php index d6467ec..3d6fc9b 100644 --- a/resources/views/menus/edit.blade.php +++ b/resources/views/menus/edit.blade.php @@ -12,6 +12,9 @@
+
+ Back +
id)}}" method="post"> @csrf diff --git a/resources/views/roles/create.blade.php b/resources/views/roles/create.blade.php index 403f4e4..b4de186 100644 --- a/resources/views/roles/create.blade.php +++ b/resources/views/roles/create.blade.php @@ -8,8 +8,11 @@
+
+ Back +
- + @csrf
diff --git a/resources/views/roles/edit.blade.php b/resources/views/roles/edit.blade.php index e96b140..a098d5a 100644 --- a/resources/views/roles/edit.blade.php +++ b/resources/views/roles/edit.blade.php @@ -8,8 +8,11 @@
+
+ Back +
- id)}}" method="post" > + id)}}" method="post" > @csrf @method("put")
diff --git a/resources/views/roles/role_menu.blade.php b/resources/views/roles/role_menu.blade.php index 32210b9..95e6dc1 100644 --- a/resources/views/roles/role_menu.blade.php +++ b/resources/views/roles/role_menu.blade.php @@ -7,6 +7,9 @@
+
+ Back +
Manage Permissions for Role: {{ $role->name }}
id)}}" method="post"> diff --git a/routes/api.php b/routes/api.php index 89a44dd..2455339 100644 --- a/routes/api.php +++ b/routes/api.php @@ -108,7 +108,12 @@ Route::group(['middleware' => 'auth:sanctum'], function (){ }); // roles api - Route::apiResource('api-roles', RolesController::class); + Route::controller(RolesController::class)->group(function (){ + Route::get('/roles', 'index')->name('api.roles'); + Route::post('/roles', 'store')->name('api.roles.store'); + Route::put('/roles/{role_id}', 'update')->name('api.roles.update'); + Route::delete('/roles/{role_id}', 'destroy')->name('api.roles.destroy'); + }); //business industries api Route::apiResource('api-business-industries', BusinessOrIndustriesController::class);