diff --git a/app/Http/Requests/DataSettingRequest.php b/app/Http/Requests/DataSettingRequest.php index 2305e39..ed42cee 100644 --- a/app/Http/Requests/DataSettingRequest.php +++ b/app/Http/Requests/DataSettingRequest.php @@ -21,7 +21,7 @@ class DataSettingRequest extends FormRequest */ public function rules(): array { - $id = $this->route('data_setting'); + $id = $this->route('data_setting_id'); return [ "key" => "required|unique:data_settings,key," . $id, "value" => "required", diff --git a/package-lock.json b/package-lock.json index 8a35c4f..5f90a71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "sibedas-pbg", + "name": "sibedas-pbg-web", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/resources/js/business-industries/index.js b/resources/js/business-industries/index.js index a88e7a4..a85eb04 100644 --- a/resources/js/business-industries/index.js +++ b/resources/js/business-industries/index.js @@ -2,58 +2,36 @@ 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.js"; +import Swal from "sweetalert2"; class BusinessIndustries { 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; + + // Initialize functions + this.initTableBusinessIndustries(); + this.initEvents(); } - init() { - this.getFetchApiData(); + initEvents() { + document.body.addEventListener("click", async (event) => { + const deleteButton = event.target.closest( + ".btn-delete-business-industry" + ); + if (deleteButton) { + event.preventDefault(); + await this.handleDelete(deleteButton); + } + }); } - getFetchApiData() { + initTableBusinessIndustries() { let tableContainer = document.getElementById( "table-business-industries" ); - - if (this.table) { - // If table exists, update its data instead of recreating - this.table - .updateConfig({ - server: { - url: `${GlobalConfig.apiHost}/api/api-business-industries`, - 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.nama_kecamatan, - item.nama_kelurahan, - item.nop, - item.nama_wajib_pajak, - item.alamat_wajib_pajak, - item.alamat_objek_pajak, - item.luas_bumi, - item.luas_bangunan, - item.njop_bumi, - item.njop_bangunan, - item.ketetapan, - item.tahun_pajak, - item.created_at, - item.id, - ]), - total: (data) => data.total, - }, - }) - .forceRender(); - return; - } - + // Create a new Grid.js instance only if it doesn't exist this.table = new Grid({ columns: [ { name: "ID", width: "80px", hidden: false }, @@ -71,27 +49,20 @@ class BusinessIndustries { { name: "Tahun Pajak", width: "120px" }, { name: "Created", width: "180px" }, { - name: "Actions", - width: "120px", - formatter: function (cell) { - return gridjs.html(` -
- - - - -
- `); - }, + name: "Action", + formatter: (cell) => + gridjs.html(` +
+ + + + +
+ `), }, ], - search: { - server: { - url: (prev, keyword) => `${prev}?search=${keyword}`, - }, - }, pagination: { limit: 15, server: { @@ -102,6 +73,11 @@ class BusinessIndustries { }, }, sort: true, + search: { + server: { + url: (prev, keyword) => `${prev}?search=${keyword}`, + }, + }, server: { url: `${GlobalConfig.apiHost}/api/api-business-industries`, headers: { @@ -131,98 +107,26 @@ class BusinessIndustries { total: (data) => data.total, }, }).render(tableContainer); - - document.addEventListener("click", this.handleDelete.bind(this)); } - handleDelete(event) { - if (event.target.classList.contains("btn-delete-business-industries")) { - event.preventDefault(); - const id = event.target.getAttribute("data-id"); - let modalElement = document.getElementById("modalConfirmation"); - let toastMessage = document.getElementById("toast-message"); + async handleDelete(deleteButton) { + const id = deleteButton.getAttribute("data-id"); - if (!modalElement) { - console.error("Modal element not found!"); - return; - } + 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!", + }); - 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-business-industries-id", id); - - // Show the modal - modal.show(); - - btnSaveConfirmation.addEventListener("click", async () => { - let deletedId = btnSaveConfirmation.getAttribute( - "data-business-industries-id" - ); - - try { - let response = await fetch( - `${GlobalConfig.apiHost}/api/api-business-industries/${deletedId}`, - { - method: "DELETE", - credentials: "include", - headers: { - "X-CSRF-TOKEN": document - .querySelector('meta[name="csrf-token"]') - .getAttribute("content"), - Authorization: `Bearer ${document - .querySelector('meta[name="api-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.refreshDataSettings(); - } 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(); - } - }); - } - } - - refreshDataSettings() { - if (this.table) { - this.table - .updateConfig({ - server: { - url: `${GlobalConfig.apiHost}/api/api-business-industries`, + if (result.isConfirmed) { + try { + let response = await fetch( + `${GlobalConfig.apiHost}/api/api-business-industries/${id}`, + { + method: "DELETE", credentials: "include", headers: { Authorization: `Bearer ${document @@ -230,31 +134,34 @@ class BusinessIndustries { .getAttribute("content")}`, "Content-Type": "application/json", }, - then: (data) => - data.data.map((item) => [ - item.id, - item.nama_kecamatan, - item.nama_kelurahan, - item.nop, - item.nama_wajib_pajak, - item.alamat_wajib_pajak, - item.alamat_objek_pajak, - item.luas_bumi, - item.luas_bangunan, - item.njop_bumi, - item.njop_bangunan, - item.ketetapan, - item.tahun_pajak, - item.created_at, - item.id, // ID for Actions column - ]), - total: (data) => data.total, - }, - }) - .forceRender(); + } + ); + + 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 BusinessIndustries().init(); + new BusinessIndustries(); }); diff --git a/resources/js/data-settings/create.js b/resources/js/data-settings/create.js index f0f604f..8199ca0 100644 --- a/resources/js/data-settings/create.js +++ b/resources/js/data-settings/create.js @@ -24,10 +24,9 @@ document.addEventListener("DOMContentLoaded", function (e) { method: "POST", credentials: "include", headers: { - "X-CSRF-TOKEN": document - .querySelector('meta[name="csrf-token"]') - .getAttribute("content"), - "Content-Type": "application/json", + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}`, }, body: formData, }); @@ -35,7 +34,7 @@ document.addEventListener("DOMContentLoaded", function (e) { if (response.ok) { let result = await response.json(); document.getElementById("toast-message").innerText = - result.message; + result.data.message; toast.show(); setTimeout(() => { window.location.href = "/data-settings"; diff --git a/resources/js/data-settings/index.js b/resources/js/data-settings/index.js index 497b7de..7ae9ef7 100644 --- a/resources/js/data-settings/index.js +++ b/resources/js/data-settings/index.js @@ -2,46 +2,34 @@ 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.js"; +import Swal from "sweetalert2"; class DataSettings { 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; + + // Initialize functions + this.initTableDataSettings(); + this.initEvents(); } - init() { - this.getFetchApiData(); + initEvents() { + document.body.addEventListener("click", async (event) => { + const deleteButton = event.target.closest( + ".btn-delete-data-settings" + ); + if (deleteButton) { + event.preventDefault(); + await this.handleDelete(deleteButton); + } + }); } - getFetchApiData() { + initTableDataSettings() { let tableContainer = document.getElementById("table-data-settings"); - - if (this.table) { - // If table exists, update its data instead of recreating - this.table - .updateConfig({ - server: { - url: `${GlobalConfig.apiHost}/api/api-data-settings`, - 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.key, - item.value, - item.created_at, - item.id, - ]), - total: (data) => data.meta.total, - }, - }) - .forceRender(); - return; - } - + // Create a new Grid.js instance only if it doesn't exist this.table = new Grid({ columns: [ "ID", @@ -65,11 +53,6 @@ class DataSettings { }, }, ], - search: { - server: { - url: (prev, keyword) => `${prev}?search=${keyword}`, - }, - }, pagination: { limit: 15, server: { @@ -80,8 +63,13 @@ class DataSettings { }, }, sort: true, + search: { + server: { + url: (prev, keyword) => `${prev}?search=${keyword}`, + }, + }, server: { - url: `${GlobalConfig.apiHost}/api/api-data-settings`, + url: `${GlobalConfig.apiHost}/api/data-settings`, headers: { Authorization: `Bearer ${document .querySelector('meta[name="api-token"]') @@ -99,94 +87,26 @@ class DataSettings { total: (data) => data.meta.total, }, }).render(tableContainer); - - document.addEventListener("click", this.handleDelete.bind(this)); } - handleDelete(event) { - if (event.target.classList.contains("btn-delete-data-settings")) { - event.preventDefault(); - const id = event.target.getAttribute("data-id"); - let modalElement = document.getElementById("modalConfirmation"); - let toastMessage = document.getElementById("toast-message"); + async handleDelete(deleteButton) { + const id = deleteButton.getAttribute("data-id"); - if (!modalElement) { - console.error("Modal element not found!"); - return; - } + 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!", + }); - 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-settings-id", id); - - // Show the modal - modal.show(); - - btnSaveConfirmation.addEventListener("click", async () => { - let dataSettingId = - btnSaveConfirmation.getAttribute("data-settings-id"); - - try { - let response = await fetch( - `/data-settings/${dataSettingId}`, - { - 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.refreshDataSettings(); - } 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(); - } - }); - } - } - - refreshDataSettings() { - if (this.table) { - this.table - .updateConfig({ - server: { - url: `${GlobalConfig.apiHost}/api/api-data-settings`, + if (result.isConfirmed) { + try { + let response = await fetch( + `${GlobalConfig.apiHost}/api/data-settings/${id}`, + { + method: "DELETE", credentials: "include", headers: { Authorization: `Bearer ${document @@ -194,21 +114,34 @@ class DataSettings { .getAttribute("content")}`, "Content-Type": "application/json", }, - then: (data) => - data.data.map((item) => [ - item.id, - item.key, - item.value, - item.created_at, - item.id, - ]), - total: (data) => data.meta.total, - }, - }) - .forceRender(); + } + ); + + 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 DataSettings().init(); + new DataSettings(); }); diff --git a/resources/js/data-settings/update.js b/resources/js/data-settings/update.js index 792bd63..7dcf384 100644 --- a/resources/js/data-settings/update.js +++ b/resources/js/data-settings/update.js @@ -24,16 +24,16 @@ document.addEventListener("DOMContentLoaded", function (e) { let response = await fetch(form.action, { method: "POST", headers: { - "X-CSRF-TOKEN": document - .querySelector('meta[name="csrf-token"]') - .getAttribute("content"), + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}`, }, body: formData, }); if (response.ok) { let result = await response.json(); - toastMessage.innerText = result.message; + toastMessage.innerText = result.data.message; toast.show(); setTimeout(() => { window.location.href = "/data-settings"; diff --git a/resources/views/business-industries/index.blade.php b/resources/views/business-industries/index.blade.php index ababeea..3d0be58 100644 --- a/resources/views/business-industries/index.blade.php +++ b/resources/views/business-industries/index.blade.php @@ -16,7 +16,7 @@
diff --git a/resources/views/data-settings/create.blade.php b/resources/views/data-settings/create.blade.php index 976eeb5..226daa1 100644 --- a/resources/views/data-settings/create.blade.php +++ b/resources/views/data-settings/create.blade.php @@ -9,7 +9,7 @@
-
+ @csrf
diff --git a/resources/views/data-settings/edit.blade.php b/resources/views/data-settings/edit.blade.php index c10b56c..77357c3 100644 --- a/resources/views/data-settings/edit.blade.php +++ b/resources/views/data-settings/edit.blade.php @@ -9,7 +9,7 @@
- + @csrf @method('PUT')
diff --git a/resources/views/data-settings/index.blade.php b/resources/views/data-settings/index.blade.php index c584619..8d3d09c 100644 --- a/resources/views/data-settings/index.blade.php +++ b/resources/views/data-settings/index.blade.php @@ -9,7 +9,6 @@ @include('layouts.partials/page-title', ['title' => 'Data Settings', 'subtitle' => 'Setting Dashboard']) -
diff --git a/routes/api.php b/routes/api.php index c1fc0cd..ae6755a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -81,7 +81,13 @@ Route::group(['middleware' => 'auth:sanctum'], function (){ Route::get('/download-template-spatialPlannings', [SpatialPlanningController::class, 'downloadExcelSpatialPlanning']); // data-settings - Route::apiResource('/api-data-settings', DataSettingController::class); + // Route::apiResource('/api-data-settings', DataSettingController::class); + Route::controller(DataSettingController::class)->group(function (){ + Route::get('/data-settings', 'index')->name('api.data-settings'); + Route::post('/data-settings', 'store')->name('api.data-settings.store'); + Route::put('/data-settings/{data_setting_id}', 'update')->name('api.data-settings.update'); + Route::delete('/data-settings/{data_setting_id}', 'destroy')->name('api.data-settings.destroy'); + }); Route::apiResource('/api-pbg-task', PbgTaskController::class);