Compare commits
22 Commits
feat/custo
...
fix/dashbo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93f0ac5ef7 | ||
|
|
8bae33519f | ||
|
|
6865e353e6 | ||
|
|
bb4ab5c769 | ||
|
|
e743b82087 | ||
|
|
c3c7b8e3ec | ||
|
|
d49035ce8d | ||
|
|
ffd9d3514c | ||
|
|
675477c734 | ||
|
|
4350c466e3 | ||
|
|
5ab407d672 | ||
|
|
2aaa487746 | ||
|
|
080582f7ab | ||
|
|
91475aeead | ||
|
|
a7afbd69fb | ||
|
|
1ff5587050 | ||
|
|
ba315b1dee | ||
|
|
33b7131c33 | ||
|
|
dd331b4a08 | ||
|
|
dcd93d66e2 | ||
|
|
5d50d6d6cc | ||
|
|
39717d184c |
@@ -199,7 +199,7 @@ class AdvertisementController extends Controller
|
||||
|
||||
public function downloadExcelAdvertisement()
|
||||
{
|
||||
$filePath = storage_path('app/public/templates/template_reklame.xlsx');
|
||||
$filePath = public_path('templates/template_reklame.xlsx');
|
||||
|
||||
// Cek apakah file ada
|
||||
if (!file_exists($filePath)) {
|
||||
|
||||
241
app/Http/Controllers/Api/BigDataResumeController.php
Normal file
241
app/Http/Controllers/Api/BigDataResumeController.php
Normal file
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\BigdataResume;
|
||||
use App\Models\DataSetting;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class BigDataResumeController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
try{
|
||||
$filterDate = $request->get("filterByDate");
|
||||
|
||||
// If filterByDate is "latest" or empty, get the most recent record
|
||||
if (!$filterDate || $filterDate === "latest") {
|
||||
$big_data_resume = BigdataResume::latest()->first();
|
||||
} else {
|
||||
// Filter by specific date
|
||||
$big_data_resume = BigdataResume::whereDate('created_at', $filterDate)
|
||||
->orderBy('id', 'desc')
|
||||
->first();
|
||||
|
||||
if (!$big_data_resume) {
|
||||
return $this->response_empty_resume();
|
||||
}
|
||||
}
|
||||
|
||||
$data_settings = DataSetting::all();
|
||||
if($data_settings->isEmpty()){
|
||||
return response()->json(['message' => 'No data setting found']);
|
||||
}
|
||||
|
||||
$target_pad = floatval(optional($data_settings->where('key', 'TARGET_PAD')->first())->value);
|
||||
$tata_ruang = floatval(optional($data_settings->where('key', 'TATA_RUANG')->first())->value);
|
||||
$realisasi_terbit_pbg_sum = floatval(optional($data_settings->where('key', 'REALISASI_TERBIT_PBG_SUM')->first())->value);
|
||||
$realisasi_terbit_pbg_count = floatval(optional($data_settings->where('key', 'REALISASI_TERBIT_PBG_COUNT')->first())->value);
|
||||
$menuggu_klik_dpmptsp_sum = floatval(optional($data_settings->where('key', 'MENUNGGU_KLIK_DPMPTSP_SUM')->first())->value);
|
||||
$menuggu_klik_dpmptsp_count = floatval(optional($data_settings->where('key', 'MENUNGGU_KLIK_DPMPTSP_COUNT')->first())->value);
|
||||
$proses_dinas_teknis_sum = floatval(optional($data_settings->where('key', 'PROSES_DINAS_TEKNIS_SUM')->first())->value);
|
||||
$proses_dinas_teknis_count = floatval(optional($data_settings->where('key', 'PROSES_DINAS_TEKNIS_COUNT')->first())->value);
|
||||
|
||||
$kekurangan_potensi = $target_pad - $big_data_resume->potention_sum;
|
||||
|
||||
// percentage kekurangan potensi
|
||||
$kekurangan_potensi_percentage = $target_pad > 0 && $target_pad > 0
|
||||
? round(($kekurangan_potensi / $target_pad) * 100, 2) : 0;
|
||||
|
||||
// percentage total potensi
|
||||
$total_potensi_percentage = $big_data_resume->potention_sum > 0 && $target_pad > 0
|
||||
? round(($big_data_resume->potention_sum / $target_pad) * 100, 2) : 0;
|
||||
|
||||
// percentage verified document
|
||||
$verified_percentage = $big_data_resume->verified_sum > 0 && $big_data_resume->potention_sum > 0
|
||||
? round(($big_data_resume->verified_sum / $big_data_resume->potention_sum) * 100, 2) : 0;
|
||||
|
||||
// percentage non-verified document
|
||||
$non_verified_percentage = $big_data_resume->non_verified_sum > 0 && $big_data_resume->potention_sum > 0
|
||||
? round(($big_data_resume->non_verified_sum / $big_data_resume->potention_sum) * 100, 2) : 0;
|
||||
|
||||
// percentage business document
|
||||
$business_percentage = $big_data_resume->business_sum > 0 && $big_data_resume->non_verified_sum > 0
|
||||
? round(($big_data_resume->business_sum / $big_data_resume->non_verified_sum) * 100, 2) : 0;
|
||||
|
||||
// percentage non-business document
|
||||
$non_business_percentage = $big_data_resume->non_business_sum > 0 && $big_data_resume->potention_sum > 0
|
||||
? round(($big_data_resume->non_business_sum / $big_data_resume->potention_sum) * 100, 2) : 0;
|
||||
|
||||
// percentage tata ruang
|
||||
$tata_ruang_percentage = $tata_ruang > 0 && $big_data_resume->potention_sum > 0
|
||||
? round(($tata_ruang / $big_data_resume->potention_sum) * 100, 2) : 0;
|
||||
|
||||
// percentage realisasi terbit pbg
|
||||
$realisasi_terbit_percentage = $big_data_resume->verified_sum > 0 && $realisasi_terbit_pbg_sum > 0
|
||||
? round(($realisasi_terbit_pbg_sum / $big_data_resume->verified_sum) * 100, 2) : 0;
|
||||
|
||||
// percentage menunggu klik dpmptsp
|
||||
$menunggu_klik_dpmptsp_percentage = $big_data_resume->verified_sum > 0 && $menuggu_klik_dpmptsp_sum > 0
|
||||
? round(($menuggu_klik_dpmptsp_sum / $big_data_resume->verified_sum) * 100, 2) : 0;
|
||||
|
||||
// percentage proses_dinas_teknis
|
||||
$proses_dinas_teknis_percentage = $big_data_resume->verified_sum > 0 && $proses_dinas_teknis_sum > 0
|
||||
? round(($proses_dinas_teknis_sum / $big_data_resume->verified_sum) * 100, 2) : 0;
|
||||
|
||||
$result = [
|
||||
'target_pad' => [
|
||||
'sum' => $target_pad,
|
||||
'percentage' => 100,
|
||||
],
|
||||
'tata_ruang' => [
|
||||
'sum' => $tata_ruang,
|
||||
'percentage' => $tata_ruang_percentage,
|
||||
],
|
||||
'kekurangan_potensi' => [
|
||||
'sum' => $kekurangan_potensi,
|
||||
'percentage' => $kekurangan_potensi_percentage
|
||||
],
|
||||
'total_potensi' => [
|
||||
'sum' => (float) $big_data_resume->potention_sum,
|
||||
'count' => $big_data_resume->potention_count,
|
||||
'percentage' => $total_potensi_percentage
|
||||
],
|
||||
'verified_document' => [
|
||||
'sum' => (float) $big_data_resume->verified_sum,
|
||||
'count' => $big_data_resume->verified_count,
|
||||
'percentage' => $verified_percentage
|
||||
],
|
||||
'non_verified_document' => [
|
||||
'sum' => (float) $big_data_resume->non_verified_sum,
|
||||
'count' => $big_data_resume->non_verified_count,
|
||||
'percentage' => $non_verified_percentage
|
||||
],
|
||||
'business_document' => [
|
||||
'sum' => (float) $big_data_resume->business_sum,
|
||||
'count' => $big_data_resume->business_count,
|
||||
'percentage' => $business_percentage
|
||||
],
|
||||
'non_business_document' => [
|
||||
'sum' => (float) $big_data_resume->non_business_sum,
|
||||
'count' => $big_data_resume->non_business_count,
|
||||
'percentage' => $non_business_percentage
|
||||
],
|
||||
'realisasi_terbit' => [
|
||||
'sum' => $realisasi_terbit_pbg_sum,
|
||||
'count' => $realisasi_terbit_pbg_count,
|
||||
'percentage' => $realisasi_terbit_percentage
|
||||
],
|
||||
'menunggu_klik_dpmptsp' => [
|
||||
'sum' => $menuggu_klik_dpmptsp_sum,
|
||||
'count' => $menuggu_klik_dpmptsp_count,
|
||||
'percentage' => $menunggu_klik_dpmptsp_percentage
|
||||
],
|
||||
'proses_dinas_teknis' => [
|
||||
'sum' => $proses_dinas_teknis_sum,
|
||||
'count' => $proses_dinas_teknis_count,
|
||||
'percentage' => $proses_dinas_teknis_percentage
|
||||
]
|
||||
];
|
||||
return response()->json($result);
|
||||
}catch(\Exception $e){
|
||||
return response()->json(['message' => 'Error when fetching data'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
private function response_empty_resume(){
|
||||
$result = [
|
||||
'target_pad' => [
|
||||
'sum' => 0,
|
||||
'percentage' => 100,
|
||||
],
|
||||
'tata_ruang' => [
|
||||
'sum' => 0,
|
||||
'percentage' => 0,
|
||||
],
|
||||
'kekurangan_potensi' => [
|
||||
'sum' => 0,
|
||||
'percentage' => 0
|
||||
],
|
||||
'total_potensi' => [
|
||||
'sum' => 0,
|
||||
'count' => 0,
|
||||
'percentage' => 0
|
||||
],
|
||||
'verified_document' => [
|
||||
'sum' => 0,
|
||||
'count' => 0,
|
||||
'percentage' => 0
|
||||
],
|
||||
'non_verified_document' => [
|
||||
'sum' => 0,
|
||||
'count' => 0,
|
||||
'percentage' => 0
|
||||
],
|
||||
'business_document' => [
|
||||
'sum' => 0,
|
||||
'count' => 0,
|
||||
'percentage' => 0
|
||||
],
|
||||
'non_business_document' => [
|
||||
'sum' => 0,
|
||||
'count' => 0,
|
||||
'percentage' => 0
|
||||
],
|
||||
'realisasi_terbit' => [
|
||||
'sum' => 0,
|
||||
'count' => 0,
|
||||
'percentage' => 0
|
||||
],
|
||||
'menunggu_klik_dpmptsp' => [
|
||||
'sum' => 0,
|
||||
'count' => 0,
|
||||
'percentage' => 0
|
||||
],
|
||||
'proses_dinas_teknis' => [
|
||||
'sum' => 0,
|
||||
'count' => 0,
|
||||
'percentage' => 0
|
||||
]
|
||||
];
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
||||
31
app/Http/Controllers/Api/LackOfPotentialController.php
Normal file
31
app/Http/Controllers/Api/LackOfPotentialController.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Advertisement;
|
||||
use App\Models\Customer;
|
||||
use App\Models\SpatialPlanning;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LackOfPotentialController extends Controller
|
||||
{
|
||||
|
||||
public function count_lack_of_potential(){
|
||||
try{
|
||||
$total_reklame = Advertisement::count();
|
||||
$total_pdam = Customer::count();
|
||||
$total_tata_ruang = SpatialPlanning::count();
|
||||
|
||||
return response()->json([
|
||||
'total_reklame' => $total_reklame,
|
||||
'total_pdam' => $total_pdam,
|
||||
'total_tata_ruang' => $total_tata_ruang
|
||||
], 200);
|
||||
}catch(\Exception $e){
|
||||
return response()->json([
|
||||
'message' => 'Error: '.$e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,11 @@
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\MenuRequest;
|
||||
use App\Http\Resources\MenuResource;
|
||||
use App\Models\Menu;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class MenusController extends Controller
|
||||
{
|
||||
@@ -13,7 +16,7 @@ class MenusController extends Controller
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = Menu::query();
|
||||
$query = Menu::query()->orderBy('id', 'desc');
|
||||
|
||||
if($request->has("search") && !empty($request->get("search"))){
|
||||
$query = $query->where("name", "like", "%".$request->get("search")."%");
|
||||
@@ -25,9 +28,15 @@ class MenusController extends Controller
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function store(MenuRequest $request)
|
||||
{
|
||||
//
|
||||
try{
|
||||
$menu = Menu::create($request->validated());
|
||||
return response()->json(['message' => 'Menu created successfully', 'data' => new MenuResource($menu)]);
|
||||
}catch(\Exception $e){
|
||||
Log::error($e);
|
||||
return response()->json(['message' => 'Error when creating menu'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,15 +44,37 @@ class MenusController extends Controller
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
//
|
||||
try{
|
||||
$menu = Menu::find($id);
|
||||
if($menu){
|
||||
return response()->json(['message' => 'Menu found', 'data' => new MenuResource($menu)]);
|
||||
} else {
|
||||
return response()->json(['message' => 'Menu not found'], 404);
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
Log::error($e);
|
||||
Log::error($e->getMessage());
|
||||
return response()->json(['message' => 'Error when finding menu'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
public function update(MenuRequest $request, string $id)
|
||||
{
|
||||
//
|
||||
try{
|
||||
$menu = Menu::findOrFail($id);
|
||||
if($menu){
|
||||
$menu->update($request->validated());
|
||||
return response()->json(['message' => 'Menu updated successfully', 'data' => new MenuResource($menu)]);
|
||||
} else {
|
||||
return response()->json(['message' => 'Menu not found'], 404);
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
Log::error($e);
|
||||
return response()->json(['message' => 'Error when updating menu'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,6 +82,28 @@ class MenusController extends Controller
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
try{
|
||||
$menu = Menu::findOrFail($id);
|
||||
if($menu){
|
||||
$this->deleteChildren($menu);
|
||||
$menu->roles()->detach();
|
||||
$menu->delete();
|
||||
return response()->json(['message' => 'Menu deleted successfully']);
|
||||
} else {
|
||||
return response()->json(['message' => 'Menu not found'], 404);
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
Log::error($e);
|
||||
return response()->json(['message' => 'Error when deleting menu'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
private function deleteChildren($menu)
|
||||
{
|
||||
foreach ($menu->children as $child) {
|
||||
$this->deleteChildren($child); // Recursively delete its children
|
||||
$child->roles()->detach(); // Detach roles before deleting
|
||||
$child->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,35 @@ class PbgTaskController extends Controller
|
||||
public function __construct(GoogleSheetService $googleSheetService){
|
||||
$this->googleSheetService = $googleSheetService;
|
||||
}
|
||||
public function index()
|
||||
public function index(Request $request)
|
||||
{
|
||||
//
|
||||
info($request);
|
||||
|
||||
$isLastUpdated = filter_var($request->query('isLastUpdated', false), FILTER_VALIDATE_BOOLEAN);
|
||||
|
||||
$query = PbgTask::query();
|
||||
|
||||
if ($isLastUpdated) {
|
||||
$query->orderBy('updated_at', 'desc');
|
||||
} else {
|
||||
$query->where('status', 20);
|
||||
}
|
||||
|
||||
// Ambil maksimal 10 data
|
||||
$pbg_task = $query->limit(10)->get();
|
||||
$totalData = $pbg_task->count();
|
||||
|
||||
// Tambahkan nomor urut
|
||||
$data = $pbg_task->map(function ($item, $index) {
|
||||
return array_merge($item->toArray(), ['no' => $index + 1]);
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'data' => $data,
|
||||
'meta' => [
|
||||
'total' => $totalData
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
146
app/Http/Controllers/Api/SpatialPlanningController.php
Normal file
146
app/Http/Controllers/Api/SpatialPlanningController.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\SpatialPlanning;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\SpatialPlanningRequest;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\SpatialPlanningResource;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use App\Imports\SpatialPlanningImport;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class SpatialPlanningController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
info($request);
|
||||
$perPage = $request->input('per_page', 15);
|
||||
$search = $request->input('search', '');
|
||||
|
||||
$query = SpatialPlanning::query();
|
||||
if ($search) {
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('name', 'like', "%$search%")
|
||||
->orWhere('kbli', 'like', "%$search%")
|
||||
->orWhere('activities', 'like', "%$search%")
|
||||
->orWhere('area', 'like', "%$search%")
|
||||
->orWhere('location', 'like', "%$search%")
|
||||
->orWhere('number', 'like', "%$search%");
|
||||
});
|
||||
}
|
||||
|
||||
$spatialPlannings = $query->paginate($perPage);
|
||||
|
||||
// Menambhakan nomor urut (No)
|
||||
$start = ($spatialPlannings->currentPage()-1) * $perPage + 1;
|
||||
|
||||
// Tambahkan nomor urut ke dalam data
|
||||
$data = $spatialPlannings->map(function ($item, $index) use ($start) {
|
||||
return array_merge($item->toArray(), ['no' => $start + $index]);
|
||||
});
|
||||
|
||||
info($data);
|
||||
|
||||
return response()->json([
|
||||
'data' => $data,
|
||||
'meta' => [
|
||||
'total' => $spatialPlannings->total(),
|
||||
'per_page' => $spatialPlannings->perPage(),
|
||||
'current_page' => $spatialPlannings->currentPage(),
|
||||
'last_page'=>$spatialPlannings->lastPage(),
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(SpatialPlanningRequest $request): SpatialPlanning
|
||||
{
|
||||
$data = $request->validated();
|
||||
return SpatialPlanning::create($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* import spatial planning from excel
|
||||
*/
|
||||
public function importFromFile(Request $request)
|
||||
{
|
||||
info($request);
|
||||
//validasi file
|
||||
$validator = Validator::make($request->all(), [
|
||||
'file' => 'required|mimes:xlsx, xls|max:10240'
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'message'=>'File vaildation failed.',
|
||||
"errors"=>$validator->errors()
|
||||
], 400);
|
||||
}
|
||||
|
||||
try {
|
||||
$file = $request->file('file');
|
||||
Excel::import(new SpatialPlanningImport, $file);
|
||||
return response()->json([
|
||||
'message'=>'File uploaded and imported successfully!'
|
||||
], 200);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'message'=>'Error during file import.',
|
||||
'error'=>$e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(SpatialPlanning $spatialPlanning): SpatialPlanning
|
||||
{
|
||||
return $spatialPlanning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(SpatialPlanningRequest $request, SpatialPlanning $spatialPlanning): SpatialPlanning
|
||||
{
|
||||
info($request);
|
||||
$data = $request->validated();
|
||||
info($data);
|
||||
|
||||
$spatialPlanning->update($data);
|
||||
|
||||
return $spatialPlanning;
|
||||
}
|
||||
|
||||
public function destroy(SpatialPlanning $spatialPlanning): Response
|
||||
{
|
||||
$spatialPlanning->delete();
|
||||
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
public function downloadExcelSpatialPlanning()
|
||||
{
|
||||
$filePath = public_path('templates/template_spatial_planning.xlsx');
|
||||
info(sprintf("File Path: %s | Exists: %s", $filePath, file_exists($filePath) ? 'Yes' : 'No'));
|
||||
|
||||
// Cek apakah file ada
|
||||
if (!file_exists($filePath)) {
|
||||
return response()-> json(['message' => 'File tidak ditemukan!'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Return file to download
|
||||
return response()->download($filePath);
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ExcelUploadRequest;
|
||||
use App\Http\Requests\SpatialPlanningsRequest;
|
||||
use App\Http\Resources\SpatialPlanningsResource;
|
||||
use App\Imports\SpatialPlanningImport;
|
||||
use App\Models\SpatialPlanning;
|
||||
use Illuminate\Http\Request;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
|
||||
class SpatialPlanningsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = SpatialPlanning::query()->orderBy('id', 'desc');
|
||||
if ($request->has("search") &&!empty($request->get("search"))) {
|
||||
$query = $query->where("name", "LIKE", "%{$request->get("search")}%")
|
||||
->orWhere("nomor", "LIKE", "%{$request->get("search")}%");
|
||||
}
|
||||
return SpatialPlanningsResource::collection($query->paginate());
|
||||
}
|
||||
|
||||
public function store(SpatialPlanningsRequest $request)
|
||||
{
|
||||
try{
|
||||
$validated = $request->validated();
|
||||
$data = SpatialPlanning::create($validated);
|
||||
return response()->json(['message' => 'Successfully created', new SpatialPlanningsResource($data)]);
|
||||
}catch(\Exception $e){
|
||||
return response()->json([
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(SpatialPlanningsRequest $request, string $id)
|
||||
{
|
||||
try{
|
||||
$validated = $request->validated();
|
||||
$data = SpatialPlanning::find($id);
|
||||
$data->update($validated);
|
||||
return response()->json(['message' => 'Successfully updated', new SpatialPlanningsResource($data)]);
|
||||
}catch(\Exception $e){
|
||||
return response()->json([
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
try{
|
||||
SpatialPlanning::destroy($id);
|
||||
return response()->json([
|
||||
'message' => 'Successfully deleted'
|
||||
], 200);
|
||||
}catch(\Exception $e){
|
||||
return response()->json([
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function upload(ExcelUploadRequest $request){
|
||||
try{
|
||||
if(!$request->hasFile('file')){
|
||||
return response()->json([
|
||||
'error' => 'No file provided'
|
||||
], 400);
|
||||
}
|
||||
|
||||
$file = $request->file('file');
|
||||
Excel::import(new SpatialPlanningImport, $file);
|
||||
return response()->json([
|
||||
'message' => 'Successfully imported'
|
||||
], 200);
|
||||
}catch(\Exception $e){
|
||||
return response()->json([
|
||||
'error' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,13 @@ class TourismController extends Controller
|
||||
$search = $request->input('search', '');
|
||||
|
||||
$query = Tourism::query();
|
||||
if ($search) {
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('business_name', 'like', "%$search%")
|
||||
->orWhere('project_name', 'like', "%$search%")
|
||||
->orWhere('business_address', 'like', "%$search%");
|
||||
});
|
||||
}
|
||||
$tourisms = $query->paginate($perPage);
|
||||
|
||||
$tourisms->getCollection()->transform(function ($tourisms) {
|
||||
@@ -36,8 +43,14 @@ class TourismController extends Controller
|
||||
return $tourisms;
|
||||
});
|
||||
|
||||
$start = ($tourisms->currentPage()-1) * $perPage + 1;
|
||||
|
||||
$data = $tourisms->map(function ($item, $index) use ($start) {
|
||||
return array_merge($item->toArray(), ['no' => $start + $index]);
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'data' => TourismResource::collection($tourisms),
|
||||
'data' => $data,
|
||||
'meta' => [
|
||||
'total' => $tourisms->total(),
|
||||
'per_page' => $tourisms->perPage(),
|
||||
@@ -93,6 +106,18 @@ class TourismController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
public function getAllLocation()
|
||||
{
|
||||
$locations = Tourism::whereNotNull('longitude')
|
||||
->whereNotNull('latitude')
|
||||
->select('project_name', 'longitude', 'latitude')
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'data' => $locations
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
@@ -127,4 +152,18 @@ class TourismController extends Controller
|
||||
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
public function downloadExcelTourism()
|
||||
{
|
||||
$filePath = public_path('templates/template_pariwisata.xlsx');
|
||||
info(sprintf("File Path: %s | Exists: %s", $filePath, file_exists($filePath) ? 'Yes' : 'No'));
|
||||
|
||||
// Cek apakah file ada
|
||||
if (!file_exists($filePath)) {
|
||||
return response()-> json(['message' => 'File tidak ditemukan!'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Return file to download
|
||||
return response()->download($filePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,17 @@ class UmkmController extends Controller
|
||||
|
||||
$query = Umkm::query();
|
||||
|
||||
if ($search) {
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('business_name', 'like', "%$search%")
|
||||
->orWhere('business_address', 'like', "%$search%")
|
||||
->orWhere('business_desc', 'like', "%$search%")
|
||||
->orWhere('business_id_number', 'like', "%$search%")
|
||||
->orWhere('owner_id', 'like', "%$search%")
|
||||
->orWhere('owner_name', 'like', "%$search%");
|
||||
});
|
||||
}
|
||||
|
||||
$umkm = $query->paginate($perPage);
|
||||
|
||||
$umkm->getCollection()->transform(function ($umkm) {
|
||||
@@ -47,8 +58,14 @@ class UmkmController extends Controller
|
||||
return $umkm;
|
||||
});
|
||||
|
||||
$start = ($umkm->currentPage()-1) * $perPage + 1;
|
||||
|
||||
$data = $umkm->map(function ($item, $index) use ($start) {
|
||||
return array_merge($item->toArray(), ['no' => $start + $index]);
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'data' => UmkmResource::collection($umkm),
|
||||
'data' => $data,
|
||||
'meta' => [
|
||||
'total' => $umkm->total(),
|
||||
'per_page' => $umkm->perPage(),
|
||||
@@ -176,7 +193,7 @@ class UmkmController extends Controller
|
||||
|
||||
public function downloadExcelUmkm()
|
||||
{
|
||||
$filePath = storage_path('app/public/templates/template_umkm.xlsx');
|
||||
$filePath = public_path('templates/template_umkm.xlsx');
|
||||
|
||||
// Cek apakah file ada
|
||||
if (!file_exists($filePath)) {
|
||||
|
||||
@@ -15,7 +15,8 @@ class BigDataController extends Controller
|
||||
return view('dashboards.bigdata', compact('latest_created'));
|
||||
}
|
||||
|
||||
public function pbg(){
|
||||
return view('index');
|
||||
public function pbg()
|
||||
{
|
||||
return view('dashboards.pbg');
|
||||
}
|
||||
}
|
||||
|
||||
125
app/Http/Controllers/Data/SpatialPlanningController.php
Normal file
125
app/Http/Controllers/Data/SpatialPlanningController.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Data;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\SpatialPlanning;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class SpatialPlanningController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('data.spatialPlannings.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* show the form for creating a new resource.
|
||||
*/
|
||||
public function bulkCreate()
|
||||
{
|
||||
return view('data.spatialPlannings.form-upload');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$title = 'Rencana Tata Ruang';
|
||||
$subtitle = "Create Data";
|
||||
|
||||
// Mengambil data untuk dropdown
|
||||
$dropdownOptions = [];
|
||||
|
||||
$fields = $this->getFields();
|
||||
$fieldTypes = $this->getFieldTypes();
|
||||
|
||||
$apiUrl = url('/api/spatial-plannings');
|
||||
return view('data.spatialPlannings.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(string $id)
|
||||
{
|
||||
$title = 'Rencana Tata Ruang';
|
||||
$subtitle = 'Update Data';
|
||||
|
||||
$modelInstance = SpatialPlanning::find($id);
|
||||
// Pastikan model ditemukan
|
||||
if (!$modelInstance) {
|
||||
return redirect()->route('spatialPlanning.index') ->with('error', 'Rencana tata ruang tidak ditemukan');
|
||||
}
|
||||
|
||||
$dropdownOptions = [];
|
||||
|
||||
$fields = $this->getFields();
|
||||
$fieldTypes = $this->getFieldTypes();
|
||||
|
||||
$apiUrl = url('/api/spatial-plannings');
|
||||
return view('data.spatialPlannings.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
private function getFields()
|
||||
{
|
||||
return [
|
||||
"name"=> "Nama",
|
||||
"kbli"=> "KBLI",
|
||||
"activities"=> "Kegiatan",
|
||||
"area"=> "Luas (m2)",
|
||||
"location"=> "Lokasi",
|
||||
"number"=> "Nomor",
|
||||
"date"=> "Tanggal",
|
||||
];
|
||||
}
|
||||
|
||||
private function getFieldTypes()
|
||||
{
|
||||
return [
|
||||
"name"=> "text",
|
||||
"kbli"=> "text",
|
||||
"activities"=> "text",
|
||||
"area"=> "text",
|
||||
"location"=> "text",
|
||||
"number"=> "text",
|
||||
"date"=> "date",
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ class TourismController extends Controller
|
||||
public function edit($id)
|
||||
{
|
||||
$title = 'Pariwisata';
|
||||
$subtitle = 'Create Data';
|
||||
$subtitle = 'Update Data';
|
||||
|
||||
$modelInstance = Tourism::find($id);
|
||||
// Pastikan model ditemukan
|
||||
|
||||
12
app/Http/Controllers/GoogleApisController.php
Normal file
12
app/Http/Controllers/GoogleApisController.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class GoogleApisController extends Controller
|
||||
{
|
||||
public function index(){
|
||||
return view('maps.google-api');
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\SpatialPlanning;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class SpatialPlanningsController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('spatial-plannings.index');
|
||||
}
|
||||
public function create()
|
||||
{
|
||||
return view('spatial-plannings.create');
|
||||
}
|
||||
|
||||
public function edit(string $id)
|
||||
{
|
||||
$data = SpatialPlanning::findOrFail($id);
|
||||
return view('spatial-plannings.update', compact('data'));
|
||||
}
|
||||
|
||||
public function upload (){
|
||||
return view('spatial-plannings.upload');
|
||||
}
|
||||
}
|
||||
@@ -40,4 +40,40 @@ class AdvertisementRequest extends FormRequest
|
||||
'contact' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* pesan error validasi
|
||||
*/
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'no.required' => 'Nomor harus diisi.',
|
||||
'business_name.required' => 'Nama usaha harus diisi.',
|
||||
'business_name.string' => 'Nama usaha harus berupa teks.',
|
||||
'npwpd.required' => 'NPWPD harus diisi.',
|
||||
'npwpd.string' => 'NPWPD harus berupa teks.',
|
||||
'advertisement_type.required' => 'Jenis reklame harus diisi.',
|
||||
'advertisement_type.string' => 'Jenis reklame harus berupa teks.',
|
||||
'advertisement_content.required' => 'Isi reklame harus diisi.',
|
||||
'advertisement_content.string' => 'Isi reklame harus berupa teks.',
|
||||
'business_address.required' => 'Alamat usaha harus diisi.',
|
||||
'business_address.string' => 'Alamat usaha harus berupa teks.',
|
||||
'advertisement_location.required' => 'Lokasi reklame harus diisi.',
|
||||
'advertisement_location.string' => 'Lokasi reklame harus berupa teks.',
|
||||
'village_name.required' => 'Nama desa harus diisi.',
|
||||
'district_name.required' => 'Nama kecamatan harus diisi.',
|
||||
'length.required' => 'Panjang harus diisi.',
|
||||
'width.required' => 'Lebar harus diisi.',
|
||||
'viewing_angle.required' => 'Sudut pandang harus diisi.',
|
||||
'viewing_angle.string' => 'Sudut pandang harus berupa teks.',
|
||||
'face.required' => 'Jumlah sisi harus diisi.',
|
||||
'face.string' => 'Jumlah sisi harus berupa teks.',
|
||||
'area.required' => 'Luas harus diisi.',
|
||||
'area.string' => 'Luas harus berupa teks.',
|
||||
'angle.required' => 'Sudut harus diisi.',
|
||||
'angle.string' => 'Sudut harus berupa teks.',
|
||||
'contact.required' => 'Kontak harus diisi.',
|
||||
'contact.string' => 'Kontak harus berupa teks.',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class MenuRequest extends FormRequest
|
||||
{
|
||||
@@ -21,12 +22,14 @@ class MenuRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$menuId = $this->route('menu_id'); // Get the menu ID if updating
|
||||
|
||||
return [
|
||||
'name' => ['required','string','max:255'],
|
||||
'url' => ['nullable','string','max:255'],
|
||||
'icon' => ['nullable','string','max:255'],
|
||||
'parent_id' => ['nullable','exists:menus,id'],
|
||||
'sort_order' => ['required','integer'],
|
||||
'name' => ['required', 'string', 'max:255', Rule::unique('menus', 'name')->ignore($menuId)],
|
||||
'url' => ['nullable', 'string', 'max:255'],
|
||||
'icon' => ['nullable', 'string', 'max:255'],
|
||||
'parent_id' => ['nullable', 'exists:menus,id'],
|
||||
'sort_order' => ['required', 'integer'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
52
app/Http/Requests/SpatialPlanningRequest.php
Normal file
52
app/Http/Requests/SpatialPlanningRequest.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class SpatialPlanningRequest 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 [
|
||||
'name' => 'string',
|
||||
'kbli' => 'string',
|
||||
'activities' => 'string',
|
||||
'area' => 'string',
|
||||
'location' => 'string',
|
||||
'number' => 'string',
|
||||
'date' => 'date_format:Y-m-d',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation messages for the defined validation rules.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'name.string' => 'Kolom Nama harus berupa teks.',
|
||||
'kbli.string' => 'Kolom KBLI harus berupa teks.',
|
||||
'activities.string' => 'Kolom Kegiatan harus berupa teks.',
|
||||
'area.string' => 'Kolom Area harus berupa teks.',
|
||||
'location.string' => 'Kolom Lokasi harus berupa teks.',
|
||||
'number.string' => 'Kolom Nomor harus berupa teks.',
|
||||
'date.date_format' => 'Format tanggal tidak valid, gunakan format Y-m-d H:i:s.',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -49,4 +49,85 @@ class TourismRequest extends FormRequest
|
||||
'tki' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation messages for the defined validation rules.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'project_id.required' => 'ID proyek harus diisi.',
|
||||
'project_id.string' => 'ID proyek harus berupa teks.',
|
||||
|
||||
'project_type_id.required' => 'ID tipe proyek harus diisi.',
|
||||
'project_type_id.string' => 'ID tipe proyek harus berupa teks.',
|
||||
|
||||
'nib.required' => 'NIB harus diisi.',
|
||||
'nib.string' => 'NIB harus berupa teks.',
|
||||
|
||||
'business_name.required' => 'Nama usaha harus diisi.',
|
||||
'business_name.string' => 'Nama usaha harus berupa teks.',
|
||||
|
||||
'oss_publication_date.required' => 'Tanggal publikasi OSS harus diisi.',
|
||||
|
||||
'investment_status_description.required' => 'Deskripsi status investasi harus diisi.',
|
||||
'investment_status_description.string' => 'Deskripsi status investasi harus berupa teks.',
|
||||
|
||||
'business_form.required' => 'Bentuk usaha harus diisi.',
|
||||
'business_form.string' => 'Bentuk usaha harus berupa teks.',
|
||||
|
||||
'project_risk.required' => 'Risiko proyek harus diisi.',
|
||||
'project_risk.string' => 'Risiko proyek harus berupa teks.',
|
||||
|
||||
'project_name.required' => 'Nama proyek harus diisi.',
|
||||
'project_name.string' => 'Nama proyek harus berupa teks.',
|
||||
|
||||
'business_scale.required' => 'Skala usaha harus diisi.',
|
||||
'business_scale.string' => 'Skala usaha harus berupa teks.',
|
||||
|
||||
'business_address.required' => 'Alamat usaha harus diisi.',
|
||||
'business_address.string' => 'Alamat usaha harus berupa teks.',
|
||||
|
||||
'district_name.required' => 'Nama kecamatan harus diisi.',
|
||||
|
||||
'village_name.required' => 'Nama desa harus diisi.',
|
||||
|
||||
'longitude.required' => 'Garis bujur harus diisi.',
|
||||
'longitude.string' => 'Garis bujur harus berupa teks.',
|
||||
|
||||
'latitude.required' => 'Garis lintang harus diisi.',
|
||||
'latitude.string' => 'Garis lintang harus berupa teks.',
|
||||
|
||||
'project_submission_date.required' => 'Tanggal pengajuan proyek harus diisi.',
|
||||
|
||||
'kbli.required' => 'Kode KBLI harus diisi.',
|
||||
'kbli.string' => 'Kode KBLI harus berupa teks.',
|
||||
|
||||
'kbli_title.required' => 'Judul KBLI harus diisi.',
|
||||
'kbli_title.string' => 'Judul KBLI harus berupa teks.',
|
||||
|
||||
'supervisory_sector.required' => 'Sektor pengawasan harus diisi.',
|
||||
'supervisory_sector.string' => 'Sektor pengawasan harus berupa teks.',
|
||||
|
||||
'user_name.required' => 'Nama pengguna harus diisi.',
|
||||
'user_name.string' => 'Nama pengguna harus berupa teks.',
|
||||
|
||||
'email.required' => 'Email harus diisi.',
|
||||
'email.string' => 'Email harus berupa teks.',
|
||||
|
||||
'contact.required' => 'Kontak harus diisi.',
|
||||
'contact.string' => 'Kontak harus berupa teks.',
|
||||
|
||||
'land_area_in_m2.required' => 'Luas lahan dalam m² harus diisi.',
|
||||
'land_area_in_m2.string' => 'Luas lahan dalam m² harus berupa teks.',
|
||||
|
||||
'investment_amount.required' => 'Jumlah investasi harus diisi.',
|
||||
'investment_amount.string' => 'Jumlah investasi harus berupa teks.',
|
||||
|
||||
'tki.required' => 'Jumlah tenaga kerja Indonesia harus diisi.',
|
||||
'tki.string' => 'Jumlah tenaga kerja Indonesia harus berupa teks.',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
19
app/Http/Resources/MenuResource.php
Normal file
19
app/Http/Resources/MenuResource.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class MenuResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return parent::toArray($request);
|
||||
}
|
||||
}
|
||||
19
app/Http/Resources/SpatialPlanningResource.php
Normal file
19
app/Http/Resources/SpatialPlanningResource.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class SpatialPlanningResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return parent::toArray($request);
|
||||
}
|
||||
}
|
||||
@@ -3,75 +3,61 @@
|
||||
namespace App\Imports;
|
||||
|
||||
use App\Models\SpatialPlanning;
|
||||
use Carbon\Carbon;
|
||||
use DateTime;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Maatwebsite\Excel\Concerns\ToCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use DateTime;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class SpatialPlanningImport implements ToCollection, WithMultipleSheets
|
||||
class SpatialPlanningImport implements ToCollection
|
||||
{
|
||||
protected static $processed = false;
|
||||
|
||||
/**
|
||||
* @param Collection $collection
|
||||
*/
|
||||
public function collection(Collection $collection)
|
||||
* Process each row in the file
|
||||
*/
|
||||
public function collection(Collection $rows)
|
||||
{
|
||||
$months = [
|
||||
"Januari" => "January", "Februari" => "February", "Maret" => "March",
|
||||
"April" => "April", "Mei" => "May", "Juni" => "June",
|
||||
"Juli" => "July", "Agustus" => "August", "September" => "September",
|
||||
"Oktober" => "October", "November" => "November", "Desember" => "December"
|
||||
];
|
||||
if (self::$processed) {
|
||||
return;
|
||||
}
|
||||
self::$processed = true;
|
||||
|
||||
$collection->skip(2)->each(function ($row) use ($months) {
|
||||
if (empty(array_filter($row->toArray()))) {
|
||||
return;
|
||||
}
|
||||
if ($rows->isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($row[6]) || empty($row[6])) {
|
||||
return;
|
||||
}
|
||||
//cari header secara otomatis
|
||||
$header = $rows->first();
|
||||
$headerIndex = collect($header)->search(fn($value) => !empty($value));
|
||||
|
||||
if(!SpatialPlanning::where("nomor", $row[6])->exists()){
|
||||
$clean_nomor = str_replace('\\','',$row[6]);
|
||||
$date_string = isset($row[7]) ? trim($row[7]) : null;
|
||||
$clean_sp_date = null;
|
||||
if ($date_string) {
|
||||
if(is_numeric($date_string)) {
|
||||
$clean_sp_date = Carbon::createFromFormat('Y-m-d', '1900-01-01')->addDays($date_string - 2)->format('Y-m-d');
|
||||
}else{
|
||||
foreach ($months as $id => $en) {
|
||||
$date_string = str_replace($id, $en, $date_string);
|
||||
}
|
||||
|
||||
$formats = ['j F Y', 'd F Y', 'j-M-Y', 'd-M-Y'];
|
||||
// Pastikan header ditemukan
|
||||
if ($headerIndex === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($formats as $format) {
|
||||
$date = DateTime::createFromFormat($format, $date_string);
|
||||
if ($date) {
|
||||
$clean_sp_date = $date->format('Y-m-d');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SpatialPlanning::create([
|
||||
'name' => $row[1],
|
||||
'kbli' => $row[2],
|
||||
'kegiatan' => $row[3],
|
||||
'luas' => $row[4],
|
||||
'lokasi' => $row[5],
|
||||
'nomor' => $clean_nomor,
|
||||
'sp_date' => $clean_sp_date,
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
foreach ($rows->skip(1) as $row) {
|
||||
$dateValue = trim($row[7]);
|
||||
info($dateValue);
|
||||
$parsedDate = Carbon::createFromFormat('Y-m-d', $dateValue)->format('Y-m-d');
|
||||
info($parsedDate);
|
||||
|
||||
public function sheets(): array {
|
||||
return [
|
||||
0 => $this
|
||||
];
|
||||
$dataToInsert[] = [
|
||||
'name'=>$row[1],
|
||||
'kbli'=>$row[2],
|
||||
'activities'=>$row[3],
|
||||
'area'=>$row[4],
|
||||
'location'=>$row[5],
|
||||
'number'=>$row[6],
|
||||
'date'=>$parsedDate,
|
||||
];
|
||||
}
|
||||
|
||||
if(!empty($dataToInsert)) {
|
||||
SpatialPlanning::insert($dataToInsert);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,13 +65,6 @@ class TourismImport implements ToCollection
|
||||
// ambill village code yang village_name sama dengan $villageName
|
||||
$villageCode = $listTrueVillage[$villageName]['village_code'] ?? '000000';
|
||||
|
||||
|
||||
// if (empty($row[16])) {
|
||||
// info("Data kosong");
|
||||
// } else {
|
||||
// info("Baris ke- | Nilai: " . $row[16]);
|
||||
// }
|
||||
|
||||
$excelSerialDate = $row[16];
|
||||
if (is_numeric($excelSerialDate)) {
|
||||
$projectSubmissionDate = Carbon::createFromFormat('Y-m-d', '1899-12-30')
|
||||
@@ -82,8 +75,6 @@ class TourismImport implements ToCollection
|
||||
->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
info("Tanggal dikonversi: " . $projectSubmissionDate);
|
||||
|
||||
$dataToInsert[] = [
|
||||
'project_id' => $row[1],
|
||||
'project_type_id' => $row[2],
|
||||
|
||||
@@ -4,16 +4,34 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class SpatialPlanning
|
||||
*
|
||||
* @property $id
|
||||
* @property $created_at
|
||||
* @property $updated_at
|
||||
* @property $name
|
||||
* @property $kbli
|
||||
* @property $activities
|
||||
* @property $area
|
||||
* @property $location
|
||||
* @property $number
|
||||
* @property $date
|
||||
*
|
||||
* @package App
|
||||
* @mixin \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
class SpatialPlanning extends Model
|
||||
{
|
||||
protected $table = "spatial_plannings";
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'kbli',
|
||||
'kegiatan',
|
||||
'luas',
|
||||
'lokasi',
|
||||
'nomor',
|
||||
'sp_date'
|
||||
];
|
||||
|
||||
protected $perPage = 20;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = ['name', 'kbli', 'activities', 'area', 'location', 'number', 'date'];
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -61,32 +61,37 @@ class ServiceSIMBG
|
||||
}
|
||||
}
|
||||
|
||||
public function syncIndexIntegration($uuid, $token)
|
||||
public function syncIndexIntegration($uuids, $token)
|
||||
{
|
||||
try{
|
||||
$url = "/api/pbg/v1/detail/" . $uuid . "/retribution/indeks-terintegrasi/";
|
||||
|
||||
$headers = [
|
||||
'Authorization' => "Bearer " . $token,
|
||||
];
|
||||
|
||||
$res = $this->service_client->get($url, $headers);
|
||||
|
||||
if (empty($res->original['success']) || !$res->original['success']) {
|
||||
// Log error
|
||||
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
|
||||
if(empty($uuids)){
|
||||
return false;
|
||||
}
|
||||
|
||||
$integrations = [];
|
||||
foreach($uuids as $uuid){
|
||||
$url = "/api/pbg/v1/detail/" . $uuid . "/retribution/indeks-terintegrasi/";
|
||||
|
||||
$data = $res->original['data']['data'] ?? null;
|
||||
if (!$data) {
|
||||
Log::error("No valid data returned from API", ['url' => $url, 'uuid' => $uuid]);
|
||||
return false;
|
||||
}
|
||||
|
||||
$resultData = PbgTaskIndexIntegrations::updateOrCreate(
|
||||
['pbg_task_uid' => $uuid],
|
||||
[
|
||||
$headers = [
|
||||
'Authorization' => "Bearer " . $token,
|
||||
];
|
||||
|
||||
$res = $this->service_client->get($url, $headers);
|
||||
|
||||
if (empty($res->original['success']) || !$res->original['success']) {
|
||||
// Log error
|
||||
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = $res->original['data']['data'] ?? null;
|
||||
if (!$data) {
|
||||
Log::error("No valid data returned from API", ['url' => $url, 'uuid' => $uuid]);
|
||||
return false;
|
||||
}
|
||||
|
||||
$integrations[] = [
|
||||
'pbg_task_uid' => $uuid,
|
||||
'indeks_fungsi_bangunan' => $data['indeks_fungsi_bangunan'] ?? null,
|
||||
'indeks_parameter_kompleksitas' => $data['indeks_parameter_kompleksitas'] ?? null,
|
||||
'indeks_parameter_permanensi' => $data['indeks_parameter_permanensi'] ?? null,
|
||||
@@ -94,8 +99,24 @@ class ServiceSIMBG
|
||||
'faktor_kepemilikan' => $data['faktor_kepemilikan'] ?? null,
|
||||
'indeks_terintegrasi' => $data['indeks_terintegrasi'] ?? null,
|
||||
'total' => $data['total'] ?? null,
|
||||
]
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
PbgTaskIndexIntegrations::upsert($integrations, ['pbg_task_uid'], ['indeks_fungsi_bangunan',
|
||||
'indeks_parameter_kompleksitas', 'indeks_parameter_permanensi', 'indeks_parameter_ketinggian', 'faktor_kepemilikan', 'indeks_terintegrasi', 'total']);
|
||||
|
||||
// $resultData = PbgTaskIndexIntegrations::updateOrCreate(
|
||||
// ['pbg_task_uid' => $uuid],
|
||||
// [
|
||||
// 'indeks_fungsi_bangunan' => $data['indeks_fungsi_bangunan'] ?? null,
|
||||
// 'indeks_parameter_kompleksitas' => $data['indeks_parameter_kompleksitas'] ?? null,
|
||||
// 'indeks_parameter_permanensi' => $data['indeks_parameter_permanensi'] ?? null,
|
||||
// 'indeks_parameter_ketinggian' => $data['indeks_parameter_ketinggian'] ?? null,
|
||||
// 'faktor_kepemilikan' => $data['faktor_kepemilikan'] ?? null,
|
||||
// 'indeks_terintegrasi' => $data['indeks_terintegrasi'] ?? null,
|
||||
// 'total' => $data['total'] ?? null,
|
||||
// ]
|
||||
// );
|
||||
|
||||
return true;
|
||||
}catch (Exception $e){
|
||||
@@ -190,7 +211,7 @@ class ServiceSIMBG
|
||||
'created_at' => now(),
|
||||
];
|
||||
|
||||
$this->syncIndexIntegration($item['uid'], $token);
|
||||
// $this->syncIndexIntegration($item['uid'], $token);
|
||||
|
||||
$this->syncTaskDetailSubmit($item['uid'], $token);
|
||||
|
||||
@@ -215,8 +236,11 @@ class ServiceSIMBG
|
||||
'slf_status', 'slf_status_name', 'function_type', 'consultation_type', 'due_date',
|
||||
'land_certificate_phase', 'task_created_at', 'updated_at'
|
||||
]);
|
||||
|
||||
$uuids = array_column($tasksCollective, 'uuid');
|
||||
$this->syncIndexIntegration($uuids, $token);
|
||||
}
|
||||
|
||||
|
||||
$importDatasource->update([
|
||||
'status' => ImportDatasourceStatus::Success->value,
|
||||
'message' => "Successfully processed: $savedCount, Failed: $failedCount"
|
||||
@@ -311,5 +335,4 @@ class ServiceSIMBG
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,6 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.23",
|
||||
"ibex/crud-generator": "^2.1",
|
||||
"laravel/pail": "^1.1",
|
||||
"laravel/pint": "^1.13",
|
||||
"laravel/sail": "^1.26",
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
<?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('spatial_plannings', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('kbli');
|
||||
$table->text('kegiatan');
|
||||
$table->decimal('luas',18,2);
|
||||
$table->text('lokasi');
|
||||
$table->string('nomor')->unique();
|
||||
$table->date('sp_date');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('spatial_plannings');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
<?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('spatial_planning', 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->string('name')->nullable();
|
||||
$table->string('kbli')->nullable();
|
||||
$table->string('activities')->nullable();
|
||||
$table->string('area')->nullable();
|
||||
$table->string('location')->nullable();
|
||||
$table->string('number')->nullable();
|
||||
$table->dateTime('date')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('spatial_planning');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
<?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::rename('spatial_planning', 'spatial_plannings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::rename('spatial_plannings', 'spatial_planning');
|
||||
}
|
||||
};
|
||||
@@ -116,6 +116,13 @@ class UsersRoleMenuSeeder extends Seeder
|
||||
"parent_id" => $dashboard->id,
|
||||
"sort_order" => 3,
|
||||
],
|
||||
[
|
||||
"name" => "PETA",
|
||||
"url" => "dashboard.maps",
|
||||
"icon" => null,
|
||||
"parent_id" => $dashboard->id,
|
||||
"sort_order" => 4,
|
||||
],
|
||||
[
|
||||
"name" => "Users",
|
||||
"url" => "users.index",
|
||||
@@ -188,7 +195,7 @@ class UsersRoleMenuSeeder extends Seeder
|
||||
],
|
||||
[
|
||||
"name" => "Tata Ruang",
|
||||
"url" => "spatial-plannings",
|
||||
"url" => "spatial-plannings.index",
|
||||
"icon" => null,
|
||||
"parent_id" => $data->id,
|
||||
"sort_order" => 6,
|
||||
@@ -229,6 +236,7 @@ class UsersRoleMenuSeeder extends Seeder
|
||||
$lack_of_potentials = Menu::where('name', 'Dashboard Potensi')->first();
|
||||
$spatial_plannings = Menu::where('name', 'Tata Ruang')->first();
|
||||
$pdam = Menu::where('name', 'PDAM')->first();
|
||||
$peta = Menu::where('name', 'PETA')->first();
|
||||
|
||||
// Superadmin gets all menus
|
||||
$superadmin->menus()->sync([
|
||||
@@ -256,6 +264,7 @@ class UsersRoleMenuSeeder extends Seeder
|
||||
$lack_of_potentials->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||
$spatial_plannings->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||
$pdam->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||
$peta->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||
]);
|
||||
|
||||
// Admin gets limited menus
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "sibedas-pbg",
|
||||
"name": "sibedas-pbg-web",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
BIN
public/templates/template_pariwisata.xlsx
Normal file
BIN
public/templates/template_pariwisata.xlsx
Normal file
Binary file not shown.
BIN
public/templates/template_spatial_planning.xlsx
Normal file
BIN
public/templates/template_spatial_planning.xlsx
Normal file
Binary file not shown.
@@ -2,6 +2,30 @@ import bootstrap from "bootstrap/dist/js/bootstrap";
|
||||
window.bootstrap = bootstrap;
|
||||
import "iconify-icon";
|
||||
import "simplebar/dist/simplebar";
|
||||
// import flatpickr from "flatpickr";
|
||||
// import "flatpickr/dist/flatpickr.min.css";
|
||||
|
||||
// class InitDatePicker {
|
||||
// constructor(selector = ".datepicker") {
|
||||
// this.selector = selector;
|
||||
// }
|
||||
// init() {
|
||||
// const elements = document.querySelectorAll(this.selector);
|
||||
// if (elements.length === 0) return; // Skip if no elements found
|
||||
|
||||
// const today = new Date();
|
||||
// const minYear = today.getFullYear() - 5;
|
||||
|
||||
// elements.forEach((element) => {
|
||||
// flatpickr(element, {
|
||||
// enableTime: false,
|
||||
// dateFormat: "Y-m-d",
|
||||
// minDate: `${minYear}-01-01`,
|
||||
// maxDate: today,
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
class Components {
|
||||
initBootstrapComponents() {
|
||||
@@ -107,6 +131,7 @@ class FormValidation {
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", function (e) {
|
||||
new Components().init(), new FormValidation().init();
|
||||
// new InitDatePicker().init();
|
||||
});
|
||||
class ThemeLayout {
|
||||
constructor() {
|
||||
|
||||
@@ -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(`
|
||||
<div class="d-flex justify-content-center gap-2">
|
||||
<a href="/data/business-industries/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
|
||||
<i class='bx bx-edit'></i>
|
||||
</a>
|
||||
<button class="btn btn-sm btn-red d-inline-flex align-items-center justify-content-center btn-delete-business-industries" data-id="${cell}">
|
||||
<i class='bx bxs-trash'></i>
|
||||
</button>
|
||||
</div>
|
||||
`);
|
||||
},
|
||||
name: "Action",
|
||||
formatter: (cell) =>
|
||||
gridjs.html(`
|
||||
<div class="d-flex justify-content-center gap-2">
|
||||
<a href="/data/business-industries/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
|
||||
<i class='bx bx-edit'></i>
|
||||
</a>
|
||||
<button data-id="${cell}" class="btn btn-sm btn-red btn-delete-business-industry d-inline-flex align-items-center justify-content-center">
|
||||
<i class='bx bxs-trash' ></i>
|
||||
</button>
|
||||
</div>
|
||||
`),
|
||||
},
|
||||
],
|
||||
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();
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,7 +12,7 @@ class Customers {
|
||||
this.table = null;
|
||||
|
||||
// Initialize functions
|
||||
this.initTableSpatialPlannings();
|
||||
this.initTableCustomers();
|
||||
this.initEvents();
|
||||
}
|
||||
initEvents() {
|
||||
@@ -25,7 +25,7 @@ class Customers {
|
||||
});
|
||||
}
|
||||
|
||||
initTableSpatialPlannings() {
|
||||
initTableCustomers() {
|
||||
let tableContainer = document.getElementById("table-customers");
|
||||
// Create a new Grid.js instance only if it doesn't exist
|
||||
this.table = new Grid({
|
||||
|
||||
@@ -1,165 +1,141 @@
|
||||
import Big from "big.js";
|
||||
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
|
||||
import flatpickr from "flatpickr";
|
||||
import "flatpickr/dist/flatpickr.min.css";
|
||||
import InitDatePicker from "../utils/InitDatePicker.js";
|
||||
|
||||
class BigData {
|
||||
async init() {
|
||||
try {
|
||||
this.filterYear = new Date().getFullYear(); // Set initial year
|
||||
|
||||
let yearSelect = document.querySelector("#yearPicker");
|
||||
let filterButton = document.querySelector("#btnFilterYear");
|
||||
|
||||
if (!yearSelect || !filterButton) {
|
||||
console.error(
|
||||
"Element #yearPicker or #btnFilterYear not found."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set default value for input
|
||||
yearSelect.value = this.filterYear;
|
||||
|
||||
yearSelect.addEventListener("change", () => {
|
||||
this.updateYear(yearSelect.value);
|
||||
});
|
||||
|
||||
// Handle button click
|
||||
filterButton.addEventListener("click", () => {
|
||||
this.updateYear(yearSelect.value);
|
||||
});
|
||||
|
||||
console.log("init filter this year", this.filterYear);
|
||||
new InitDatePicker(
|
||||
"#datepicker-dashboard-bigdata",
|
||||
this.handleChangeDate.bind(this)
|
||||
).init();
|
||||
|
||||
// Load initial data
|
||||
await this.updateData(this.filterYear);
|
||||
this.updateData("latest");
|
||||
} catch (error) {
|
||||
console.error("Error initializing data:", error);
|
||||
}
|
||||
}
|
||||
updateYear(value) {
|
||||
let inputYear = parseInt(value, 10);
|
||||
if (!isNaN(inputYear)) {
|
||||
this.filterYear = inputYear;
|
||||
this.updateData(this.filterYear);
|
||||
} else {
|
||||
console.error("Invalid year input");
|
||||
}
|
||||
|
||||
handleChangeDate(filterDate) {
|
||||
if (!filterDate) return;
|
||||
this.updateData(filterDate);
|
||||
}
|
||||
async updateData(year) {
|
||||
async updateData(filterDate) {
|
||||
try {
|
||||
this.totalTargetPAD = await this.getDataSettings("TARGET_PAD");
|
||||
this.resultDataTotal = await this.getDataTotalPotensi(year);
|
||||
this.dataVerification = await this.getDataVerfication(year);
|
||||
this.dataNonVerification = await this.getDataNonVerfication(year);
|
||||
this.dataBusiness = await this.getDataBusiness(year);
|
||||
this.dataNonBusiness = await this.getDataNonBusiness(year);
|
||||
this.dataTataRuang = await this.getDataSettings("TATA_RUANG");
|
||||
this.dataSumRealisasiTerbit = await this.getDataSettings(
|
||||
"REALISASI_TERBIT_PBG_SUM"
|
||||
);
|
||||
this.dataCountRealisasiTerbit = await this.getDataSettings(
|
||||
"REALISASI_TERBIT_PBG_COUNT"
|
||||
);
|
||||
this.dataSumMenungguKlikDPMPTSP = await this.getDataSettings(
|
||||
"MENUNGGU_KLIK_DPMPTSP_SUM"
|
||||
);
|
||||
this.dataCountMenungguKlikDPMPTSP = await this.getDataSettings(
|
||||
"MENUNGGU_KLIK_DPMPTSP_COUNT"
|
||||
);
|
||||
this.dataSumProsesDinasTeknis = await this.getDataSettings(
|
||||
"PROSES_DINAS_TEKNIS_SUM"
|
||||
);
|
||||
this.dataCountProsesDinasTeknis = await this.getDataSettings(
|
||||
"PROSES_DINAS_TEKNIS_COUNT"
|
||||
);
|
||||
console.log("Filtering data for date:", filterDate);
|
||||
this.resumeBigData = await this.getBigDataResume(filterDate);
|
||||
// this.totalTargetPAD = await this.getDataSettings("TARGET_PAD");
|
||||
// this.resultDataTotal = await this.getDataTotalPotensi(year);
|
||||
// this.dataVerification = await this.getDataVerfication(year);
|
||||
// this.dataNonVerification = await this.getDataNonVerfication(year);
|
||||
// this.dataBusiness = await this.getDataBusiness(year);
|
||||
// this.dataNonBusiness = await this.getDataNonBusiness(year);
|
||||
// this.dataTataRuang = await this.getDataSettings("TATA_RUANG");
|
||||
// this.dataSumRealisasiTerbit = await this.getDataSettings(
|
||||
// "REALISASI_TERBIT_PBG_SUM"
|
||||
// );
|
||||
// this.dataCountRealisasiTerbit = await this.getDataSettings(
|
||||
// "REALISASI_TERBIT_PBG_COUNT"
|
||||
// );
|
||||
// this.dataSumMenungguKlikDPMPTSP = await this.getDataSettings(
|
||||
// "MENUNGGU_KLIK_DPMPTSP_SUM"
|
||||
// );
|
||||
// this.dataCountMenungguKlikDPMPTSP = await this.getDataSettings(
|
||||
// "MENUNGGU_KLIK_DPMPTSP_COUNT"
|
||||
// );
|
||||
// this.dataSumProsesDinasTeknis = await this.getDataSettings(
|
||||
// "PROSES_DINAS_TEKNIS_SUM"
|
||||
// );
|
||||
// this.dataCountProsesDinasTeknis = await this.getDataSettings(
|
||||
// "PROSES_DINAS_TEKNIS_COUNT"
|
||||
// );
|
||||
|
||||
// total potensi
|
||||
this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0);
|
||||
this.bigTotalPotensi = new Big(this.resultDataTotal.totalData ?? 0);
|
||||
// // total potensi
|
||||
// this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0);
|
||||
// this.bigTotalPotensi = new Big(this.resultDataTotal.totalData ?? 0);
|
||||
|
||||
this.resultPercentage = 0;
|
||||
if (this.bigTotalPotensi > 0 && this.bigTargetPAD > 0) {
|
||||
this.resultPercentage = this.bigTotalPotensi
|
||||
.div(this.bigTargetPAD)
|
||||
.times(100)
|
||||
.toFixed(2);
|
||||
if (this.resultPercentage > 100) {
|
||||
this.resultPercentage = 100;
|
||||
}
|
||||
}
|
||||
// this.resultPercentage = 0;
|
||||
// if (this.bigTotalPotensi > 0 && this.bigTargetPAD > 0) {
|
||||
// this.resultPercentage = this.bigTotalPotensi
|
||||
// .div(this.bigTargetPAD)
|
||||
// .times(100)
|
||||
// .toFixed(2);
|
||||
// if (this.resultPercentage > 100) {
|
||||
// this.resultPercentage = 100;
|
||||
// }
|
||||
// }
|
||||
|
||||
// tata ruang
|
||||
this.bigTotalTataRuang = new Big(this.dataTataRuang);
|
||||
this.percentageResultTataRuang =
|
||||
this.bigTotalTataRuang <= 0 || this.bigTotalPotensi <= 0
|
||||
? 0
|
||||
: this.bigTotalTataRuang
|
||||
.div(this.bigTotalPotensi)
|
||||
.times(100)
|
||||
.toFixed(2);
|
||||
// // tata ruang
|
||||
// this.bigTotalTataRuang = new Big(this.dataTataRuang);
|
||||
// this.percentageResultTataRuang =
|
||||
// this.bigTotalTataRuang <= 0 || this.bigTotalPotensi <= 0
|
||||
// ? 0
|
||||
// : this.bigTotalTataRuang
|
||||
// .div(this.bigTotalPotensi)
|
||||
// .times(100)
|
||||
// .toFixed(2);
|
||||
|
||||
// kekurangan potensi
|
||||
this.totalKekuranganPotensi = new Big(
|
||||
this.bigTargetPAD - this.bigTotalPotensi
|
||||
);
|
||||
// // kekurangan potensi
|
||||
// this.totalKekuranganPotensi = new Big(
|
||||
// this.bigTargetPAD - this.bigTotalPotensi
|
||||
// );
|
||||
|
||||
this.percentageKekuranganPotensi =
|
||||
this.totalKekuranganPotensi <= 0 || this.bigTargetPAD <= 0
|
||||
? 0
|
||||
: this.totalKekuranganPotensi
|
||||
.div(this.bigTargetPAD)
|
||||
.times(100)
|
||||
.toFixed(2);
|
||||
// this.percentageKekuranganPotensi =
|
||||
// this.totalKekuranganPotensi <= 0 || this.bigTargetPAD <= 0
|
||||
// ? 0
|
||||
// : this.totalKekuranganPotensi
|
||||
// .div(this.bigTargetPAD)
|
||||
// .times(100)
|
||||
// .toFixed(2);
|
||||
|
||||
// non-verification documents
|
||||
this.bigTotalNonVerification = new Big(
|
||||
this.dataNonVerification.total
|
||||
);
|
||||
this.percentageResultNonVerification =
|
||||
this.bigTotalNonVerification <= 0 || this.bigTotalPotensi <= 0
|
||||
? 0
|
||||
: this.bigTotalNonVerification
|
||||
.div(this.bigTotalPotensi)
|
||||
.times(100)
|
||||
.toFixed(2);
|
||||
// // non-verification documents
|
||||
// this.bigTotalNonVerification = new Big(
|
||||
// this.dataNonVerification.total
|
||||
// );
|
||||
// this.percentageResultNonVerification =
|
||||
// this.bigTotalNonVerification <= 0 || this.bigTotalPotensi <= 0
|
||||
// ? 0
|
||||
// : this.bigTotalNonVerification
|
||||
// .div(this.bigTotalPotensi)
|
||||
// .times(100)
|
||||
// .toFixed(2);
|
||||
|
||||
// verification documents
|
||||
this.bigTotalVerification = new Big(this.dataVerification.total);
|
||||
this.percetageResultVerification =
|
||||
this.bigTotalVerification <= 0 || this.bigTotalPotensi <= 0
|
||||
? 0
|
||||
: this.bigTotalVerification
|
||||
.div(this.bigTargetPAD)
|
||||
.times(100)
|
||||
.toFixed(2);
|
||||
// // verification documents
|
||||
// this.bigTotalVerification = new Big(this.dataVerification.total);
|
||||
// this.percetageResultVerification =
|
||||
// this.bigTotalVerification <= 0 || this.bigTotalPotensi <= 0
|
||||
// ? 0
|
||||
// : this.bigTotalVerification
|
||||
// .div(this.bigTargetPAD)
|
||||
// .times(100)
|
||||
// .toFixed(2);
|
||||
|
||||
// business documents
|
||||
this.bigTotalBusiness = new Big(this.dataBusiness.total);
|
||||
this.percentageResultBusiness =
|
||||
this.bigTotalNonVerification <= 0 || this.bigTotalBusiness <= 0
|
||||
? 0
|
||||
: this.bigTotalBusiness
|
||||
.div(this.bigTotalNonVerification)
|
||||
.times(100)
|
||||
.toFixed(2);
|
||||
// // business documents
|
||||
// this.bigTotalBusiness = new Big(this.dataBusiness.total);
|
||||
// this.percentageResultBusiness =
|
||||
// this.bigTotalNonVerification <= 0 || this.bigTotalBusiness <= 0
|
||||
// ? 0
|
||||
// : this.bigTotalBusiness
|
||||
// .div(this.bigTotalNonVerification)
|
||||
// .times(100)
|
||||
// .toFixed(2);
|
||||
|
||||
// non-business documents
|
||||
this.bigTotalNonBusiness = new Big(this.dataNonBusiness.total);
|
||||
this.percentageResultNonBusiness =
|
||||
this.bigTotalNonBusiness <= 0 ||
|
||||
this.bigTotalNonVerification <= 0
|
||||
? 0
|
||||
: this.bigTotalNonBusiness
|
||||
.div(this.bigTotalNonVerification)
|
||||
.times(100)
|
||||
.toFixed(2);
|
||||
// // non-business documents
|
||||
// this.bigTotalNonBusiness = new Big(this.dataNonBusiness.total);
|
||||
// this.percentageResultNonBusiness =
|
||||
// this.bigTotalNonBusiness <= 0 ||
|
||||
// this.bigTotalNonVerification <= 0
|
||||
// ? 0
|
||||
// : this.bigTotalNonBusiness
|
||||
// .div(this.bigTotalNonVerification)
|
||||
// .times(100)
|
||||
// .toFixed(2);
|
||||
|
||||
if (!this.bigTargetPAD) {
|
||||
console.error("Failed to load chart data");
|
||||
return;
|
||||
}
|
||||
// if (!this.bigTargetPAD) {
|
||||
// console.error("Failed to load chart data");
|
||||
// return;
|
||||
// }
|
||||
|
||||
this.initChartTargetPAD();
|
||||
this.initChartUsaha();
|
||||
@@ -177,6 +153,33 @@ class BigData {
|
||||
}
|
||||
}
|
||||
|
||||
async getBigDataResume(filterByDate) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/bigdata-resume?filterByDate=${filterByDate}`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${
|
||||
document.querySelector("meta[name='api-token']")
|
||||
.content
|
||||
}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error("Network response was not ok", response);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error fetching chart data:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
async getDataTotalPotensi(year) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
@@ -370,53 +373,60 @@ class BigData {
|
||||
.querySelectorAll(".document-total.chart-target-pad")
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.bigTargetPAD.toString()
|
||||
// this.bigTargetPAD.toString()
|
||||
this.resumeBigData.target_pad.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".small-percentage.chart-target-pad")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${100}%`;
|
||||
element.innerText = `${this.resumeBigData.target_pad.percentage}%`;
|
||||
});
|
||||
}
|
||||
initChartTotalPotensi() {
|
||||
const countAll = this.resultDataTotal.countData ?? 0;
|
||||
// const countAll = this.resultDataTotal.countData ?? 0;
|
||||
|
||||
document
|
||||
.querySelectorAll(".document-count.chart-total-potensi")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${countAll}`;
|
||||
// element.innerText = `${countAll}`;
|
||||
element.innerText = `${this.resumeBigData.total_potensi.count}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".document-total.chart-total-potensi")
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.bigTotalPotensi.toString()
|
||||
// this.bigTotalPotensi.toString()
|
||||
this.resumeBigData.total_potensi.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".small-percentage.chart-total-potensi")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.resultPercentage}%`;
|
||||
// element.innerText = `${this.resultPercentage}%`;
|
||||
element.innerText = `${this.resumeBigData.total_potensi.percentage}%`;
|
||||
});
|
||||
}
|
||||
initChartVerificationDocuments() {
|
||||
document
|
||||
.querySelectorAll(".document-count.chart-berkas-terverifikasi")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.dataVerification.count}`;
|
||||
// element.innerText = `${this.dataVerification.count}`;
|
||||
element.innerText = `${this.resumeBigData.verified_document.count}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".document-total.chart-berkas-terverifikasi")
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.bigTotalVerification.toString()
|
||||
// this.bigTotalVerification.toString()
|
||||
this.resumeBigData.verified_document.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".small-percentage.chart-berkas-terverifikasi")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.percetageResultVerification}%`;
|
||||
// element.innerText = `${this.percetageResultVerification}%`;
|
||||
element.innerText = `${this.resumeBigData.verified_document.percentage}%`;
|
||||
});
|
||||
}
|
||||
initChartNonVerificationDocuments() {
|
||||
@@ -425,7 +435,8 @@ class BigData {
|
||||
".document-count.chart-berkas-belum-terverifikasi"
|
||||
)
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.dataNonVerification.count}`;
|
||||
// element.innerText = `${this.dataNonVerification.count}`;
|
||||
element.innerText = `${this.resumeBigData.non_verified_document.count}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(
|
||||
@@ -433,7 +444,8 @@ class BigData {
|
||||
)
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.bigTotalNonVerification.toString()
|
||||
// this.bigTotalNonVerification.toString()
|
||||
this.resumeBigData.non_verified_document.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
@@ -441,45 +453,52 @@ class BigData {
|
||||
".small-percentage.chart-berkas-belum-terverifikasi"
|
||||
)
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.percentageResultNonVerification}%`;
|
||||
// element.innerText = `${this.percentageResultNonVerification}%`;
|
||||
element.innerText = `${this.resumeBigData.non_verified_document.percentage}%`;
|
||||
});
|
||||
}
|
||||
initChartUsaha() {
|
||||
document
|
||||
.querySelectorAll(".document-count.chart-business")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.dataBusiness.count}`;
|
||||
// element.innerText = `${this.dataBusiness.count}`;
|
||||
element.innerText = `${this.resumeBigData.business_document.count}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".document-total.chart-business")
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.bigTotalBusiness.toString()
|
||||
// this.bigTotalBusiness.toString()
|
||||
this.resumeBigData.business_document.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".small-percentage.chart-business")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.percentageResultBusiness}%`;
|
||||
// element.innerText = `${this.percentageResultBusiness}%`;
|
||||
element.innerText = `${this.resumeBigData.business_document.percentage}%`;
|
||||
});
|
||||
}
|
||||
initChartNonUsaha() {
|
||||
document
|
||||
.querySelectorAll(".document-count.chart-non-business")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.dataNonBusiness.count}`;
|
||||
// element.innerText = `${this.dataNonBusiness.count}`;
|
||||
element.innerText = `${this.resumeBigData.non_business_document.count}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".document-total.chart-non-business")
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.bigTotalNonBusiness.toString()
|
||||
// this.bigTotalNonBusiness.toString()
|
||||
this.resumeBigData.non_business_document.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".small-percentage.chart-non-business")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.percentageResultNonBusiness}%`;
|
||||
// element.innerText = `${this.percentageResultNonBusiness}%`;
|
||||
element.innerText = `${this.resumeBigData.non_business_document.percentage}%`;
|
||||
});
|
||||
}
|
||||
initChartKekuranganPotensi() {
|
||||
@@ -492,70 +511,78 @@ class BigData {
|
||||
.querySelectorAll(".document-total.chart-kekurangan-potensi")
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.totalKekuranganPotensi.toString()
|
||||
// this.totalKekuranganPotensi.toString()
|
||||
this.resumeBigData.kekurangan_potensi.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".small-percentage.chart-kekurangan-potensi")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.percentageKekuranganPotensi}%`;
|
||||
// element.innerText = `${this.percentageKekuranganPotensi}%`;
|
||||
element.innerText = `${this.resumeBigData.kekurangan_potensi.percentage}%`;
|
||||
});
|
||||
}
|
||||
initChartRealisasiTerbitPBG() {
|
||||
document
|
||||
.querySelectorAll(".document-count.chart-realisasi-tebit-pbg")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.dataCountRealisasiTerbit}`;
|
||||
// element.innerText = `${this.dataCountRealisasiTerbit}`;
|
||||
element.innerText = `${this.resumeBigData.realisasi_terbit.count}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".document-total.chart-realisasi-tebit-pbg")
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.dataSumRealisasiTerbit
|
||||
// this.dataSumRealisasiTerbit
|
||||
this.resumeBigData.realisasi_terbit.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".small-percentage.chart-realisasi-tebit-pbg")
|
||||
.forEach((element) => {
|
||||
element.innerText = `0.00%`;
|
||||
element.innerText = `${this.resumeBigData.realisasi_terbit.percentage}%`;
|
||||
});
|
||||
}
|
||||
initChartMenungguKlikDPMPTSP() {
|
||||
document
|
||||
.querySelectorAll(".document-count.chart-menunggu-klik-dpmptsp")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.dataCountMenungguKlikDPMPTSP}`;
|
||||
// element.innerText = `${this.dataCountMenungguKlikDPMPTSP}`;
|
||||
element.innerText = `${this.resumeBigData.menunggu_klik_dpmptsp.count}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".document-total.chart-menunggu-klik-dpmptsp")
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.dataSumMenungguKlikDPMPTSP
|
||||
// this.dataSumMenungguKlikDPMPTSP
|
||||
this.resumeBigData.menunggu_klik_dpmptsp.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".small-percentage.chart-menunggu-klik-dpmptsp")
|
||||
.forEach((element) => {
|
||||
element.innerText = `0.00%`;
|
||||
element.innerText = `${this.resumeBigData.menunggu_klik_dpmptsp.percentage}%`;
|
||||
});
|
||||
}
|
||||
initChartProsesDinasTeknis() {
|
||||
document
|
||||
.querySelectorAll(".document-count.chart-proses-dinas-teknis")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.dataCountProsesDinasTeknis}`;
|
||||
// element.innerText = `${this.dataCountProsesDinasTeknis}`;
|
||||
element.innerText = `${this.resumeBigData.proses_dinas_teknis.count}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".document-total.chart-proses-dinas-teknis")
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.dataSumProsesDinasTeknis
|
||||
// this.dataSumProsesDinasTeknis
|
||||
this.resumeBigData.proses_dinas_teknis.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".small-percentage.chart-proses-dinas-teknis")
|
||||
.forEach((element) => {
|
||||
element.innerText = `0.00%`;
|
||||
element.innerText = `${this.resumeBigData.proses_dinas_teknis.percentage}%`;
|
||||
});
|
||||
}
|
||||
initChartPotensiTataRuang() {
|
||||
@@ -568,13 +595,15 @@ class BigData {
|
||||
.querySelectorAll(".document-total.chart-potensi-tata-ruang")
|
||||
.forEach((element) => {
|
||||
element.innerText = `Rp.${addThousandSeparators(
|
||||
this.bigTotalTataRuang.toString()
|
||||
// this.bigTotalTataRuang.toString()
|
||||
this.resumeBigData.tata_ruang.sum.toString()
|
||||
)}`;
|
||||
});
|
||||
document
|
||||
.querySelectorAll(".small-percentage.chart-potensi-tata-ruang")
|
||||
.forEach((element) => {
|
||||
element.innerText = `${this.percentageResultTataRuang}%`;
|
||||
// element.innerText = `${this.percentageResultTataRuang}%`;
|
||||
element.innerText = `${this.resumeBigData.tata_ruang.percentage}%`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,42 @@
|
||||
import Big from "big.js";
|
||||
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
|
||||
import InitDatePicker from "../utils/InitDatePicker.js";
|
||||
|
||||
class LackOfPotential {
|
||||
async init() {
|
||||
new InitDatePicker(
|
||||
"#datepicker-lack-of-potential",
|
||||
this.handleChangedDate.bind(this)
|
||||
).init();
|
||||
this.bigTotalLackPotential = 0;
|
||||
this.totalPotensi = await this.getDataTotalPotensi(2025);
|
||||
this.totalPotensi = await this.getDataTotalPotensi("latest");
|
||||
this.totalTargetPAD = await this.getDataSettings("TARGET_PAD");
|
||||
this.allCountData = await this.getValueDashboard();
|
||||
this.reklameCount = this.allCountData.total_reklame ?? 0;
|
||||
this.pdamCount = this.allCountData.total_pdam ?? 0;
|
||||
this.tataRuangCount = this.allCountData.total_tata_ruang ?? 0;
|
||||
|
||||
this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0);
|
||||
this.bigTotalPotensi = new Big(this.totalPotensi.totalData ?? 0);
|
||||
this.bigTotalLackPotential = this.bigTargetPAD - this.bigTotalPotensi;
|
||||
this.bigTotalPotensi = new Big(this.totalPotensi.total ?? 0);
|
||||
this.bigTotalLackPotential = this.bigTargetPAD.minus(
|
||||
this.bigTotalPotensi
|
||||
);
|
||||
this.initChartKekuranganPotensi();
|
||||
this.initDataValueDashboard();
|
||||
}
|
||||
async handleChangedDate(filterDate) {
|
||||
const totalPotensi = await this.getDataTotalPotensi(filterDate);
|
||||
this.bigTotalPotensi = new Big(totalPotensi.total ?? 0);
|
||||
this.bigTotalLackPotential = this.bigTargetPAD.minus(
|
||||
this.bigTotalPotensi
|
||||
);
|
||||
|
||||
this.initChartKekuranganPotensi();
|
||||
}
|
||||
async getDataTotalPotensi(year) {
|
||||
async getDataTotalPotensi(filterDate) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/all-task-documents?year=${year}`,
|
||||
`${GlobalConfig.apiHost}/api/bigdata-resume?filterByDate=${filterDate}`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
@@ -34,8 +55,7 @@ class LackOfPotential {
|
||||
|
||||
const data = await response.json();
|
||||
return {
|
||||
countData: data.data.count,
|
||||
totalData: data.data.total,
|
||||
total: data.total_potensi.sum,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching chart data:", error);
|
||||
@@ -45,7 +65,7 @@ class LackOfPotential {
|
||||
async getDataSettings(string_key) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/api-data-settings?search=${string_key}`,
|
||||
`${GlobalConfig.apiHost}/api/data-settings?search=${string_key}`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
@@ -69,6 +89,33 @@ class LackOfPotential {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
async getValueDashboard() {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/dashboard-potential-count`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${
|
||||
document.querySelector("meta[name='api-token']")
|
||||
.content
|
||||
}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error("Network response was not ok", response);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error fetching chart data:", error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
initChartKekuranganPotensi() {
|
||||
document
|
||||
.querySelectorAll(".document-count.chart-lack-of-potential")
|
||||
@@ -88,6 +135,12 @@ class LackOfPotential {
|
||||
element.innerText = ``;
|
||||
});
|
||||
}
|
||||
initDataValueDashboard() {
|
||||
document.getElementById("reklame-count").innerText = this.reklameCount;
|
||||
document.getElementById("pdam-count").innerText = this.pdamCount;
|
||||
document.getElementById("pbb-bangunan-count").innerText =
|
||||
this.tataRuangCount;
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", async function (e) {
|
||||
await new LackOfPotential().init();
|
||||
|
||||
470
resources/js/dashboards/pbg.js
Normal file
470
resources/js/dashboards/pbg.js
Normal file
@@ -0,0 +1,470 @@
|
||||
import Big from "big.js";
|
||||
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
|
||||
import ApexCharts from "apexcharts";
|
||||
import "gridjs/dist/gridjs.umd.js";
|
||||
import GeneralTable from "../table-generator.js";
|
||||
|
||||
var chart;
|
||||
document.addEventListener("DOMContentLoaded", async function () {
|
||||
await initChart();
|
||||
const yearPicker = document.getElementById("yearPicker");
|
||||
|
||||
async function updateDataByYear(selectedYear) {
|
||||
// Target PAD Element
|
||||
const targetPadElement = document.getElementById("target-pad");
|
||||
if (!targetPadElement) return;
|
||||
const targetPadValue = await getDataSettings("TARGET_PAD");
|
||||
targetPadElement.textContent = formatCurrency(targetPadValue);
|
||||
|
||||
// Total Potensi Berkas
|
||||
const totalPotensiBerkas = document.getElementById("total-potensi-berkas");
|
||||
if (!totalPotensiBerkas) return;
|
||||
const totalPotensiBerkasValue = await getDataTotalPotensi(selectedYear);
|
||||
totalPotensiBerkas.textContent = formatCurrency(totalPotensiBerkasValue.totalData);
|
||||
|
||||
// Total Berkas Terverifikasi
|
||||
const totalBerkasTerverifikasi = document.getElementById("total-berkas-terverifikasi");
|
||||
if (!totalBerkasTerverifikasi) return;
|
||||
const totalBerkasTerverifikasiValue = await getDataVerification(selectedYear);
|
||||
totalBerkasTerverifikasi.textContent = formatCurrency(totalBerkasTerverifikasiValue.totalData);
|
||||
|
||||
// Total Kekurangan potensi
|
||||
const totalKekuranganPotensi = document.getElementById("total-kekurangan-potensi");
|
||||
if (!totalKekuranganPotensi) return;
|
||||
const totalKekuranganPotensiValue = new Big(targetPadValue) - new Big(totalPotensiBerkasValue.totalData);
|
||||
totalKekuranganPotensi.textContent = formatCurrency(totalKekuranganPotensiValue)
|
||||
|
||||
// Total Potensi PBG dari tata ruang
|
||||
const totalPotensiPBGTataRuang = document.getElementById("total-potensi-pbd-tata-ruang");
|
||||
if (!totalPotensiPBGTataRuang) return;
|
||||
const totalPotensiPBGTataRuangValue = await getDataSettings("TATA_RUANG");
|
||||
totalPotensiPBGTataRuang.textContent = formatCurrency(totalPotensiPBGTataRuangValue);
|
||||
|
||||
// Total Berkas Belum terverifikasi
|
||||
const totalBerkasBelumTerverifikasi = document.getElementById("total-berkas-belum-terverifikasi");
|
||||
if (!totalBerkasBelumTerverifikasi) return;
|
||||
const totalBerkasBelumTerverifikasiValue = await getDataNonVerification(selectedYear);
|
||||
const totalBerkasBelumTerverifikasiCount = totalBerkasBelumTerverifikasiValue.countData;
|
||||
totalBerkasBelumTerverifikasi.textContent = formatCurrency(totalBerkasBelumTerverifikasiValue.totalData);
|
||||
|
||||
// Total Berkas Usaha
|
||||
const totalBerkasUsahaValue = await getDataBusiness(selectedYear);
|
||||
const totalBerkasUsahaCount = totalBerkasUsahaValue.countData;
|
||||
const totalBerkasUsahaTotalData = totalBerkasUsahaValue.totalData;
|
||||
|
||||
// Total Berkas Non Usaha
|
||||
const totalBerkasNonUsahaValue = await getDataNonBusiness(selectedYear);
|
||||
const totalBerkasNonUsahaCount = totalBerkasNonUsahaValue.countData;
|
||||
const totalBerkasNonUsahaTotalData = totalBerkasNonUsahaValue.totalData;
|
||||
|
||||
// Pie Chart Section
|
||||
let persenUsaha = totalBerkasBelumTerverifikasiCount > 0
|
||||
? ((totalBerkasUsahaCount / totalBerkasBelumTerverifikasiCount) * 100).toFixed(2)
|
||||
: "0";
|
||||
|
||||
let persenNonUsaha = totalBerkasBelumTerverifikasiCount > 0
|
||||
? ((totalBerkasNonUsahaCount / totalBerkasBelumTerverifikasiCount) * 100).toFixed(2)
|
||||
: "0";
|
||||
|
||||
const dataSeriesPieChart = [Number(persenUsaha), Number(persenNonUsaha)]
|
||||
const labelsPieChart = ["Berkas Usaha", "Berkas Non Usaha"];
|
||||
document.querySelector("td[data-category='non-usaha']").textContent = formatCurrency(totalBerkasNonUsahaTotalData).toLocaleString();
|
||||
document.querySelector("td[data-category='non-usaha-percentage']").textContent = persenNonUsaha + "%";
|
||||
|
||||
document.querySelector("td[data-category='usaha']").textContent = formatCurrency(totalBerkasUsahaTotalData).toLocaleString();
|
||||
document.querySelector("td[data-category='usaha-percentage']").textContent = persenUsaha + "%";
|
||||
|
||||
updatePieChart(dataSeriesPieChart, labelsPieChart);
|
||||
|
||||
// Load all Tourism location
|
||||
const allLocation = await getAllLocation();
|
||||
console.log(allLocation);
|
||||
|
||||
// Filter hanya data yang memiliki angka valid
|
||||
let validLocations = allLocation.dataLocation.filter(loc => {
|
||||
return !isNaN(parseFloat(loc.longitude)) && !isNaN(parseFloat(loc.latitude));
|
||||
});
|
||||
|
||||
// Ubah string ke float
|
||||
validLocations = validLocations.map(loc => ({
|
||||
name: loc.project_name,
|
||||
longitude: parseFloat(loc.longitude),
|
||||
latitude: parseFloat(loc.latitude)
|
||||
}));
|
||||
|
||||
console.log(validLocations.name)
|
||||
|
||||
// Inisialisasi peta
|
||||
var map = L.map('map').setView([-7.0230, 107.5275], 10);
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© OpenStreetMap contributors'
|
||||
}).addTo(map);
|
||||
|
||||
// Tambahkan marker ke peta
|
||||
validLocations.forEach(function(loc) {
|
||||
L.marker([loc.latitude, loc.longitude])
|
||||
.addTo(map)
|
||||
.bindPopup(`<b>${loc.name}</b>`) // Popup saat diklik
|
||||
.bindTooltip(loc.name, { permanent: false, direction: "top" }); // Tooltip saat di-hover
|
||||
});
|
||||
|
||||
// Realisasi terbit PBG
|
||||
const totalRealisasiTerbitPBG = document.getElementById("realisasi-terbit-pbg");
|
||||
if (!totalRealisasiTerbitPBG) return;
|
||||
const totalRealisasiTerbitPBGValue = await getDataSettings("REALISASI_TERBIT_PBG_SUM");
|
||||
totalRealisasiTerbitPBG.textContent = formatCurrency(totalRealisasiTerbitPBGValue);
|
||||
|
||||
// Menunggu Klik DPMPTSP
|
||||
const totalMenungguKlikDpmptsp = document.getElementById("waiting-click-dpmptsp");
|
||||
if (!totalMenungguKlikDpmptsp) return;
|
||||
const totalMenungguKlikDpmptspValue = await getDataSettings("MENUNGGU_KLIK_DPMPTSP_SUM");
|
||||
totalMenungguKlikDpmptsp.textContent = formatCurrency(totalMenungguKlikDpmptspValue);
|
||||
|
||||
// Proses Dinas Teknis
|
||||
const totalProsesDinasTeknis = document.getElementById("processing-technical-services");
|
||||
if (!totalProsesDinasTeknis) return;
|
||||
const totalProsesDinasTeknisValue = await getDataSettings("PROSES_DINAS_TEKNIS_SUM");
|
||||
totalProsesDinasTeknis.textContent = formatCurrency(totalProsesDinasTeknisValue);
|
||||
|
||||
// Load Tabel Baru di Update
|
||||
const tableLastUpdated = new GeneralTable(
|
||||
"pbg-filter-by-updated-at",
|
||||
`${GlobalConfig.apiHost}/api/api-pbg-task?isLastUpdated=true`,
|
||||
`${GlobalConfig.apiHost}`,
|
||||
pbgTaskColumns
|
||||
);
|
||||
|
||||
tableLastUpdated.processData = function (data) {
|
||||
console.log("Response Data:", data);
|
||||
return data.data.map((item) => {
|
||||
return [
|
||||
item.no,
|
||||
item.name,
|
||||
item.registration_number,
|
||||
item.document_number,
|
||||
item.address,
|
||||
];
|
||||
});
|
||||
};
|
||||
|
||||
tableLastUpdated.init();
|
||||
|
||||
// Load Tabel Status SK Terbit
|
||||
const tableSKPBGTerbit = new GeneralTable(
|
||||
"pbg-filter-by-status",
|
||||
`${GlobalConfig.apiHost}/api/api-pbg-task?isLastUpdated=false`,
|
||||
`${GlobalConfig.apiHost}`,
|
||||
pbgTaskColumns
|
||||
);
|
||||
|
||||
tableSKPBGTerbit.processData = function (data) {
|
||||
console.log("Response Data:", data);
|
||||
return data.data.map((item) => {
|
||||
return [
|
||||
item.no,
|
||||
item.name,
|
||||
item.registration_number,
|
||||
item.document_number,
|
||||
item.address,
|
||||
];
|
||||
});
|
||||
};
|
||||
|
||||
tableSKPBGTerbit.init();
|
||||
|
||||
document.querySelector("#pbg-filter-by-updated-at .gridjs-search").hidden = true;
|
||||
document.querySelector("#pbg-filter-by-updated-at .gridjs-footer").hidden = true;
|
||||
document.querySelector("#pbg-filter-by-status .gridjs-search").hidden = true;
|
||||
document.querySelector("#pbg-filter-by-status .gridjs-footer").hidden = true;
|
||||
}
|
||||
|
||||
await updateDataByYear(yearPicker.value);
|
||||
|
||||
yearPicker.addEventListener("change", async function () {
|
||||
console.log("event change dropdown")
|
||||
await updateDataByYear(yearPicker.value);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
async function getDataSettings(string_key) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/api-data-settings?search=${string_key}`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${
|
||||
document.querySelector("meta[name='api-token']").content
|
||||
}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error("Network response was not ok", response);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data.data?.[0]?.value ?? 0; // Pastikan tidak error jika data kosong
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async function getDataTotalPotensi(year) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/all-task-documents?year=${year}`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${
|
||||
document.querySelector("meta[name='api-token']").content
|
||||
}`,
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error("Network response was not ok", response);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return {
|
||||
totalData: data.data.total,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching chart data:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getDataVerification(year) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/verification-documents?year=${year}`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${
|
||||
document.querySelector("meta[name='api-token']")
|
||||
.content
|
||||
}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error("Network response was not ok", response);
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return {
|
||||
totalData: data.data.total,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching chart data:", error);
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
async function getDataNonVerification(year) {
|
||||
try {
|
||||
const response = await fetch (
|
||||
`${GlobalConfig.apiHost}/api/non-verification-documents?year=${year}`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${
|
||||
document.querySelector("meta[name='api-token']")
|
||||
.content
|
||||
}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error("Network response was not ok", response);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return {
|
||||
countData: data.data.count,
|
||||
totalData: data.data.total,
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching chart data:", error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async function getDataBusiness(year) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/business-documents?year=${year}`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${
|
||||
document.querySelector("meta[name='api-token']")
|
||||
.content
|
||||
}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error("Network response was not ok", response);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return {
|
||||
countData: data.data.count,
|
||||
totalData: data.data.total,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching chart data:", error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async function getDataNonBusiness(year) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/non-business-documents?year=${year}`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${
|
||||
document.querySelector("meta[name='api-token']")
|
||||
.content
|
||||
}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error("Network response was not ok", response);
|
||||
}
|
||||
const data = await response.json();
|
||||
return {
|
||||
countData: data.data.count,
|
||||
totalData: data.data.total
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching chart data:", error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllLocation() {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/get-all-location`,
|
||||
{
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${
|
||||
document.querySelector("meta[name='api-token']")
|
||||
.content
|
||||
}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
console.error("Network response was not ok", response);
|
||||
}
|
||||
const data = await response.json();
|
||||
return {
|
||||
dataLocation: data.data,
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching chart data:", error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async function initChart() {
|
||||
var options = {
|
||||
chart: {
|
||||
height: 180,
|
||||
type: 'donut',
|
||||
},
|
||||
series: [0, 0], // Inisialisasi dengan nilai awal
|
||||
labels: ["Berkas Usaha", "Berkas Non Usaha"],
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
stroke: {
|
||||
width: 0
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
donut: {
|
||||
size: '60%',
|
||||
}
|
||||
}
|
||||
},
|
||||
colors: ["#7e67fe", "#17c553"],
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
responsive: [{
|
||||
breakpoint: 480,
|
||||
options: {
|
||||
chart: {
|
||||
width: 200
|
||||
}
|
||||
}
|
||||
}],
|
||||
fill: {
|
||||
type: 'gradient'
|
||||
}
|
||||
};
|
||||
|
||||
chart = new ApexCharts(document.querySelector("#conversions"), options);
|
||||
chart.render();
|
||||
}
|
||||
|
||||
async function updatePieChart(dataSeries, labels) {
|
||||
if (!Array.isArray(dataSeries) || dataSeries.length === 0) {
|
||||
console.error("Data series tidak valid:", dataSeries);
|
||||
return;
|
||||
}
|
||||
|
||||
// Perbarui data series chart
|
||||
chart.updateSeries(dataSeries);
|
||||
|
||||
// Perbarui label jika diperlukan
|
||||
if (Array.isArray(labels) && labels.length === dataSeries.length) {
|
||||
chart.updateOptions({
|
||||
labels: labels
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Fungsi untuk format angka ke Rupiah
|
||||
function formatCurrency(number) {
|
||||
return new Intl.NumberFormat("id-ID", {
|
||||
style: "currency",
|
||||
currency: "IDR",
|
||||
minimumFractionDigits: 0
|
||||
}).format(number);
|
||||
}
|
||||
|
||||
const pbgTaskColumns = [
|
||||
"No",
|
||||
"Name",
|
||||
"Nomor Registrasi",
|
||||
"Nomor Dokumen",
|
||||
"Alamat",
|
||||
]
|
||||
@@ -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";
|
||||
@@ -46,6 +45,8 @@ document.addEventListener("DOMContentLoaded", function (e) {
|
||||
error.message;
|
||||
toast.show();
|
||||
console.error("Error:", error);
|
||||
submitButton.disabled = false;
|
||||
spinner.classList.add("d-none");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Request failed:", error);
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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";
|
||||
@@ -43,6 +43,8 @@ document.addEventListener("DOMContentLoaded", function (e) {
|
||||
toastMessage.innerText = error.message;
|
||||
toast.show();
|
||||
console.error("Error:", error);
|
||||
submitButton.disabled = false;
|
||||
spinner.classList.add("d-none");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Request failed:", error);
|
||||
|
||||
@@ -28,12 +28,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
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";
|
||||
|
||||
@@ -49,7 +44,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log("Response data:", data);
|
||||
if (!data.errors) {
|
||||
// Remove existing icon (if any) before adding the new one
|
||||
if (authLogo) {
|
||||
@@ -74,11 +68,11 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
toast.classList.add('show'); // Show the toast
|
||||
setTimeout(() => {
|
||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||
}, 3000);
|
||||
}, 2000);
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '/data/advertisements';
|
||||
}, 3000);
|
||||
}, 1000);
|
||||
} else {
|
||||
if (authLogo) {
|
||||
// Hapus ikon yang sudah ada jika ada
|
||||
@@ -96,21 +90,21 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// Tambahkan ikon ke dalam auth-logo
|
||||
authLogo.appendChild(icon);
|
||||
}
|
||||
// Set error message for the toast
|
||||
toastBody.textContent = "Error: " + (responseData.message || "Something went wrong");
|
||||
toast.classList.add('show'); // Show the toast
|
||||
|
||||
// Enable button and reset its text on error
|
||||
modalButton.disabled = false;
|
||||
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
||||
|
||||
// Set error message for the toast
|
||||
toastBody.textContent = "Failed: " + (data.message || "Something went wrong");
|
||||
toast.classList.add('show'); // Show the toast
|
||||
|
||||
setTimeout(() => {
|
||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||
}, 3000);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error:", error);
|
||||
.catch(errors => {
|
||||
if (authLogo) {
|
||||
// Hapus ikon yang sudah ada jika ada
|
||||
const existingIcon = authLogo.querySelector('.bx');
|
||||
@@ -127,14 +121,14 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// Tambahkan ikon ke dalam auth-logo
|
||||
authLogo.appendChild(icon);
|
||||
}
|
||||
// Enable button and reset its text on error
|
||||
modalButton.disabled = false;
|
||||
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
||||
|
||||
// Set error message for the toast
|
||||
toastBody.textContent = "An error occurred while processing your request.";
|
||||
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);
|
||||
@@ -144,7 +138,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// Fungsi fetchOptions untuk autocomplete server-side
|
||||
window.fetchOptions = function (field) {
|
||||
let inputValue = document.getElementById(field).value;
|
||||
console.log("Query Value:", inputValue); // Debugging log
|
||||
if (inputValue.length < 2) return;
|
||||
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
||||
|
||||
|
||||
63
resources/js/data/spatialPlannings/data-spatialPlannings.js
Normal file
63
resources/js/data/spatialPlannings/data-spatialPlannings.js
Normal file
@@ -0,0 +1,63 @@
|
||||
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 dataSpatialPlanningColumns = [
|
||||
"No",
|
||||
"Nama",
|
||||
"KBLI",
|
||||
"Kegiatan",
|
||||
"Luas",
|
||||
"Lokasi",
|
||||
"Nomor",
|
||||
"Tanggal",
|
||||
{
|
||||
name: "Actions",
|
||||
widht: "120px",
|
||||
formatter: function (cell, row) {
|
||||
const id = row.cells[8].data;
|
||||
const model = "data/spatial-plannings";
|
||||
return gridjs.html(`
|
||||
<div class="d-flex justify-items-end gap-10">
|
||||
<button class="btn btn-warning me-2 btn-edit"
|
||||
data-id="${id}"
|
||||
data-model="${model}">
|
||||
<i class='bx bx-edit'></i></button>
|
||||
|
||||
<button class="btn btn-red btn-delete"
|
||||
data-id="${id}">
|
||||
<i class='bx bxs-trash'></i></button>
|
||||
</div>
|
||||
`);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const table = new GeneralTable(
|
||||
"spatial-planning-data-table",
|
||||
`${GlobalConfig.apiHost}/api/spatial-plannings`,
|
||||
`${GlobalConfig.apiHost}`,
|
||||
dataSpatialPlanningColumns
|
||||
);
|
||||
|
||||
table.processData = function (data) {
|
||||
return data.data.map((item) => {
|
||||
return [
|
||||
item.no,
|
||||
item.name,
|
||||
item.kbli,
|
||||
item.activities,
|
||||
item.area,
|
||||
item.location,
|
||||
item.number,
|
||||
item.date,
|
||||
item.id,
|
||||
];
|
||||
});
|
||||
};
|
||||
|
||||
table.init();
|
||||
});
|
||||
185
resources/js/data/spatialPlannings/form-create-update.js
Normal file
185
resources/js/data/spatialPlannings/form-create-update.js
Normal file
@@ -0,0 +1,185 @@
|
||||
import GlobalConfig from "../../global-config";
|
||||
|
||||
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");
|
||||
var authLogo = document.querySelector(".auth-logo");
|
||||
|
||||
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;
|
||||
});
|
||||
|
||||
const url = form.getAttribute("action");
|
||||
|
||||
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) => {
|
||||
if (!data.errors) {
|
||||
// Remove existing icon (if any) before adding the new one
|
||||
if (authLogo) {
|
||||
// Hapus ikon yang sudah ada jika ada
|
||||
const existingIcon = authLogo.querySelector(".bx");
|
||||
if (existingIcon) {
|
||||
authLogo.removeChild(existingIcon);
|
||||
}
|
||||
|
||||
// Buat ikon baru
|
||||
const icon = document.createElement("i");
|
||||
icon.classList.add("bx", "bxs-check-square");
|
||||
icon.style.fontSize = "25px";
|
||||
icon.style.color = "green"; // Pastikan 'green' dalam bentuk string
|
||||
|
||||
// Tambahkan ikon ke dalam auth-logo
|
||||
authLogo.appendChild(icon);
|
||||
}
|
||||
|
||||
// Set success message for the toast
|
||||
toastBody.textContent = isEdit
|
||||
? "Data updated successfully!"
|
||||
: "Data created successfully!";
|
||||
toast.classList.add("show"); // Show the toast
|
||||
setTimeout(() => {
|
||||
toast.classList.remove("show"); // Hide the toast after 3 seconds
|
||||
}, 3000);
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = "/data/spatial-plannings";
|
||||
}, 3000);
|
||||
} else {
|
||||
if (authLogo) {
|
||||
// Hapus ikon yang sudah ada jika ada
|
||||
const existingIcon = authLogo.querySelector(".bx");
|
||||
if (existingIcon) {
|
||||
authLogo.removeChild(existingIcon);
|
||||
}
|
||||
|
||||
// Buat ikon baru
|
||||
const icon = document.createElement("i");
|
||||
icon.classList.add("bx", "bxs-error-alt");
|
||||
icon.style.fontSize = "25px";
|
||||
icon.style.color = "red"; // Pastikan 'green' dalam bentuk string
|
||||
|
||||
// Tambahkan ikon ke dalam auth-logo
|
||||
authLogo.appendChild(icon);
|
||||
}
|
||||
// Set error message for the toast
|
||||
toastBody.textContent =
|
||||
"Error: " + (data.message || "Something went wrong");
|
||||
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) => {
|
||||
if (authLogo) {
|
||||
// Hapus ikon yang sudah ada jika ada
|
||||
const existingIcon = authLogo.querySelector(".bx");
|
||||
if (existingIcon) {
|
||||
authLogo.removeChild(existingIcon);
|
||||
}
|
||||
|
||||
// Buat ikon baru
|
||||
const icon = document.createElement("i");
|
||||
icon.classList.add("bx", "bxs-error-alt");
|
||||
icon.style.fontSize = "25px";
|
||||
icon.style.color = "red"; // Pastikan 'green' dalam bentuk string
|
||||
|
||||
// Tambahkan ikon ke dalam auth-logo
|
||||
authLogo.appendChild(icon);
|
||||
}
|
||||
// Set error message for the toast
|
||||
toastBody.textContent =
|
||||
"An error occurred while processing your request.";
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
// Fungsi fetchOptions untuk autocomplete server-side
|
||||
window.fetchOptions = function (field) {
|
||||
let inputValue = document.getElementById(field).value;
|
||||
if (inputValue.length < 2) return;
|
||||
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
||||
|
||||
let url = `${
|
||||
GlobalConfig.apiHost
|
||||
}/api/combobox/search-options?query=${encodeURIComponent(
|
||||
inputValue
|
||||
)}&field=${field}`;
|
||||
|
||||
// Jika field desa, tambahkan kecamatan sebagai filter
|
||||
if (field === "village_name") {
|
||||
url += `&district=${encodeURIComponent(districtValue)}`;
|
||||
}
|
||||
|
||||
fetch(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${document
|
||||
.querySelector('meta[name="api-token"]')
|
||||
.getAttribute("content")}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
let dataList = document.getElementById(field + "Options");
|
||||
dataList.innerHTML = "";
|
||||
|
||||
data.forEach((item) => {
|
||||
let option = document.createElement("option");
|
||||
option.value = item.name;
|
||||
option.dataset.code = item.code;
|
||||
dataList.appendChild(option);
|
||||
});
|
||||
})
|
||||
.catch((error) => console.error("Error fetching options:", error));
|
||||
};
|
||||
|
||||
document.querySelector(".btn-back").addEventListener("click", function () {
|
||||
window.history.back();
|
||||
});
|
||||
});
|
||||
150
resources/js/data/spatialPlannings/form-upload.js
Normal file
150
resources/js/data/spatialPlannings/form-upload.js
Normal file
@@ -0,0 +1,150 @@
|
||||
import { Dropzone } from "dropzone";
|
||||
import GlobalConfig from "../../global-config.js";
|
||||
|
||||
Dropzone.autoDiscover = false;
|
||||
|
||||
var previewTemplate,
|
||||
dropzone,
|
||||
dropzonePreviewNode = document.querySelector("#dropzone-preview-list");
|
||||
console.log(previewTemplate);
|
||||
console.log(dropzone);
|
||||
console.log(dropzonePreviewNode);
|
||||
|
||||
(dropzonePreviewNode.id = ""),
|
||||
dropzonePreviewNode &&
|
||||
((previewTemplate = dropzonePreviewNode.parentNode.innerHTML),
|
||||
dropzonePreviewNode.parentNode.removeChild(dropzonePreviewNode),
|
||||
(dropzone = new Dropzone(".dropzone", {
|
||||
url: `${GlobalConfig.apiHost}/api/spatial-plannings/import`,
|
||||
// url: "https://httpbin.org/post",
|
||||
method: "post",
|
||||
acceptedFiles: ".xls,.xlsx", // Use acceptedFiles for better validation
|
||||
previewTemplate: previewTemplate,
|
||||
previewsContainer: "#dropzone-preview",
|
||||
autoProcessQueue: false, // Disable auto post
|
||||
headers: {
|
||||
Authorization: `Bearer ${document
|
||||
.querySelector('meta[name="api-token"]')
|
||||
.getAttribute("content")}`
|
||||
},
|
||||
init: function() {
|
||||
// Listen for the success event
|
||||
this.on("success", function(file, response) {
|
||||
console.log("File successfully uploaded:", file);
|
||||
console.log("API Response:", response);
|
||||
|
||||
// Show success toast
|
||||
showToast('bxs-check-square', 'green', response.message);
|
||||
document.getElementById("submit-upload").innerHTML = "Upload Files";
|
||||
// Tunggu sebentar lalu reload halaman
|
||||
setTimeout(() => {
|
||||
window.location.href = "/data/spatial-plannings";
|
||||
}, 2000);
|
||||
});
|
||||
// Listen for the error event
|
||||
this.on("error", function(file, errorMessage) {
|
||||
console.error("Error uploading file:", file);
|
||||
console.error("Error message:", errorMessage);
|
||||
// Handle the error response
|
||||
|
||||
// Show error toast
|
||||
showToast('bxs-error-alt', 'red', errorMessage.message);
|
||||
document.getElementById("submit-upload").innerHTML = "Upload Files";
|
||||
});
|
||||
}
|
||||
})));
|
||||
|
||||
// Add event listener to control the submission manually
|
||||
document.querySelector("#submit-upload").addEventListener("click", function() {
|
||||
console.log("Ini adalah value dropzone", dropzone.files[0]);
|
||||
const formData = new FormData()
|
||||
console.log("Dropzonefiles",dropzone.files);
|
||||
|
||||
this.innerHTML = '<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>Loading...';
|
||||
|
||||
// Pastikan ada file dalam queue sebelum memprosesnya
|
||||
if (dropzone.files.length > 0) {
|
||||
formData.append('file', dropzone.files[0])
|
||||
console.log("ini adalah form data on submit", ...formData);
|
||||
dropzone.processQueue(); // Ini akan manual memicu upload
|
||||
} else {
|
||||
// Show error toast when no file is selected
|
||||
showToast('bxs-error-alt', 'red', "Please add a file first.");
|
||||
document.getElementById("submit-upload").innerHTML = "Upload Files";
|
||||
}
|
||||
});
|
||||
|
||||
// Optional: Listen for the 'addedfile' event to log or control file add behavior
|
||||
dropzone.on("addedfile", function (file) {
|
||||
console.log("File ditambahkan:", file);
|
||||
console.log("Nama File:", file.name);
|
||||
console.log("Tipe File:", file.type);
|
||||
console.log("Ukuran File:", (file.size / 1024).toFixed(2) + " KB");
|
||||
});
|
||||
|
||||
dropzone.on("complete", function(file) {
|
||||
dropzone.removeFile(file);
|
||||
});
|
||||
|
||||
// Add event listener to download file template
|
||||
document.getElementById('downloadtempspatialPlannings').addEventListener('click', function() {
|
||||
var url = `${GlobalConfig.apiHost}/api/download-template-spatialPlannings`;
|
||||
fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `Bearer ${document
|
||||
.querySelector('meta[name="api-token"]')
|
||||
.getAttribute("content")}`
|
||||
},
|
||||
})
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
return response.blob(); // Jika respons OK, konversi menjadi blob
|
||||
} else {
|
||||
return response.json(); // Jika respons gagal, konversi menjadi JSON untuk menangani pesan error
|
||||
}
|
||||
})
|
||||
.then((blob) => {
|
||||
console.log(blob);
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none';
|
||||
a.href = url;
|
||||
a.download = 'template_rencana_tata_ruang.xlsx';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Gagal mendownload file:", error);
|
||||
showToast('bxs-error-alt', 'red', "Template file is not already exist.");
|
||||
})
|
||||
})
|
||||
|
||||
// Function to show toast
|
||||
function showToast(iconClass, iconColor, message) {
|
||||
const toastElement = document.getElementById('toastUploadSpatialPlannings');
|
||||
const toastBody = toastElement.querySelector('.toast-body');
|
||||
const toastHeader = toastElement.querySelector('.toast-header');
|
||||
|
||||
// Remove existing icon (if any) before adding the new one
|
||||
const existingIcon = toastHeader.querySelector('.bx');
|
||||
if (existingIcon) {
|
||||
toastHeader.querySelector('.auth-logo').removeChild(existingIcon); // Remove the existing icon
|
||||
}
|
||||
|
||||
// Add the new icon to the toast header
|
||||
const icon = document.createElement('i');
|
||||
icon.classList.add('bx', iconClass);
|
||||
icon.style.fontSize = '25px';
|
||||
icon.style.color = iconColor;
|
||||
toastHeader.querySelector('.auth-logo').appendChild(icon);
|
||||
|
||||
// Set the toast message
|
||||
toastBody.textContent = message;
|
||||
|
||||
// Show the toast
|
||||
const toast = new bootstrap.Toast(toastElement); // Inisialisasi Bootstrap Toast
|
||||
toast.show();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import GlobalConfig from "../../global-config.js";
|
||||
import GeneralTable from "../../table-generator.js";
|
||||
|
||||
const dataTourismsColumns = [
|
||||
"No",
|
||||
"Nama Perusahaan",
|
||||
"Nama Proyek",
|
||||
"Alamat Usaha",
|
||||
@@ -54,6 +55,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
table.processData = function (data) {
|
||||
return data.data.map((item) => {
|
||||
return [
|
||||
item.no,
|
||||
item.business_name,
|
||||
item.project_name,
|
||||
item.business_address,
|
||||
|
||||
@@ -28,12 +28,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
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";
|
||||
|
||||
@@ -49,7 +44,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
console.log("Response data:", data);
|
||||
if (!data.errors) {
|
||||
// Remove existing icon (if any) before adding the new one
|
||||
if (authLogo) {
|
||||
@@ -113,7 +107,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error);
|
||||
if (authLogo) {
|
||||
// Hapus ikon yang sudah ada jika ada
|
||||
const existingIcon = authLogo.querySelector(".bx");
|
||||
@@ -148,7 +141,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// Fungsi fetchOptions untuk autocomplete server-side
|
||||
window.fetchOptions = function (field) {
|
||||
let inputValue = document.getElementById(field).value;
|
||||
console.log("Query Value:", inputValue); // Debugging log
|
||||
if (inputValue.length < 2) return;
|
||||
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ dropzone.on("complete", function(file) {
|
||||
|
||||
// Add event listener to download file template
|
||||
document.getElementById('downloadtemptourisms').addEventListener('click', function() {
|
||||
var url = `${GlobalConfig.apiHost}/api/download-template-umkm`;
|
||||
var url = `${GlobalConfig.apiHost}/api/download-template-tourism`;
|
||||
fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
@@ -105,11 +105,12 @@ document.getElementById('downloadtemptourisms').addEventListener('click', functi
|
||||
}
|
||||
})
|
||||
.then((blob) => {
|
||||
console.log(blob);
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none';
|
||||
a.href = url;
|
||||
a.download = 'template_tourisms.xlsx';
|
||||
a.download = 'template_pariwisata.xlsx';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
@@ -122,7 +123,7 @@ document.getElementById('downloadtemptourisms').addEventListener('click', functi
|
||||
|
||||
// Function to show toast
|
||||
function showToast(iconClass, iconColor, message) {
|
||||
const toastElement = document.getElementById('toastUploadUmkm');
|
||||
const toastElement = document.getElementById('toastUploadTourisms');
|
||||
const toastBody = toastElement.querySelector('.toast-body');
|
||||
const toastHeader = toastElement.querySelector('.toast-header');
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import GlobalConfig from "../../global-config.js";
|
||||
import GeneralTable from "../../table-generator.js";
|
||||
|
||||
const dataUMKMColumns = [
|
||||
"No",
|
||||
"Nama Usaha",
|
||||
"Alamat Usaha",
|
||||
"Deskripsi Usaha",
|
||||
@@ -54,6 +55,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
table.processData = function (data) {
|
||||
return data.data.map((item) => {
|
||||
return [
|
||||
item.no,
|
||||
item.business_name,
|
||||
item.business_address,
|
||||
item.business_desc,
|
||||
|
||||
@@ -28,12 +28,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
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";
|
||||
|
||||
@@ -74,11 +69,11 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
toast.classList.add('show'); // Show the toast
|
||||
setTimeout(() => {
|
||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||
}, 3000);
|
||||
}, 2000);
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '/data/umkm';
|
||||
}, 3000);
|
||||
}, 1000);
|
||||
} else {
|
||||
if (authLogo) {
|
||||
// Hapus ikon yang sudah ada jika ada
|
||||
@@ -96,14 +91,16 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// Tambahkan ikon ke dalam auth-logo
|
||||
authLogo.appendChild(icon);
|
||||
}
|
||||
// Set error message for the toast
|
||||
toastBody.textContent = "Error: " + (data.message || "Something went wrong");
|
||||
toast.classList.add('show'); // Show the toast
|
||||
|
||||
// Enable button and reset its text on error
|
||||
modalButton.disabled = false;
|
||||
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
||||
|
||||
|
||||
// Set error message for the toast
|
||||
toastBody.textContent = "Error: " + (data.message || "Something went wrong");
|
||||
toast.classList.add('show'); // Show the toast
|
||||
|
||||
setTimeout(() => {
|
||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||
}, 3000);
|
||||
@@ -127,14 +124,15 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// Tambahkan ikon ke dalam auth-logo
|
||||
authLogo.appendChild(icon);
|
||||
}
|
||||
// Set error message for the toast
|
||||
toastBody.textContent = "An error occurred while processing your request.";
|
||||
toast.classList.add('show'); // Show the toast
|
||||
|
||||
// Enable button and reset its text on error
|
||||
modalButton.disabled = false;
|
||||
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
||||
|
||||
// Set error message for the toast
|
||||
toastBody.textContent = "An error occurred while processing your request.";
|
||||
toast.classList.add('show'); // Show the toast
|
||||
|
||||
setTimeout(() => {
|
||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||
}, 3000);
|
||||
@@ -144,7 +142,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// Fungsi fetchOptions untuk autocomplete server-side
|
||||
window.fetchOptions = function (field) {
|
||||
let inputValue = document.getElementById(field).value;
|
||||
console.log("Query Value:", inputValue); // Debugging log
|
||||
if (inputValue.length < 2) return;
|
||||
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
||||
|
||||
|
||||
@@ -1,55 +1,67 @@
|
||||
document.addEventListener("DOMContentLoaded", function (e) {
|
||||
const toastNotification = document.getElementById("toastNotification");
|
||||
const toast = new bootstrap.Toast(toastNotification);
|
||||
document
|
||||
.getElementById("btnCreateMenus")
|
||||
.addEventListener("click", async function () {
|
||||
let submitButton = this;
|
||||
let spinner = document.getElementById("spinner");
|
||||
let form = document.getElementById("formCreateMenus");
|
||||
class CreateMenu {
|
||||
constructor() {
|
||||
this.initCreateMenu();
|
||||
}
|
||||
|
||||
if (!form) {
|
||||
console.error("Form element not found!");
|
||||
return;
|
||||
}
|
||||
// Get form data
|
||||
let formData = new FormData(form);
|
||||
initCreateMenu() {
|
||||
const toastNotification = document.getElementById("toastNotification");
|
||||
const toast = new bootstrap.Toast(toastNotification);
|
||||
document
|
||||
.getElementById("btnCreateMenus")
|
||||
.addEventListener("click", async function () {
|
||||
let submitButton = this;
|
||||
let spinner = document.getElementById("spinner");
|
||||
let form = document.getElementById("formCreateMenus");
|
||||
|
||||
// Disable button and show spinner
|
||||
submitButton.disabled = true;
|
||||
spinner.classList.remove("d-none");
|
||||
if (!form) {
|
||||
console.error("Form element not found!");
|
||||
return;
|
||||
}
|
||||
// Get form data
|
||||
let formData = new FormData(form);
|
||||
|
||||
try {
|
||||
let response = await fetch(form.action, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": document
|
||||
.querySelector('meta[name="csrf-token"]')
|
||||
.getAttribute("content"),
|
||||
},
|
||||
body: formData,
|
||||
});
|
||||
// Disable button and show spinner
|
||||
submitButton.disabled = true;
|
||||
spinner.classList.remove("d-none");
|
||||
|
||||
if (response.ok) {
|
||||
let result = await response.json();
|
||||
document.getElementById("toast-message").innerText =
|
||||
result.message;
|
||||
toast.show();
|
||||
setTimeout(() => {
|
||||
window.location.href = "/menus";
|
||||
}, 2000);
|
||||
} else {
|
||||
let error = await response.json();
|
||||
try {
|
||||
let response = await fetch(form.action, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${document
|
||||
.querySelector('meta[name="api-token"]')
|
||||
.getAttribute("content")}`,
|
||||
},
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
let result = await response.json();
|
||||
document.getElementById("toast-message").innerText =
|
||||
result.message;
|
||||
toast.show();
|
||||
setTimeout(() => {
|
||||
window.location.href = "/menus";
|
||||
}, 2000);
|
||||
} else {
|
||||
let error = await response.json();
|
||||
document.getElementById("toast-message").innerText =
|
||||
error.message;
|
||||
toast.show();
|
||||
console.error("Error:", error);
|
||||
submitButton.disabled = false;
|
||||
spinner.classList.add("d-none");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Request failed:", error);
|
||||
document.getElementById("toast-message").innerText =
|
||||
error.message;
|
||||
toast.show();
|
||||
console.error("Error:", error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Request failed:", error);
|
||||
document.getElementById("toast-message").innerText =
|
||||
error.message;
|
||||
toast.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function (e) {
|
||||
new CreateMenu();
|
||||
});
|
||||
|
||||
@@ -2,13 +2,27 @@ import { Grid } from "gridjs/dist/gridjs.umd.js";
|
||||
import gridjs from "gridjs/dist/gridjs.umd.js";
|
||||
import "gridjs/dist/gridjs.umd.js";
|
||||
import GlobalConfig from "../global-config";
|
||||
import Swal from "sweetalert2";
|
||||
|
||||
class Menus {
|
||||
constructor() {
|
||||
this.toastMessage = document.getElementById("toast-message");
|
||||
this.toastElement = document.getElementById("toastNotification");
|
||||
this.toast = new bootstrap.Toast(this.toastElement);
|
||||
this.table = null;
|
||||
}
|
||||
init() {
|
||||
|
||||
// Initialize functions
|
||||
this.initTableMenus();
|
||||
this.initEvents();
|
||||
}
|
||||
initEvents() {
|
||||
document.body.addEventListener("click", async (event) => {
|
||||
const deleteButton = event.target.closest(".btn-delete-menu");
|
||||
if (deleteButton) {
|
||||
event.preventDefault();
|
||||
await this.handleDelete(deleteButton);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initTableMenus() {
|
||||
@@ -19,7 +33,7 @@ class Menus {
|
||||
this.table
|
||||
.updateConfig({
|
||||
server: {
|
||||
url: `${GlobalConfig.apiHost}/api/api-menus`,
|
||||
url: `${GlobalConfig.apiHost}/api/menus`,
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${document
|
||||
@@ -60,7 +74,8 @@ class Menus {
|
||||
<a href="/menus/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
|
||||
<i class='bx bx-edit'></i>
|
||||
</a>
|
||||
<button data-id="${cell}" class="btn btn-red btn-sm btn-delete-menu d-inline-flex align-items-center justify-content-center">
|
||||
<button data-id="${cell}"
|
||||
class="btn btn-red btn-sm btn-delete-menu d-inline-flex align-items-center justify-content-center">
|
||||
<i class='bx bxs-trash' ></i>
|
||||
</button>
|
||||
</div>
|
||||
@@ -83,7 +98,7 @@ class Menus {
|
||||
},
|
||||
},
|
||||
server: {
|
||||
url: `${GlobalConfig.apiHost}/api/api-menus`,
|
||||
url: `${GlobalConfig.apiHost}/api/menus`,
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${document
|
||||
@@ -104,118 +119,63 @@ class Menus {
|
||||
total: (data) => data.total,
|
||||
},
|
||||
}).render(tableContainer);
|
||||
|
||||
document.addEventListener("click", this.handleDelete.bind(this));
|
||||
}
|
||||
|
||||
handleDelete(event) {
|
||||
if (event.target.classList.contains("btn-delete-menu")) {
|
||||
event.preventDefault();
|
||||
const id = event.target.getAttribute("data-id");
|
||||
let modalElement = document.getElementById("modalConfirmation");
|
||||
let toastMessage = document.getElementById("toast-message");
|
||||
async handleDelete(button) {
|
||||
const id = button.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-menu-id", id);
|
||||
|
||||
// Show the modal
|
||||
modal.show();
|
||||
|
||||
btnSaveConfirmation.addEventListener("click", async () => {
|
||||
let menuId = btnSaveConfirmation.getAttribute("data-menu-id");
|
||||
|
||||
try {
|
||||
let response = await fetch(`/menus/${menuId}`, {
|
||||
if (result.isConfirmed) {
|
||||
try {
|
||||
let response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/menus/${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.refreshTableMenus();
|
||||
} 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
refreshTableMenus() {
|
||||
if (this.table) {
|
||||
this.table
|
||||
.updateConfig({
|
||||
server: {
|
||||
url: `${GlobalConfig.apiHost}/api/api-menus`,
|
||||
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.url,
|
||||
item.icon,
|
||||
item.parent_id,
|
||||
item.sort_order,
|
||||
item.id,
|
||||
]),
|
||||
total: (data) => data.total,
|
||||
},
|
||||
})
|
||||
.forceRender();
|
||||
} else {
|
||||
this.initTableMenus(); // If no table exists, reinitialize it
|
||||
}
|
||||
);
|
||||
|
||||
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 Menus().init();
|
||||
new Menus();
|
||||
});
|
||||
|
||||
@@ -1,53 +1,67 @@
|
||||
document.addEventListener("DOMContentLoaded", function (e) {
|
||||
let form = document.getElementById("formUpdateMenus");
|
||||
let submitButton = document.getElementById("btnUpdateMenus");
|
||||
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 UpdateMenu {
|
||||
constructor() {
|
||||
this.initUpdateMenu();
|
||||
}
|
||||
|
||||
if (!form) {
|
||||
console.error("Form element not found!");
|
||||
return;
|
||||
}
|
||||
// Get form data
|
||||
let formData = new FormData(form);
|
||||
initUpdateMenu() {
|
||||
const toastNotification = document.getElementById("toastNotification");
|
||||
const toast = new bootstrap.Toast(toastNotification);
|
||||
document
|
||||
.getElementById("btnUpdateMenus")
|
||||
.addEventListener("click", async function () {
|
||||
let submitButton = this;
|
||||
let spinner = document.getElementById("spinner");
|
||||
let form = document.getElementById("formUpdateMenus");
|
||||
|
||||
// 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 = "/menus";
|
||||
}, 2000);
|
||||
} else {
|
||||
let error = await response.json();
|
||||
document.getElementById("toast-message").innerText =
|
||||
error.message;
|
||||
toast.show();
|
||||
console.error("Error:", error);
|
||||
submitButton.disabled = false;
|
||||
spinner.classList.add("d-none");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Request failed:", error);
|
||||
document.getElementById("toast-message").innerText =
|
||||
error.message;
|
||||
toast.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (response.ok) {
|
||||
let result = await response.json();
|
||||
toastMessage.innerText = result.message;
|
||||
toast.show();
|
||||
setTimeout(() => {
|
||||
window.location.href = "/menus";
|
||||
}, 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 UpdateMenu();
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
import flatpickr from "flatpickr";
|
||||
|
||||
class CreateSpatialPlannings {
|
||||
constructor() {
|
||||
this.initCreateSpatial();
|
||||
}
|
||||
|
||||
initCreateSpatial() {
|
||||
const toastNotification = document.getElementById("toastNotification");
|
||||
const toast = new bootstrap.Toast(toastNotification);
|
||||
document
|
||||
.getElementById("btnCreateSpatialPlannings")
|
||||
.addEventListener("click", async function () {
|
||||
let submitButton = this;
|
||||
let spinner = document.getElementById("spinner");
|
||||
let form = document.getElementById(
|
||||
"formCreateSpatialPlannings"
|
||||
);
|
||||
|
||||
if (!form) {
|
||||
console.error("Form element not found!");
|
||||
return;
|
||||
}
|
||||
// Get form data
|
||||
let formData = new FormData(form);
|
||||
|
||||
// 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 = "/data/spatial-plannings";
|
||||
}, 2000);
|
||||
} else {
|
||||
let error = await response.json();
|
||||
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 CreateSpatialPlannings();
|
||||
});
|
||||
@@ -1,156 +0,0 @@
|
||||
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 SpatialPlannings {
|
||||
constructor() {
|
||||
this.toastMessage = document.getElementById("toast-message");
|
||||
this.toastElement = document.getElementById("toastNotification");
|
||||
this.toast = new bootstrap.Toast(this.toastElement);
|
||||
this.table = null;
|
||||
|
||||
// Initialize functions
|
||||
this.initTableSpatialPlannings();
|
||||
this.initEvents();
|
||||
}
|
||||
initEvents() {
|
||||
document.body.addEventListener("click", async (event) => {
|
||||
const deleteButton = event.target.closest(
|
||||
".btn-delete-spatial-plannings"
|
||||
);
|
||||
if (deleteButton) {
|
||||
event.preventDefault();
|
||||
await this.handleDelete(deleteButton);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initTableSpatialPlannings() {
|
||||
let tableContainer = document.getElementById("table-spatial-plannings");
|
||||
// Create a new Grid.js instance only if it doesn't exist
|
||||
this.table = new Grid({
|
||||
columns: [
|
||||
"ID",
|
||||
"Name",
|
||||
"KBLI",
|
||||
"Kegiatan",
|
||||
"Luas",
|
||||
"Lokasi",
|
||||
"Nomor",
|
||||
"Date",
|
||||
{
|
||||
name: "Action",
|
||||
formatter: (cell) =>
|
||||
gridjs.html(`
|
||||
<div class="d-flex justify-content-center gap-2">
|
||||
<a href="/data/spatial-plannings/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
|
||||
<i class='bx bx-edit'></i>
|
||||
</a>
|
||||
<button id="btn-delete-spatial-plannings" data-id="${cell}" class="btn btn-sm btn-red btn-delete-spatial-plannings d-inline-flex align-items-center justify-content-center">
|
||||
<i class='bx bxs-trash' ></i>
|
||||
</button>
|
||||
</div>
|
||||
`),
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
limit: 15,
|
||||
server: {
|
||||
url: (prev, page) =>
|
||||
`${prev}${prev.includes("?") ? "&" : "?"}page=${
|
||||
page + 1
|
||||
}`,
|
||||
},
|
||||
},
|
||||
sort: true,
|
||||
search: {
|
||||
server: {
|
||||
url: (prev, keyword) => `${prev}?search=${keyword}`,
|
||||
},
|
||||
},
|
||||
server: {
|
||||
url: `${GlobalConfig.apiHost}/api/spatial-plannings`,
|
||||
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.kbli,
|
||||
item.kegiatan,
|
||||
item.luas,
|
||||
item.lokasi,
|
||||
item.nomor,
|
||||
item.sp_date,
|
||||
item.id,
|
||||
]),
|
||||
total: (data) => data.meta.total,
|
||||
},
|
||||
}).render(tableContainer);
|
||||
}
|
||||
|
||||
async handleDelete(deleteButton) {
|
||||
const id = deleteButton.getAttribute("data-id");
|
||||
|
||||
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 (result.isConfirmed) {
|
||||
try {
|
||||
let response = await fetch(
|
||||
`${GlobalConfig.apiHost}/api/spatial-plannings/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
Authorization: `Bearer ${document
|
||||
.querySelector('meta[name="api-token"]')
|
||||
.getAttribute("content")}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
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 SpatialPlannings();
|
||||
});
|
||||
@@ -1,67 +0,0 @@
|
||||
class UpdateSpatialPlannings {
|
||||
constructor() {
|
||||
this.initUpdateSpatial();
|
||||
}
|
||||
|
||||
initUpdateSpatial() {
|
||||
const toastNotification = document.getElementById("toastNotification");
|
||||
const toast = new bootstrap.Toast(toastNotification);
|
||||
document
|
||||
.getElementById("btnUpdateSpatialPlannings")
|
||||
.addEventListener("click", async function () {
|
||||
let submitButton = this;
|
||||
let spinner = document.getElementById("spinner");
|
||||
let form = document.getElementById(
|
||||
"formUpdateSpatialPlannings"
|
||||
);
|
||||
|
||||
if (!form) {
|
||||
console.error("Form element not found!");
|
||||
return;
|
||||
}
|
||||
// Get form data
|
||||
let formData = new FormData(form);
|
||||
|
||||
// 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 = "/data/spatial-plannings";
|
||||
}, 2000);
|
||||
} else {
|
||||
let error = await response.json();
|
||||
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 UpdateSpatialPlannings();
|
||||
});
|
||||
@@ -1,83 +0,0 @@
|
||||
import { Dropzone } from "dropzone";
|
||||
Dropzone.autoDiscover = false;
|
||||
|
||||
class UploadSpatialPlannings {
|
||||
constructor() {
|
||||
this.spatialDropzone = null;
|
||||
this.formElement = document.getElementById(
|
||||
"formUploadSpatialPlannings"
|
||||
);
|
||||
this.uploadButton = document.getElementById("submit-upload");
|
||||
this.spinner = document.getElementById("spinner");
|
||||
if (!this.formElement) {
|
||||
console.error(
|
||||
"Element formUploadSpatialPlannings tidak ditemukan!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
this.initDropzone();
|
||||
this.setupUploadButton();
|
||||
}
|
||||
|
||||
initDropzone() {
|
||||
const toastNotification = document.getElementById("toastNotification");
|
||||
const toast = new bootstrap.Toast(toastNotification);
|
||||
var previewTemplate,
|
||||
dropzonePreviewNode = document.querySelector(
|
||||
"#dropzone-preview-list"
|
||||
);
|
||||
(dropzonePreviewNode.id = ""),
|
||||
dropzonePreviewNode &&
|
||||
((previewTemplate = dropzonePreviewNode.parentNode.innerHTML),
|
||||
dropzonePreviewNode.parentNode.removeChild(dropzonePreviewNode),
|
||||
(this.spatialDropzone = new Dropzone(".dropzone", {
|
||||
url: this.formElement.action,
|
||||
method: "post",
|
||||
acceptedFiles: ".xls,.xlsx",
|
||||
previewTemplate: previewTemplate,
|
||||
previewsContainer: "#dropzone-preview",
|
||||
autoProcessQueue: false,
|
||||
headers: {
|
||||
Authorization: `Bearer ${document
|
||||
.querySelector('meta[name="api-token"]')
|
||||
.getAttribute("content")}`,
|
||||
},
|
||||
init: function () {
|
||||
this.on("success", function (file, response) {
|
||||
document.getElementById("toast-message").innerText =
|
||||
response.message;
|
||||
toast.show();
|
||||
setTimeout(() => {
|
||||
window.location.href =
|
||||
"/data/spatial-plannings";
|
||||
}, 2000);
|
||||
});
|
||||
this.on("error", function (file, errorMessage) {
|
||||
document.getElementById("toast-message").innerText =
|
||||
errorMessage.message;
|
||||
toast.show();
|
||||
this.uploadButton.disabled = false;
|
||||
this.spinner.classList.add("d-none");
|
||||
});
|
||||
},
|
||||
})));
|
||||
}
|
||||
|
||||
setupUploadButton() {
|
||||
this.uploadButton.addEventListener("click", (e) => {
|
||||
if (this.spatialDropzone.files.length > 0) {
|
||||
this.spatialDropzone.processQueue();
|
||||
this.uploadButton.disabled = true;
|
||||
this.spinner.classList.remove("d-none");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function (e) {
|
||||
new UploadSpatialPlannings().init();
|
||||
});
|
||||
34
resources/js/utils/InitDatePicker.js
Normal file
34
resources/js/utils/InitDatePicker.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import flatpickr from "flatpickr";
|
||||
import "flatpickr/dist/flatpickr.min.css";
|
||||
|
||||
class InitDatePicker {
|
||||
constructor(selector = ".datepicker", onChangeCallback = null) {
|
||||
this.selector = selector;
|
||||
this.onChangeCallback = onChangeCallback;
|
||||
}
|
||||
|
||||
init() {
|
||||
const today = new Date();
|
||||
|
||||
document.querySelectorAll(this.selector).forEach((element) => {
|
||||
flatpickr(element, {
|
||||
enableTime: false,
|
||||
dateFormat: "Y-m-d",
|
||||
maxDate: today,
|
||||
onChange: (selectedDates, dateStr) => {
|
||||
if (this.onChangeCallback) {
|
||||
this.onChangeCallback(dateStr); // Call callback with selected date
|
||||
}
|
||||
},
|
||||
onReady: (selectedDates, dateStr, instance) => {
|
||||
// Call the callback with the default date when initialized
|
||||
if (this.onChangeCallback && dateStr) {
|
||||
this.onChangeCallback(dateStr);
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default InitDatePicker;
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace [% namespace %];
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
|
||||
[% response_methods %]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
return new [% api_resource_class %]($[% model_name_singular_variable %], [% model_was_deleted %]);
|
||||
@@ -1,4 +0,0 @@
|
||||
return $this->successResponse(
|
||||
[% model_was_deleted %],
|
||||
$this->transform($[% model_name_singular_variable %])
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
return new [% api_resource_collection_class %]($[% model_name_plural_variable %], [% models_were_retrieved %]);
|
||||
@@ -1,26 +0,0 @@
|
||||
$[% data_variable %] = $[% model_name_plural_variable %]->transform(function ($[% model_name_singular_variable %]) {
|
||||
return $this->transform($[% model_name_singular_variable %]);
|
||||
});
|
||||
|
||||
return $this->successResponse(
|
||||
[% models_were_retrieved %],
|
||||
$[% data_variable %],
|
||||
[
|
||||
'links' => [
|
||||
'first' => $[% model_name_plural_variable %]->url(1),
|
||||
'last' => $[% model_name_plural_variable %]->url($[% model_name_plural_variable %]->lastPage()),
|
||||
'prev' => $[% model_name_plural_variable %]->previousPageUrl(),
|
||||
'next' => $[% model_name_plural_variable %]->nextPageUrl(),
|
||||
],
|
||||
'meta' =>
|
||||
[
|
||||
'current_page' => $[% model_name_plural_variable %]->currentPage(),
|
||||
'from' => $[% model_name_plural_variable %]->firstItem(),
|
||||
'last_page' => $[% model_name_plural_variable %]->lastPage(),
|
||||
'path' => $[% model_name_plural_variable %]->resolveCurrentPath(),
|
||||
'per_page' => $[% model_name_plural_variable %]->perPage(),
|
||||
'to' => $[% model_name_plural_variable %]->lastItem(),
|
||||
'total' => $[% model_name_plural_variable %]->total(),
|
||||
],
|
||||
]
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
return new [% api_resource_class %]($[% model_name_singular_variable %], [% model_was_retrieved %]);
|
||||
@@ -1,4 +0,0 @@
|
||||
return $this->successResponse(
|
||||
[% model_was_retrieved %],
|
||||
$this->transform($[% model_name_singular_variable %])
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
return new [% api_resource_class %]($[% model_name_singular_variable %], [% model_was_added %]);
|
||||
@@ -1,4 +0,0 @@
|
||||
return $this->successResponse(
|
||||
[% model_was_added %],
|
||||
$this->transform($[% model_name_singular_variable %])
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
return new [% api_resource_class %]($[% model_name_singular_variable %], [% model_was_updated %]);
|
||||
@@ -1,4 +0,0 @@
|
||||
return $this->successResponse(
|
||||
[% model_was_updated %],
|
||||
$this->transform($[% model_name_singular_variable %])
|
||||
);
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* Get an error response
|
||||
*
|
||||
* @param mix $message
|
||||
*
|
||||
* @return Illuminate\Http\Response
|
||||
*/
|
||||
protected function errorResponse($message)
|
||||
{
|
||||
return response()->json([
|
||||
'errors' => (array) $message,
|
||||
'success' => false,
|
||||
], 422);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
/**
|
||||
* Gets a new validator instance with the defined rules.
|
||||
*
|
||||
* @param [% request_fullname %] $request
|
||||
*
|
||||
* @return Illuminate\Support\Facades\Validator
|
||||
*/
|
||||
protected function getValidator(Request $request)
|
||||
{
|
||||
$rules = [
|
||||
[% validation_rules %]
|
||||
];
|
||||
[% file_validation_snippet %]
|
||||
return Validator::make($request->all(), $rules);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* Get a success response
|
||||
*
|
||||
* @param mix $message
|
||||
* @param mix $data
|
||||
* @param array $meta
|
||||
*
|
||||
* @return Illuminate\Http\Response
|
||||
*/
|
||||
protected function successResponse($message, $data, array $meta = [])
|
||||
{
|
||||
return response()->json(
|
||||
array_merge([
|
||||
'data' => $data,
|
||||
'message' => $message,
|
||||
'success' => true,
|
||||
], $meta), 200);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Transform the giving [% model_name %] to public friendly array
|
||||
*
|
||||
* @param [% use_full_model_name %] $[% model_name_singular_variable %]
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function [% transform_method_name %]([% model_name_class %] $[% model_name_singular_variable %])
|
||||
{
|
||||
return [
|
||||
[% model_api_array %]
|
||||
];
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
$validator = $this->getValidator($request);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return $this->errorResponse($validator->errors()->all());
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace [% namespace %];
|
||||
|
||||
[% use_command_placeholder %]
|
||||
use Exception;
|
||||
|
||||
class [% controller_name %] [% controller_extends %]
|
||||
{
|
||||
[% constructor %]
|
||||
/**
|
||||
* Display a listing of the assets.
|
||||
*
|
||||
* @return Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$[% model_name_plural_variable %] = [% model_name_class %]::[% with_relations_for_index %]paginate([% models_per_page %]);
|
||||
|
||||
[% index_return_success %]
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new [% model_name %] in the storage.
|
||||
*
|
||||
* @param [% request_fullname %] [% request_variable %]
|
||||
*
|
||||
* @return Illuminate\Http\Response
|
||||
*/
|
||||
public function store([% type_hinted_request_name %])
|
||||
{
|
||||
try {
|
||||
[% validator_request %]
|
||||
$[% data_variable %] = [% call_get_data %];
|
||||
[% on_store_setter %]
|
||||
$[% model_name_singular_variable %] = [% model_name_class %]::create($[% data_variable %]);
|
||||
|
||||
[% store_return_success %]
|
||||
} catch (Exception $exception) {
|
||||
return $this->errorResponse([% unexpected_error %]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified [% model_name %].
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return Illuminate\Http\Response
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$[% model_name_singular_variable %] = [% model_name_class %]::[% with_relations_for_show %]findOrFail($id);
|
||||
|
||||
[% show_return_success %]
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified [% model_name %] in the storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @param [% request_fullname %] [% request_variable %]
|
||||
*
|
||||
* @return Illuminate\Http\Response
|
||||
*/
|
||||
public function update($id, [% type_hinted_request_name %])
|
||||
{
|
||||
try {
|
||||
[% validator_request %]
|
||||
$[% data_variable %] = [% call_get_data %];
|
||||
[% on_update_setter %]
|
||||
$[% model_name_singular_variable %] = [% model_name_class %]::findOrFail($id);
|
||||
$[% model_name_singular_variable %]->update($[% data_variable %]);
|
||||
|
||||
[% update_return_success %]
|
||||
} catch (Exception $exception) {
|
||||
return $this->errorResponse([% unexpected_error %]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified [% model_name %] from the storage.
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
try {
|
||||
$[% model_name_singular_variable %] = [% model_name_class %]::findOrFail($id);
|
||||
$[% model_name_singular_variable %]->delete();
|
||||
|
||||
[% destroy_return_success %]
|
||||
} catch (Exception $exception) {
|
||||
return $this->errorResponse([% unexpected_error %]);
|
||||
}
|
||||
}
|
||||
[% get_validator_method %]
|
||||
[% get_data_method %]
|
||||
[% upload_method %]
|
||||
[% transform_method %]
|
||||
[% response_methods %]
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace [% namespace %];
|
||||
|
||||
[% use_command_placeholder %]
|
||||
|
||||
class [% controller_name %] [% controller_extends %]
|
||||
{
|
||||
[% constructor %]
|
||||
/**
|
||||
* Display the documentation which corresponds to the giving version.
|
||||
*
|
||||
* @return Illuminate\View\View
|
||||
*/
|
||||
public function index($version)
|
||||
{
|
||||
$viewName = sprintf('[% view_access_fullname %]index', $this->getVersion($version));
|
||||
|
||||
return view($viewName);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace [% namespace %];
|
||||
|
||||
[% use_command_placeholder %]
|
||||
|
||||
class [% controller_name %] [% controller_extends %]
|
||||
{
|
||||
[% constructor %]
|
||||
/**
|
||||
* Display the documentation's view.
|
||||
*
|
||||
* @return Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('[% view_access_fullname %]index');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<span class="label label-danger" title="[% this_parameter_must_be_present_in_the_request %]">[% required_title %]</span>
|
||||
@@ -1,11 +0,0 @@
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>[% string_title %]</td>
|
||||
<td>
|
||||
<span class="label label-primary" title="[% this_parameter_is_an_http_header %]">[% header_title %]</span>
|
||||
</td>
|
||||
<td>[% access_token_with_bearer %]</td>
|
||||
@if(isset($showValidation) && $showValidation)
|
||||
<td></td>
|
||||
@endif
|
||||
</tr>
|
||||
@@ -1,16 +0,0 @@
|
||||
<h4 class="text-danger"><strong>401 - Unauthorized</strong></h4>
|
||||
<p class="text-muted">[% the_user_does_not_have_permission_to_access_the_requested_resource %]</p>
|
||||
<table class="table table-stripped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>success</td>
|
||||
<td>[% boolean_title %]</td>
|
||||
<td>[% indicate_whether_the_request_was_successful_or_not %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>error</td>
|
||||
<td>[% array_of_strings %]</td>
|
||||
<td>[% the_error_message %]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -1,16 +0,0 @@
|
||||
<h4 class="text-danger"><strong>202 - Accepted</strong></h4>
|
||||
<p class="text-muted">[% the_requested_model_does_not_exists %]</p>
|
||||
<table class="table table-stripped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>success</td>
|
||||
<td>[% boolean_title %]</td>
|
||||
<td>[% indicate_whether_the_request_was_successful_or_not %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>error</td>
|
||||
<td>[% array_of_strings %]</td>
|
||||
<td>[% the_error_message %]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -1,16 +0,0 @@
|
||||
<h4 class="text-danger"><strong>422 - Unprocessable Entity</strong></h4>
|
||||
<p class="text-muted">[% the_request_failed_validation %]</p>
|
||||
<table class="table table-stripped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>success</td>
|
||||
<td>[% boolean_title %]</td>
|
||||
<td>[% indicate_whether_the_request_was_successful_or_not %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>errors</td>
|
||||
<td>[% array_of_strings %]</td>
|
||||
<td>[% list_of_the_invalid_errors %]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -1,5 +0,0 @@
|
||||
<tr>
|
||||
<td>[% field_name %]</td>
|
||||
<td>[% field_type_title %]</td>
|
||||
<td>[% api_field_description %]</td>
|
||||
</tr>
|
||||
@@ -1,12 +0,0 @@
|
||||
<tr>
|
||||
<td>[% field_name %]</td>
|
||||
<td>[% field_type_title %]</td>
|
||||
<td><span class="label label-default" title="[% this_parameter_is_part_of_the_body %]">[% body_title %]</span></td>
|
||||
<td>[% api_field_description %]</td>
|
||||
@if($showValidation)
|
||||
<td>
|
||||
[% validation_rule_required %]
|
||||
<span>[% validation_rules %]</span>
|
||||
</td>
|
||||
@endif
|
||||
</tr>
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
$showValidation = (isset($withValidation) && $withValidation) ? true : false;
|
||||
?>
|
||||
<table class="table table-stripped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>[% parameter_name_title %]</th>
|
||||
<th>[% data_type_title %]</th>
|
||||
<th>[% parameter_type_title %]</th>
|
||||
<th>[% description_title %]</th>
|
||||
@if($showValidation)
|
||||
<th>[% validation_title %]</th>
|
||||
@endif
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% include_parameter_for_authorized_request %]
|
||||
@if(isset($withPathId) && $withPathId)
|
||||
<tr>
|
||||
<td>[% model_name %]</td>
|
||||
<td>[% primary_key_type_title %]</td>
|
||||
<td><span class="label label-info" title="[% this_parameter_is_part_of_the_path %]">[% path_title %]</span></td>
|
||||
<td>[% the_id_of_the_model %]</td>
|
||||
@if($showValidation)
|
||||
<td>
|
||||
[% validation_rule_required %]
|
||||
</td>
|
||||
@endif
|
||||
</tr>
|
||||
|
||||
@endif
|
||||
|
||||
[% fields_list_for_body %]
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
@@ -1,14 +0,0 @@
|
||||
<table class="table table-stripped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>[% parameter_name_title %]</th>
|
||||
<th>[% data_type_title %]</th>
|
||||
<th>[% parameter_type_title %]</th>
|
||||
<th>[% description_title %]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% include_parameter_for_authorized_request %]
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
@@ -1,5 +0,0 @@
|
||||
<tr>
|
||||
<td>[% field_name %]</td>
|
||||
<td>[% field_type_title %]</td>
|
||||
<td>[% api_field_description %]</td>
|
||||
</tr>
|
||||
@@ -1,12 +0,0 @@
|
||||
<table class="table table-stripped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>[% name_title %]</th>
|
||||
<th>[% type_title %]</th>
|
||||
<th>[% description_title %]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% fields_list_for_body %]
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -1,21 +0,0 @@
|
||||
<h4 class="text-success"><strong>200 - Ok</strong></h4>
|
||||
<p class="text-muted">[% request_was_successful %]</p>
|
||||
<table class="table table-stripped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>success</td>
|
||||
<td>[% boolean_title %]</td>
|
||||
<td>[% indicate_whether_the_request_was_successful_or_not %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>message</td>
|
||||
<td>[% string_title %]</td>
|
||||
<td>[% the_success_message %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>data</td>
|
||||
<td>[% array_title %]</td>
|
||||
<td>[% the_key_is_the_model_property_and_the_value_is_the_model_value %]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -1,386 +0,0 @@
|
||||
@extends('[% layout_name %]')
|
||||
|
||||
@section('content')
|
||||
|
||||
<h2>[% model_plural %]</h2>
|
||||
[% general_description %]
|
||||
<hr>
|
||||
|
||||
<h2>[% available_resources %]</h2>
|
||||
<div class="card mb-3" id="index-documentation">
|
||||
|
||||
<div class="card-header text-bg-primary d-flex justify-content-between align-items-center p-3">
|
||||
<div>
|
||||
<span class="">GET</span>
|
||||
<span><strong>/{{ Route::getRoutes()->getByName('[% index_route_name %]')->uri() }}</strong></span>
|
||||
<p class="mb-0">[% index_route_description %]</p>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" data-bs-toggle="collapse" data-bs-target="#index" aria-controls="index" class="btn btn-primary btn-sm" aria-expanded="false">
|
||||
<span class="fa-solid fa-chevron-down"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body collapse" id="index">
|
||||
<h3><strong>[% request_title %]</strong></h3>
|
||||
[% authorized_request_for_index %]
|
||||
|
||||
<hr>
|
||||
<h3><strong>[% response_title %]</strong></h3>
|
||||
|
||||
<p>[% index_route_response_description %]</p>
|
||||
<p></p>
|
||||
|
||||
<h4><strong class="text-success">200 - Ok</strong></h4>
|
||||
<p class="text-muted">[% request_was_successful %]</p>
|
||||
<table class="table table-stripped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>success</td>
|
||||
<td>[% boolean_title %]</td>
|
||||
<td>Was the request successful or not.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>message</td>
|
||||
<td>[% string_title %]</td>
|
||||
<td>[% the_success_message %]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>data</td>
|
||||
<td>[% array_title %]</td>
|
||||
<td>
|
||||
[% the_key_is_the_model_property_and_the_value_is_the_model_value %]
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>links</td>
|
||||
<td>[% array_title %]</td>
|
||||
<td>
|
||||
<table class="table table-stripped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-2">[% key_title %]</th>
|
||||
<th class="col-md-2">[% data_type_title %]</th>
|
||||
<th class="col-md-8">[% description_title %]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>first</td>
|
||||
<td>[% string_title %]</td>
|
||||
<td>[% link_to_retrieve_first_page %]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>last</td>
|
||||
<td>[% string_title %]</td>
|
||||
<td>[% link_to_retrieve_last_page %]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>prev</td>
|
||||
<td>[% string_title %]</td>
|
||||
<td>[% link_to_retrieve_previous_page %]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>next</td>
|
||||
<td>[% string_title %]</td>
|
||||
<td>[% link_to_retrieve_next_page %]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td>meta</td>
|
||||
<td>[% array_title %]</td>
|
||||
<td>
|
||||
<table class="table table-stripped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-2">[% key_title %]</th>
|
||||
<th class="col-md-2">[% data_type_title %]</th>
|
||||
<th class="col-md-8">[% description_title %]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>current_page</td>
|
||||
<td>[% integer_title %]</td>
|
||||
<td>[% the_number_of_current_page %]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>from</td>
|
||||
<td>[% integer_title %]</td>
|
||||
<td>[% the_index_of_the_first_retrieved_item %]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>last_page</td>
|
||||
<td>[% integer_title %]</td>
|
||||
<td>[% the_number_of_the_last_page %]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Path</td>
|
||||
<td>[% string_title %]</td>
|
||||
<td>[% the_base_link_to_the_resource %]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>per_page</td>
|
||||
<td>[% integer_title %]</td>
|
||||
<td>[% the_number_of_models_per_page %]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>to</td>
|
||||
<td>[% integer_title %]</td>
|
||||
<td>[% the_index_of_the_last_retrieved_item %]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>total</td>
|
||||
<td>[% integer_title %]</td>
|
||||
<td>[% the_total_of_available_pages %]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
[% include_failed_authentication_for_authorized_request %]
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card mb-3" id="store-documentation">
|
||||
|
||||
<div class="card-header text-bg-success d-flex justify-content-between align-items-center p-3">
|
||||
<div>
|
||||
<span>POST</span>
|
||||
<span><strong>/{{ Route::getRoutes()->getByName('[% store_route_name %]')->uri() }}</strong></span>
|
||||
<p class="mb-0">[% store_route_description %]</p>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" data-bs-toggle="collapse" data-bs-target="#store" aria-controls="store" class="btn btn-success btn-sm" aria-expanded="false">
|
||||
<span class="fa-solid fa-chevron-down"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body collapse" id="store">
|
||||
<h3><strong>[% request_title %]</strong></h3>
|
||||
|
||||
@include('[% path_to_view_home %]fields-list', [
|
||||
'withValidation' => true
|
||||
])
|
||||
|
||||
<hr>
|
||||
<h3><strong>[% response_title %]</strong></h3>
|
||||
<p>[% store_route_response_description %]</p>
|
||||
<p></p>
|
||||
|
||||
@include('[% path_to_view_home %]retrieved')
|
||||
@include('[% path_to_view_home %]failed-to-retrieve')
|
||||
@include('[% path_to_view_home %]failed-validation')
|
||||
[% include_failed_authentication_for_authorized_request %]
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="card mb-3" id="update-documentation">
|
||||
|
||||
<div class="card-header text-bg-warning d-flex justify-content-between align-items-center p-3">
|
||||
<div>
|
||||
<span class="">POST</span>
|
||||
<span><strong>/{{ Route::getRoutes()->getByName('[% update_route_name %]')->uri() }}</strong></span>
|
||||
<p class="mb-0">[% update_route_description %]</p>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" data-bs-toggle="collapse" data-bs-target="#update" aria-controls="update" class="btn btn-warning btn-sm" aria-expanded="false">
|
||||
<span class="fa-solid fa-chevron-down"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-collapse collapse" id="update">
|
||||
<div class="card-body">
|
||||
|
||||
<h3><strong>[% request_title %]</strong></h3>
|
||||
|
||||
@include('[% path_to_view_home %]fields-list', [
|
||||
'withValidation' => true,
|
||||
'withPathId' => true,
|
||||
])
|
||||
|
||||
<hr>
|
||||
<h3><strong>[% response_title %]</strong></h3>
|
||||
<p>[% update_route_response_description %]</p>
|
||||
<p></p>
|
||||
|
||||
@include('[% path_to_view_home %]retrieved')
|
||||
@include('[% path_to_view_home %]failed-to-retrieve')
|
||||
@include('[% path_to_view_home %]failed-validation')
|
||||
[% include_failed_authentication_for_authorized_request %]
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="card mb-3" id="show-documentation">
|
||||
|
||||
<div class="card-header text-bg-info d-flex justify-content-between align-items-center p-3">
|
||||
<div>
|
||||
<span class="">GET</span>
|
||||
<span><strong>/{{ Route::getRoutes()->getByName('[% show_route_name %]')->uri() }}</strong></span>
|
||||
<p class="mb-0">[% show_route_description %]</p>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" data-bs-toggle="collapse" data-bs-target="#show" aria-controls="show" class="btn btn-info btn-sm" aria-expanded="false">
|
||||
<span class="fa-solid fa-chevron-down"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body collapse" id="show">
|
||||
|
||||
<h3><strong>[% request_title %]</strong></h3>
|
||||
|
||||
<table class="table table-stripped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-2">[% parameter_name_title %]</th>
|
||||
<th class="col-md-2">[% data_type_title %]</th>
|
||||
<th class="col-md-2">[% parameter_type_title %]</th>
|
||||
<th class="col-md-6">[% description_title %]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% include_parameter_for_authorized_request %]
|
||||
<tr>
|
||||
<td>[% model_name %]</td>
|
||||
<td>[% integer_title %]</td>
|
||||
<td><span class="label label-info" title="[% this_parameter_is_part_of_the_path %]">[% path_title %]</span></td>
|
||||
<td>[% the_id_of_model_to_retrieve %]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<hr>
|
||||
<h3><strong>[% response_title %]</strong></h3>
|
||||
<p>[% show_route_response_description %] </p>
|
||||
<p></p>
|
||||
|
||||
@include('[% path_to_view_home %]retrieved')
|
||||
@include('[% path_to_view_home %]failed-to-retrieve')
|
||||
[% include_failed_authentication_for_authorized_request %]
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card card-danger mb-3" id="destroy-documentation">
|
||||
|
||||
<div class="card-header text-bg-danger d-flex justify-content-between align-items-center p-3">
|
||||
<div>
|
||||
<span class="">DELETE</span>
|
||||
<span><strong>/{{ Route::getRoutes()->getByName('[% destroy_route_name %]')->uri() }}</strong></span>
|
||||
<p class="mb-0">[% destroy_route_description %]</p>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" data-bs-toggle="collapse" data-bs-target="#destroy" aria-controls="destroy" class="btn btn-danger btn-sm" aria-expanded="false">
|
||||
<span class="fa-solid fa-chevron-down"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body collapse" id="destroy">
|
||||
|
||||
<h3><strong>[% request_title %]</strong></h3>
|
||||
|
||||
<table class="table table-stripped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-2">[% parameter_name_title %]</th>
|
||||
<th class="col-md-2">[% data_type_title %]</th>
|
||||
<th class="col-md-2">[% parameter_type_title %]</th>
|
||||
<th class="col-md-6">[% description_title %]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% include_parameter_for_authorized_request %]
|
||||
<tr>
|
||||
<td>[% model_name %]</td>
|
||||
<td>[% integer_title %]</td>
|
||||
<td><span class="label label-info" title="[% this_parameter_is_part_of_the_path %]">[% path_title %]</span></td>
|
||||
<td>[% the_id_of_model_to_delete %]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<hr>
|
||||
<h3><strong>[% response_title %]</strong></h3>
|
||||
<p>[% destroy_route_response_description %]</p>
|
||||
<p></p>
|
||||
|
||||
@include('[% path_to_view_home %]retrieved')
|
||||
@include('[% path_to_view_home %]failed-to-retrieve')
|
||||
[% include_failed_authentication_for_authorized_request %]
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>[% model_definition_title %]</h2>
|
||||
<div class="card" id="[% model_name %]-model-documentation">
|
||||
|
||||
<div class="card-header text-bg-secondary d-flex justify-content-between align-items-center p-3">
|
||||
<div>
|
||||
<span class="">[% model_name_title %]</span>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" data-bs-toggle="collapse" data-bs-target="#model-definitions" aria-controls="model-definitions" class="btn btn-secondary btn-sm" aria-expanded="false">
|
||||
<span class="fa-solid fa-chevron-down"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body collapse" id="model-definitions">
|
||||
<table class="table table-stripped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>[% field_name_title %]</th>
|
||||
<th>[% field_type_title %]</th>
|
||||
<th>[% description_title %]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% fields_list_for_body %]
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
@@ -1,2 +0,0 @@
|
||||
Route::get('[% prefix %][% version %]', [[% controller_name %]::class, 'index'])
|
||||
->name('[% index_route_name %]');
|
||||
@@ -1,2 +0,0 @@
|
||||
Route::get('[% prefix %][% version %]', '[% controller_name %]@index')
|
||||
->name('[% index_route_name %]');
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace [% namespace %];
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
|
||||
/**
|
||||
* Valid versions
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $versions = [
|
||||
'[% api_version_number %]',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get a valid version from the available list.
|
||||
*
|
||||
* @param string $version
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getVersion($version)
|
||||
{
|
||||
if (in_array($version, $this->versions)) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
return end($this->versions);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user