Compare commits

..

19 Commits

Author SHA1 Message Date
arifal
7994a62cea change name dashboard 2025-02-19 06:24:44 +07:00
arifal
3a09e2e68a Merge branch 'bug-fix/tourisms' into feat/dashboard-kekurangan-potensi 2025-02-19 06:17:16 +07:00
arifal
116dc1c8c7 add dashboard potential 2025-02-19 06:15:35 +07:00
@jamaludinarifrohman6661
f10bc153b4 fix: tourisms 2025-02-19 01:39:27 +07:00
@jamaludinarifrohman6661
06a3bb8c8b fix:pariwisata and report pariwisata 2025-02-19 01:07:20 +07:00
arifal
6c936d4c14 add more handle if zero devided 2025-02-18 03:40:20 +07:00
arifal
d4d0a485cd fix vite resources 2025-02-18 03:32:00 +07:00
arifal
864fb26471 add local db backup 2025-02-18 02:58:11 +07:00
arifal
fd97a34344 add vite resources 2025-02-18 02:50:34 +07:00
arifal
1dd971fb73 create update tourisms 2025-02-18 02:45:39 +07:00
arifal
aff31e08ef merge feature umkm 2025-02-18 00:46:51 +07:00
@jamaludinarifrohman6661
2fb8aeceaa feature: viewnya ketinggalan 2025-02-18 00:35:50 +07:00
@jamaludinarifrohman6661
ecc243d1cc Upload Pariwisata dan report pariwisata 2025-02-17 23:58:31 +07:00
arifal
beac71d182 add business industry crud 2025-02-17 18:40:00 +07:00
@jamaludinarifrohman6661
8c236c460d feature: umkm crud and add template file for reklame 2025-02-17 13:03:54 +07:00
arifal hidayat
154b7f40df add sync data setting 2025-02-17 01:52:49 +07:00
arifal
59e9431b2d fetch data from data setting and make seeder realisasi terbit, menunggu klik dpmptsp, proses dinas teknis 2025-02-14 18:28:14 +07:00
arifal
074edc607d add hardcode number for realisasi terbit, proses dinas teknis, menunggu klik dashboards 2025-02-14 17:04:49 +07:00
@jamaludinarifrohman6661
41ddbaef24 feature/create-migration-and-crud-api 2025-02-12 16:46:06 +07:00
98 changed files with 8603 additions and 3130 deletions

View File

@@ -53,7 +53,7 @@ class AdvertisementController extends Controller
$advertisement->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $advertisement->district_code)->first();
$advertisement->district_name = $district ? $district->district_name : null;
$advertisement->district_name = $district ? $district->district_name : null;
return $advertisement;
});
@@ -75,10 +75,10 @@ class AdvertisementController extends Controller
{
$data = $request->validated();
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->value('village_code');
// Cari district_code berdasarkan district_name
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
// Tambahkan village_code dan district_code ke data
$data['village_code'] = $village_code;
@@ -142,10 +142,10 @@ class AdvertisementController extends Controller
{
$data = $request->validated();
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->value('village_code');
// Cari district_code berdasarkan district_name
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
// Tambahkan village_code dan district_code ke data
$data['village_code'] = $village_code;
@@ -196,4 +196,17 @@ class AdvertisementController extends Controller
return response()->json($results);
}
public function downloadExcelAdvertisement()
{
$filePath = storage_path('app/public/templates/template_reklame.xlsx');
// 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);
}
}

View File

@@ -0,0 +1,120 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\BusinessIndustryRequest;
use App\Imports\BusinessIndustriesImport;
use App\Models\BusinessOrIndustry;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use \Illuminate\Support\Facades\Validator;
class BusinessOrIndustriesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$query = BusinessOrIndustry::query()->orderBy('id', 'desc');
if ($request->has("search") && !empty($request->get("search"))) {
$search = $request->get("search");
info($request); // Debugging log
$query->where(function ($q) use ($search) {
$q->where("nop", "LIKE", "%{$search}%")
->orWhere("nama_kecamatan", "LIKE", "%{$search}%")
->orWhere("nama_kelurahan", "LIKE", "%{$search}%");
});
}
return response()->json($query->paginate());
}
/**
* 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(BusinessIndustryRequest $request, string $id)
{
try{
$data = BusinessOrIndustry::findOrFail($id);
$data->update($request->validated());
return response()->json(['message' => 'Data updated successfully.'], 200);
}catch(\Exception $e){
\Log::error($e->getMessage());
return response()->json(['message' => 'Failed to update data'],500);
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
try{
$data = BusinessOrIndustry::findOrFail($id);
$data->delete();
return response()->json(['message' => 'Data deleted successfully.'], 200);
}catch(\Exception $e){
\Log::error($e->getMessage());
return response()->json(['message' => 'Failed to delete data'],500);
}
}
public function upload(Request $request){
if ($request->hasFile('file')) {
$file = $request->file('file');
}
// Validasi file
$validator = Validator::make($request->all(), [
'file' => 'required|mimes:xlsx,xls|max:102400', // Max 100MB
]);
if ($validator->fails()) {
return response()->json([
'message' => 'File validation failed.',
'errors' => $validator->errors()
], 400);
}
try {
// Ambil file dari request
$file = $request->file('file');
// Menggunakan Laravel Excel untuk mengimpor file
Excel::import(new BusinessIndustriesImport, $file);
// Jika sukses, kembalikan respons sukses
return response()->json([
'message' => 'File uploaded and imported successfully!'
], 200);
} catch (\Exception $e) {
// Jika ada error, kembalikan error response
return response()->json([
'message' => 'Error during file import.',
'error' => $e->getMessage()
], 500);
}
}
}

View File

@@ -6,6 +6,7 @@ use App\Enums\ImportDatasourceStatus;
use App\Http\Controllers\Controller;
use App\Http\Requests\PbgTaskMultiStepRequest;
use App\Http\Resources\PbgTaskResource;
use App\Models\DataSetting;
use App\Models\ImportDatasource;
use App\Models\PbgTask;
use App\Models\PbgTaskGoogleSheet;
@@ -109,18 +110,55 @@ class PbgTaskController extends Controller
}
public function syncPbgFromGoogleSheet(){
$import_datasource = ImportDatasource::create([
"message" => "initialization",
"response_body" => null,
"status" => ImportDatasourceStatus::Processing->value,
]);
try{
$totalRowCount = $this->googleSheetService->getLastRowByColumn("C");
$sheetData = $this->googleSheetService->getSheetDataCollection($totalRowCount);
$sheet_big_data = $this->googleSheetService->get_data_by_sheet();
$data_setting_result = []; // Initialize result storage
$found_section = null; // Track which section is found
foreach ($sheet_big_data as $row) {
// Check for section headers
if (in_array("•PROSES PENERBITAN:", $row)) {
$found_section = "MENUNGGU_KLIK_DPMPTSP";
} elseif (in_array("•BERKAS AKTUAL TERVERIFIKASI DINAS TEKNIS 2024:", $row)) {
$found_section = "REALISASI_TERBIT_PBG";
} elseif (in_array("•TERPROSES DI DPUTR: belum selesai rekomtek'", $row)) {
$found_section = "PROSES_DINAS_TEKNIS";
}
// If a section is found and we reach "Grand Total", save the corresponding values
if ($found_section && isset($row[0]) && trim($row[0]) === "Grand Total") {
if ($found_section === "MENUNGGU_KLIK_DPMPTSP") {
$data_setting_result["MENUNGGU_KLIK_DPMPTSP_COUNT"] = $row[2] ?? null;
$data_setting_result["MENUNGGU_KLIK_DPMPTSP_SUM"] = $row[3] ?? null;
} elseif ($found_section === "REALISASI_TERBIT_PBG") {
$data_setting_result["REALISASI_TERBIT_PBG_COUNT"] = $row[2] ?? null;
$data_setting_result["REALISASI_TERBIT_PBG_SUM"] = $row[4] ?? null;
} elseif ($found_section === "PROSES_DINAS_TEKNIS") {
$data_setting_result["PROSES_DINAS_TEKNIS_COUNT"] = $row[2] ?? null;
$data_setting_result["PROSES_DINAS_TEKNIS_SUM"] = $row[3] ?? null;
}
// Reset section tracking after capturing "Grand Total"
$found_section = null;
}
}
foreach ($data_setting_result as $key => $value) {
DataSetting::updateOrInsert(
["key" => $key], // Find by key
["value" => $value] // Update or insert value
);
}
$mapToUpsert = [];
$count = 0;
$import_datasource = ImportDatasource::create([
"message" => "initialization",
"response_body" => null,
"status" => ImportDatasourceStatus::Processing->value,
]);
foreach($sheetData as $data){
$mapToUpsert[] =
[

View File

@@ -0,0 +1,130 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\Tourism;
use Illuminate\Http\Request;
use App\Http\Requests\TourismRequest;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use App\Http\Resources\TourismResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\TourismImport;
use Illuminate\Support\Facades\Storage;
class TourismController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$perPage = $request->input('per_page', 15);
$search = $request->input('search', '');
$query = Tourism::query();
$tourisms = $query->paginate($perPage);
$tourisms->getCollection()->transform(function ($tourisms) {
$village = DB::table('villages')->where('village_code', $tourisms->village_code)->first();
$tourisms->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $tourisms->district_code)->first();
$tourisms->district_name = $village ? $village->village_name : null;
return $tourisms;
});
return response()->json([
'data' => TourismResource::collection($tourisms),
'meta' => [
'total' => $tourisms->total(),
'per_page' => $tourisms->perPage(),
'current_page' => $tourisms->currentPage(),
'last_page'=>$tourisms->lastPage(),
]
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(TourismRequest $request): Tourism
{
$data = $request->validated();
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
$data['district_code'] = $district_code;
$data['village_code'] = $village_code;
return Tourism::create($data);
}
/**
* Import advertisements from Excel
*/
public function importFromFile(Request $request)
{
//Validasi file
$validator = Validator::make($request->all(), [
'file' => 'required|mimes:xlsx, xls|max:10240'
]);
if ($validator->fails()) {
return response()->json([
'message'=>'File validation failed.',
'errors'=>$validator->errors()
], 400);
}
try {
$file = $request->file('file');
Excel::import(new TourismImport, $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(Tourism $tourism): Tourism
{
return $tourism;
}
/**
* Update the specified resource in storage.
*/
public function update(TourismRequest $request, Tourism $tourism): Tourism
{
$data = $request->validated();
// Cari district_code berdasarkan district_name
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
// Tambahkan village_code dan district_code ke data
$data['village_code'] = $village_code;
$data['district_code'] = $district_code;
$tourism->update($data);
return $tourism;
}
public function destroy(Tourism $tourism): Response
{
$tourism->delete();
return response()->noContent();
}
}

View File

@@ -0,0 +1,189 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\Umkm;
use Illuminate\Http\Request;
use App\Http\Requests\UmkmRequest;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use App\Http\Resources\UmkmResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\UmkmImport;
use Illuminate\Support\Facades\Storage;
class UmkmController 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 = Umkm::query();
$umkm = $query->paginate($perPage);
$umkm->getCollection()->transform(function ($umkm) {
$village = DB::table('villages')->where('village_code', $umkm->village_code)->first();
$umkm->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $umkm->district_code)->first();
$umkm->district_name = $district ? $district->district_name : null;
$business_scale = DB::table('business_scale')->where('id', $umkm->business_scale_id)->first();
$umkm->business_scale = $business_scale ? $business_scale->business_scale : null;
$permit_status = DB::table('permit_status')->where('id', $umkm->permit_status_id)->first();
$umkm->permit_status = $permit_status ? $permit_status->permit_status : null;
$business_form = DB::table('business_form')->where('id', $umkm->business_form_id)->first();
$umkm->business_form = $business_form ? $business_form->business_form : null;
return $umkm;
});
return response()->json([
'data' => UmkmResource::collection($umkm),
'meta' => [
'total' => $umkm->total(),
'per_page' => $umkm->perPage(),
'current_page' => $umkm->currentPage(),
'last_page' => $umkm->lastPage(),
]
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(UmkmRequest $request): Umkm
{
info($request);
$data = $request->validated();
// Cari kode berdasarkan nama
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
$business_scale_id = DB::table('business_scale')->where('id', $data['business_scale_id'])->value('id');
$permit_status_id = DB::table('permit_status')->where('id', $data['permit_status_id'])->value('id');
$business_form_id = DB::table('business_form')->where('id', $data['business_form_id'])->value('id');
info($business_scale_id);
// Update data dengan kode yang ditemukan
$data['village_code'] = $village_code;
$data['district_code'] = $district_code;
$data['land_area'] = (double) $request['land_area'];
$data['business_scale_id'] = (int) $business_scale_id;
$data['permit_status_id'] = (int) $permit_status_id;
$data['business_form_id'] = (int) $business_form_id;
info($data);
// Simpan ke database
return Umkm::create($data);
}
/**
* Import advertisements from Excel or CSV.
*/
public function importFromFile(Request $request)
{
// Validasi file
$validator = Validator::make($request->all(), [
'file' => 'required|mimes:xlsx, xls|max:10240',
]);
if ($validator->fails()) {
return response()->json([
'message' => 'File validation failed.',
'errors' => $validator->errors()
], 400);
}
try {
// Ambil file dari request
$file = $request->file('file');
// Menggunakan Laravel Excel untuk mengimpor file
Excel::import(new UmkmImport, $file);
// Jika sukses, kembalikan response sukses
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(Umkm $umkm): Umkm
{
return $umkm;
}
/**
* Update the specified resource in storage.
*/
public function update(UmkmRequest $request, Umkm $umkm): Umkm
{
info($request);
$data = $request->validated();
// Cari district_code berdasarkan district_name
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
$business_scale_id = DB::table('business_scale')->where('id', $data['business_scale_id'])->value('id');
$permit_status_id = DB::table('permit_status')->where('id', $data['permit_status_id'])->value('id');
$business_form_id = DB::table('business_form')->where('id', $data['business_form_id'])->value('id');
// Tambahkan village_code dan district_code ke data
$data['village_code'] = $village_code;
$data['district_code'] = $district_code;
$data['land_area'] = (double) $request['land_area'];
$data['business_scale_id'] = (int) $business_scale_id;
$data['permit_status_id'] = (int) $permit_status_id;
$data['business_form_id'] = (int) $business_form_id;
// Log data setelah transformasi
info($data);
$umkm->update($data);
return $umkm;
}
public function destroy(Umkm $umkm): Response
{
$umkm->delete();
return response()->noContent();
}
public function downloadExcelUmkm()
{
$filePath = storage_path('app/public/templates/template_umkm.xlsx');
// 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);
}
}

View File

@@ -4,9 +4,11 @@ namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use App\Http\Requests\UsersRequest;
use App\Http\Resources\UserResource;
use App\Models\User;
use App\Traits\GlobalApiResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
@@ -35,4 +37,27 @@ class UsersController extends Controller
$request->user()->tokens()->delete();
return response()->json(['message' => 'logged out successfully']);
}
public function store(UsersRequest $request){
$validate_data = $request->validated();
DB::beginTransaction();
try{
$user = User::create([
'name' => $validate_data->name,
'email' => $validate_data->email,
'password' => Hash::make($validate_data->password),
'firstname' => $validate_data->firstname,
'lastname' => $validate_data->lastname,
'position' => $validate_data->position
]);
$user->roles()->attach($request->role_id);
DB::commit();
return response()->json(['message' => 'Successfully created'],201);
}catch(\Exception $e){
DB::rollBack();
return response()->json(['message' => $e->getMessage()],500);
};
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace App\Http\Controllers;
use App\Models\BusinessOrIndustry;
use Illuminate\Http\Request;
class BusinessOrIndustriesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('business-industries.index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view("business-industries.create");
}
/**
* 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)
{
$data = BusinessOrIndustry::findOrFail($id);
return view('business-industries.edit', compact('data'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Http\Controllers\Dashboards;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class LackOfPotentialController extends Controller
{
public function lack_of_potential(){
return view('dashboards.lack_of_potential');
}
}

View File

@@ -0,0 +1,145 @@
<?php
namespace App\Http\Controllers\Data;
use App\Http\Controllers\Controller;
use App\Models\Tourism;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class TourismController extends Controller
{
/**
* Display a listing of the resource
*/
public function index()
{
return view('data.tourisms.index');
}
/**
* show the form for creating a new rsource.
*/
public function bulkCreate()
{
return view('data.tourisms.form-upload');
}
/**
* Show th form for creating a new resource
*/
public function create()
{
$title = 'Pariwisata';
$subtitle = 'Create Data';
// Mengambil data untuk dropdown
$dropdownOptions = [
'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'),
'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code')
];
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/tourisms');
return view('data.tourisms.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
}
/**
* show the form for editing the specified resource.
*/
public function edit($id)
{
$title = 'Pariwisata';
$subtitle = 'Create Data';
$modelInstance = Tourism::find($id);
// Pastikan model ditemukan
if (!$modelInstance) {
return redirect()->route('tourisms.index') ->with('error', 'Pariwisata tidak ditemukan');
}
// Mengambil dan memetakan village_name dan district_name
$village = DB::table('villages')->where('village_code', $modelInstance->village_code)->first();
$modelInstance->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $modelInstance->district_code)->first();
$modelInstance->district_name = $district ? $district->district_name : null;
$dropdownOptions = [
'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'),
'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code')
];
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/tourisms');
return view('data.tourisms.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
}
private function getFields()
{
return [
"project_id" => "ID Proyek",
"project_type_id" => "Jenis Proyek",
"nib" => "NIB",
"business_name" => "Nama Perusahaan",
"oss_publication_date" => "Tanggal Terbit OSS",
"investment_status_description" => "Uraian Status Penanaman Modal",
"business_form" => "Uraian Jenis Perusahaan",
"project_risk" => "Risiko Proyek",
"project_name" => "Nama Proyek",
"business_scale" => "Uraian Skala Usaha",
"business_address" => "Alamat Usaha",
"district_name" => "Kecamatan",
"village_name" => "Desa",
"longitude" => "Longitude",
"latitude" => "Latitude",
"project_submission_date" => "Tanggal Pengajuan Project",
"kbli" => "KBLI",
"kbli_title" => "Judul KBLI",
"supervisory_sector" => "Sektor Pembina",
"user_name" => "Nama User",
"email" => "Email",
"contact" => "Kontak",
"land_area_in_m2" => "Luas Tanah (m2)",
"investment_amount" => "Jumlah Investasi",
"tki" => "TKI",
];
}
private function getFieldTypes()
{
return [
"project_id" => "text",
"project_type_id" => "text",
"nib" => "text",
"business_name" => "text",
"oss_publication_date" => "date",
"investment_status_description" => "text",
"business_form" => "text",
"project_risk" => "text",
"project_name" => "text",
"business_scale" => "text",
"business_address" => "text",
"district_name" => "combobox",
"village_name" => "combobox",
"longitude" => "text",
"latitude" => "text",
"project_submission_date" => "date",
"kbli" => "text",
"kbli_title" => "text",
"supervisory_sector" => "text",
"user_name" => "text",
"email" => "text",
"contact" => "text",
"land_area_in_m2" => "text",
"investment_amount" => "text",
"tki" => "text",
];
}
}

View File

@@ -0,0 +1,149 @@
<?php
namespace App\Http\Controllers\Data;
use App\Http\Controllers\Controller;
use App\Models\Umkm;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class UmkmController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('data.umkm.index');
}
/**
* Show the form for creating a new resource.
*/
public function bulkCreate()
{
return view('data.umkm.form-upload');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$title = 'UMKM';
$subtitle = 'Create Data';
// Mengambil data untuk dropdown
$dropdownOptions = [
'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'),
'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'),
'business_scale_id' => DB::table('business_scale')->orderBy('business_scale')->pluck('business_scale', 'id'),
'permit_status_id' => DB::table('permit_status')->orderBy('permit_status')->pluck('permit_status', 'id'),
'business_form_id' => DB::table('business_form')->orderBy('business_form')->pluck('business_form', 'id')
];
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/umkm');
return view('data.umkm.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$title = 'UMKM';
$subtitle = 'Update Data';
$modelInstance = Umkm::find($id);
// Pastikan model ditemukan
if (!$modelInstance) {
return redirect()->route('umkm.index')->with('error', 'Umkm not found');
}
// Mengambil dan memetakan village_name dan district_name
$village = DB::table('villages')->where('village_code', $modelInstance->village_code)->first();
$modelInstance->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $modelInstance->district_code)->first();
$modelInstance->district_name = $district ? $district->district_name : null;
$business_scale = DB::table('business_scale')->where('id', $modelInstance->business_scale_id)->first();
$modelInstance->business_scale_id = $business_scale ? $business_scale->id : null;
$permit_status = DB::table('permit_status')->where('id', $modelInstance->permit_status_id)->first();
$modelInstance->permit_status_id = $permit_status ? $permit_status->id : null;
$business_form = DB::table('business_form')->where('id', $modelInstance->business_form_id)->first();
$modelInstance->business_form_id = $business_form ? $business_form->id : null;
// dd($modelInstance['business_form_id']);
// Mengambil data untuk dropdown
$dropdownOptions = [
'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'),
'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'),
'business_scale_id' => DB::table('business_scale')->orderBy('business_scale')->pluck('business_scale', 'id'),
'permit_status_id' => DB::table('permit_status')->orderBy('permit_status')->pluck('permit_status', 'id'),
'business_form_id' => DB::table('business_form')->orderBy('business_form')->pluck('business_form', 'id')
];
info("AdvertisementController@edit diakses dengan Model Instance: $modelInstance");
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/umkm');
// dd($modelInstance->business_form_id, $dropdownOptions['business_form']);
return view('data.umkm.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
}
private function getFields()
{
return [
"business_name" => "Nama Usaha",
"business_address" => "Alamat Usaha",
"business_desc" => "Deskripsi Usaha",
"business_contact" => "Kontak Usaha",
"business_id_number" => "NIB",
"business_scale_id" => "Skala Usaha",
"owner_id" => "NIK",
"owner_name" => "Nama Pemilik",
"owner_address" => "Alamat Pemilik",
"owner_contact" => "Kontak Pemilik",
"business_type" => "Jenis Usaha",
"district_name" => "Kecamatan",
"village_name" => "Desa",
"number_of_employee" => "Jumlah Karyawan",
"land_area" => "Luas Tanah",
"permit_status_id" => "Ijin Status",
"business_form_id" => "Bisnis Form",
"revenue" => "Omset"
];
}
private function getFieldTypes()
{
return [
"business_name" => "text",
"business_address" => "text",
"business_desc" => "textarea",
"business_contact" => "text",
"business_id_number" => "text",
"business_scale_id" => "select",
"owner_id" => "text",
"owner_name" => "text",
"owner_address" => "text",
"owner_contact" => "text",
"business_type" => "text",
"district_name" => "combobox",
"village_name" => "combobox",
"number_of_employee" => "text",
"land_area" => "text",
"permit_status_id" => "select",
"business_form_id" => "select",
"revenue" => "text"
];
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Master;
use App\Http\Controllers\Controller;
use App\Http\Requests\UsersRequest;
use App\Models\Role;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
@@ -28,7 +29,7 @@ class UsersController extends Controller
$roles = Role::all();
return view('master.users.create', compact('roles'));
}
public function store(Request $request){
public function store(UsersRequest $request){
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
@@ -39,6 +40,7 @@ class UsersController extends Controller
'role_id' => 'required|exists:roles,id'
]);
DB::beginTransaction();
try{
$user = User::create([

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Report;
use App\Http\Controllers\Controller;
use App\Models\TourismBasedKBLI;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class ReportTourismController extends Controller
{
/**
* Display a listring of the resource
*/
public function index()
{
$tourismBasedKBLI = TourismBasedKBLI::all();
info($tourismBasedKBLI);
return view('report.tourisms.index', compact('tourismBasedKBLI'));
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class BusinessIndustryRequest 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 [
'nama_kecamatan' => 'required|string|max:255',
'nama_kelurahan' => 'required|string|max:255',
'nop' => 'required|string|max:255|unique:business_or_industries,nop,' . $this->route('api_business_industry'),
'nama_wajib_pajak' => 'required|string|max:255',
'alamat_wajib_pajak' => 'nullable|string|max:255',
'alamat_objek_pajak' => 'required|string|max:255',
'luas_bumi' => 'required|numeric',
'luas_bangunan' => 'required|numeric',
'njop_bumi' => 'required|numeric',
'njop_bangunan' => 'required|numeric',
'ketetapan' => 'required|string|max:255',
'tahun_pajak' => 'required|integer|min:1900|max:' . date('Y'),
];
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class TourismRequest 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 [
'project_id' => 'required|string',
'project_type_id' => 'required|string',
'nib' => 'required|string',
'business_name' => 'required|string',
'oss_publication_date' => 'required',
'investment_status_description' => 'required|string',
'business_form' => 'required|string',
'project_risk' => 'required|string',
'project_name' => 'required|string',
'business_scale' => 'required|string',
'business_address' => 'required|string',
'district_name' => 'required',
'village_name' => 'required',
'longitude' => 'required|string',
'latitude' => 'required|string',
'project_submission_date' => 'required',
'kbli' => 'required|string',
'kbli_title' => 'required|string',
'supervisory_sector' => 'required|string',
'user_name' => 'required|string',
'email' => 'required|string',
'contact' => 'required|string',
'land_area_in_m2' => 'required|string',
'investment_amount' => 'required|string',
'tki' => 'required|string',
];
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UmkmRequest 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 [
'business_name' => 'required|string',
'business_address' => 'required|string',
'business_desc' => 'required|string',
'business_contact' => 'required|string',
'business_id_number' => 'string',
'business_scale_id' => 'required',
'owner_id' => 'required|string',
'owner_name' => 'required|string',
'owner_address' => 'required|string',
'owner_contact' => 'required|string',
'business_type' => 'required|string',
'business_form_id' => 'required|string',
'revenue' => 'required|numeric|between:0,999999999999999999.99',
'village_name' => 'required|string',
'district_name' => 'required',
'number_of_employee' => 'required',
'permit_status_id' => 'required',
'land_area' => 'required|integer|between:0,99999999999',
];
}
/**
* Get the validation messages for the request.
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'business_name.required' => 'Nama usaha wajib diisi.',
'business_name.string' => 'Nama usaha harus berupa teks.',
'business_address.required' => 'Alamat usaha wajib diisi.',
'business_address.string' => 'Alamat usaha harus berupa teks.',
'business_desc.required' => 'Deskripsi usaha wajib diisi.',
'business_desc.string' => 'Deskripsi usaha harus berupa teks.',
'business_contact.required' => 'Kontak usaha wajib diisi.',
'business_contact.string' => 'Kontak usaha harus berupa teks.',
'business_id_number.string' => 'Nomor ID usaha harus berupa teks.',
'business_scale_id.required' => 'Skala usaha wajib diisi.',
'owner_id.required' => 'ID pemilik wajib diisi.',
'owner_id.string' => 'ID pemilik harus berupa teks.',
'owner_name.required' => 'Nama pemilik wajib diisi.',
'owner_name.string' => 'Nama pemilik harus berupa teks.',
'owner_address.required' => 'Alamat pemilik wajib diisi.',
'owner_address.string' => 'Alamat pemilik harus berupa teks.',
'owner_contact.required' => 'Kontak pemilik wajib diisi.',
'owner_contact.string' => 'Kontak pemilik harus berupa teks.',
'business_type.required' => 'Jenis usaha wajib diisi.',
'business_type.string' => 'Jenis usaha harus berupa teks.',
'business_form.required' => 'Bentuk usaha wajib diisi.',
'business_form.string' => 'Bentuk usaha harus berupa teks.',
'revenue.required' => 'Omset wajib diisi.',
'revenue.numeric' => 'Omset harus berupa angka yang valid.',
'revenue.between' => 'Omset harus berada di antara 0 dan 9.999.999.999,99.',
'village_name.required' => 'Nama desa wajib diisi.',
'village_name.string' => 'Nama desa harus berupa teks.',
'district_name.required' => 'Nama distrik wajib diisi.',
'number_of_employee.required' => 'Jumlah karyawan wajib diisi.',
'permit_status_id.required' => 'Status izin wajib diisi.',
'land_area.required' => 'Luas lahan wajib diisi.',
'land_area.integer' => 'Luas lahan harus berupa angka bulat.',
'land_area.between' => 'Luas lahan harus berada di antara 0 dan 99.999.999.999.',
];
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class UsersRequest 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
{
$userId = $this->route('user'); // Get user ID from route (used in update)
return [
'name' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'email',
'max:255',
Rule::unique('users')->ignore($userId), // Ignore the user's own email when updating
],
'password' => [$this->isMethod('post') ? 'required' : 'nullable', 'confirmed', 'max:255'],
'firstname' => ['required', 'string', 'max:255'],
'lastname' => ['required', 'string', 'max:255'],
'position' => ['required', 'string', 'max:255'],
'role_id' => ['required', 'exists:roles,id'],
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class TourismResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class UmkmResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
}

View File

@@ -47,7 +47,7 @@ class AdvertisementImport implements ToCollection
$districtCode = $districts[$districtName] ?? null;
$listTrueVillage = DB::table('villages')
->where('district_code', $districtCode) // Perbaikan pada where()
->where('district_code', $districtCode)
->get()
->mapWithKeys(function ($item) {
return [strtolower(trim($item->village_name)) => [

View File

@@ -0,0 +1,39 @@
<?php
namespace App\Imports;
use App\Models\BusinessOrIndustry;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\ToCollection;
use Illuminate\Support\Collection;
class BusinessIndustriesImport implements ToCollection
{
/**
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function collection(Collection $rows)
{
foreach ($rows->skip(1) as $row){
$clean_nop = preg_replace('/[^A-Za-z0-9]/', '', $row[2]);
if (!BusinessOrIndustry::where('nop', $clean_nop)->exists()) {
BusinessOrIndustry::create([
'nama_kecamatan' => $row[0],
'nama_kelurahan' => $row[1],
'nop' => $clean_nop, // Store cleaned 'nop'
'nama_wajib_pajak' => $row[3],
'alamat_wajib_pajak' => $row[4],
'alamat_objek_pajak' => $row[5],
'luas_bumi' => $row[6],
'luas_bangunan' => $row[7],
'njop_bumi' => $row[8],
'njop_bangunan' => $row[9],
'ketetapan' => $row[10],
'tahun_pajak' => $row[11],
]);
}
}
}
}

View File

@@ -0,0 +1,122 @@
<?php
namespace App\Imports;
use App\Models\Tourism;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Illuminate\Support\Facades\DB;
use DateTime;
use Carbon\Carbon;
class TourismImport implements ToCollection
{
protected static $processed = false;
/**
* Process each row in the file.
*/
public function collection(Collection $rows)
{
if (self::$processed) {
return;
}
self::$processed = true;
if ($rows->isEmpty())
{
return;
}
// Ambil data districts dengan normalisasi nama
$districts = DB::table('districts')
->get()
->mapWithKeys(function ($item) {
return [strtolower(trim($item->district_name)) => $item->district_code];
})
->toArray();
// Cari header secara otomatis
$header = $rows->first();
$headerIndex = collect($header)->search(fn($value) => !empty($value));
// Pastikan header ditemukan
if ($headerIndex === false) {
return;
}
foreach ($rows->skip(1) as $row) {
// Normalisasi nama kecamatan dan desa
$districtName = strtolower(trim(str_replace('Kecamatan', '', $row[12])));
$villageName = strtolower(trim($row[13]));
// Cari distric_code dari table districts
$districtCode = $districts[$districtName] ?? null;
$listTrueVillage = DB::table('villages')
->where('district_code', $districtCode)
->get()
->mapWithKeys(function ($item) {
return [strtolower(trim($item->village_name)) => [
'village_code' => $item->village_code,
'district_code' => $item->district_code
]];
})
->toArray();
// 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')
->addDays($excelSerialDate)
->format('Y-m-d H:i:s');
} else {
$projectSubmissionDate = Carbon::createFromFormat('m/d/Y', $excelSerialDate)
->format('Y-m-d H:i:s');
}
info("Tanggal dikonversi: " . $projectSubmissionDate);
$dataToInsert[] = [
'project_id' => $row[1],
'project_type_id' => $row[2],
'nib' => $row[3],
'business_name' => $row[4],
'oss_publication_date' => DateTime::createFromFormat('d/m/Y', $row[5]),
'investment_status_description' => $row[6],
'business_form' => $row[7],
'project_risk' => $row[8],
'project_name' => $row[9],
'business_scale' => $row[10],
'business_address' => $row[12],
'district_code' => $districtCode,
'village_code' => $villageCode,
'longitude' => $row[14],
'latitude' => (string) $row[15],
'project_submission_date' => $projectSubmissionDate,
'kbli'=> $row[17],
'kbli_title'=>$row[18],
'supervisory_sector'=>$row[19],
'user_name'=>$row[20],
'email'=>$row[21],
'contact'=>$row[22],
'land_area_in_m2'=>$row[23],
'investment_amount'=>$row[24],
'tki'=>$row[25]
];
}
if(!empty($dataToInsert)) {
Tourism::insert($dataToInsert);
} else {
return;
}
}
}

View File

@@ -0,0 +1,98 @@
<?php
namespace App\Imports;
use App\Models\Umkm;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Illuminate\Support\Facades\DB;
class UmkmImport implements ToCollection
{
protected static $processed = false;
/**
* Process each row in the file.
*/
public function collection(Collection $rows)
{
if (self::$processed) {
return;
}
self::$processed = true;
if ($rows->isEmpty())
{
return;
}
// Ambil data districts dengan normalisasi nama
$districts = DB::table('districts')
->get()
->mapWithKeys(function ($item) {
return [strtolower(trim($item->district_name)) => $item->district_code];
})
->toArray();
// Cari header secara otomatis
$header = $rows->first();
$headerIndex = collect($header)->search(fn($value) => !empty($value));
// Pastikan header ditemukan
if ($headerIndex === false) {
return;
}
info($rows);
foreach ($rows->skip(1) as $row) {
// Normalisasi nama kecamatan dan desa
$districtName = strtolower(trim(str_replace('Kecamatan', '', $row[14])));
$villageName = strtolower(trim($row[13]));
// Cari distric_code dari table districts
$districtCode = $districts[$districtName] ?? null;
$listTrueVillage = DB::table('villages')
->where('district_code', $districtCode)
->get()
->mapWithKeys(function ($item) {
return [strtolower(trim($item->village_name)) => [
'village_code' => $item->village_code,
'district_code' => $item->district_code
]];
})
->toArray();
// ambil village code yang village_name sama dengan $villageName
$villageCode = $listTrueVillage[$villageName]['village_code'] ?? '0000';
$dataToInsert[] = [
'business_name' => $row[0],
'business_address' => $row[1],
'business_desc' => $row[2],
'business_contact' => $row[3],
'business_id_number' => $row[4],
'business_scale_id' => $row[5],
'owner_id' => $row[6],
'owner_name' => $row[7],
'owner_address' => $row[8],
'owner_contact' => $row[9],
'business_type' => $row[10],
'business_form_id' => $row[11],
'revenue' => $row[12],
'village_code' => $villageCode,
'district_code' => $districtCode,
'number_of_employee' => $row[15],
'land_area' => $row[16],
'permit_status_id' => $row[17],
];
}
info($dataToInsert);
if (!empty($dataToInsert)) {
Umkm::insert($dataToInsert);
} else {
return;
}
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class BusinessOrIndustry extends Model
{
protected $table = "business_or_industries";
protected $fillable = [
'nama_kecamatan',
'nama_kelurahan',
'nop',
'nama_wajib_pajak',
'alamat_wajib_pajak',
'alamat_objek_pajak',
'luas_bumi',
'luas_bangunan',
'njop_bumi',
'njop_bangunan',
'ketetapan',
'tahun_pajak',
];
}

55
app/Models/Tourism.php Normal file
View File

@@ -0,0 +1,55 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Class Tourism
*
* @property $id
* @property $created_at
* @property $updated_at
* @property $project_id
* @property $project_type_id
* @property $nib
* @property $business_name
* @property $oss_publication_date
* @property $investment_status_description
* @property $business_form
* @property $project_risk
* @property $project_name
* @property $business_scale
* @property $business_address
* @property $district_code
* @property $village_code
* @property $longitude
* @property $latitude
* @property $project_submission_date
* @property $kbli
* @property $kbli_title
* @property $supervisory_sector
* @property $user_name
* @property $email
* @property $contact
* @property $land_area_in_m2
* @property $investment_amount
* @property $tki
*
* @package App
* @mixin \Illuminate\Database\Eloquent\Builder
*/
class Tourism extends Model
{
protected $perPage = 20;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = ['project_id', 'project_type_id', 'nib', 'business_name', 'oss_publication_date', 'investment_status_description', 'business_form', 'project_risk', 'project_name', 'business_scale', 'business_address', 'district_code', 'village_code', 'longitude', 'latitude', 'project_submission_date', 'kbli', 'kbli_title', 'supervisory_sector', 'user_name', 'email', 'contact', 'land_area_in_m2', 'investment_amount', 'tki'];
}

View File

@@ -0,0 +1,14 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TourismBasedKBLI extends Model
{
protected $table = 'v_tourisms_based_kbli';
protected $primaryKey = null;
public $timestamps = false;
protected $fillable = ['kbli_title', 'total_records'];
}

48
app/Models/Umkm.php Normal file
View File

@@ -0,0 +1,48 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Class Umkm
*
* @property $id
* @property $created_at
* @property $updated_at
* @property $business_name
* @property $business_address
* @property $business_desc
* @property $business_contact
* @property $business_id_number
* @property $business_scale_id
* @property $owner_id
* @property $owner_name
* @property $owner_address
* @property $owner_contact
* @property $business_type
* @property $business_form_id
* @property $revenue
* @property $village_code
* @property $distric_code
* @property $number_of_employee
* @property $land_area
* @property $permit_status_id
*
* @package App
* @mixin \Illuminate\Database\Eloquent\Builder
*/
class Umkm extends Model
{
protected $perPage = 20;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = ['business_name', 'business_address', 'business_desc', 'business_contact', 'business_id_number', 'business_scale_id', 'owner_id', 'owner_name', 'owner_address', 'owner_contact', 'business_type', 'business_form_id', 'revenue', 'village_code', 'district_code', 'number_of_employee', 'land_area', 'permit_status_id'];
}

View File

@@ -140,4 +140,13 @@ class GoogleSheetService
throw $e;
}
}
public function get_data_by_sheet($no_sheet = 1){
$spreadsheet = $this->service->spreadsheets->get($this->spreadsheetID);
$sheets = $spreadsheet->getSheets();
$sheetTitle = $sheets[$no_sheet]->getProperties()->getTitle();
$range = "{$sheetTitle}";
$response = $this->service->spreadsheets_values->get($this->spreadsheetID, $range);
$values = $response->getValues();
return!empty($values)? $values : [];
}
}

View File

@@ -29,10 +29,15 @@ class ServiceSIMBG
*/
public function __construct()
{
$this->email = trim((string) GlobalSetting::where('key','SIMBG_EMAIL')->firstOrFail()->value);
$this->password = trim((string) GlobalSetting::where('key','SIMBG_PASSWORD')->firstOrFail()->value);
$this->simbg_host = trim((string)GlobalSetting::where('key','SIMBG_HOST')->firstOrFail()->value);
$this->fetch_per_page = trim((string)GlobalSetting::where('key','FETCH_PER_PAGE')->firstOrFail()->value);
$settings = GlobalSetting::whereIn('key', [
'SIMBG_EMAIL', 'SIMBG_PASSWORD', 'SIMBG_HOST', 'FETCH_PER_PAGE'
])->pluck('value', 'key');
$this->email = trim((string) ($settings['SIMBG_EMAIL'] ?? ""));
$this->password = trim((string) ($settings['SIMBG_PASSWORD'] ?? ""));
$this->simbg_host = trim((string) ($settings['SIMBG_HOST'] ?? ""));
$this->fetch_per_page = trim((string) ($settings['FETCH_PER_PAGE'] ?? ""));
$this->service_client = new ServiceClient($this->simbg_host);
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class CustomCircle extends Component
{
/**
* Create a new component instance.
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.custom-circle');
}
}

View File

@@ -0,0 +1,46 @@
<?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('umkm', 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('business_name');
$table->string('business_address');
$table->string('business_desc');
$table->string('business_contact');
$table->string('business_id_number')->nullable();
$table->integer('business_scale_id');
$table->string('owner_id');
$table->string('owner_name');
$table->string('owner_address');
$table->string('owner_contact');
$table->string('business_type');
$table->string('business_form');
$table->decimal('revenue');
$table->string('village_code');
$table->integer('distric_code');
$table->integer('number_of_employee');
$table->float('land_area')->nullable();
$table->integer('permit_status_id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('umkm');
}
};

View File

@@ -0,0 +1,29 @@
<?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('business_scale', 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('business_scale');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('business_scale');
}
};

View File

@@ -0,0 +1,29 @@
<?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('permit_status', 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('permit_status');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('permit_status');
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('umkm', function (Blueprint $table) {
$table->dropColumn('business_form');
$table->integer('business_form_id')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('umkm', function (Blueprint $table) {
$table->dropColumn('business_form_id');
$table->string('business_form')->nullable();
});
}
};

View File

@@ -0,0 +1,29 @@
<?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('business_form', 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('business_form');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('business_form');
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('umkm', function (Blueprint $table) {
$table->renameColumn('distric_code', 'district_code');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('umkm', function (Blueprint $table) {
$table->renameColumn('district_code', 'distric_code');
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('umkm', function (Blueprint $table) {
Schema::rename('umkm', 'umkms');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('umkm', function (Blueprint $table) {
Schema::rename('umkm', 'umkms');
});
}
};

View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('umkms', function (Blueprint $table) {
// Mengubah kolom 'revenue' menjadi decimal(20, 2)
$table->decimal('revenue', 20, 2)->change();
// Mengubah kolom 'land_area' menjadi decimal(20, 2)
$table->integer('land_area')->nullable()->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('umkm', function (Blueprint $table) {
// Mengembalikan kolom 'revenue' ke decimal default (jika ada)
$table->decimal('revenue')->change();
// Mengembalikan kolom 'land_area' ke tipe sebelumnya (float atau lainnya)
$table->float('land_area')->nullable()->change();
});
}
};

View File

@@ -0,0 +1,36 @@
<?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('tourism', 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('business_name');
$table->string('project_name');
$table->string('business_address');
$table->string('village_code');
$table->string('land_area');
$table->string('investment_amount');
$table->string('number_of_employee');
$table->string('business_type_id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tourism');
}
};

View File

@@ -0,0 +1,29 @@
<?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('business_type', 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('business_type');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('business_type');
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('tourism', function (Blueprint $table) {
$table->string('district_code')->after('business_address');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('tourism', function (Blueprint $table) {
$table->dropColumn('district_code');
});
}
};

View File

@@ -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('tourism', 'tourisms');
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::rename('tourisms', 'tourism');
}
};

View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('tourisms', function (Blueprint $table) {
$table->integer('project_id')->nullable()->after('id');
$table->string('jenis_proyek')->nullable()->after('project_id');
$table->string('nib')->nullable()->after('jenis_proyek');
$table->integer('business_scale_id')->nullable()->after('project_name');
$table->date('terbit_oss')->nullable()->after('business_name');
$table->string('status_penanaman_modal')->nullable()->after('terbit_oss');
$table->string('business_form')->nullable()->after('status_penanaman_modal');
$table->string('uraian_resiko_proyek')->nullable()->after('business_form');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('tourisms', function (Blueprint $table) {
$table->dropColumn(['project_id', 'jenis_proyek', 'nib', 'business_scale_id', 'terbit_oss',
'status_penanaman_modal', 'business_form', 'uraian_resiko_proyek']);
});
}
};

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('tourisms', function (Blueprint $table) {
$table->string('project_id')->change();
$table->integer('district_code')->change();
$table->integer('business_type_id')->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('tourisms', function (Blueprint $table) {
$table->integer('project_id')->change();
$table->string('district_code')->change();
$table->string('business_type_id')->change();
});
}
};

View File

@@ -0,0 +1,39 @@
<?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('business_or_industries', function (Blueprint $table) {
$table->id();
$table->string('nama_kecamatan');
$table->string('nama_kelurahan');
$table->string('nop')->unique();
$table->string('nama_wajib_pajak');
$table->text('alamat_wajib_pajak')->nullable();
$table->text('alamat_objek_pajak');
$table->decimal('luas_bumi',20,2)->default(0);
$table->decimal('luas_bangunan',20,2)->default(0);
$table->decimal('njop_bumi',20,2)->default(0);
$table->decimal('njop_bangunan',20,2)->default(0);
$table->decimal('ketetapan',20,2)->default(0);
$table->integer('tahun_pajak');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('business_or_industries');
}
};

View File

@@ -0,0 +1,54 @@
<?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::dropIfExists('tourisms');
Schema::create('tourisms', 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('project_id');
$table->string('project_type_id');
$table->string('nib');
$table->string('business_name');
$table->datetime('oss_publication_date');
$table->string('investment_status_description');
$table->string('business_form');
$table->string('project_risk');
$table->string('project_name');
$table->string('business_scale');
$table->string('business_address');
$table->integer('district_code');
$table->integer('village_code');
$table->string('longitude');
$table->string('latitude');
$table->datetime('project_submission_date');
$table->string('kbli');
$table->string('kbli_title');
$table->string('supervisory_sector');
$table->string('user_name');
$table->string('email');
$table->string('contact');
$table->string('land_area_in_m2');
$table->string('investment_amount');
$table->string('tki');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tourisms');
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('tourisms', function (Blueprint $table) {
$table->string('village_code')->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('tourisms', function (Blueprint $table) {
$table->integer('village_code')->change();
});
}
};

View File

@@ -0,0 +1,26 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class BusinessFormSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
DB::table('business_form')->insert([
['business_form' => 'Perseorangan'],
['business_form' => 'Persekutuan'],
['business_form' => 'Koperasi'],
['business_form' => 'CV'],
['business_form' => 'PT'],
['business_form' => 'PTTB'],
['business_form' => 'Perseroan'],
]);
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class BusinessScaleSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
DB::table('business_scale')->insert([
['business_scale' => 'Micro'],
['business_scale' => 'Kecil'],
['business_scale' => 'Menengah'],
]);
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class BusinessTypeSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
DB::table('business_type')->insert([
['business_type' => 'Villas'],
['business_type' => 'Hotels'],
['business_type' => 'Restaurants / Food Stores'],
['business_type' => 'Cafes'],
['business_type' => 'Adventure / Outdoor Activities'],
['business_type' => 'Event Organizers'],
['business_type' => 'Travel & Tours'],
['business_type' => 'Miscellaneous'],
['business_type' => 'Others'],
]);
}
}

View File

@@ -23,7 +23,37 @@ class DataSettingSeeder extends Seeder
"key" => "TATA_RUANG",
"value" => "10000000000",
"type" => "integer"
]
],
[
"key" => "REALISASI_TERBIT_PBG_SUM",
"value" => "1507253788",
"type" => "integer"
],
[
"key" => "REALISASI_TERBIT_PBG_COUNT",
"value" => "88",
"type" => "integer"
],
[
"key" => "MENUNGGU_KLIK_DPMPTSP_SUM",
"value" => "83457536",
"type" => "integer"
],
[
"key" => "MENUNGGU_KLIK_DPMPTSP_COUNT",
"value" => "266",
"type" => "integer"
],
[
"key" => "PROSES_DINAS_TEKNIS_SUM",
"value" => "83457536",
"type" => "integer"
],
[
"key" => "PROSES_DINAS_TEKNIS_COUNT",
"value" => "11",
"type" => "integer"
],
];
foreach ($data_settings as $setting) {

View File

@@ -0,0 +1,22 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class PermitStatusSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
DB::table('permit_status')->insert([
['permit_status' => 'Not Registered'],
['permit_status' => 'Registered'],
['permit_status' => 'Application Process'],
]);
}
}

View File

@@ -67,6 +67,13 @@ class UsersRoleMenuSeeder extends Seeder
"icon" => "mingcute:task-line",
"parent_id" => null,
"sort_order" => 5,
],
[
"name" => "Laporan",
"url" => "/laporan",
"icon" => "mingcute:task-line",
"parent_id" => null,
"sort_order" => 6,
]
];
@@ -84,6 +91,7 @@ class UsersRoleMenuSeeder extends Seeder
$settings = Menu::where('name', 'Settings')->first();
$dataSettings = Menu::where('name', 'Data Settings')->first();
$data = Menu::where('name', 'Data')->first();
$laporan = Menu::where('name', 'Laporan')->first();
// create children menu
$children_menus = [
@@ -101,6 +109,13 @@ class UsersRoleMenuSeeder extends Seeder
"parent_id" => $dashboard->id,
"sort_order" => 2,
],
[
"name" => "Dashboard Potensi",
"url" => "dashboard.lack_of_potential",
"icon" => null,
"parent_id" => $dashboard->id,
"sort_order" => 3,
],
[
"name" => "Users",
"url" => "users.index",
@@ -148,6 +163,34 @@ class UsersRoleMenuSeeder extends Seeder
"url" => "advertisements.index",
"icon" => null,
"parent_id" => $data->id,
"sort_order" => 2,
],
[
"name" => "Usaha atau Industri",
"url" => "business-industries.index",
"icon" => null,
"parent_id" => $data->id,
"sort_order" => 3,
],
[
"name" => "UMKM",
"url" => "umkm.index",
"icon" => null,
"parent_id" => $data->id,
"sort_order" => 4,
],
[
"name" => "Pariwisata",
"url" => "tourisms.index",
"icon" => null,
"parent_id" => $data->id,
"sort_order" => 5,
],
[
"name" => "Lap Pariwisata",
"url" => "tourisms.index",
"icon" => null,
"parent_id" => $laporan->id,
"sort_order" => 1,
],
];
@@ -165,6 +208,11 @@ class UsersRoleMenuSeeder extends Seeder
$setting_dashboard = Menu::where('name', 'Setting Dashboard')->first();
$setting_pbg = Menu::where('name', 'PBG')->first();
$reklame = Menu::where('name', 'Reklame')->first();
$businessIndustries = Menu::where('name', 'Usaha atau Industri')->first();
$pariwisata = Menu::where('name', 'Pariwisata')->first();
$laporan_pariwisata = Menu::where('name', 'Lap Pariwisata')->first();
$umkm = Menu::where('name', 'UMKM')->first();
$lack_of_potentials = Menu::where('name', 'Dashboard Potensi')->first();
// Superadmin gets all menus
$superadmin->menus()->sync([
@@ -174,6 +222,7 @@ class UsersRoleMenuSeeder extends Seeder
$settings->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
$dataSettings->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
$data->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
$laporan->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
// children
$dashboard_pimpinan->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$dashboard_pbg->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
@@ -184,6 +233,11 @@ class UsersRoleMenuSeeder extends Seeder
$setting_dashboard->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$setting_pbg->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$reklame->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$businessIndustries->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$pariwisata->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$laporan_pariwisata->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$umkm->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$lack_of_potentials->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
]);
// Admin gets limited menus

View File

@@ -0,0 +1,5 @@
CREATE VIEW business_type_counts AS
SELECT b.business_type, COUNT(t.id) AS count
FROM tourisms t
JOIN business_type b ON t.business_type_id = b.id
GROUP BY b.business_type;

5886
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +1,36 @@
{
"private": true,
"type": "module",
"scripts": {
"build": "vite build",
"dev": "vite"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"axios": "^1.7.4",
"concurrently": "^9.0.1",
"laravel-vite-plugin": "^1.0",
"postcss": "^8.4.47",
"sass": "^1.81.1",
"tailwindcss": "^3.4.13",
"vite": "^5.0"
},
"dependencies": {
"apexcharts": "^3.44.2",
"big.js": "^6.2.2",
"bootstrap": "^5.3.3",
"countup.js": "^2.3.2",
"dropzone": "^5.9.0",
"flatpickr": "^4.6.13",
"gmaps": "^0.4.25",
"gridjs": "^5.1.0",
"iconify-icon": "^2.1.0",
"jsvectormap": "^1.5.1",
"moment": "^2.29.4",
"node-waves": "^0.7.6",
"quill": "^1.3.7",
"simplebar": "^5.3.9",
"wnumb": "^1.2.0"
}
"private": true,
"type": "module",
"scripts": {
"build": "vite build",
"dev": "vite"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"axios": "^1.7.4",
"concurrently": "^9.0.1",
"laravel-vite-plugin": "^1.0",
"postcss": "^8.4.47",
"sass": "^1.81.1",
"tailwindcss": "^3.4.13",
"vite": "^5.0"
},
"dependencies": {
"apexcharts": "^3.44.2",
"big.js": "^6.2.2",
"bootstrap": "^5.3.3",
"countup.js": "^2.3.2",
"dropzone": "^5.9.0",
"flatpickr": "^4.6.13",
"gmaps": "^0.4.25",
"gridjs": "^5.1.0",
"iconify-icon": "^2.1.0",
"jsvectormap": "^1.5.1",
"moment": "^2.29.4",
"node-waves": "^0.7.6",
"quill": "^1.3.7",
"simplebar": "^5.3.9",
"sweetalert2": "^11.16.0",
"wnumb": "^1.2.0"
}
}

View File

@@ -25,6 +25,13 @@
"__commonjsHelpers-C4iS2aBk.js"
]
},
"_table-generator-DPFVsCqk.js": {
"file": "assets/table-generator-DPFVsCqk.js",
"name": "table-generator",
"imports": [
"_gridjs.umd-BiCNXlqL.js"
]
},
"_world-BH8KG5u4.js": {
"file": "assets/world-BH8KG5u4.js",
"name": "world",
@@ -95,6 +102,33 @@
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/business-industries/create.js": {
"file": "assets/create-CiRhiWZV.js",
"name": "create",
"src": "resources/js/business-industries/create.js",
"isEntry": true,
"imports": [
"_dropzone-B5tMhgFp.js",
"_global-config-9uDKFQ8j.js"
]
},
"resources/js/business-industries/index.js": {
"file": "assets/index-BIXijOG8.js",
"name": "index",
"src": "resources/js/business-industries/index.js",
"isEntry": true,
"imports": [
"_gridjs.umd-BiCNXlqL.js",
"_global-config-9uDKFQ8j.js",
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/business-industries/update.js": {
"file": "assets/update-C8VOvIbF.js",
"name": "update",
"src": "resources/js/business-industries/update.js",
"isEntry": true
},
"resources/js/config.js": {
"file": "assets/config-DqV4EBmE.js",
"name": "config",
@@ -102,7 +136,7 @@
"isEntry": true
},
"resources/js/dashboards/bigdata.js": {
"file": "assets/bigdata-DYDUaCEC.js",
"file": "assets/bigdata-BGlke4DN.js",
"name": "bigdata",
"src": "resources/js/dashboards/bigdata.js",
"isEntry": true,
@@ -120,7 +154,7 @@
"isEntry": true
},
"resources/js/data-settings/index.js": {
"file": "assets/index-BOfsbw53.js",
"file": "assets/index-C4raIbBK.js",
"name": "index",
"src": "resources/js/data-settings/index.js",
"isEntry": true,
@@ -137,13 +171,14 @@
"isEntry": true
},
"resources/js/data/advertisements/data-advertisements.js": {
"file": "assets/data-advertisements-C_ZfB4RA.js",
"file": "assets/data-advertisements-ckr1EtLP.js",
"name": "data-advertisements",
"src": "resources/js/data/advertisements/data-advertisements.js",
"isEntry": true,
"imports": [
"_gridjs.umd-BiCNXlqL.js",
"_global-config-9uDKFQ8j.js",
"_table-generator-DPFVsCqk.js",
"__commonjsHelpers-C4iS2aBk.js"
]
},
@@ -157,16 +192,79 @@
]
},
"resources/js/data/advertisements/form-upload.js": {
"file": "assets/form-upload-Ci7Kyzc7.js",
"file": "assets/form-upload-tA9zPESO.js",
"name": "form-upload",
"src": "resources/js/data/advertisements/form-upload.js",
"isEntry": true,
"imports": [
"_dropzone-B5tMhgFp.js"
"_dropzone-B5tMhgFp.js",
"_global-config-9uDKFQ8j.js"
]
},
"resources/js/data/tourisms/data-tourisms.js": {
"file": "assets/data-tourisms-Db9aMSJn.js",
"name": "data-tourisms",
"src": "resources/js/data/tourisms/data-tourisms.js",
"isEntry": true,
"imports": [
"_gridjs.umd-BiCNXlqL.js",
"_global-config-9uDKFQ8j.js",
"_table-generator-DPFVsCqk.js",
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/data/tourisms/form-create-update.js": {
"file": "assets/form-create-update-SviVezNW.js",
"name": "form-create-update",
"src": "resources/js/data/tourisms/form-create-update.js",
"isEntry": true,
"imports": [
"_global-config-9uDKFQ8j.js"
]
},
"resources/js/data/tourisms/form-upload.js": {
"file": "assets/form-upload-BtbLOLpA.js",
"name": "form-upload",
"src": "resources/js/data/tourisms/form-upload.js",
"isEntry": true,
"imports": [
"_dropzone-B5tMhgFp.js",
"_global-config-9uDKFQ8j.js"
]
},
"resources/js/data/umkm/data-umkm.js": {
"file": "assets/data-umkm-CLB33rMj.js",
"name": "data-umkm",
"src": "resources/js/data/umkm/data-umkm.js",
"isEntry": true,
"imports": [
"_gridjs.umd-BiCNXlqL.js",
"_global-config-9uDKFQ8j.js",
"_table-generator-DPFVsCqk.js",
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/data/umkm/form-create-update.js": {
"file": "assets/form-create-update-BrB0xTMN.js",
"name": "form-create-update",
"src": "resources/js/data/umkm/form-create-update.js",
"isEntry": true,
"imports": [
"_global-config-9uDKFQ8j.js"
]
},
"resources/js/data/umkm/form-upload.js": {
"file": "assets/form-upload-BDyAWo4b.js",
"name": "form-upload",
"src": "resources/js/data/umkm/form-upload.js",
"isEntry": true,
"imports": [
"_dropzone-B5tMhgFp.js",
"_global-config-9uDKFQ8j.js"
]
},
"resources/js/master/users/create.js": {
"file": "assets/create-RO4xgm-f.js",
"file": "assets/create-BfiYISiN.js",
"name": "create",
"src": "resources/js/master/users/create.js",
"isEntry": true
@@ -323,6 +421,16 @@
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/report/tourisms/index.js": {
"file": "assets/index-DlxOSPEG.js",
"name": "index",
"src": "resources/js/report/tourisms/index.js",
"isEntry": true,
"imports": [
"_gridjs.umd-BiCNXlqL.js",
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/roles/create.js": {
"file": "assets/create-Dd-lHOwF.js",
"name": "create",
@@ -391,7 +499,7 @@
"isEntry": true
},
"resources/scss/dashboards/_bigdata.scss": {
"file": "assets/_bigdata-0hCjAhYp.css",
"file": "assets/_bigdata-Syu0AGbZ.css",
"src": "resources/scss/dashboards/_bigdata.scss",
"isEntry": true
},
@@ -401,7 +509,7 @@
"isEntry": true
},
"resources/scss/style.scss": {
"file": "assets/style-DUYVmgAM.css",
"file": "assets/style-CnBzxVPJ.css",
"src": "resources/scss/style.scss",
"isEntry": true
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,125 @@
import { Dropzone } from "dropzone";
import GlobalConfig from "../global-config";
Dropzone.autoDiscover = false;
var previewTemplate,
dropzone,
dropzonePreviewNode = document.querySelector("#dropzone-preview-list");
console.log(previewTemplate);
console.log(dropzone);
console.log(dropzonePreviewNode);
const toastNotification = document.getElementById("toastNotification");
const toast = new bootstrap.Toast(toastNotification);
(dropzonePreviewNode.id = ""),
dropzonePreviewNode &&
((previewTemplate = dropzonePreviewNode.parentNode.innerHTML),
dropzonePreviewNode.parentNode.removeChild(dropzonePreviewNode),
(dropzone = new Dropzone(".dropzone", {
url: `${GlobalConfig.apiHost}/api/api-business-industries/upload`,
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
document.getElementById("toast-message").innerText =
response.message;
toast.show();
document.getElementById("submit-upload").innerHTML =
"Upload Files";
// Tunggu sebentar lalu reload halaman
setTimeout(() => {
window.location.href = "/data/business-industries";
}, 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
document.getElementById("toast-message").innerText =
errorMessage.message;
toast.show();
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
document.getElementById("toast-message").innerText =
"Please add a file first.";
toast.show();
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);
});
// Function to show toast
// function showToast(iconClass, iconColor, message) {
// const toastElement = document.getElementById("toastUploadAdvertisement");
// 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();
// }

View File

@@ -0,0 +1,260 @@
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";
class BusinessIndustries {
constructor() {
this.table = null; // Store Grid.js instance
}
init() {
this.getFetchApiData();
}
getFetchApiData() {
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;
}
this.table = new Grid({
columns: [
{ name: "ID", width: "80px", hidden: false },
{ name: "Nama Kecamatan", width: "200px" },
{ name: "Nama Kelurahan", width: "200px" },
{ name: "NOP", width: "150px" },
{ name: "Nama Wajib Pajak", width: "250px" },
{ name: "Alamat Wajib Pajak", width: "300px" },
{ name: "Alamat Objek Pajak", width: "300px" },
{ name: "Luas Bumi", width: "150px" },
{ name: "Luas Bangunan", width: "150px" },
{ name: "NJOP Bumi", width: "150px" },
{ name: "NJOP Bangunan", width: "150px" },
{ name: "Ketetapan", width: "150px" },
{ 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>
`);
},
},
],
search: {
server: {
url: (prev, keyword) => `${prev}?search=${keyword}`,
},
},
pagination: {
limit: 15,
server: {
url: (prev, page) =>
`${prev}${prev.includes("?") ? "&" : "?"}page=${
page + 1
}`,
},
},
sort: true,
server: {
url: `${GlobalConfig.apiHost}/api/api-business-industries`,
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, // ID for Actions column
]),
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");
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-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`,
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, // ID for Actions column
]),
total: (data) => data.total,
},
})
.forceRender();
}
}
}
document.addEventListener("DOMContentLoaded", function (e) {
new BusinessIndustries().init();
});

View File

@@ -0,0 +1,79 @@
class UpdateBusinessIndustries {
init() {
this.handleUpdateData();
}
handleUpdateData() {
const form = document.getElementById("formUpdateBusinessIndustries");
const submitButton = document.getElementById(
"btnUpdateBusinessIndustries"
);
const toastNotification = document.getElementById("toastNotification");
const toastBody = document.getElementById("toastBody"); // Add an element inside toast to display messages
const spinner = document.getElementById("spinner");
const toast = new bootstrap.Toast(toastNotification);
if (!submitButton) {
console.error("Error: Submit button not found!");
return;
}
submitButton.addEventListener("click", async function (e) {
e.preventDefault();
// Disable button and show spinner
submitButton.disabled = true;
spinner.classList.remove("d-none");
// Create FormData object
const formData = new FormData(form);
const formObject = {};
formData.forEach((value, key) => {
formObject[key] = value;
});
formData.append("_method", "PUT");
try {
let response = await fetch(form.action, {
method: "POST", // Laravel's update route uses PUT, so adjust accordingly
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
body: JSON.stringify(formObject),
});
let data = await response.json();
if (response.ok) {
// Show success toast
document.getElementById("toast-message").innerText =
data.message;
toast.show();
setTimeout(() => {
window.location.href = "/data/business-industries";
}, 2000);
} else {
// Show error toast with message from API
document.getElementById("toast-message").innerText =
data.message;
toast.show();
submitButton.disabled = false;
spinner.classList.add("d-none");
}
} catch (error) {
// Show error toast for network errors
document.getElementById("toast-message").innerText =
data.message;
toast.show();
submitButton.disabled = false;
spinner.classList.add("d-none");
}
});
}
}
document.addEventListener("DOMContentLoaded", function (e) {
new UpdateBusinessIndustries().init();
});

View File

@@ -49,13 +49,31 @@ class BigData {
}
async updateData(year) {
try {
this.totalTargetPAD = await this.getTargetPAD(year);
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.getDataTataRuang(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);
@@ -100,7 +118,7 @@ class BigData {
this.dataNonVerification.total
);
this.percentageResultNonVerification =
this.bigTotalNonVerification <= 0 || this.bigTotalPotensi
this.bigTotalNonVerification <= 0 || this.bigTotalPotensi <= 0
? 0
: this.bigTotalNonVerification
.div(this.bigTotalPotensi)
@@ -120,7 +138,7 @@ class BigData {
// business documents
this.bigTotalBusiness = new Big(this.dataBusiness.total);
this.percentageResultBusiness =
this.bigTotalNonVerification <= 0
this.bigTotalNonVerification <= 0 || this.bigTotalBusiness <= 0
? 0
: this.bigTotalBusiness
.div(this.bigTotalNonVerification)
@@ -190,38 +208,6 @@ class BigData {
}
}
async getTargetPAD(year) {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/api-data-settings?search=target_pad`,
{
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);
return 0;
}
const data = await response.json();
const valueTargetPAD = data.data[0]?.value ?? 0;
const currentMonth = new Date().getMonth() + 1;
let result = (currentMonth / 12) * valueTargetPAD;
return result;
} catch (error) {
console.error("Error fetching chart data:", error);
return 0;
}
}
async getDataVerfication(year) {
try {
const response = await fetch(
@@ -346,10 +332,10 @@ class BigData {
}
}
async getDataTataRuang() {
async getDataSettings(string_key) {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/api-data-settings?search=tata_ruang`,
`${GlobalConfig.apiHost}/api/api-data-settings?search=${string_key}`,
{
credentials: "include",
headers: {
@@ -519,12 +505,14 @@ class BigData {
document
.querySelectorAll(".document-count.chart-realisasi-tebit-pbg")
.forEach((element) => {
element.innerText = `0`;
element.innerText = `${this.dataCountRealisasiTerbit}`;
});
document
.querySelectorAll(".document-total.chart-realisasi-tebit-pbg")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators("0.00")}`;
element.innerText = `Rp.${addThousandSeparators(
this.dataSumRealisasiTerbit
)}`;
});
document
.querySelectorAll(".small-percentage.chart-realisasi-tebit-pbg")
@@ -536,12 +524,14 @@ class BigData {
document
.querySelectorAll(".document-count.chart-menunggu-klik-dpmptsp")
.forEach((element) => {
element.innerText = `${0}`;
element.innerText = `${this.dataCountMenungguKlikDPMPTSP}`;
});
document
.querySelectorAll(".document-total.chart-menunggu-klik-dpmptsp")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators("0.00")}`;
element.innerText = `Rp.${addThousandSeparators(
this.dataSumMenungguKlikDPMPTSP
)}`;
});
document
.querySelectorAll(".small-percentage.chart-menunggu-klik-dpmptsp")
@@ -553,12 +543,14 @@ class BigData {
document
.querySelectorAll(".document-count.chart-proses-dinas-teknis")
.forEach((element) => {
element.innerText = `${0}`;
element.innerText = `${this.dataCountProsesDinasTeknis}`;
});
document
.querySelectorAll(".document-total.chart-proses-dinas-teknis")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators("0.00")}`;
element.innerText = `Rp.${addThousandSeparators(
this.dataSumProsesDinasTeknis
)}`;
});
document
.querySelectorAll(".small-percentage.chart-proses-dinas-teknis")

View File

@@ -0,0 +1,119 @@
import Big from "big.js";
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
class LackOfPotential {
async init() {
this.bigTotalLackPotential = 0;
this.totalPotensi = await this.getDataTotalPotensi(2025);
this.totalTargetPAD = await this.getDataSettings("TARGET_PAD");
this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0);
this.bigTotalPotensi = new Big(this.totalPotensi.totalData ?? 0);
this.bigTotalLackPotential = this.bigTargetPAD - this.bigTotalPotensi;
this.initChartKekuranganPotensi();
}
async 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 {
countData: data.data.count,
totalData: data.data.total,
};
} catch (error) {
console.error("Error fetching chart data:", error);
return null;
}
}
async 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;
} catch (error) {
console.error("Error fetching chart data:", error);
return 0;
}
}
initChartKekuranganPotensi() {
document
.querySelectorAll(".document-count.chart-lack-of-potential")
.forEach((element) => {
element.innerText = ``;
});
document
.querySelectorAll(".document-total.chart-lack-of-potential")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(
this.bigTotalLackPotential.toString()
)}`;
});
document
.querySelectorAll(".small-percentage.chart-lack-of-potential")
.forEach((element) => {
element.innerText = ``;
});
}
}
document.addEventListener("DOMContentLoaded", async function (e) {
await new LackOfPotential().init();
});
function resizeDashboard() {
let targetElement = document.getElementById("lack-of-potential-wrapper");
let dashboardElement = document.getElementById(
"lack-of-potential-fixed-container"
);
let targetWidth = targetElement.offsetWidth;
let dashboardWidth = 1400;
let scaleFactor = (targetWidth / dashboardWidth).toFixed(2);
// Prevent scaling beyond 1 (100%) to avoid overflow
scaleFactor = Math.min(scaleFactor, 1);
dashboardElement.style.transformOrigin = "left top";
dashboardElement.style.transition = "transform 0.2s ease-in-out";
dashboardElement.style.transform = `scale(${scaleFactor})`;
// Ensure horizontal scrolling is allowed if necessary
document.body.style.overflowX = "auto";
}
window.addEventListener("load", resizeDashboard);
window.addEventListener("resize", resizeDashboard);

View File

@@ -57,7 +57,7 @@ class DataSettings {
<a href="/data-settings/${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-centerbtn-delete-data-settings" data-id="${cell}">
<button class="btn btn-sm btn-red d-inline-flex align-items-center justify-content-center btn-delete-data-settings" data-id="${cell}">
<i class='bx bxs-trash' ></i>
</button>
</div>

View File

@@ -1,4 +1,5 @@
import { Dropzone } from "dropzone";
import GlobalConfig from "../../global-config.js";
Dropzone.autoDiscover = false;
@@ -14,7 +15,7 @@ console.log(dropzonePreviewNode);
((previewTemplate = dropzonePreviewNode.parentNode.innerHTML),
dropzonePreviewNode.parentNode.removeChild(dropzonePreviewNode),
(dropzone = new Dropzone(".dropzone", {
url: "http://localhost:8000/api/advertisements/import",
url: `${GlobalConfig.apiHost}/api/advertisements/import`,
// url: "https://httpbin.org/post",
method: "post",
acceptedFiles: ".xls,.xlsx", // Use acceptedFiles for better validation
@@ -85,6 +86,40 @@ dropzone.on("complete", function(file) {
dropzone.removeFile(file);
});
// Add event listener to donwload file template
document.getElementById('downloadtempadvertisement').addEventListener('click', function() {
var url = `${GlobalConfig.apiHost}/api/download-template-advertisement`;
fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`
},
})
.then(response => {
if (response.ok) {
return response.blob();
} else {
return response.json();
}
})
.then((blob) => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'template_reklame.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('toastUploadAdvertisement');

View File

@@ -0,0 +1,95 @@
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 dataTourismsColumns = [
"Nama Perusahaan",
"Nama Proyek",
"Alamat Usaha",
"Kecamatan",
"Desa",
"Luas Tanah (m2)",
"Jumlah Investasi",
"TKI",
"Longitude",
"Latitude",
{
name: "Actions",
widht: "120px",
formatter: function (cell, row) {
const id = row.cells[10].data;
const long = row.cells[8].data;
const lat = row.cells[9].data;
const model = "data/tourisms";
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-info me-2 btn-view"
data-long="${long}" data-lat="${lat}">
<i class='bx bx-map'></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(
"tourisms-data-table",
`${GlobalConfig.apiHost}/api/tourisms`,
`${GlobalConfig.apiHost}`,
dataTourismsColumns
);
table.processData = function (data) {
return data.data.map((item) => {
return [
item.business_name,
item.project_name,
item.business_address,
item.district_name,
item.village_name,
item.land_area_in_m2,
item.investment_amount,
item.tki,
item.longitude,
item.latitude,
item.id,
];
});
};
table.init();
// Event listener untuk tombol "View" yang memunculkan modal
document.addEventListener("click", function (e) {
if (e.target && e.target.classList.contains("btn-view")) {
const long = e.target.getAttribute("data-long");
const lat = e.target.getAttribute("data-lat");
// Menyiapkan URL iframe dengan koordinat yang didapatkan
const iframeSrc = `https://www.google.com/maps?q=${lat},${long}&hl=es;z=14&output=embed`;
// Menemukan modal dan iframe di dalam modal
const modal = document.querySelector(".modalGMaps");
const iframe = modal.querySelector("iframe");
// Set src iframe untuk menampilkan peta dengan koordinat yang relevan
iframe.src = iframeSrc;
// Menampilkan modal
var modalInstance = new bootstrap.Modal(modal);
modalInstance.show();
}
});
});

View File

@@ -0,0 +1,193 @@
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;
});
// Log semua data dalam FormData
for (let pair of formData.entries()) {
console.log(pair[0] + ": " + pair[1]);
}
const url = form.getAttribute("action");
console.log("Ini adalah url dari form action", url);
const method = isEdit ? "PUT" : "POST";
fetch(url, {
method: method,
body: JSON.stringify(data),
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((data) => {
console.log("Response data:", data);
if (!data.errors) {
// 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/tourisms";
}, 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) => {
console.error("Error:", 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;
console.log("Query Value:", inputValue); // Debugging log
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();
});
});

View File

@@ -0,0 +1,149 @@
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/tourisms/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/tourisms";
}, 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('downloadtemptourisms').addEventListener('click', function() {
var url = `${GlobalConfig.apiHost}/api/download-template-umkm`;
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) => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'template_tourisms.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('toastUploadUmkm');
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();
}

View File

@@ -0,0 +1,81 @@
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 dataUMKMColumns = [
"Nama Usaha",
"Alamat Usaha",
"Deskripsi Usaha",
"Kontak Usaha",
"NIB",
"Skala Usaha",
"NIK",
"Nama Pemilik",
"Alamat Pemilik",
"Kontak Pemilik",
"Jenis Usaha",
"Bentuk Usaha",
"Revenue",
"Desa",
"Kecamatan",
"Jumlah Karyawan",
"Luas Tanah",
"Ijin Status",
{
name: "Actions",
widht: "120px",
formatter: function(cell, row) {
const id = row.cells[18].data;
const model = "data/umkm";
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(
"umkm-data-table",
`${GlobalConfig.apiHost}/api/umkm`,
`${GlobalConfig.apiHost}`,
dataUMKMColumns
);
table.processData = function (data) {
return data.data.map((item) => {
return [
item.business_name,
item.business_address,
item.business_desc,
item.business_contact,
item.business_id_number,
item.business_scale,
item.owner_id,
item.owner_name,
item.owner_address,
item.owner_contact,
item.business_type,
item.business_form,
item.revenue,
item.village_name,
item.district_name,
item.number_of_employee,
item.land_area,
item.permit_status,
item.id,
];
});
};
table.init();
});

View 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;
});
// Log semua data dalam FormData
for (let pair of formData.entries()) {
console.log(pair[0] + ": " + pair[1]);
}
const url = form.getAttribute("action");
console.log("Ini adalah url dari form action", url);
const method = isEdit ? "PUT" : "POST";
fetch(url, {
method: method,
body: JSON.stringify(data),
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(data => {
console.log("Response data:", data);
if (!data.errors) {
// 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/umkm';
}, 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 => {
console.error("Error:", 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;
console.log("Query Value:", inputValue); // Debugging log
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();
});
});

View File

@@ -0,0 +1,149 @@
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/umkm/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/umkm";
}, 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('downloadtempumkm').addEventListener('click', function() {
var url = `${GlobalConfig.apiHost}/api/download-template-umkm`;
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) => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'template_umkm.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('toastUploadUmkm');
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();
}

View File

@@ -44,12 +44,18 @@ 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);
document.getElementById("toast-message").innerText =
error.message;
toast.show();
submitButton.disabled = false;
spinner.classList.add("d-none");
}
});
});

View File

@@ -0,0 +1,16 @@
import gridjs from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js";
// Mengambil data dari input dengan id="business_type_counts"
const businessTypeCountsElement = document.getElementById("tourism_based_KBLI");
console.log(businessTypeCountsElement);
const businessTypeCounts = JSON.parse(businessTypeCountsElement.value); // Cek apakah data sudah terbawa dengan benar
// Membuat Grid.js instance
new gridjs.Grid({
columns: ["Jenis Bisnis Pariwisata", "Jumlah Total"], // Nama kolom
data: businessTypeCounts.map(item => [item.kbli_title, item.total_records]), // Mengubah data untuk Grid.js
search: true, // Menambahkan fitur pencarian
pagination: true, // Menambahkan fitur pagination
sort: true, // Menambahkan fitur sorting
}).render(document.getElementById("tourisms-report-data-table"));

View File

@@ -1,5 +1,6 @@
import { Grid } from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js";
import Swal from "sweetalert2";
class GeneralTable {
constructor(tableId, apiUrl, baseUrl, columns, options = {}) {
@@ -94,9 +95,29 @@ class GeneralTable {
handleDelete(event) {
const id = event.target.getAttribute('data-id');
console.log(id);
if (confirm("Are you sure you want to delete this item?")) {
this.deleteRecord(id);
}
// if (confirm("Are you sure you want to delete this item?")) {
// this.deleteRecord(id);
// }
Swal.fire({
title: "Are you sure?",
text: "You won't be able to revert this!",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#d33",
cancelButtonColor: "#3085d6",
confirmButtonText: "Yes, delete it!"
}).then((result) => {
if (result.isConfirmed) {
this.deleteRecord(id);
Swal.fire({
title: "Deleted!",
text: "Your record has been deleted.",
icon: "success",
showConfirmButton: false, // Menghilangkan tombol OK
timer: 2000 // Menutup otomatis dalam 2 detik (opsional)
});
}
});
}
async deleteRecord(id) {
@@ -110,23 +131,30 @@ class GeneralTable {
.getAttribute("content")}`,
"Content-Type": "application/json",
},
// headers: {
// 'Authorization': `Bearer ${document.querySelector('meta[name="api-token"]').getAttribute("content")}`,
// 'Content-Type': 'application/json',
// },
});
if (response.status === 204) { // Jika status code 204, berarti berhasil
alert('Data deleted successfully!');
if (response.status === 204) {
location.reload();
} else {
const data = await response.json(); // Jika ada data di response body
alert('Failed to delete data: ' + (data.message || 'Unknown error.'));
const data = await response.json();
showErrorAlert(`Failed to delete record: ${data.message || "Unknown error"}`);
}
} catch (error) {
console.error('Error deleting data:', error);
alert('Error deleting data.');
showErrorAlert("Error deleting data. Please try again.");
}
}
}
// Fungsi untuk menampilkan alert
function showErrorAlert(message) {
const alertContainer = document.getElementById("alert-container");
alertContainer.innerHTML = `
<div class="alert alert-danger alert-dismissible fade show" role="alert">
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
`;
}
export default GeneralTable;

View File

@@ -0,0 +1,53 @@
//
// custom_circle.scss
//
.custom-circle-wrapper {
width: 100px; // Default width
height: 100px; // Default height
border: 4px solid white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-color: rgb(1, 44, 124);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Efek bayangan */
text-align: center;
&.large {
width: 150px;
height: 150px;
}
&.small {
width: 95px;
height: 95px;
}
}
.custom-circle-content {
display: flex;
flex-direction: column;
align-items: center;
}
.custom-circle-text {
font-size: 14px;
font-weight: bold;
color: white;
padding: 0;
margin: 0;
}
.custom-circle-data {
font-size: 12px;
color: white;
background-color: #f0195b;
padding: 0 5px;
border-radius: 3px;
}
.custom-circle-data-type {
font-size: 12px;
color: white;
}

View File

@@ -41,9 +41,10 @@
}
#dashboard-fixed-wrapper {
background-image: url("../../../public/images/bg-dashboard.jpg");
background-image: url("/public/images/bg-dashboard.jpg");
background-size: cover;
background-position: center;
max-width: 100vw; /* Ensures it doesn't exceed viewport */
}
#dashboard-fixed-wrapper::before {
@@ -62,10 +63,6 @@
); /* Black overlay with 50% opacity */
}
#dashboard-fixed-wrapper {
max-width: 100vw; /* Ensures it doesn't exceed viewport */
}
#dashboard-fixed-container {
min-width: 1110px;
max-width: unset; /* Allow it to grow if needed */

View File

@@ -0,0 +1,234 @@
//
// lack-of-potential.scss
//
.square {
height: 100px;
width: 100px;
position: absolute;
z-index: -1;
}
.dia-top-left-bottom-right:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(
to top right,
transparent calc(50% - 2px),
black,
transparent calc(50% + 2px)
);
}
.dia-top-right-bottom-left:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(
to top left,
transparent calc(50% - 2px),
black,
transparent calc(50% + 2px)
);
}
.lack-of-potential-wrapper {
background-image: url("/public/images/bg-dashboard.jpg");
background-size: cover;
background-position: center;
background-color: rgba(255, 255, 255, 0.7);
max-width: 100vw;
}
.lack-of-potential-wrapper::before {
content: "";
position: absolute;
pointer-events: none; /* Prevents the overlay from blocking interaction */
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.7);
}
// #lack-of-potential-fixed-container {
// min-width: 1110px;
// max-width: unset; /* Allow it to grow if needed */
// }
// @media (max-width: 768px) {
// #lack-of-potential-fixed-container {
// transform: scale(0.8); /* Adjust the scale as needed */
// }
// }
// line degrees
.line {
background-color: black;
position: absolute;
height: 3px;
}
.home-to-non-usaha {
width: 100px;
top: 13%;
left: 38%;
transform: rotate(90deg);
}
.restoran-to-bapenda {
width: 110px;
top: 14%;
left: 60%;
transform: rotate(40deg);
}
.pbb-to-bapenda {
width: 80px;
top: 21%;
left: 80%;
}
.reklame-to-bapenda {
width: 120px;
left: 75%;
top: 30%;
transform: rotateZ(142deg);
}
.non-usaha-to-bapenda {
width: 116px;
left: 18%;
top: 33%;
transform: rotateZ(124deg);
}
.non-usaha-to-pdam {
width: 100px;
left: 38%;
top: 34%;
transform: rotateZ(90deg);
}
.non-usaha-to-kecamatan {
width: 140px;
left: 55%;
top: 33%;
transform: rotateZ(237deg);
}
.bapenda-to-usaha {
width: 114px;
left: 18%;
top: 49%;
transform: rotateZ(56deg);
}
.pdam-to-usaha {
width: 88px;
left: 39%;
top: 49%;
transform: rotateZ(90deg);
}
.kecamatan-to-usaha {
width: 118px;
left: 56%;
top: 50%;
transform: rotateZ(117deg);
}
.usaha-to-villa {
width: 100px;
left: 10%;
top: 63%;
transform: rotateZ(143deg);
}
.usaha-to-pabrik {
width: 150px;
left: 15%;
top: 70%;
transform: rotateZ(143deg);
}
.usaha-to-pariwisata {
width: 150px;
left: 43%;
top: 70%;
transform: rotateZ(38deg);
}
.usaha-to-protocol {
width: 106px;
left: 36%;
top: 71%;
transform: rotateZ(86deg);
}
.pariwisata-to-disbudpar {
width: 86px;
left: 54%;
top: 83%;
transform: rotateZ(150deg);
}
.non-usaha-to-wasdal {
width: 300px;
left: -32%;
top: 34%;
transform: rotateZ(226deg);
}
.usaha-to-wasdal {
width: 300px;
left: -34%;
top: 50%;
transform: rotateZ(129deg);
}
.wasdal-to-upt {
width: 155px;
left: 3%;
top: -67%;
transform: rotateZ(127deg);
}
.wasdal-to-satpol {
width: 155px;
left: 19%;
top: -52%;
transform: rotateZ(76deg);
}
.wasdal-to-kejari {
width: 182px;
left: 25%;
top: -55%;
transform: rotateZ(51deg);
}
.wasdal-to-tni {
width: 260px;
left: 29%;
top: -62%;
transform: rotateZ(30deg);
}
.wasdal-to-potential {
width: 50px;
left: 28%;
top: 41%;
}
.potential-to-tata-ruang {
width: 50px;
left: 72%;
top: 41%;
}
.tata-ruang-to-non-usaha {
width: 220px;
left: 0%;
top: 30%;
transform: rotateZ(144deg);
}
.tata-ruang-to-usaha {
width: 280px;
left: 0%;
top: 52%;
transform: rotateZ(224deg);
}
.tata-ruang-to-peta {
width: 122px;
left: 8%;
top: 41%;
}
.peta-to-tapak {
width: 30px;
left: 47%;
top: 41%;
}

View File

@@ -45,6 +45,8 @@
@import "components/tooltip";
@import "components/widgets";
@import "components/circle";
@import "components/custom_circle";
@import "dashboards/lack-of-potential";
// Plugin
@import "plugins/simplebar";

View File

@@ -36,10 +36,10 @@ class="authentication-bg"
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<input type="email" class="form-control" id="email" name="email" value="user@demo.com" placeholder="Enter your email">
<input type="email" class="form-control" id="email" name="email" placeholder="Enter your email">
</div>
<div class="mb-3">
<input type="password" class="form-control" id="password" name="password" value="password" placeholder="Enter your password">
<input type="password" class="form-control" id="password" name="password" placeholder="Enter your password">
</div>
<div class="d-grid">
<button class="btn btn-dark btn-lg fw-medium" type="submit">Sign In</button>

View File

@@ -0,0 +1,78 @@
@extends('layouts.vertical', ['subtitle' => 'Business Industries'])
@section('content')
@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'Business Industries'])
<x-toast-notification />
<div class="row">
<div class="col-xl-12">
<div class="card">
<div class="card-header">
<h5 class="card-title">Upload Data</h5>
<p class="card-subtitle">
Please upload a file with the extension <strong>.xls or .xlsx</strong> with a maximum size of <strong>10 MB</strong>.
<br>
For <strong>.xls</strong> and <strong>.xlsx</strong> files, ensure that the data is contained within a <strong>single sheet</strong> with the following columns:
<!-- <strong>No, Nama Wajib Pajak, NPWPD, Jenis Reklame, Isi Reklame, Alamat Wajib Pajak, Lokasi Reklame, Desa,
Kecamatan, Panajang, Lebar, Sudut Pandang, Muka, Luas, Sudut, Kontak.</strong> -->
</p>
</div>
<div class="card-body">
<div class="mb-3">
<div class="dropzone">
<form enctype="multipart/form-data">
<div class="fallback">
<input id="file-dropzone"type="file" name="file" multiple/>
</div>
</form>
<div class="dz-message needsclick">
<i class="h1 bx bx-cloud-upload"></i>
<h3>Drop files here or click to upload.</h3>
</div>
</div>
<ul class="list-unstyled mb-0" id="dropzone-preview">
<li class="mt-2" id="dropzone-preview-list">
<!-- This is used as the file preview template -->
<div class="border rounded">
<div class="d-flex align-items-center p-2">
<div class="flex-shrink-0 me-3">
<div class="avatar-sm bg-light rounded">
<img data-dz-thumbnail class="img-fluid rounded d-block" src="#"
alt="" />
</div>
</div>
<div class="flex-grow-1">
<div class="pt-1">
<h5 class="fs-14 mb-1" data-dz-name>&nbsp;
</h5>
<p class="fs-13 text-muted mb-0" data-dz-size></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
</div>
<div class="flex-shrink-0 ms-3">
<button data-dz-remove class="btn btn-sm btn-danger">Delete</button>
</div>
</div>
</div>
</li>
</ul>
<!-- end dropzon-preview -->
</div>
<div class="d-flex justify-content-end">
<button id="submit-upload" class="btn btn-primary">Upload Files</button>
</div>
</div> <!-- end card body -->
</div> <!-- end card -->
</div> <!-- end col -->
</div> <!-- end row -->
@endsection
@section('scripts')
@vite(['resources/js/business-industries/create.js'])
@endsection

View File

@@ -0,0 +1,89 @@
@extends('layouts.vertical', ['subtitle' => 'Create'])
@section('content')
@include('layouts.partials/page-title', ['title' => 'Data Settings', 'subtitle' => 'Setting Dashboard'])
<x-toast-notification />
<div class="row d-flex justify-content-center">
<div class="col-lg-6">
<div class="card">
<div class="card-body">
<form id="formUpdateBusinessIndustries" action="{{ route('api-business-industries.update', $data->id) }}" method="POST">
@csrf
@method('PUT')
<div class="mb-3">
<label for="nama_kecamatan" class="form-label">Nama Kecamatan</label>
<input type="text" id="nama_kecamatan" class="form-control" name="nama_kecamatan" value="{{ $data->nama_kecamatan }}">
</div>
<div class="mb-3">
<label for="nama_kelurahan" class="form-label">Nama Kelurahan</label>
<input type="text" id="nama_kelurahan" class="form-control" name="nama_kelurahan" value="{{ $data->nama_kelurahan }}">
</div>
<div class="mb-3">
<label for="nop" class="form-label">NOP</label>
<input type="text" id="nop" class="form-control" name="nop" value="{{ $data->nop }}">
</div>
<div class="mb-3">
<label for="nama_wajib_pajak" class="form-label">Nama Wajib Pajak</label>
<input type="text" id="nama_wajib_pajak" class="form-control" name="nama_wajib_pajak" value="{{ $data->nama_wajib_pajak }}">
</div>
<div class="mb-3">
<label for="alamat_wajib_pajak" class="form-label">Alamat Wajib Pajak</label>
<input type="text" id="alamat_wajib_pajak" class="form-control" name="alamat_wajib_pajak" value="{{ $data->alamat_wajib_pajak }}">
</div>
<div class="mb-3">
<label for="alamat_objek_pajak" class="form-label">Alamat Objek Pajak</label>
<input type="text" id="alamat_objek_pajak" class="form-control" name="alamat_objek_pajak" value="{{ $data->alamat_objek_pajak }}">
</div>
<div class="mb-3">
<label for="luas_bumi" class="form-label">Luas Bumi</label>
<input type="number" id="luas_bumi" class="form-control" name="luas_bumi" value="{{ $data->luas_bumi }}">
</div>
<div class="mb-3">
<label for="luas_bangunan" class="form-label">Luas Bangunan</label>
<input type="number" id="luas_bangunan" class="form-control" name="luas_bangunan" value="{{ $data->luas_bangunan }}">
</div>
<div class="mb-3">
<label for="njop_bumi" class="form-label">NJOP Bumi</label>
<input type="number" id="njop_bumi" class="form-control" name="njop_bumi" value="{{ $data->njop_bumi }}">
</div>
<div class="mb-3">
<label for="njop_bangunan" class="form-label">NJOP Bangunan</label>
<input type="number" id="njop_bangunan" class="form-control" name="njop_bangunan" value="{{ $data->njop_bangunan }}">
</div>
<div class="mb-3">
<label for="ketetapan" class="form-label">Ketetapan</label>
<input type="text" id="ketetapan" class="form-control" name="ketetapan" value="{{ $data->ketetapan }}">
</div>
<div class="mb-3">
<label for="tahun_pajak" class="form-label">Tahun Pajak</label>
<input type="number" id="tahun_pajak" class="form-control" name="tahun_pajak" value="{{ $data->tahun_pajak }}">
</div>
<button class="btn btn-primary me-1" type="button" id="btnUpdateBusinessIndustries">
<span id="spinner" class="spinner-border spinner-border-sm me-1 d-none" role="status" aria-hidden="true"></span>
Update
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/business-industries/update.js'])
@endsection

View File

@@ -0,0 +1,31 @@
@extends('layouts.vertical', ['subtitle' => 'Business Industries'])
@section('css')
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
@endsection
@section('content')
@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'Business Industries'])
<x-toast-notification />
<x-modal-confirmation buttonText="Delete" confirmationMessage="Are you sure you want to delete this?" />
<div class="row">
<div class="col-12">
<div class="card w-100">
<div class="card-body">
<div class="d-flex flex-wrap justify-content-end align-items-center mb-2">
<a href="{{ route('business-industries.create')}}" class="btn btn-success btn-sm d-block d-sm-inline w-auto">Create</a>
</div>
<div id="table-business-industries"></div>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/business-industries/index.js'])
@endsection

View File

@@ -0,0 +1,30 @@
@props(['title' => 'title component', 'visible_data' => false, 'data' => 'data text', 'visible_data_type' => false,
'data_type' => '','style' => '', 'size' => '', 'line' => []])
@section('css')
@vite(['resources/scss/components/_custom_circle.scss'])
@endsection
<div class="custom-circle-wrapper {{ $size }}" style="{{ $style }}">
<div class="custom-circle-content">
<p class="custom-circle-text">{{ $title }}</p>
@if ($visible_data === "true")
<div class="custom-circle-data">{{ $data }}</div>
@endif
@if ($visible_data_type === "true")
<div class="custom-circle-data-type">{{ $data_type }}</div>
@endif
@if (!empty($lines))
<svg class="absolute w-full h-full" viewBox="0 0 100 100" preserveAspectRatio="none">
@foreach ($lines as $line)
<line
x1="{{ $line['x1'] }}" y1="{{ $line['y1'] }}"
x2="{{ $line['x2'] }}" y2="{{ $line['y2'] }}"
stroke="{{ $line['color'] ?? 'black' }}"
stroke-width="{{ $line['width'] ?? 2 }}"
/>
@endforeach
</svg>
@endif
</div>
</div>

View File

@@ -33,7 +33,7 @@
<div id="dashboard-fixed-container" class="row" style="width:1110px;height:770px;position:relative;margin:auto;">
@component('components.circle', [
'document_title' => 'Kekurangan Potensi',
'document_color' => '#911701',
'document_color' => '#ff5757',
'document_type' => '',
'document_id' => 'chart-kekurangan-potensi',
'visible_small_circle' => true,
@@ -43,7 +43,7 @@
@component('components.circle', [
'document_title' => 'Target PAD 2024',
'document_color' => '#020e42',
'document_color' => '#204f6b',
'document_type' => '',
'document_id' => 'chart-target-pad',
'visible_small_circle' => true,
@@ -61,7 +61,7 @@
@component('components.circle', [
'document_title' => 'Total Potensi Berkas',
'document_color' => '#02acfa',
'document_color' => '#0097b3',
'document_type' => 'Pemohon',
'document_id' => 'chart-total-potensi',
'visible_small_circle' => true,
@@ -77,7 +77,7 @@
@component('components.circle', [
'document_title' => 'Perkiraan Potensi PBG Dari Tata Ruang',
'document_color' => '#bf04bc',
'document_color' => '#ed9d2e',
'document_type' => '',
'document_id' => 'chart-potensi-tata-ruang',
'visible_small_circle' => true,
@@ -90,7 +90,7 @@
@component('components.circle', [
'document_title' => 'Non Usaha',
'document_color' => '#028399',
'document_color' => '#399787',
'document_type' => 'Berkas',
'document_id' => 'chart-non-business',
'visible_small_circle' => true,
@@ -100,7 +100,7 @@
@component('components.circle', [
'document_title' => 'Usaha',
'document_color' => '#616b7d',
'document_color' => '#5e7c89',
'document_type' => 'Berkas',
'document_id' => 'chart-business',
'visible_small_circle' => true,
@@ -110,7 +110,7 @@
@component('components.circle', [
'document_title' => 'Berkas Terverifikasi',
'document_color' => '#0561f5',
'document_color' => '#5170ff',
'document_type' => 'Berkas',
'document_id' => 'chart-berkas-terverifikasi',
'visible_small_circle' => true,
@@ -126,7 +126,7 @@
@component('components.circle', [
'document_title' => 'Berkas Belum Terverifikasi',
'document_color' => '#b973ff',
'document_color' => '#5170ff',
'document_type' => 'Berkas',
'document_id' => 'chart-berkas-belum-terverifikasi',
'visible_small_circle' => true,
@@ -143,7 +143,7 @@
@component('components.circle',[
'document_title' => 'Realisasi Terbit PBG',
'document_color' => '#09ab5a',
'document_color' => '#8cc540',
'document_type' => 'Berkas',
'document_id' => 'chart-realisasi-tebit-pbg',
'visible_small_circle' => true,
@@ -156,7 +156,7 @@
@component('components.circle',[
'document_title' => 'Menunggu Klik DPMPTSP',
'document_color' => '#0294ad',
'document_color' => '#00bf61',
'document_type' => 'Berkas',
'document_id' => 'chart-menunggu-klik-dpmptsp',
'visible_small_circle' => true,
@@ -169,7 +169,7 @@
@component('components.circle',[
'document_title' => 'Berproses Di Dinas Teknis',
'document_color' => '#422519',
'document_color' => '#737373',
'document_type' => 'Berkas',
'document_id' => 'chart-proses-dinas-teknis',
'visible_small_circle' => true,

View File

@@ -0,0 +1,108 @@
@extends('layouts.vertical', ['subtitle' => 'Dashboards'])
@section('css')
@vite(['resources/scss/dashboards/_lack-of-potential.scss'])
@endsection
@section('content')
@include('layouts.partials.page-title', ['title' => 'Dashboards', 'subtitle' => 'Lack Of Potential'])
<div class="lack-of-potential-wrapper">
<div class="row" id="lack-of-potential-wrapper">
<div class="col-12">
<h3 class="mt-3 ms-2 text-danger">
ANALISA BIG DATA MELALUI APLIKASI SIBEDAS PBG
</h3>
</div>
</div>
<div class="">
<div class="">
<div id="lack-of-potential-fixed-container" class="" style="width:1400px;height:770px;position:relative;margin:auto;z-index:1;">
<div style="position: absolute; top: 200px; left: 50px;">
<x-custom-circle title="Restoran" size="small" style="background-color: #0e4753;" />
<div class="square dia-top-left-bottom-right" style="top:30px;left:50px;width:150px;height:120px;"></div>
<x-custom-circle title="PBB Bangunan" visible_data="true" data="649.157" size="small" style="background-color: #0e4753;" />
<div class="square" style="width:150px;height:2px;background-color:black;left:50px;top:150px;"></div>
<x-custom-circle title="Reklame" visible_data="true" data="2.428" size="small" style="background-color: #0e4753;" />
<div class="square dia-top-right-bottom-left" style="top:140px;left:50px;width:150px;height:120px;"></div>
</div>
<div style="position: absolute; top: 300px; left: 200px;">
<div class="square dia-top-right-bottom-left" style="top:-100px;left:30px;width:150px;height:120px;"></div>
<div class="square dia-top-left-bottom-right" style="top:-100px;left:120px;width:120px;height:120px;"></div>
<x-custom-circle title="BAPENDA" size="small" style="float:left;background-color: #234f6c;" />
<x-custom-circle title="PDAM" visible_data="true" data="9.022" visible_data_type="true" data_type="Pelanggan" size="small" style="float:left;background-color: #234f6c;" />
<x-custom-circle title="KECAMATAN" size="small" style="float:left;background-color: #234f6c;" />
</div>
<div style="position: absolute; top: 0px; left: 270px;">
<div class="square" style="width:5px;height:600px;background-color:black;left:70px;top:50px;"></div>
<div class="square dia-top-left-bottom-right" style="top:350px;left:-50px;width:120px;height:120px;"></div>
<div class="square dia-top-right-bottom-left" style="top:350px;left:70px;width:120px;height:120px;"></div>
<x-custom-circle title="Rumah Tinggal" size="small" style="background-color: #234f6c;margin:auto;" />
<x-custom-circle title="Non Usaha" size="large" style="background-color: #3a968b;margin-top:20px;" />
<x-custom-circle title="USAHA" size="large" style="background-color: #627c8b;margin-top:150px;" />
</div>
<div style="position: absolute; top: 650px; left: 110px;">
<x-custom-circle title="Villa" size="small" style="float:left;background-color: #234f6c;" />
<x-custom-circle title="Pabrik" size="small" style="float:left;background-color: #234f6c;" />
<x-custom-circle title="Jalan Protocol" size="small" style="float:left;background-color: #234f6c;" />
<x-custom-circle title="Ruko" size="small" style="float:left;background-color: #234f6c;" />
<x-custom-circle title="Pariwisata" size="small" style="float:left;background-color: #234f6c;" />
<x-custom-circle title="DISBUDPAR" size="small" style="background-color: #3a968b;" />
</div>
<div style="position: absolute; top: 280px; left: 550px;">
<x-custom-circle title="Tim Wasdal Gabungan" size="large" style="background-color: #da6635;float:left" />
<div class="square" style="width:650px;height:5px;background-color:black;left:100px;top:75px;"></div>
@component('components.circle', [
'document_title' => 'Kekurangan Potensi',
'document_color' => '#ff5757',
'document_type' => '',
'document_id' => 'chart-lack-of-potential',
'visible_small_circle' => false,
'style' => 'margin-left:180px;top:-20px;'
])
@endcomponent
<x-custom-circle title="Tata Ruang" size="large" style="background-color: #da6635;float:left;margin-left:250px;" />
</div>
<div style="position: absolute; top: 310px; left: 1150px;">
<x-custom-circle title="Peta" visible_data_type="true" data_type="1:5000" size="small" style="background-color: #224f6d;float:left;" />
<x-custom-circle title="Tapak Bangunan" size="small" style="background-color: #2390af;float:left;margin-left:20px;" />
</div>
<x-custom-circle title="UUCK" size="small" style="background-color: #2390af;position:absolute;left:1270px;top:440px;" />
<div style="position: absolute; top: 470px; left: 430px;">
<x-custom-circle title="UPT Wasdal" size="small" style="background-color: #0f4853;float:left;" />
<x-custom-circle title="Satpol PP" size="small" style="background-color: #0f4853;float:left;" />
<x-custom-circle title="KEJARI" size="small" style="background-color: #0f4853;float:left;" />
<x-custom-circle title="TNI & POLRI" size="small" style="background-color: #0f4853;float:left;" />
</div>
<x-custom-circle title="UUCK" size="small" style="background-color: #2390af;position:absolute;left:980px;top:500px;" />
<div style="position: absolute; top: 50px; left: 1100px;">
<x-custom-circle title="Non Usaha" size="large" style="background-color: #3a968b;margin-top:20px;" />
<x-custom-circle title="USAHA" size="large" style="background-color: #627c8b;margin-top:260px;" />
</div>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/dashboards/lack-of-potential.js'])
@endsection

View File

@@ -8,14 +8,10 @@
<div class="col-xl-12">
<div class="card">
<div class="card-header">
<h5 class="card-title">Upload Data Reklame</h5>
<p class="card-subtitle">
Please upload a file with the extension <strong>.xls or .xlsx</strong> with a maximum size of <strong>10 MB</strong>.
<br>
For <strong>.xls</strong> and <strong>.xlsx</strong> files, ensure that the data is contained within a <strong>single sheet</strong> with the following columns:
<strong>No, Nama Wajib Pajak, NPWPD, Jenis Reklame, Isi Reklame, Alamat Wajib Pajak, Lokasi Reklame, Desa,
Kecamatan, Panajang, Lebar, Sudut Pandang, Muka, Luas, Sudut, Kontak.</strong>
</p>
<div class="d-flex justify-content-between align-items-center">
<h5 class="card-title">Upload Data Reklame</h5>
<button id="downloadtempadvertisement" class="btn btn-secondary">Download Template</button>
</div>
</div>
<div class="card-body">
@@ -31,6 +27,10 @@
<div class="dz-message needsclick">
<i class="h1 bx bx-cloud-upload"></i>
<h3>Drop files here or click to upload.</h3>
<p class="card-subtitle">
Please upload a file with the extension <strong>.xls or .xlsx</strong> with a maximum size of <strong>10 MB</strong>.
<br>
</p>
</div>
</div>
@@ -82,7 +82,7 @@
<div class="toast-body">
</div>
</div>
</div>
</div>
@endsection

View File

@@ -0,0 +1,91 @@
@extends('layouts.vertical', ['subtitle' => 'File Upload'])
@section('content')
@include('layouts.partials/page-title', ['title' => 'Form', 'subtitle' => 'File Uploads'])
<div class="row">
<div class="col-xl-12">
<div class="card">
<div class="card-header">
<div class="d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0">Upload Data Pariwisata</h5>
<button id="downloadtemptourisms" class="btn btn-secondary">Download Template</button>
</div>
</div>
<div class="card-body">
<div class="mb-3">
<div class="dropzone">
<form action="" method="post" enctype="multipart/form-data">
<div class="fallback">
<input id="file-dropzone"type="file" name="file" multiple/>
</div>
</form>
<div class="dz-message needsclick">
<i class="h1 bx bx-cloud-upload"></i>
<h3>Drop files here or click to upload.</h3>
<p class="card-subtitle">
Please upload a file with the extension <strong>.xls or .xlsx</strong> with a maximum size of <strong>10 MB</strong>.
<br>
</p>
</div>
</div>
<ul class="list-unstyled mb-0" id="dropzone-preview">
<li class="mt-2" id="dropzone-preview-list">
<!-- This is used as the file preview template -->
<div class="border rounded">
<div class="d-flex align-items-center p-2">
<div class="flex-shrink-0 me-3">
<div class="avatar-sm bg-light rounded">
<img data-dz-thumbnail class="img-fluid rounded d-block" src="#"
alt="" />
</div>
</div>
<div class="flex-grow-1">
<div class="pt-1">
<h5 class="fs-14 mb-1" data-dz-name>&nbsp;
</h5>
<p class="fs-13 text-muted mb-0" data-dz-size></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
</div>
<div class="flex-shrink-0 ms-3">
<button data-dz-remove class="btn btn-sm btn-danger">Delete</button>
</div>
</div>
</div>
</li>
</ul>
<!-- end dropzon-preview -->
</div>
<div class="d-flex justify-content-end">
<button id="submit-upload" class="btn btn-primary">Upload Files</button>
</div>
</div> <!-- end card body -->
</div> <!-- end card -->
</div> <!-- end col -->
</div> <!-- end row -->
<div class="toast-container position-fixed end-0 top-0 p-3">
<div id="toastUploadUmkm" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<div class="auth-logo me-auto">
</div>
<small class="text-muted"></small>
<button type="button" class="btn-close" data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
<div class="toast-body">
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/data/tourisms/form-upload.js'])
@endsection

View File

@@ -0,0 +1,130 @@
@extends('layouts.vertical', ['subtitle' => $subtitle]) <!-- Menggunakan subtitle dari controller -->
@section('content')
@include('layouts.partials/page-title', ['title' => $title, 'subtitle' => $subtitle]) <!-- Menggunakan title dan subtitle dari controller -->
<div class="row d-flex justify-content-center">
@if (session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="col-lg-12 col-md-12">
<div class="card">
<div class="card-header">
<button class="btn btn-danger float-end btn-back">
<i class='bx bx-arrow-back'></i>
Back
</button>
</div>
<div class="card-body">
<form id="create-update-form" action="{{ isset($modelInstance) && $modelInstance->id ? $apiUrl . '/' . $modelInstance->id : $apiUrl }}" method="POST">
@csrf
@if(isset($modelInstance))
@method('PUT')
@endif
<div class="row">
@foreach($fields as $field => $label)
<div class="col-md-6 form-group mb-3">
<label for="{{ $field }}">{{ $label }}</label>
@php
$fieldType = $fieldTypes[$field] ?? 'text'; // Default text jika tidak ditemukan tipe
@endphp
@if($fieldType == 'textarea')
<textarea id="{{ $field }}" name="{{ $field }}" class="form-control">{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}</textarea>
@elseif($fieldType == 'select' && isset($dropdownOptions[$field]))
<select id="{{ $field }}" name="{{ $field }}" class="form-control">
@foreach($dropdownOptions[$field] as $code => $name)
@php
// $selectedValue = old($field, $modelInstance->{$field});
$selectedValue = old($field, $modelInstance->$field ?? '');
$isSelected = strval($selectedValue) === strval($code);
@endphp
<option value="{{ $code }}" class="{{ $isSelected ? 'selected' : '' }}" {{ $isSelected ? 'selected' : '' }}>
{{ $name }}
</option>
@endforeach
</select>
@elseif($fieldType == 'combobox' && isset($dropdownOptions[$field]))
<input class="form-control" list="{{ $field }}Options" id="{{ $field }}" name="{{ $field }}"
value="{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}" placeholder="Type to search..." oninput="fetchOptions('{{ $field }}')">
<datalist id="{{ $field }}Options"></datalist>
@elseif($fieldType == 'date')
<input type="date" id="{{ $field }}" name="{{ $field }}" class="form-control"
value="{{ old($field, isset($modelInstance) && $modelInstance->{$field} ? \Carbon\Carbon::parse($modelInstance->{$field})->format('Y-m-d') : '') }}">
@else
<input type="{{ $fieldType }}" id="{{ $field }}" name="{{ $field }}" class="form-control" value="{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}">
@endif
</div>
@endforeach
</div>
<div class="d-flex justify-content-end">
<button type="button" class="btn {{ isset($modelInstance) ? 'btn-warning' : 'btn-success' }} width-lg btn-modal" data-bs-toggle="modal" data-bs-target="#confirmationModalCenter">
{{ isset($modelInstance) ? 'Update' : 'Create' }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="confirmationModalCenter" tabindex="-1"
aria-labelledby="confirmationModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmationModalCenterTitle">
{{ isset($modelInstance) ? 'Update Confirmation' : 'Create Confirmation' }}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<p>{{ isset($modelInstance) ? 'Are you sure you want to save the data changes?' : 'Are you sure you want to create new data based on the form contents?' }}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary {{ isset($modelInstance) ? 'btn-edit' : 'btn-create' }}" data-bs-dismiss="modal">Save changes</button>
</div>
</div>
</div>
</div>
<div class="toast-container position-fixed end-0 top-0 p-3">
<div id="toastEditUpdate" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<div class="auth-logo me-auto">
</div>
<small class="text-muted"></small>
<button type="button" class="btn-close" data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
<div class="toast-body">
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/data/tourisms/form-create-update.js'])
@endsection

View File

@@ -0,0 +1,61 @@
@extends('layouts.vertical', ['subtitle' => 'Pariwisata'])
@section('css')
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
@endsection
@section('content')
@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'Pariwisata'])
<div class="card">
<div class="card-header">
<h5 class="card-title">Daftar Pariwisata</h5>
</div>
<div class="card-body">
<div class="row">
<div class="d-flex justify-content-end gap-10 pb-3">
<button class="btn btn-success me-2 width-lg btn-create" data-model="data/tourisms">
<i class='bx bxs-file-plus'></i>
Create</button>
<button class="btn btn-primary width-lg btn-bulk-create" data-model="data/tourisms">
<i class='bx bx-upload' ></i>
Bulk Create
</button>
</div>
<div>
<div id="tourisms-data-table"></div>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade modalGMaps" tabindex="-1"
aria-labelledby="confirmationModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<iframe
src=""
width="100%"
height="450"
style="border:0;"
allowfullscreen=""
loading="lazy">
</iframe>
</div>
</div>
</div>
</div>
{{-- <div id="alert-container"></div> --}}
@endsection
@section('scripts')
@vite(['resources/js/data/tourisms/data-tourisms.js'])
@endsection

View File

@@ -0,0 +1,91 @@
@extends('layouts.vertical', ['subtitle' => 'File Upload'])
@section('content')
@include('layouts.partials/page-title', ['title' => 'Form', 'subtitle' => 'File Uploads'])
<div class="row">
<div class="col-xl-12">
<div class="card">
<div class="card-header">
<div class="d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0">Upload Data Umkm</h5>
<button id="downloadtempumkm" class="btn btn-secondary">Download Template</button>
</div>
</div>
<div class="card-body">
<div class="mb-3">
<div class="dropzone">
<form action="" method="post" enctype="multipart/form-data">
<div class="fallback">
<input id="file-dropzone"type="file" name="file" multiple/>
</div>
</form>
<div class="dz-message needsclick">
<i class="h1 bx bx-cloud-upload"></i>
<h3>Drop files here or click to upload.</h3>
<p class="card-subtitle">
Please upload a file with the extension <strong>.xls or .xlsx</strong> with a maximum size of <strong>10 MB</strong>.
<br>
</p>
</div>
</div>
<ul class="list-unstyled mb-0" id="dropzone-preview">
<li class="mt-2" id="dropzone-preview-list">
<!-- This is used as the file preview template -->
<div class="border rounded">
<div class="d-flex align-items-center p-2">
<div class="flex-shrink-0 me-3">
<div class="avatar-sm bg-light rounded">
<img data-dz-thumbnail class="img-fluid rounded d-block" src="#"
alt="" />
</div>
</div>
<div class="flex-grow-1">
<div class="pt-1">
<h5 class="fs-14 mb-1" data-dz-name>&nbsp;
</h5>
<p class="fs-13 text-muted mb-0" data-dz-size></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
</div>
<div class="flex-shrink-0 ms-3">
<button data-dz-remove class="btn btn-sm btn-danger">Delete</button>
</div>
</div>
</div>
</li>
</ul>
<!-- end dropzon-preview -->
</div>
<div class="d-flex justify-content-end">
<button id="submit-upload" class="btn btn-primary">Upload Files</button>
</div>
</div> <!-- end card body -->
</div> <!-- end card -->
</div> <!-- end col -->
</div> <!-- end row -->
<div class="toast-container position-fixed end-0 top-0 p-3">
<div id="toastUploadUmkm" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<div class="auth-logo me-auto">
</div>
<small class="text-muted"></small>
<button type="button" class="btn-close" data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
<div class="toast-body">
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/data/umkm/form-upload.js'])
@endsection

View File

@@ -0,0 +1,127 @@
@extends('layouts.vertical', ['subtitle' => $subtitle]) <!-- Menggunakan subtitle dari controller -->
@section('content')
@include('layouts.partials/page-title', ['title' => $title, 'subtitle' => $subtitle]) <!-- Menggunakan title dan subtitle dari controller -->
<div class="row d-flex justify-content-center">
@if (session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="col-lg-12 col-md-12">
<div class="card">
<div class="card-header">
<button class="btn btn-danger float-end btn-back">
<i class='bx bx-arrow-back'></i>
Back
</button>
</div>
<div class="card-body">
<form id="create-update-form" action="{{ isset($modelInstance) && $modelInstance->id ? $apiUrl . '/' . $modelInstance->id : $apiUrl }}" method="POST">
@csrf
@if(isset($modelInstance))
@method('PUT')
@endif
<div class="row">
@foreach($fields as $field => $label)
<div class="col-md-6 form-group mb-3">
<label for="{{ $field }}">{{ $label }}</label>
@php
$fieldType = $fieldTypes[$field] ?? 'text'; // Default text jika tidak ditemukan tipe
@endphp
@if($fieldType == 'textarea')
<textarea id="{{ $field }}" name="{{ $field }}" class="form-control">{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}</textarea>
@elseif($fieldType == 'select' && isset($dropdownOptions[$field]))
<select id="{{ $field }}" name="{{ $field }}" class="form-control">
@foreach($dropdownOptions[$field] as $code => $name)
@php
// $selectedValue = old($field, $modelInstance->{$field});
$selectedValue = old($field, $modelInstance->$field ?? '');
$isSelected = strval($selectedValue) === strval($code);
@endphp
<option value="{{ $code }}" class="{{ $isSelected ? 'selected' : '' }}" {{ $isSelected ? 'selected' : '' }}>
{{ $name }}
</option>
@endforeach
</select>
@elseif($fieldType == 'combobox' && isset($dropdownOptions[$field]))
<input class="form-control" list="{{ $field }}Options" id="{{ $field }}" name="{{ $field }}"
value="{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}" placeholder="Type to search..." oninput="fetchOptions('{{ $field }}')">
<datalist id="{{ $field }}Options"></datalist>
@else
<input type="{{ $fieldType }}" id="{{ $field }}" name="{{ $field }}" class="form-control" value="{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}">
@endif
</div>
@endforeach
</div>
<div class="d-flex justify-content-end">
<button type="button" class="btn {{ isset($modelInstance) ? 'btn-warning' : 'btn-success' }} width-lg btn-modal" data-bs-toggle="modal" data-bs-target="#confirmationModalCenter">
{{ isset($modelInstance) ? 'Update' : 'Create' }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="confirmationModalCenter" tabindex="-1"
aria-labelledby="confirmationModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmationModalCenterTitle">
{{ isset($modelInstance) ? 'Update Confirmation' : 'Create Confirmation' }}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<p>{{ isset($modelInstance) ? 'Are you sure you want to save the data changes?' : 'Are you sure you want to create new data based on the form contents?' }}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary {{ isset($modelInstance) ? 'btn-edit' : 'btn-create' }}" data-bs-dismiss="modal">Save changes</button>
</div>
</div>
</div>
</div>
<div class="toast-container position-fixed end-0 top-0 p-3">
<div id="toastEditUpdate" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<div class="auth-logo me-auto">
</div>
<small class="text-muted"></small>
<button type="button" class="btn-close" data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
<div class="toast-body">
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/data/umkm/form-create-update.js'])
@endsection

View File

@@ -0,0 +1,38 @@
@extends('layouts.vertical', ['subtitle' => 'UMKM'])
@section('css')
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
@endsection
@section('content')
@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'UMKM'])
<div class="card">
<div class="card-header">
<h5 class="card-title">Daftar UMKM</h5>
</div>
<div class="card-body">
<div class="row">
<div class="d-flex justify-content-end gap-10 pb-3">
<button class="btn btn-success me-2 width-lg btn-create" data-model="data/umkm">
<i class='bx bxs-file-plus'></i>
Create</button>
<button class="btn btn-primary width-lg btn-bulk-create" data-model="data/umkm">
<i class='bx bx-upload' ></i>
Bulk Create
</button>
</div>
<div>
<div id="umkm-data-table"></div>
</div>
</div>
</div>
</div>
<div id="alert-container"></div>
@endsection
@section('scripts')
@vite(['resources/js/data/umkm/data-umkm.js'])
@endsection

View File

@@ -0,0 +1,28 @@
@extends('layouts.vertical', ['subtitle' => 'Report Pariwisata'])
@section('css')
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
@endsection
@section('content')
@include('layouts.partials/page-title', ['title' => 'Report', 'subtitle' => 'Report Pariwisata'])
<input id="tourism_based_KBLI" type="hidden" value="{{ json_encode($tourismBasedKBLI) }}">
<div class="card">
<div class="card-header">
<h5 class="card-title">Laporan Pariwisata</h5>
</div>
<div class="card-body">
<div class="row">
<div>
<div id="tourisms-report-data-table"></div>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/report/tourisms/index.js'])
@endsection

View File

@@ -77,5 +77,5 @@
@endsection
@section('scripts')
@vite(['resources/roles/role_menu.js'])
@vite(['resources/js/roles/role_menu.js'])
@endsection

View File

@@ -1,5 +1,6 @@
<?php
use App\Http\Controllers\Api\BusinessOrIndustriesController;
use App\Http\Controllers\Api\DashboardController;
use App\Http\Controllers\Api\DataSettingController;
use App\Http\Controllers\Api\GlobalSettingsController;
@@ -13,6 +14,8 @@ use App\Http\Controllers\Api\ScrapingController;
use App\Http\Controllers\Api\UsersController;
use App\Http\Controllers\Settings\SyncronizeController;
use App\Http\Controllers\Api\AdvertisementController;
use App\Http\Controllers\Api\UmkmController;
use App\Http\Controllers\Api\TourismController;
use Illuminate\Support\Facades\Route;
Route::post('/login', [UsersController::class, 'login'])->name('api.user.login');
@@ -52,7 +55,18 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
Route::apiResource('advertisements', AdvertisementController::class);
Route::get('/combobox/search-options', [AdvertisementController::class, 'searchOptionsInAdvertisements']);
Route::post('/advertisements/import', [AdvertisementController::class, 'importFromFile']);
Route::get('/download-template-advertisement', [AdvertisementController::class, 'downloadExcelAdvertisement']);
// umkm
Route::apiResource('umkm', UmkmController::class);
Route::post('/umkm/import', [UmkmController::class, 'importFromFile']);
Route::get('/download-template-umkm', [UmkmController::class, 'downloadExcelUmkm']);
//tourism
Route::apiResource('tourisms', TourismController::class);
Route::post('/tourisms/import', [TourismController::class, 'importFromFile']);
// data-settings
Route::apiResource('/api-data-settings', DataSettingController::class);
@@ -71,6 +85,10 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
// roles api
Route::apiResource('api-roles', RolesController::class);
//business industries api
Route::apiResource('api-business-industries', BusinessOrIndustriesController::class);
Route::post('api-business-industries/upload', [BusinessOrIndustriesController::class, 'upload'])->name('business-industries.upload');
});

View File

@@ -1,5 +1,7 @@
<?php
use App\Http\Controllers\BusinessOrIndustriesController;
use App\Http\Controllers\Dashboards\LackOfPotentialController;
use App\Http\Controllers\DataSettingController;
use App\Http\Controllers\Dashboards\BigDataController;
use App\Http\Controllers\Home\HomeController;
@@ -10,6 +12,9 @@ use App\Http\Controllers\RolesController;
use App\Http\Controllers\Settings\SettingsController;
use App\Http\Controllers\Settings\SyncronizeController;
use App\Http\Controllers\Data\AdvertisementController;
use App\Http\Controllers\Data\UmkmController;
use App\Http\Controllers\Data\TourismController;
use App\Http\Controllers\Report\ReportTourismController;
use Illuminate\Support\Facades\Route;
require __DIR__ . '/auth.php';
@@ -23,6 +28,7 @@ Route::group(['middleware' => 'auth'], function(){
Route::group(['prefix' => '/dashboards'], function(){
Route::get('/bigdata', [BigDataController::class, 'index'])->name('dashboard.home');
Route::get('/dashboard-pbg', [BigDataController::class, 'pbg'])->name('dashboard.pbg');
Route::get('/lack-of-potential', [LackOfPotentialController::class, 'lack_of_potential'])->name('dashboard.lack_of_potential');
});
// settings
@@ -62,5 +68,25 @@ Route::group(['middleware' => 'auth'], function(){
// Rute khusus untuk create dan bulk-create
Route::get('/advertisements/create', [AdvertisementController::class, 'create'])->name('advertisements.create');
Route::get('/advertisements/bulk-create', [AdvertisementController::class, 'bulkCreate'])->name('advertisements.bulk-create');
// Resource route, kecuali create karena dibuat terpisah
Route::resource('/umkm', UmkmController::class)->except(['create', 'show']);
// Rute khusus untuk create dan bulk-create
Route::get('/umkm/create', [UmkmController::class, 'create'])->name('umkm.create');
Route::get('/umkm/bulk-create', [UmkmController::class, 'bulkCreate'])->name('umkm.bulk-create');
// Resource route, kecuali create karena dibuat terpisah
Route::resource('/tourisms', TourismController::class)->except(['create', 'show']);
// Rute khusus untuk create dan bulk-create
Route::get('/tourisms/create', [TourismController::class, 'create'])->name('tourisms.create');
Route::get('/tourisms/bulk-create', [TourismController::class, 'bulkCreate'])->name('tourisms.bulk-create');
Route::resource('/business-industries',BusinessOrIndustriesController::class);
});
// Report
Route::group(['prefix' => '/report'], function(){
// Resource route, kecuali create karena dibuat terpisah
Route::resource('/tourisms-report', ReportTourismController::class);
});
});

File diff suppressed because one or more lines are too long

View File

@@ -49,11 +49,14 @@ export default defineConfig({
"resources/js/data/advertisements/form-upload.js",
//js-additional
"resources/js/dashboards/bigdata.js",
"resources/js/settings/syncronize/syncronize.js",
"resources/js/pbg-task/index.js",
"resources/js/settings/general/general-settings.js",
"resources/js/tables/common-table.js",
// dashboards
"resources/js/dashboards/bigdata.js",
"resources/js/dashboards/lack-of-potential.js",
// roles
"resources/js/roles/index.js",
"resources/js/roles/create.js",
@@ -71,6 +74,19 @@ export default defineConfig({
"resources/js/data-settings/index.js",
"resources/js/data-settings/create.js",
"resources/js/data-settings/update.js",
// business-industries
"resources/js/business-industries/create.js",
"resources/js/business-industries/update.js",
"resources/js/business-industries/index.js",
// umkm
"resources/js/data/umkm/data-umkm.js",
"resources/js/data/umkm/form-upload.js",
"resources/js/data/umkm/form-create-update.js",
// tourisms
"resources/js/data/tourisms/data-tourisms.js",
"resources/js/data/tourisms/form-create-update.js",
"resources/js/data/tourisms/form-upload.js",
"resources/js/report/tourisms/index.js",
],
refresh: true,
}),