Feature: crud reklame
This commit is contained in:
108
app/Http/Controllers/Api/AdvertisementController.php
Normal file
108
app/Http/Controllers/Api/AdvertisementController.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\Advertisement;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\AdvertisementRequest;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\AdvertisementResource;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AdvertisementController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$perPage = $request->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();
|
||||
}
|
||||
}
|
||||
126
app/Http/Controllers/Data/AdvertisementController.php
Normal file
126
app/Http/Controllers/Data/AdvertisementController.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Data;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Advertisement;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AdvertisementController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('data.advertisements.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$title = 'Advertisement';
|
||||
$subtitle = 'Create Data';
|
||||
|
||||
// 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'),
|
||||
];
|
||||
|
||||
$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",
|
||||
];
|
||||
}
|
||||
}
|
||||
43
app/Http/Requests/AdvertisementRequest.php
Normal file
43
app/Http/Requests/AdvertisementRequest.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class AdvertisementRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|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',
|
||||
];
|
||||
}
|
||||
}
|
||||
19
app/Http/Resources/AdvertisementResource.php
Normal file
19
app/Http/Resources/AdvertisementResource.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class AdvertisementResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return parent::toArray($request);
|
||||
}
|
||||
}
|
||||
46
app/Models/Advertisement.php
Normal file
46
app/Models/Advertisement.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class Advertisement
|
||||
*
|
||||
* @property $id
|
||||
* @property $created_at
|
||||
* @property $updated_at
|
||||
* @property $no
|
||||
* @property $business_name
|
||||
* @property $npwpd
|
||||
* @property $advertisement_type
|
||||
* @property $advertisement_content
|
||||
* @property $business_address
|
||||
* @property $advertisement_location
|
||||
* @property $village_code
|
||||
* @property $district_code
|
||||
* @property $length
|
||||
* @property $width
|
||||
* @property $viewing_angle
|
||||
* @property $face
|
||||
* @property $area
|
||||
* @property $angle
|
||||
* @property $contact
|
||||
*
|
||||
* @package App
|
||||
* @mixin \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
class Advertisement extends Model
|
||||
{
|
||||
|
||||
protected $perPage = 20;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
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'];
|
||||
|
||||
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
74
composer.lock
generated
74
composer.lock
generated
@@ -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"
|
||||
}
|
||||
|
||||
81
config/crud.php
Normal file
81
config/crud.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Stubs Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The stubs path directory to generate crud. You may configure your
|
||||
| stubs paths here, allowing you to customize the own stubs of the
|
||||
| model,controller or view. Or, you may simply stick with the CrudGenerator defaults!
|
||||
|
|
||||
| Example: 'stub_path' => 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',
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('advertisements', function (Blueprint $table) {
|
||||
$table->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');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('villages', function (Blueprint $table) {
|
||||
$table->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');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
//
|
||||
Schema::table('advertisements', function (Blueprint $table) {
|
||||
// Mengubah tipe data kolom 'village_code' menjadi BIGINT
|
||||
$table->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();
|
||||
});
|
||||
}
|
||||
};
|
||||
76
resources/js/data/advertisements/data-advertisements.js
Normal file
76
resources/js/data/advertisements/data-advertisements.js
Normal file
@@ -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(`
|
||||
<div class="d-flex justify-items-end gap-10">
|
||||
<button class="btn btn-yellow me-2 btn-edit"
|
||||
data-id="${id}"
|
||||
data-model="${model}">Update</button>
|
||||
<button class="btn btn-red btn-delete"
|
||||
data-id="${id}">Delete</button>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
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();
|
||||
});
|
||||
93
resources/js/form-create-update.js
Normal file
93
resources/js/form-create-update.js
Normal file
@@ -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 = `
|
||||
<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
124
resources/js/table-generator.js
Normal file
124
resources/js/table-generator.js
Normal file
@@ -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;
|
||||
25
resources/views/data/advertisements/index.blade.php
Normal file
25
resources/views/data/advertisements/index.blade.php
Normal file
@@ -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'])
|
||||
|
||||
<div class="row">
|
||||
<div class="d-flex justify-content-end gap-10 pb-3">
|
||||
<button class="btn btn-success me-2 width-lg btn-create" data-model="data/advertisements">Create</button>
|
||||
<button class="btn btn-primary width-lg btn-bulk-create">Bulk Create</button>
|
||||
</div>
|
||||
<div>
|
||||
<div id="reklame-data-table"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
@vite(['resources/js/data/advertisements/data-advertisements.js'])
|
||||
@endsection
|
||||
117
resources/views/form-create-update/form.blade.php
Normal file
117
resources/views/form-create-update/form.blade.php
Normal file
@@ -0,0 +1,117 @@
|
||||
@extends('layouts.vertical', ['subtitle' => $subtitle]) <!-- Menggunakan subtitle dari controller -->
|
||||
|
||||
@section('content')
|
||||
|
||||
@include('layouts.partials/page-title', ['title' => $title, 'subtitle' => $subtitle]) <!-- Menggunakan title dan subtitle dari controller -->
|
||||
|
||||
<div class="row d-flex justify-content-center">
|
||||
@if (session('error'))
|
||||
<div class="alert alert-danger">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form id="create-update-form" action="{{ isset($modelInstance) && $modelInstance->id ? $apiUrl . '/' . $modelInstance->id : $apiUrl }}" method="POST">
|
||||
@csrf
|
||||
@if(isset($modelInstance))
|
||||
@method('PUT')
|
||||
@endif
|
||||
|
||||
@foreach($fields as $field => $label)
|
||||
<div class="form-group mb-3">
|
||||
<label for="{{ $field }}">{{ $label }}</label>
|
||||
@php
|
||||
$fieldType = $fieldTypes[$field] ?? 'text'; // Default text jika tidak ditemukan tipe
|
||||
@endphp
|
||||
|
||||
@if($fieldType == 'textarea')
|
||||
<textarea id="{{ $field }}" name="{{ $field }}" class="form-control">{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}</textarea>
|
||||
@elseif($fieldType == 'select' && isset($dropdownOptions[$field]))
|
||||
<select id="{{ $field }}" name="{{ $field }}" class="form-control">
|
||||
@foreach($dropdownOptions[$field] as $code => $name)
|
||||
<option value="{{ $code }}" {{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') == $code ? 'selected' : '' }}>{{ $name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@elseif($fieldType == 'combobox' && isset($dropdownOptions[$field]))
|
||||
<input class="form-control" list="{{ $field }}Options" id="{{ $field }}" name="{{ $field }}"
|
||||
value="{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}" placeholder="Type to search...">
|
||||
<datalist id="{{ $field }}Options">
|
||||
@foreach($dropdownOptions[$field] as $code => $name)
|
||||
<option value="{{ $name }}" data-code="{{ $code }}">
|
||||
@endforeach
|
||||
</datalist>
|
||||
@else
|
||||
<input type="{{ $fieldType }}" id="{{ $field }}" name="{{ $field }}" class="form-control" value="{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}">
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
<div class="d-flex justify-content-end">
|
||||
<button type="button" class="btn btn-primary width-lg btn-modal" data-bs-toggle="modal" data-bs-target="#confirmationModalCenter">
|
||||
{{ isset($modelInstance) ? 'Update' : 'Create' }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="confirmationModalCenter" tabindex="-1"
|
||||
aria-labelledby="confirmationModalCenterTitle" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="confirmationModalCenterTitle">
|
||||
{{ isset($modelInstance) ? 'Update Confirmation' : 'Create Confirmation' }}
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{ isset($modelInstance) ? 'Are you sure you want to save the data changes?' : 'Are you sure you want to create new data based on the form contents?' }}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary"
|
||||
data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary {{ isset($modelInstance) ? 'btn-edit' : 'btn-create' }}" data-bs-dismiss="modal">Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast-container position-fixed end-0 top-0 p-3">
|
||||
<div id="toastEditUpdate" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast-header">
|
||||
<div class="auth-logo me-auto">
|
||||
<img class="logo-dark" src="/images/logo-dark.png" alt="logo-dark" height="18" />
|
||||
<img class="logo-light" src="/images/logo-light.png" alt="logo-light"
|
||||
height="18" />
|
||||
</div>
|
||||
<small class="text-muted">2 seconds ago</small>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
Heads up, toasts will stack automatically
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
@vite(['resources/js/form-create-update.js'])
|
||||
@endsection
|
||||
@@ -91,6 +91,9 @@
|
||||
<li class="sub-nav-item">
|
||||
<a class="sub-nav-link" href="{{ route ('request-assignments.index' ) }}">PBG</a>
|
||||
</li>
|
||||
<li class="sub-nav-item">
|
||||
<a class="sub-nav-link" href="{{ route ('advertisements.index') }}">Reklame</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -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,6 +40,9 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
|
||||
|
||||
// scraping
|
||||
Route::apiResource('/scraping', ScrapingController::class);
|
||||
|
||||
// reklame
|
||||
Route::apiResource('advertisements', AdvertisementController::class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user