From 9c41fad2328c6d6d5dd929fc6c021c4cf00b4854 Mon Sep 17 00:00:00 2001 From: "@jamaludinarifrohman6661" Date: Fri, 7 Feb 2025 18:11:33 +0700 Subject: [PATCH] Feature: crud reklame --- .../Api/AdvertisementController.php | 108 +++++++++++++++ .../Data/AdvertisementController.php | 126 ++++++++++++++++++ app/Http/Requests/AdvertisementRequest.php | 43 ++++++ app/Http/Resources/AdvertisementResource.php | 19 +++ app/Models/Advertisement.php | 46 +++++++ composer.json | 1 + composer.lock | 74 +++++++++- config/crud.php | 81 +++++++++++ ..._06_025400_create_advertisements_table.php | 43 ++++++ ...025_02_06_030915_create_villages_table.php | 31 +++++ ...208_update_column_advertisements_table.php | 32 +++++ .../advertisements/data-advertisements.js | 76 +++++++++++ resources/js/form-create-update.js | 93 +++++++++++++ resources/js/table-generator.js | 124 +++++++++++++++++ .../views/data/advertisements/index.blade.php | 25 ++++ .../views/form-create-update/form.blade.php | 117 ++++++++++++++++ .../views/layouts/partials/sidebar.blade.php | 3 + routes/api.php | 6 +- routes/web.php | 6 + vite.config.js | 4 +- 20 files changed, 1053 insertions(+), 5 deletions(-) create mode 100644 app/Http/Controllers/Api/AdvertisementController.php create mode 100644 app/Http/Controllers/Data/AdvertisementController.php create mode 100644 app/Http/Requests/AdvertisementRequest.php create mode 100644 app/Http/Resources/AdvertisementResource.php create mode 100644 app/Models/Advertisement.php create mode 100644 config/crud.php create mode 100644 database/migrations/2025_02_06_025400_create_advertisements_table.php create mode 100644 database/migrations/2025_02_06_030915_create_villages_table.php create mode 100644 database/migrations/2025_02_06_090208_update_column_advertisements_table.php create mode 100644 resources/js/data/advertisements/data-advertisements.js create mode 100644 resources/js/form-create-update.js create mode 100644 resources/js/table-generator.js create mode 100644 resources/views/data/advertisements/index.blade.php create mode 100644 resources/views/form-create-update/form.blade.php diff --git a/app/Http/Controllers/Api/AdvertisementController.php b/app/Http/Controllers/Api/AdvertisementController.php new file mode 100644 index 0000000..713d128 --- /dev/null +++ b/app/Http/Controllers/Api/AdvertisementController.php @@ -0,0 +1,108 @@ +input('per_page', 15); // Default 15 jika tidak dikirim oleh client + $advertisements = Advertisement::paginate($perPage); + + $advertisements->getCollection()->transform(function ($advertisement) { + $village = DB::table('villages')->where('village_code', $advertisement->village_code)->first(); + $advertisement->village_name = $village ? $village->village_name : null; + + $district = DB::table('districts')->where('district_code', $advertisement->district_code)->first(); + $advertisement->district_name = $district ? $district->district_name : null; + return $advertisement; + }); + + return response()->json([ + 'data' => AdvertisementResource::collection($advertisements), + 'meta' => [ + 'total' => $advertisements->total(), + 'per_page' => $advertisements->perPage(), + 'current_page' => $advertisements->currentPage(), + 'last_page' => $advertisements->lastPage(), + ] + ]); + } + + /** + * Store a newly created resource in storage. + */ + public function store(AdvertisementRequest $request): Advertisement + { + $data = $request->validated(); + + // Transformasi village_name dan district_name menjadi village_code dan district_code + if (isset($data['village_name'])) { + // Ambil village_code berdasarkan village_name dari database + $data['village_code'] = DB::table('villages')->where('village_name', $data['village_name'])->value('village_code'); + unset($data['village_name']); // Hapus village_name jika sudah tidak diperlukan + } + + if (isset($data['district_name'])) { + // Ambil district_code berdasarkan district_name dari database + $data['district_code'] = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code'); + unset($data['district_name']); // Hapus district_name jika sudah tidak diperlukan + } + + // Log data setelah transformasi + info($data); + return Advertisement::create($data); + } + + /** + * Display the specified resource. + */ + public function show(Advertisement $advertisement): Advertisement + { + return $advertisement; + } + + /** + * Update the specified resource in storage. + */ + public function update(AdvertisementRequest $request, Advertisement $advertisement): Advertisement + { + $data = $request->validated(); + // Transformasi village_name dan district_name menjadi village_code dan district_code + if (isset($data['village_name'])) { + // Ambil village_code berdasarkan village_name dari database + $data['village_code'] = DB::table('villages')->where('village_name', $data['village_name'])->value('village_code'); + unset($data['village_name']); // Hapus village_name jika sudah tidak diperlukan + } + + if (isset($data['district_name'])) { + // Ambil district_code berdasarkan district_name dari database + $data['district_code'] = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code'); + unset($data['district_name']); // Hapus district_name jika sudah tidak diperlukan + } + + // Log data setelah transformasi + info($data); + $advertisement->update($data); + + return $advertisement; + } + + public function destroy(Advertisement $advertisement): Response + { + $advertisement->delete(); + + return response()->noContent(); + } +} diff --git a/app/Http/Controllers/Data/AdvertisementController.php b/app/Http/Controllers/Data/AdvertisementController.php new file mode 100644 index 0000000..603057c --- /dev/null +++ b/app/Http/Controllers/Data/AdvertisementController.php @@ -0,0 +1,126 @@ + DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'), + 'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'), + ]; + + $fields = $this->getFields(); + $fieldTypes = $this->getFieldTypes(); + + $apiUrl = url('/api/advertisements'); + + // $route = 'advertisements.create'; + // info("AdvertisementController@edit diakses dengan ID: $title"); + return view('form-create-update.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions')); + } + + /** + * Show the form for editing the specified resource. + */ + public function edit($id) + { + info("AdvertisementController@edit diakses dengan ID: $id"); + $title = 'Advertisement'; + $subtitle = 'Update Data'; + $modelInstance = Advertisement::find($id); + // Pastikan model ditemukan + if (!$modelInstance) { + info("AdvertisementController@edit: Model tidak ditemukan."); + return redirect()->route('advertisements.index')->with('error', 'Advertisement not found'); + } + + // Mengambil dan memetakan village_name dan district_name + $village = DB::table('villages')->where('village_code', $modelInstance->village_code)->first(); + $modelInstance->village_name = $village ? $village->village_name : null; + + $district = DB::table('districts')->where('district_code', $modelInstance->district_code)->first(); + $modelInstance->district_name = $district ? $district->district_name : null; + + // Mengambil data untuk dropdown + $dropdownOptions = [ + 'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'), + 'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'), + ]; + + info("AdvertisementController@edit diakses dengan Model Instance: $modelInstance"); + $fields = $this->getFields(); + $fieldTypes = $this->getFieldTypes(); + + $apiUrl = url('/api/advertisements'); + + // $route = 'advertisements.update'; // Menggunakan route update untuk form edit + // info("AdvertisementController@edit diakses dengan route: $route"); + return view('form-create-update.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions')); + } + + private function getFields() + { + return [ + "no" => "No", + "business_name" => "Nama Wajib Pajak", + "npwpd" => "NPWPD", + "advertisement_type" => "Jenis Reklame", + "advertisement_content" => "Isi Reklame", + "business_address" => "Alamat Wajib Pajak", + "advertisement_location" => "Lokasi Reklame", + "village_name" => "Desa", + "district_name" => "Kecamatan", + "length" => "Panjang", + "width" => "Lebar", + "viewing_angle" => "Sudut Pandang", + "face" => "Muka", + "area" => "Luas", + "angle" => "Sudut", + "contact" => "Kontak", + ]; + } + + private function getFieldTypes() + { + return [ + "no" => "text", + "business_name" => "text", + "npwpd" => "text", + "advertisement_type" => "text", + "advertisement_content" => "textarea", + "business_address" => "text", + "advertisement_location" => "text", + "village_name" => "combobox", + "district_name" => "combobox", + "length" => "text", + "width" => "text", + "viewing_angle" => "text", + "face" => "text", + "area" => "text", + "angle" => "text", + "contact" => "text", + ]; + } +} diff --git a/app/Http/Requests/AdvertisementRequest.php b/app/Http/Requests/AdvertisementRequest.php new file mode 100644 index 0000000..c2f29a8 --- /dev/null +++ b/app/Http/Requests/AdvertisementRequest.php @@ -0,0 +1,43 @@ +|string> + */ + public function rules(): array + { + return [ + 'no' => 'required', + 'business_name' => 'required|string', + 'npwpd' => 'required|string', + 'advertisement_type' => 'required|string', + 'advertisement_content' => 'required|string', + 'business_address' => 'required|string', + 'advertisement_location' => 'required|string', + 'village_name' => 'required', + 'district_name' => 'required', + 'length' => 'required', + 'width' => 'required', + 'viewing_angle' => 'required|string', + 'face' => 'required|string', + 'area' => 'required|string', + 'angle' => 'required|string', + 'contact' => 'required|string', + ]; + } +} diff --git a/app/Http/Resources/AdvertisementResource.php b/app/Http/Resources/AdvertisementResource.php new file mode 100644 index 0000000..15291a7 --- /dev/null +++ b/app/Http/Resources/AdvertisementResource.php @@ -0,0 +1,19 @@ + + */ + public function toArray(Request $request): array + { + return parent::toArray($request); + } +} diff --git a/app/Models/Advertisement.php b/app/Models/Advertisement.php new file mode 100644 index 0000000..e4579a1 --- /dev/null +++ b/app/Models/Advertisement.php @@ -0,0 +1,46 @@ + + */ + protected $fillable = ['no', 'business_name', 'npwpd', 'advertisement_type', 'advertisement_content', 'business_address', 'advertisement_location', 'village_code', 'district_code', 'length', 'width', 'viewing_angle', 'face', 'area', 'angle', 'contact']; + + +} diff --git a/composer.json b/composer.json index 7ae003f..7b57f35 100755 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ }, "require-dev": { "fakerphp/faker": "^1.23", + "ibex/crud-generator": "^2.1", "laravel/pail": "^1.1", "laravel/pint": "^1.13", "laravel/sail": "^1.26", diff --git a/composer.lock b/composer.lock index f63b203..14ca53b 100755 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7bb7c3b4b4eb50972252c4683f797104", + "content-hash": "600bc468a0c3848ac887e905a0cd06a8", "packages": [ { "name": "brick/math", @@ -5870,6 +5870,74 @@ }, "time": "2020-07-09T08:09:16+00:00" }, + { + "name": "ibex/crud-generator", + "version": "v2.1.2", + "source": { + "type": "git", + "url": "https://github.com/awais-vteams/laravel-crud-generator.git", + "reference": "3906f4a702c91bbe3a84d940c3021d1511834320" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/awais-vteams/laravel-crud-generator/zipball/3906f4a702c91bbe3a84d940c3021d1511834320", + "reference": "3906f4a702c91bbe3a84d940c3021d1511834320", + "shasum": "" + }, + "require": { + "laravel/framework": "^10.30|^11.0", + "php": "^8.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Ibex\\CrudGenerator\\CrudServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Ibex\\CrudGenerator\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "M Awais", + "email": "asargodha@gmail.com" + } + ], + "description": "Laravel CRUD Generator", + "keywords": [ + "alpine js", + "bootstrap css", + "crud", + "crud generator", + "laravel", + "laravel crud generator", + "laravel package", + "tailwind css" + ], + "support": { + "issues": "https://github.com/awais-vteams/laravel-crud-generator/issues", + "source": "https://github.com/awais-vteams/laravel-crud-generator/tree/v2.1.2" + }, + "funding": [ + { + "url": "https://github.com/awais-vteams", + "type": "github" + }, + { + "url": "https://ko-fi.com/mawais", + "type": "ko_fi" + } + ], + "time": "2024-12-09T06:01:54+00:00" + }, { "name": "laravel/pail", "version": "v1.2.1", @@ -7906,12 +7974,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.2" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/config/crud.php b/config/crud.php new file mode 100644 index 0000000..fa310df --- /dev/null +++ b/config/crud.php @@ -0,0 +1,81 @@ + resource_path('stubs/') + | Default: "default" + | Files: + | Controller.stub + | Model.stub + | Request.stub + | views/ + | bootstrap/ + | create.stub + | edit.stub + | form.stub + | form-field.stub + | index.stub + | show.stub + | view-field.stub + */ + + 'stub_path' => 'default', + + /* + |-------------------------------------------------------------------------- + | Application Layout + |-------------------------------------------------------------------------- + | + | This value is the name of your application layout. This value is used when creating + | views for crud. Default will be the "layouts.app". + | + | layout = false or layout = null will not create the layout files. + */ + + 'layout' => 'layouts.app', + + 'model' => [ + 'namespace' => 'App\Models', + + /* + * Do not make these columns $fillable in Model or views + */ + 'unwantedColumns' => [ + 'id', + 'uuid', + 'ulid', + 'password', + 'email_verified_at', + 'remember_token', + 'created_at', + 'updated_at', + 'deleted_at', + ], + ], + + 'controller' => [ + 'namespace' => 'App\Http\Controllers', + 'apiNamespace' => 'App\Http\Controllers\Api', + ], + + 'resources' => [ + 'namespace' => 'App\Http\Resources', + ], + + 'livewire' => [ + 'namespace' => 'App\Livewire', + ], + + 'request' => [ + 'namespace' => 'App\Http\Requests', + ], +]; diff --git a/database/migrations/2025_02_06_025400_create_advertisements_table.php b/database/migrations/2025_02_06_025400_create_advertisements_table.php new file mode 100644 index 0000000..9b0d0e6 --- /dev/null +++ b/database/migrations/2025_02_06_025400_create_advertisements_table.php @@ -0,0 +1,43 @@ +id(); + $table->timestamps(); + $table->integer('no'); + $table->string('business_name'); + $table->string('npwpd'); + $table->string('advertisement_type'); + $table->string('advertisement_content'); + $table->string('business_address'); + $table->string('advertisement_location'); + $table->integer('village_code'); + $table->integer('district_code'); + $table->float('length'); + $table->float('width'); + $table->string('viewing_angle'); + $table->string('face'); + $table->string('area'); + $table->string('angle'); + $table->string('contact'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('advertisements'); + } +}; diff --git a/database/migrations/2025_02_06_030915_create_villages_table.php b/database/migrations/2025_02_06_030915_create_villages_table.php new file mode 100644 index 0000000..de92c43 --- /dev/null +++ b/database/migrations/2025_02_06_030915_create_villages_table.php @@ -0,0 +1,31 @@ +id(); + $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); + $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')); + $table->integer('district_code'); + $table->string('village_code'); + $table->string('village_name'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('villages'); + } +}; diff --git a/database/migrations/2025_02_06_090208_update_column_advertisements_table.php b/database/migrations/2025_02_06_090208_update_column_advertisements_table.php new file mode 100644 index 0000000..2a9bbd7 --- /dev/null +++ b/database/migrations/2025_02_06_090208_update_column_advertisements_table.php @@ -0,0 +1,32 @@ +string('village_code')->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // + Schema::table('advertisements', function (Blueprint $table) { + // Mengubah kembali tipe data kolom 'village_code' ke tipe sebelumnya (misalnya INT) + $table->integer('village_code')->change(); + }); + } +}; diff --git a/resources/js/data/advertisements/data-advertisements.js b/resources/js/data/advertisements/data-advertisements.js new file mode 100644 index 0000000..8b9401c --- /dev/null +++ b/resources/js/data/advertisements/data-advertisements.js @@ -0,0 +1,76 @@ +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 GeneralTable from "../../table-generator.js"; + +const dataAdvertisementsColumns = [ + "No", + "Nama Wajib Pajak", + "NPWPD", + "Jenis Reklame", + "Isi Reklame", + "Alamat Wajib Pajak", + "Lokasi Reklame", + "Desa", + "Kecamatan", + "Panjang", + "Lebar", + "Sudut Pandang", + "Muka", + "Luas", + "Sudut", + "Kontak", + { + name: "Actions", + widht: "120px", + formatter: function(cell, row) { + const id = row.cells[16].data; + const model = "data/advertisements"; + return gridjs.html(` +
+ + +
+ `); + } + } +]; + +document.addEventListener("DOMContentLoaded", () => { + const table = new GeneralTable( + "reklame-data-table", + `${GlobalConfig.apiHost}/api/advertisements`, + `${GlobalConfig.apiHost}`, + dataAdvertisementsColumns + ); + + table.processData = function (data) { + return data.data.map((item) => { + return [ + item.no, + item.business_name, + item.npwpd, + item.advertisement_type, + item.advertisement_content, + item.business_address, + item.advertisement_location, + item.village_name, + item.district_name, + item.length, + item.width, + item.viewing_angle, + item.face, + item.area, + item.angle, + item.contact, + item.id, + ]; + }); + }; + + table.init(); +}); \ No newline at end of file diff --git a/resources/js/form-create-update.js b/resources/js/form-create-update.js new file mode 100644 index 0000000..9caac6c --- /dev/null +++ b/resources/js/form-create-update.js @@ -0,0 +1,93 @@ +document.addEventListener("DOMContentLoaded", function () { + const saveButton = document.querySelector(".modal-footer .btn-primary"); + const modalButton = document.querySelector(".btn-modal"); + const form = document.querySelector("form#create-update-form"); + + if (!saveButton || !form) return; + + saveButton.addEventListener("click", function () { + // Disable tombol dan tampilkan spinner + modalButton.disabled = true; + modalButton.innerHTML = ` + + Loading... + `; + const isEdit = saveButton.classList.contains("btn-edit"); + const formData = new FormData(form) + const toast = document.getElementById('toastEditUpdate'); + const toastBody = toast.querySelector('.toast-body'); + const toastHeader = toast.querySelector('.toast-header small'); + + const data = {}; + + // Mengonversi FormData ke dalam JSON + formData.forEach((value, key) => { + data[key] = value; + }); + + // Log semua data dalam FormData + for (let pair of formData.entries()) { + console.log(pair[0] + ": " + pair[1]); + } + const url = form.getAttribute("action"); + console.log("Ini adalah url dari form action", url); + + const method = isEdit ? "PUT" : "POST"; + + fetch(url, { + method: method, + body: JSON.stringify(data), + headers: { + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}`, + "Content-Type": "application/json", + } + }) + .then(response => response.json()) + .then(data => { + console.log("Response data:", data); + if (!data.errors) { + // Set success message for the toast + toastBody.textContent = isEdit ? "Data updated successfully!" : "Data created successfully!"; + toastHeader.textContent = "Just now"; + toast.classList.add('show'); // Show the toast + setTimeout(() => { + toast.classList.remove('show'); // Hide the toast after 3 seconds + }, 3000); + + setTimeout(() => { + window.location.reload(); + }, 3000); + } else { + // Set error message for the toast + toastBody.textContent = "Error: " + (responseData.message || "Something went wrong"); + toastHeader.textContent = "Error occurred"; + toast.classList.add('show'); // Show the toast + + // Enable button and reset its text on error + modalButton.disabled = false; + modalButton.innerHTML = isEdit ? "Update" : "Create"; + + setTimeout(() => { + toast.classList.remove('show'); // Hide the toast after 3 seconds + }, 3000); + } + }) + .catch(error => { + console.error("Error:", error); + // Set error message for the toast + toastBody.textContent = "An error occurred while processing your request."; + toastHeader.textContent = "Error occurred"; + toast.classList.add('show'); // Show the toast + + // Enable button and reset its text on error + modalButton.disabled = false; + modalButton.innerHTML = isEdit ? "Update" : "Create"; + + setTimeout(() => { + toast.classList.remove('show'); // Hide the toast after 3 seconds + }, 3000); + }); + }); +}); \ No newline at end of file diff --git a/resources/js/table-generator.js b/resources/js/table-generator.js new file mode 100644 index 0000000..6500379 --- /dev/null +++ b/resources/js/table-generator.js @@ -0,0 +1,124 @@ +import { Grid } from "gridjs/dist/gridjs.umd.js"; +import "gridjs/dist/gridjs.umd.js"; + +class GeneralTable { + constructor(tableId, apiUrl, baseUrl, columns, options = {}) { + this.tableId = tableId; + this.apiUrl = apiUrl; + this.baseUrl = baseUrl; // Tambahkan base URL + this.columns = columns; + this.options = options; + } + + init() { + const table = new Grid({ + columns: this.columns, + search: this.options.search || { + server: { + url: (prev, keyword) => `${prev}?search=${keyword}`, + }, + }, + pagination: this.options.pagination || { + limit: 15, + server: { + url: (prev, page) => + `${prev}${prev.includes("?") ? "&" : "?"}page=${page + 1}`, + }, + }, + sort: this.options.sort || true, + server: { + url: this.apiUrl, + headers: this.options.headers || { + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}`, + "Content-Type": "application/json", + }, + then: (data) => this.processData(data), + total: (data) => data.meta.total, + }, + }); + + table.render(document.getElementById(this.tableId)); + this.handleActions(); + } + + // Memproses data dari API + processData(data) { + return data.data.map((item) => { + return this.columns.map((column) => { + return item[column] || ''; + }); + }); + } + + handleActions() { + document.addEventListener("click", (event) => { + if (event.target && event.target.classList.contains('btn-edit')) { + this.handleEdit(event); + } + if (event.target && event.target.classList.contains('btn-delete')) { + this.handleDelete(event); + } + if (event.target && event.target.classList.contains('btn-create')) { + this.handleCreate(event); + } + }); + } + + // Fungsi untuk menangani create + handleCreate(event) { + // Menggunakan model dan ID untuk membangun URL dinamis + const model = event.target.getAttribute('data-model'); // Mengambil model dari data-model + window.location.href = `${this.baseUrl}/${model}/create`; + } + + // Fungsi untuk menangani edit + handleEdit(event) { + const id = event.target.getAttribute('data-id'); + const model = event.target.getAttribute('data-model'); // Mengambil model dari data-model + console.log('Editing record with ID:', id); + // Menggunakan model dan ID untuk membangun URL dinamis + window.location.href = `${this.baseUrl}/${model}/${id}/edit`; + } + + // Fungsi untuk menangani delete + handleDelete(event) { + const id = event.target.getAttribute('data-id'); + console.log(id); + if (confirm("Are you sure you want to delete this item?")) { + this.deleteRecord(id); + } + } + + async deleteRecord(id) { + try { + console.log(id); + const response = await fetch(`${this.apiUrl}/${id}`, { // Menambahkan model dalam URL + method: 'DELETE', + headers: this.options.headers || { + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}`, + "Content-Type": "application/json", + }, + // headers: { + // 'Authorization': `Bearer ${document.querySelector('meta[name="api-token"]').getAttribute("content")}`, + // 'Content-Type': 'application/json', + // }, + }); + if (response.status === 204) { // Jika status code 204, berarti berhasil + alert('Data deleted successfully!'); + location.reload(); + } else { + const data = await response.json(); // Jika ada data di response body + alert('Failed to delete data: ' + (data.message || 'Unknown error.')); + } + } catch (error) { + console.error('Error deleting data:', error); + alert('Error deleting data.'); + } + } +} + +export default GeneralTable; \ No newline at end of file diff --git a/resources/views/data/advertisements/index.blade.php b/resources/views/data/advertisements/index.blade.php new file mode 100644 index 0000000..a33a860 --- /dev/null +++ b/resources/views/data/advertisements/index.blade.php @@ -0,0 +1,25 @@ +@extends('layouts.vertical', ['subtitle' => 'Reklame']) + +@section('css') +@vite(['node_modules/gridjs/dist/theme/mermaid.min.css']) +@endsection + +@section('content') + +@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'Reklame']) + +
+
+ + +
+
+
+
+
+ +@endsection + +@section('scripts') +@vite(['resources/js/data/advertisements/data-advertisements.js']) +@endsection \ No newline at end of file diff --git a/resources/views/form-create-update/form.blade.php b/resources/views/form-create-update/form.blade.php new file mode 100644 index 0000000..e075973 --- /dev/null +++ b/resources/views/form-create-update/form.blade.php @@ -0,0 +1,117 @@ +@extends('layouts.vertical', ['subtitle' => $subtitle]) + +@section('content') + +@include('layouts.partials/page-title', ['title' => $title, 'subtitle' => $subtitle]) + +
+ @if (session('error')) +
+ {{ session('error') }} +
+ @endif + + @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif +
+
+
+
+ @csrf + @if(isset($modelInstance)) + @method('PUT') + @endif + + @foreach($fields as $field => $label) +
+ + @php + $fieldType = $fieldTypes[$field] ?? 'text'; // Default text jika tidak ditemukan tipe + @endphp + + @if($fieldType == 'textarea') + + @elseif($fieldType == 'select' && isset($dropdownOptions[$field])) + + @elseif($fieldType == 'combobox' && isset($dropdownOptions[$field])) + + + @foreach($dropdownOptions[$field] as $code => $name) + + @else + + @endif +
+ @endforeach +
+ +
+
+
+
+
+
+ + + + +
+ +
+ +@endsection + +@section('scripts') +@vite(['resources/js/form-create-update.js']) +@endsection \ No newline at end of file diff --git a/resources/views/layouts/partials/sidebar.blade.php b/resources/views/layouts/partials/sidebar.blade.php index 99331ed..c2cc32c 100644 --- a/resources/views/layouts/partials/sidebar.blade.php +++ b/resources/views/layouts/partials/sidebar.blade.php @@ -91,6 +91,9 @@ + diff --git a/routes/api.php b/routes/api.php index afc9dec..9a83058 100644 --- a/routes/api.php +++ b/routes/api.php @@ -7,6 +7,7 @@ use App\Http\Controllers\Api\RequestAssignmentController; use App\Http\Controllers\Api\ScrapingController; use App\Http\Controllers\Api\UsersController; use App\Http\Controllers\Settings\SyncronizeController; +use App\Http\Controllers\Api\AdvertisementController; use Illuminate\Support\Facades\Route; Route::post('/login', [UsersController::class, 'login'])->name('api.user.login'); @@ -39,10 +40,13 @@ Route::group(['middleware' => 'auth:sanctum'], function (){ // scraping Route::apiResource('/scraping', ScrapingController::class); + + // reklame + Route::apiResource('advertisements', AdvertisementController::class); }); Route::get('/sync-task', [SyncronizeController::class, 'syncPbgTask'])->name('api.task'); Route::get('/get-user-token', [SyncronizeController::class, 'getUserToken'])->name('api.task.token'); Route::get('/get-index-integration-retribution/{uuid}', [SyncronizeController::class, 'syncIndexIntegration'])->name('api.task.inntegration'); -Route::get('/sync-task-submit/{uuid}', [SyncronizeController::class, 'syncTaskDetailSubmit'])->name('api.task.submit'); \ No newline at end of file +Route::get('/sync-task-submit/{uuid}', [SyncronizeController::class, 'syncTaskDetailSubmit'])->name('api.task.submit'); diff --git a/routes/web.php b/routes/web.php index 40d4e8c..670b664 100755 --- a/routes/web.php +++ b/routes/web.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Master\UsersController; use App\Http\Controllers\RequestAssignment\PbgTaskController; use App\Http\Controllers\Settings\SettingsController; use App\Http\Controllers\Settings\SyncronizeController; +use App\Http\Controllers\Data\AdvertisementController; use Illuminate\Support\Facades\Route; require __DIR__ . '/auth.php'; @@ -39,4 +40,9 @@ Route::group(['middleware' => 'auth'], function(){ Route::get('/index', 'index')->name('request-assignments.index'); }); }); + + // data + Route::group(['prefix' => '/data'], function(){ + Route::resource('/advertisements', AdvertisementController::class); + }); }); \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index 2895dc6..6593003 100755 --- a/vite.config.js +++ b/vite.config.js @@ -31,7 +31,9 @@ export default defineConfig({ "resources/js/pages/maps-spain.js", "resources/js/pages/maps-russia.js", "resources/js/pages/maps-iraq.js", - "resources/js/pages/maps-canada.js" + "resources/js/pages/maps-canada.js", + "resources/js/data/advertisements/data-advertisements.js", + "resources/js/form-create-update.js" ], refresh: true,