Compare commits
37 Commits
fix/dashbo
...
fix/sync-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cc698a623 | ||
|
|
544ad1db46 | ||
|
|
30ca819aa1 | ||
|
|
b0bab784d1 | ||
|
|
01fda22c89 | ||
|
|
de300c2c32 | ||
|
|
7f8a2e4936 | ||
|
|
38948b6633 | ||
|
|
aa9943ba45 | ||
|
|
9e55ea0dbb | ||
|
|
93f0ac5ef7 | ||
|
|
8bae33519f | ||
|
|
6865e353e6 | ||
|
|
bb4ab5c769 | ||
|
|
e743b82087 | ||
|
|
c3c7b8e3ec | ||
|
|
d49035ce8d | ||
|
|
ffd9d3514c | ||
|
|
675477c734 | ||
|
|
4350c466e3 | ||
|
|
5ab407d672 | ||
|
|
2aaa487746 | ||
|
|
080582f7ab | ||
|
|
91475aeead | ||
|
|
a7afbd69fb | ||
|
|
1ff5587050 | ||
|
|
9c8a1a3f3f | ||
|
|
5c4be7635b | ||
|
|
ba315b1dee | ||
|
|
33b7131c33 | ||
|
|
7a56735099 | ||
|
|
dd331b4a08 | ||
|
|
dcd93d66e2 | ||
|
|
5d50d6d6cc | ||
|
|
39717d184c | ||
|
|
54146c8c08 | ||
|
|
e8da7193ef |
85
README.md
85
README.md
@@ -1,66 +1,37 @@
|
|||||||
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
|
# Usage icon
|
||||||
|
|
||||||
<p align="center">
|
search or pick icon in <a href="https://icon-sets.iconify.design/mingcute/?keyword=mingcute">here</a>
|
||||||
<a href="https://github.com/laravel/framework/actions"><img src="https://github.com/laravel/framework/workflows/tests/badge.svg" alt="Build Status"></a>
|
|
||||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
|
|
||||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
|
|
||||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## About Laravel
|
# Set up queue for running automatically
|
||||||
|
|
||||||
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
|
- Install Supervisor
|
||||||
|
|
||||||
- [Simple, fast routing engine](https://laravel.com/docs/routing).
|
```
|
||||||
- [Powerful dependency injection container](https://laravel.com/docs/container).
|
sudo apt update && sudo apt install supervisor -y
|
||||||
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
|
```
|
||||||
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
|
|
||||||
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
|
|
||||||
- [Robust background job processing](https://laravel.com/docs/queues).
|
|
||||||
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
|
|
||||||
|
|
||||||
Laravel is accessible, powerful, and provides tools required for large, robust applications.
|
- Create Supervisor Config
|
||||||
|
|
||||||
## Learning Laravel
|
```
|
||||||
|
sudo nano /etc/supervisor/conf.d/laravel-worker.conf
|
||||||
|
|
||||||
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
|
[program:laravel-worker]
|
||||||
|
process_name=%(program_name)s_%(process_num)02d
|
||||||
|
command=php /path-to-your-project/artisan queue:work --tries=3 --timeout=600
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
numprocs=1
|
||||||
|
user=www-data
|
||||||
|
redirect_stderr=true
|
||||||
|
stdout_logfile=/var/log/supervisor/laravel-worker.log
|
||||||
|
```
|
||||||
|
|
||||||
You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch.
|
- Reload Supervisor
|
||||||
|
|
||||||
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
|
```
|
||||||
|
sudo supervisorctl reread
|
||||||
## Laravel Sponsors
|
sudo supervisorctl update
|
||||||
|
sudo supervisorctl start laravel-worker
|
||||||
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the [Laravel Partners program](https://partners.laravel.com).
|
sudo supervisorctl restart laravel-worker
|
||||||
|
sudo supervisorctl status
|
||||||
### Premium Partners
|
```
|
||||||
|
|
||||||
- **[Vehikl](https://vehikl.com/)**
|
|
||||||
- **[Tighten Co.](https://tighten.co)**
|
|
||||||
- **[WebReinvent](https://webreinvent.com/)**
|
|
||||||
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
|
|
||||||
- **[64 Robots](https://64robots.com)**
|
|
||||||
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
|
|
||||||
- **[Cyber-Duck](https://cyber-duck.co.uk)**
|
|
||||||
- **[DevSquad](https://devsquad.com/hire-laravel-developers)**
|
|
||||||
- **[Jump24](https://jump24.co.uk)**
|
|
||||||
- **[Redberry](https://redberry.international/laravel/)**
|
|
||||||
- **[Active Logic](https://activelogic.com)**
|
|
||||||
- **[byte5](https://byte5.de)**
|
|
||||||
- **[OP.GG](https://op.gg)**
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
|
|
||||||
|
|
||||||
## Code of Conduct
|
|
||||||
|
|
||||||
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
|
|
||||||
|
|
||||||
## Security Vulnerabilities
|
|
||||||
|
|
||||||
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ class AdvertisementController extends Controller
|
|||||||
|
|
||||||
public function downloadExcelAdvertisement()
|
public function downloadExcelAdvertisement()
|
||||||
{
|
{
|
||||||
$filePath = storage_path('app/public/templates/template_reklame.xlsx');
|
$filePath = public_path('templates/template_reklame.xlsx');
|
||||||
|
|
||||||
// Cek apakah file ada
|
// Cek apakah file ada
|
||||||
if (!file_exists($filePath)) {
|
if (!file_exists($filePath)) {
|
||||||
|
|||||||
259
app/Http/Controllers/Api/BigDataResumeController.php
Normal file
259
app/Http/Controllers/Api/BigDataResumeController.php
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Resources\BigdataResumeResource;
|
||||||
|
use App\Models\BigdataResume;
|
||||||
|
use App\Models\DataSetting;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class BigDataResumeController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
$filterDate = $request->get("filterByDate");
|
||||||
|
|
||||||
|
// If filterByDate is "latest" or empty, get the most recent record
|
||||||
|
if (!$filterDate || $filterDate === "latest") {
|
||||||
|
$big_data_resume = BigdataResume::latest()->first();
|
||||||
|
} else {
|
||||||
|
// Filter by specific date
|
||||||
|
$big_data_resume = BigdataResume::whereDate('created_at', $filterDate)
|
||||||
|
->orderBy('id', 'desc')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$big_data_resume) {
|
||||||
|
return $this->response_empty_resume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data_settings = DataSetting::all();
|
||||||
|
if($data_settings->isEmpty()){
|
||||||
|
return response()->json(['message' => 'No data setting found']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$target_pad = floatval(optional($data_settings->where('key', 'TARGET_PAD')->first())->value);
|
||||||
|
$realisasi_terbit_pbg_sum = floatval(optional($data_settings->where('key', 'REALISASI_TERBIT_PBG_SUM')->first())->value);
|
||||||
|
$realisasi_terbit_pbg_count = floatval(optional($data_settings->where('key', 'REALISASI_TERBIT_PBG_COUNT')->first())->value);
|
||||||
|
$menuggu_klik_dpmptsp_sum = floatval(optional($data_settings->where('key', 'MENUNGGU_KLIK_DPMPTSP_SUM')->first())->value);
|
||||||
|
$menuggu_klik_dpmptsp_count = floatval(optional($data_settings->where('key', 'MENUNGGU_KLIK_DPMPTSP_COUNT')->first())->value);
|
||||||
|
$proses_dinas_teknis_sum = floatval(optional($data_settings->where('key', 'PROSES_DINAS_TEKNIS_SUM')->first())->value);
|
||||||
|
$proses_dinas_teknis_count = floatval(optional($data_settings->where('key', 'PROSES_DINAS_TEKNIS_COUNT')->first())->value);
|
||||||
|
|
||||||
|
$tata_ruang = $big_data_resume->spatial_sum;
|
||||||
|
$kekurangan_potensi = $target_pad - $big_data_resume->potention_sum;
|
||||||
|
|
||||||
|
// percentage kekurangan potensi
|
||||||
|
$kekurangan_potensi_percentage = $target_pad > 0 && $target_pad > 0
|
||||||
|
? round(($kekurangan_potensi / $target_pad) * 100, 2) : 0;
|
||||||
|
|
||||||
|
// percentage total potensi
|
||||||
|
$total_potensi_percentage = $big_data_resume->potention_sum > 0 && $target_pad > 0
|
||||||
|
? round(($big_data_resume->potention_sum / $target_pad) * 100, 2) : 0;
|
||||||
|
|
||||||
|
// percentage verified document
|
||||||
|
$verified_percentage = $big_data_resume->verified_sum > 0 && $big_data_resume->potention_sum > 0
|
||||||
|
? round(($big_data_resume->verified_sum / $big_data_resume->potention_sum) * 100, 2) : 0;
|
||||||
|
|
||||||
|
// percentage non-verified document
|
||||||
|
$non_verified_percentage = $big_data_resume->non_verified_sum > 0 && $big_data_resume->potention_sum > 0
|
||||||
|
? round(($big_data_resume->non_verified_sum / $big_data_resume->potention_sum) * 100, 2) : 0;
|
||||||
|
|
||||||
|
// percentage business document
|
||||||
|
$business_percentage = $big_data_resume->business_sum > 0 && $big_data_resume->non_verified_sum > 0
|
||||||
|
? round(($big_data_resume->business_sum / $big_data_resume->non_verified_sum) * 100, 2) : 0;
|
||||||
|
|
||||||
|
// percentage non-business document
|
||||||
|
$non_business_percentage = $big_data_resume->non_business_sum > 0 && $big_data_resume->potention_sum > 0
|
||||||
|
? round(($big_data_resume->non_business_sum / $big_data_resume->potention_sum) * 100, 2) : 0;
|
||||||
|
|
||||||
|
// percentage tata ruang
|
||||||
|
$tata_ruang_percentage = $tata_ruang > 0 && $big_data_resume->potention_sum > 0
|
||||||
|
? round(($tata_ruang / $big_data_resume->potention_sum) * 100, 2) : 0;
|
||||||
|
|
||||||
|
// percentage realisasi terbit pbg
|
||||||
|
$realisasi_terbit_percentage = $big_data_resume->verified_sum > 0 && $realisasi_terbit_pbg_sum > 0
|
||||||
|
? round(($realisasi_terbit_pbg_sum / $big_data_resume->verified_sum) * 100, 2) : 0;
|
||||||
|
|
||||||
|
// percentage menunggu klik dpmptsp
|
||||||
|
$menunggu_klik_dpmptsp_percentage = $big_data_resume->verified_sum > 0 && $menuggu_klik_dpmptsp_sum > 0
|
||||||
|
? round(($menuggu_klik_dpmptsp_sum / $big_data_resume->verified_sum) * 100, 2) : 0;
|
||||||
|
|
||||||
|
// percentage proses_dinas_teknis
|
||||||
|
$proses_dinas_teknis_percentage = $big_data_resume->verified_sum > 0 && $proses_dinas_teknis_sum > 0
|
||||||
|
? round(($proses_dinas_teknis_sum / $big_data_resume->verified_sum) * 100, 2) : 0;
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
'target_pad' => [
|
||||||
|
'sum' => $target_pad,
|
||||||
|
'percentage' => 100,
|
||||||
|
],
|
||||||
|
'tata_ruang' => [
|
||||||
|
'sum' => $big_data_resume->spatial_sum,
|
||||||
|
'count' => $big_data_resume->spatial_count,
|
||||||
|
'percentage' => $tata_ruang_percentage,
|
||||||
|
],
|
||||||
|
'kekurangan_potensi' => [
|
||||||
|
'sum' => $kekurangan_potensi,
|
||||||
|
'percentage' => $kekurangan_potensi_percentage
|
||||||
|
],
|
||||||
|
'total_potensi' => [
|
||||||
|
'sum' => (float) $big_data_resume->potention_sum,
|
||||||
|
'count' => $big_data_resume->potention_count,
|
||||||
|
'percentage' => $total_potensi_percentage
|
||||||
|
],
|
||||||
|
'verified_document' => [
|
||||||
|
'sum' => (float) $big_data_resume->verified_sum,
|
||||||
|
'count' => $big_data_resume->verified_count,
|
||||||
|
'percentage' => $verified_percentage
|
||||||
|
],
|
||||||
|
'non_verified_document' => [
|
||||||
|
'sum' => (float) $big_data_resume->non_verified_sum,
|
||||||
|
'count' => $big_data_resume->non_verified_count,
|
||||||
|
'percentage' => $non_verified_percentage
|
||||||
|
],
|
||||||
|
'business_document' => [
|
||||||
|
'sum' => (float) $big_data_resume->business_sum,
|
||||||
|
'count' => $big_data_resume->business_count,
|
||||||
|
'percentage' => $business_percentage
|
||||||
|
],
|
||||||
|
'non_business_document' => [
|
||||||
|
'sum' => (float) $big_data_resume->non_business_sum,
|
||||||
|
'count' => $big_data_resume->non_business_count,
|
||||||
|
'percentage' => $non_business_percentage
|
||||||
|
],
|
||||||
|
'realisasi_terbit' => [
|
||||||
|
'sum' => $realisasi_terbit_pbg_sum,
|
||||||
|
'count' => $realisasi_terbit_pbg_count,
|
||||||
|
'percentage' => $realisasi_terbit_percentage
|
||||||
|
],
|
||||||
|
'menunggu_klik_dpmptsp' => [
|
||||||
|
'sum' => $menuggu_klik_dpmptsp_sum,
|
||||||
|
'count' => $menuggu_klik_dpmptsp_count,
|
||||||
|
'percentage' => $menunggu_klik_dpmptsp_percentage
|
||||||
|
],
|
||||||
|
'proses_dinas_teknis' => [
|
||||||
|
'sum' => $proses_dinas_teknis_sum,
|
||||||
|
'count' => $proses_dinas_teknis_count,
|
||||||
|
'percentage' => $proses_dinas_teknis_percentage
|
||||||
|
]
|
||||||
|
];
|
||||||
|
return response()->json($result);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
return response()->json(['message' => 'Error when fetching data'], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bigdata_report(Request $request){
|
||||||
|
try{
|
||||||
|
$query = BigdataResume::query()->orderBy('id', 'desc');
|
||||||
|
|
||||||
|
if($request->filled('search')){
|
||||||
|
$query->where('name', 'LIKE', '%'.$request->input('search').'%');
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = $query->paginate(15);
|
||||||
|
return BigdataResumeResource::collection($query)->response()->getData(true);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
return response()->json(['message' => 'Error when fetching data'], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(Request $request, string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
private function response_empty_resume(){
|
||||||
|
$result = [
|
||||||
|
'target_pad' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'percentage' => 100,
|
||||||
|
],
|
||||||
|
'tata_ruang' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'percentage' => 0,
|
||||||
|
],
|
||||||
|
'kekurangan_potensi' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'percentage' => 0
|
||||||
|
],
|
||||||
|
'total_potensi' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'count' => 0,
|
||||||
|
'percentage' => 0
|
||||||
|
],
|
||||||
|
'verified_document' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'count' => 0,
|
||||||
|
'percentage' => 0
|
||||||
|
],
|
||||||
|
'non_verified_document' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'count' => 0,
|
||||||
|
'percentage' => 0
|
||||||
|
],
|
||||||
|
'business_document' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'count' => 0,
|
||||||
|
'percentage' => 0
|
||||||
|
],
|
||||||
|
'non_business_document' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'count' => 0,
|
||||||
|
'percentage' => 0
|
||||||
|
],
|
||||||
|
'realisasi_terbit' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'count' => 0,
|
||||||
|
'percentage' => 0
|
||||||
|
],
|
||||||
|
'menunggu_klik_dpmptsp' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'count' => 0,
|
||||||
|
'percentage' => 0
|
||||||
|
],
|
||||||
|
'proses_dinas_teknis' => [
|
||||||
|
'sum' => 0,
|
||||||
|
'count' => 0,
|
||||||
|
'percentage' => 0
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ use App\Models\BusinessOrIndustry;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use \Illuminate\Support\Facades\Validator;
|
use \Illuminate\Support\Facades\Validator;
|
||||||
|
use App\Http\Requests\ExcelUploadRequest;
|
||||||
class BusinessOrIndustriesController extends Controller
|
class BusinessOrIndustriesController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -79,29 +80,15 @@ class BusinessOrIndustriesController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function upload(Request $request){
|
public function upload(ExcelUploadRequest $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 {
|
try {
|
||||||
// Ambil file dari request
|
if(!$request->hasFile('file')){
|
||||||
$file = $request->file('file');
|
return response()->json([
|
||||||
|
'error' => 'No file provided'
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
// Menggunakan Laravel Excel untuk mengimpor file
|
$file = $request->file('file');
|
||||||
Excel::import(new BusinessIndustriesImport, $file);
|
Excel::import(new BusinessIndustriesImport, $file);
|
||||||
|
|
||||||
// Jika sukses, kembalikan respons sukses
|
// Jika sukses, kembalikan respons sukses
|
||||||
|
|||||||
130
app/Http/Controllers/Api/CustomersController.php
Normal file
130
app/Http/Controllers/Api/CustomersController.php
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\CustomersRequest;
|
||||||
|
use App\Http\Requests\ExcelUploadRequest;
|
||||||
|
use App\Http\Resources\CustomersResource;
|
||||||
|
use App\Imports\CustomersImport;
|
||||||
|
use App\Models\Customer;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
|
||||||
|
class CustomersController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$query = Customer::query()->orderBy('id', 'desc');
|
||||||
|
if ($request->has('search') &&!empty($request->get('search'))) {
|
||||||
|
$query = $query->where('nomor_pelanggan', 'LIKE', '%'.$request->get('search').'%')
|
||||||
|
->orWhere('nama', 'LIKE', '%'.$request->get('search').'%')
|
||||||
|
->orWhere('kota_pelayanan', 'LIKE', '%'.$request->get('search').'%');
|
||||||
|
}
|
||||||
|
return CustomersResource::collection($query->paginate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(CustomersRequest $request)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
$customer = Customer::create($request->validated());
|
||||||
|
return response()->json(['message' => 'Successfully created', new CustomersResource($customer)]);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Failed to create customer',
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(string $id)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
$customer = Customer::find($id);
|
||||||
|
if($customer){
|
||||||
|
return new CustomersResource($customer);
|
||||||
|
} else {
|
||||||
|
return response()->json(['message' => 'Customer not found'], 404);
|
||||||
|
}
|
||||||
|
}catch(\Exception $e){
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Failed to retrieve customer',
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(CustomersRequest $request, string $id)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
$customer = Customer::find($id);
|
||||||
|
if($customer){
|
||||||
|
$customer->update($request->validated());
|
||||||
|
return response()->json(['message' => 'Successfully updated', new CustomersResource($customer)]);
|
||||||
|
} else {
|
||||||
|
return response()->json(['message' => 'Customer not found'], 404);
|
||||||
|
}
|
||||||
|
}catch(\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Failed to update customer',
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(string $id)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
$customer = Customer::find($id);
|
||||||
|
if($customer){
|
||||||
|
$customer->delete();
|
||||||
|
return response()->json(['message' => 'Successfully deleted']);
|
||||||
|
}else {
|
||||||
|
return response()->json(['message' => 'Customer not found'], 404);
|
||||||
|
}
|
||||||
|
}catch(\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Failed to delete customer',
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function upload(ExcelUploadRequest $request){
|
||||||
|
try{
|
||||||
|
if(!$request->hasFile('file')){
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'No file provided'
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $request->file('file');
|
||||||
|
Excel::import(new CustomersImport, $file);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'File uploaded successfully',
|
||||||
|
]);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
\Log::info($e->getMessage());
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'Failed to upload file',
|
||||||
|
'message' => $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Http/Controllers/Api/LackOfPotentialController.php
Normal file
31
app/Http/Controllers/Api/LackOfPotentialController.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Advertisement;
|
||||||
|
use App\Models\Customer;
|
||||||
|
use App\Models\SpatialPlanning;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class LackOfPotentialController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function count_lack_of_potential(){
|
||||||
|
try{
|
||||||
|
$total_reklame = Advertisement::count();
|
||||||
|
$total_pdam = Customer::count();
|
||||||
|
$total_tata_ruang = SpatialPlanning::count();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'total_reklame' => $total_reklame,
|
||||||
|
'total_pdam' => $total_pdam,
|
||||||
|
'total_tata_ruang' => $total_tata_ruang
|
||||||
|
], 200);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Error: '.$e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,11 @@
|
|||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\MenuRequest;
|
||||||
|
use App\Http\Resources\MenuResource;
|
||||||
use App\Models\Menu;
|
use App\Models\Menu;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class MenusController extends Controller
|
class MenusController extends Controller
|
||||||
{
|
{
|
||||||
@@ -13,7 +16,7 @@ class MenusController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$query = Menu::query();
|
$query = Menu::query()->orderBy('id', 'desc');
|
||||||
|
|
||||||
if($request->has("search") && !empty($request->get("search"))){
|
if($request->has("search") && !empty($request->get("search"))){
|
||||||
$query = $query->where("name", "like", "%".$request->get("search")."%");
|
$query = $query->where("name", "like", "%".$request->get("search")."%");
|
||||||
@@ -25,9 +28,15 @@ class MenusController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Store a newly created resource in storage.
|
* Store a newly created resource in storage.
|
||||||
*/
|
*/
|
||||||
public function store(Request $request)
|
public function store(MenuRequest $request)
|
||||||
{
|
{
|
||||||
//
|
try{
|
||||||
|
$menu = Menu::create($request->validated());
|
||||||
|
return response()->json(['message' => 'Menu created successfully', 'data' => new MenuResource($menu)]);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
Log::error($e);
|
||||||
|
return response()->json(['message' => 'Error when creating menu'], 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,15 +44,37 @@ class MenusController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function show(string $id)
|
public function show(string $id)
|
||||||
{
|
{
|
||||||
//
|
try{
|
||||||
|
$menu = Menu::find($id);
|
||||||
|
if($menu){
|
||||||
|
return response()->json(['message' => 'Menu found', 'data' => new MenuResource($menu)]);
|
||||||
|
} else {
|
||||||
|
return response()->json(['message' => 'Menu not found'], 404);
|
||||||
|
}
|
||||||
|
}catch(\Exception $e){
|
||||||
|
Log::error($e);
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
return response()->json(['message' => 'Error when finding menu'], 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*/
|
*/
|
||||||
public function update(Request $request, string $id)
|
public function update(MenuRequest $request, string $id)
|
||||||
{
|
{
|
||||||
//
|
try{
|
||||||
|
$menu = Menu::findOrFail($id);
|
||||||
|
if($menu){
|
||||||
|
$menu->update($request->validated());
|
||||||
|
return response()->json(['message' => 'Menu updated successfully', 'data' => new MenuResource($menu)]);
|
||||||
|
} else {
|
||||||
|
return response()->json(['message' => 'Menu not found'], 404);
|
||||||
|
}
|
||||||
|
}catch(\Exception $e){
|
||||||
|
Log::error($e);
|
||||||
|
return response()->json(['message' => 'Error when updating menu'], 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,6 +82,28 @@ class MenusController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function destroy(string $id)
|
public function destroy(string $id)
|
||||||
{
|
{
|
||||||
//
|
try{
|
||||||
|
$menu = Menu::findOrFail($id);
|
||||||
|
if($menu){
|
||||||
|
$this->deleteChildren($menu);
|
||||||
|
$menu->roles()->detach();
|
||||||
|
$menu->delete();
|
||||||
|
return response()->json(['message' => 'Menu deleted successfully']);
|
||||||
|
} else {
|
||||||
|
return response()->json(['message' => 'Menu not found'], 404);
|
||||||
|
}
|
||||||
|
}catch(\Exception $e){
|
||||||
|
Log::error($e);
|
||||||
|
return response()->json(['message' => 'Error when deleting menu'], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deleteChildren($menu)
|
||||||
|
{
|
||||||
|
foreach ($menu->children as $child) {
|
||||||
|
$this->deleteChildren($child); // Recursively delete its children
|
||||||
|
$child->roles()->detach(); // Detach roles before deleting
|
||||||
|
$child->delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,35 @@ class PbgTaskController extends Controller
|
|||||||
public function __construct(GoogleSheetService $googleSheetService){
|
public function __construct(GoogleSheetService $googleSheetService){
|
||||||
$this->googleSheetService = $googleSheetService;
|
$this->googleSheetService = $googleSheetService;
|
||||||
}
|
}
|
||||||
public function index()
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
//
|
info($request);
|
||||||
|
|
||||||
|
$isLastUpdated = filter_var($request->query('isLastUpdated', false), FILTER_VALIDATE_BOOLEAN);
|
||||||
|
|
||||||
|
$query = PbgTask::query();
|
||||||
|
|
||||||
|
if ($isLastUpdated) {
|
||||||
|
$query->orderBy('updated_at', 'desc');
|
||||||
|
} else {
|
||||||
|
$query->where('status', 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil maksimal 10 data
|
||||||
|
$pbg_task = $query->limit(10)->get();
|
||||||
|
$totalData = $pbg_task->count();
|
||||||
|
|
||||||
|
// Tambahkan nomor urut
|
||||||
|
$data = $pbg_task->map(function ($item, $index) {
|
||||||
|
return array_merge($item->toArray(), ['no' => $index + 1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $data,
|
||||||
|
'meta' => [
|
||||||
|
'total' => $totalData
|
||||||
|
]
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\RoleRequest;
|
||||||
use App\Models\Role;
|
use App\Models\Role;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ class RolesController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$query = Role::query();
|
$query = Role::query()->orderBy('id', 'desc');
|
||||||
|
|
||||||
if($request->has('search') && !empty($request->get('search'))){
|
if($request->has('search') && !empty($request->get('search'))){
|
||||||
$query = $query->where('name', 'like', '%'. $request->get('search') . '%');
|
$query = $query->where('name', 'like', '%'. $request->get('search') . '%');
|
||||||
@@ -25,9 +26,14 @@ class RolesController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Store a newly created resource in storage.
|
* Store a newly created resource in storage.
|
||||||
*/
|
*/
|
||||||
public function store(Request $request)
|
public function store(RoleRequest $request)
|
||||||
{
|
{
|
||||||
//
|
try{
|
||||||
|
$role = Role::create($request->validated());
|
||||||
|
return response()->json(['message' => 'Successfully created', 'data' => $role]);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
return response()->json(['message' => 'Error when creating role', 'error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,15 +41,34 @@ class RolesController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function show(string $id)
|
public function show(string $id)
|
||||||
{
|
{
|
||||||
//
|
try{
|
||||||
|
$role = Role::find($id);
|
||||||
|
if($role){
|
||||||
|
return response()->json(['data' => $role]);
|
||||||
|
} else {
|
||||||
|
return response()->json(['message' => 'Role not found'], 404);
|
||||||
|
}
|
||||||
|
}catch(\Exception $e){
|
||||||
|
return response()->json(['message' => 'Error when getting role', 'error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*/
|
*/
|
||||||
public function update(Request $request, string $id)
|
public function update(RoleRequest $request, string $id)
|
||||||
{
|
{
|
||||||
//
|
try{
|
||||||
|
$role = Role::find($id);
|
||||||
|
if($role){
|
||||||
|
$role->update($request->validated());
|
||||||
|
return response()->json(['message' => 'Successfully updated', 'data' => $role]);
|
||||||
|
} else {
|
||||||
|
return response()->json(['message' => 'Role not found'], 404);
|
||||||
|
}
|
||||||
|
}catch(\Exception $e){
|
||||||
|
return response()->json(['message' => 'Error when updating role', 'error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,6 +76,16 @@ class RolesController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function destroy(string $id)
|
public function destroy(string $id)
|
||||||
{
|
{
|
||||||
//
|
try{
|
||||||
|
$role = Role::find($id);
|
||||||
|
if($role){
|
||||||
|
$role->delete();
|
||||||
|
return response()->json(['message' => 'Successfully deleted']);
|
||||||
|
} else {
|
||||||
|
return response()->json(['message' => 'Role not found'], 404);
|
||||||
|
}
|
||||||
|
}catch(\Exception $e){
|
||||||
|
return response()->json(['message' => 'Error when deleting role', 'error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
146
app/Http/Controllers/Api/SpatialPlanningController.php
Normal file
146
app/Http/Controllers/Api/SpatialPlanningController.php
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Models\SpatialPlanning;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Requests\SpatialPlanningRequest;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Resources\SpatialPlanningResource;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use App\Imports\SpatialPlanningImport;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class SpatialPlanningController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
info($request);
|
||||||
|
$perPage = $request->input('per_page', 15);
|
||||||
|
$search = $request->input('search', '');
|
||||||
|
|
||||||
|
$query = SpatialPlanning::query();
|
||||||
|
if ($search) {
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('name', 'like', "%$search%")
|
||||||
|
->orWhere('kbli', 'like', "%$search%")
|
||||||
|
->orWhere('activities', 'like', "%$search%")
|
||||||
|
->orWhere('area', 'like', "%$search%")
|
||||||
|
->orWhere('location', 'like', "%$search%")
|
||||||
|
->orWhere('number', 'like', "%$search%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$spatialPlannings = $query->paginate($perPage);
|
||||||
|
|
||||||
|
// Menambhakan nomor urut (No)
|
||||||
|
$start = ($spatialPlannings->currentPage()-1) * $perPage + 1;
|
||||||
|
|
||||||
|
// Tambahkan nomor urut ke dalam data
|
||||||
|
$data = $spatialPlannings->map(function ($item, $index) use ($start) {
|
||||||
|
return array_merge($item->toArray(), ['no' => $start + $index]);
|
||||||
|
});
|
||||||
|
|
||||||
|
info($data);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $data,
|
||||||
|
'meta' => [
|
||||||
|
'total' => $spatialPlannings->total(),
|
||||||
|
'per_page' => $spatialPlannings->perPage(),
|
||||||
|
'current_page' => $spatialPlannings->currentPage(),
|
||||||
|
'last_page'=>$spatialPlannings->lastPage(),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(SpatialPlanningRequest $request): SpatialPlanning
|
||||||
|
{
|
||||||
|
$data = $request->validated();
|
||||||
|
return SpatialPlanning::create($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* import spatial planning from excel
|
||||||
|
*/
|
||||||
|
public function importFromFile(Request $request)
|
||||||
|
{
|
||||||
|
info($request);
|
||||||
|
//validasi file
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'file' => 'required|mimes:xlsx, xls|max:10240'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return response()->json([
|
||||||
|
'message'=>'File vaildation failed.',
|
||||||
|
"errors"=>$validator->errors()
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$file = $request->file('file');
|
||||||
|
Excel::import(new SpatialPlanningImport, $file);
|
||||||
|
return response()->json([
|
||||||
|
'message'=>'File uploaded and imported successfully!'
|
||||||
|
], 200);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message'=>'Error during file import.',
|
||||||
|
'error'=>$e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(SpatialPlanning $spatialPlanning): SpatialPlanning
|
||||||
|
{
|
||||||
|
return $spatialPlanning;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(SpatialPlanningRequest $request, SpatialPlanning $spatialPlanning): SpatialPlanning
|
||||||
|
{
|
||||||
|
info($request);
|
||||||
|
$data = $request->validated();
|
||||||
|
info($data);
|
||||||
|
|
||||||
|
$spatialPlanning->update($data);
|
||||||
|
|
||||||
|
return $spatialPlanning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(SpatialPlanning $spatialPlanning): Response
|
||||||
|
{
|
||||||
|
$spatialPlanning->delete();
|
||||||
|
|
||||||
|
return response()->noContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function downloadExcelSpatialPlanning()
|
||||||
|
{
|
||||||
|
$filePath = public_path('templates/template_spatial_planning.xlsx');
|
||||||
|
info(sprintf("File Path: %s | Exists: %s", $filePath, file_exists($filePath) ? 'Yes' : 'No'));
|
||||||
|
|
||||||
|
// Cek apakah file ada
|
||||||
|
if (!file_exists($filePath)) {
|
||||||
|
return response()-> json(['message' => 'File tidak ditemukan!'], Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return file to download
|
||||||
|
return response()->download($filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,13 @@ class TourismController extends Controller
|
|||||||
$search = $request->input('search', '');
|
$search = $request->input('search', '');
|
||||||
|
|
||||||
$query = Tourism::query();
|
$query = Tourism::query();
|
||||||
|
if ($search) {
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('business_name', 'like', "%$search%")
|
||||||
|
->orWhere('project_name', 'like', "%$search%")
|
||||||
|
->orWhere('business_address', 'like', "%$search%");
|
||||||
|
});
|
||||||
|
}
|
||||||
$tourisms = $query->paginate($perPage);
|
$tourisms = $query->paginate($perPage);
|
||||||
|
|
||||||
$tourisms->getCollection()->transform(function ($tourisms) {
|
$tourisms->getCollection()->transform(function ($tourisms) {
|
||||||
@@ -36,8 +43,14 @@ class TourismController extends Controller
|
|||||||
return $tourisms;
|
return $tourisms;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$start = ($tourisms->currentPage()-1) * $perPage + 1;
|
||||||
|
|
||||||
|
$data = $tourisms->map(function ($item, $index) use ($start) {
|
||||||
|
return array_merge($item->toArray(), ['no' => $start + $index]);
|
||||||
|
});
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'data' => TourismResource::collection($tourisms),
|
'data' => $data,
|
||||||
'meta' => [
|
'meta' => [
|
||||||
'total' => $tourisms->total(),
|
'total' => $tourisms->total(),
|
||||||
'per_page' => $tourisms->perPage(),
|
'per_page' => $tourisms->perPage(),
|
||||||
@@ -93,6 +106,18 @@ class TourismController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAllLocation()
|
||||||
|
{
|
||||||
|
$locations = Tourism::whereNotNull('longitude')
|
||||||
|
->whereNotNull('latitude')
|
||||||
|
->select('project_name', 'longitude', 'latitude')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $locations
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Display the specified resource.
|
||||||
*/
|
*/
|
||||||
@@ -127,4 +152,18 @@ class TourismController extends Controller
|
|||||||
|
|
||||||
return response()->noContent();
|
return response()->noContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function downloadExcelTourism()
|
||||||
|
{
|
||||||
|
$filePath = public_path('templates/template_pariwisata.xlsx');
|
||||||
|
info(sprintf("File Path: %s | Exists: %s", $filePath, file_exists($filePath) ? 'Yes' : 'No'));
|
||||||
|
|
||||||
|
// Cek apakah file ada
|
||||||
|
if (!file_exists($filePath)) {
|
||||||
|
return response()-> json(['message' => 'File tidak ditemukan!'], Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return file to download
|
||||||
|
return response()->download($filePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,17 @@ class UmkmController extends Controller
|
|||||||
|
|
||||||
$query = Umkm::query();
|
$query = Umkm::query();
|
||||||
|
|
||||||
|
if ($search) {
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('business_name', 'like', "%$search%")
|
||||||
|
->orWhere('business_address', 'like', "%$search%")
|
||||||
|
->orWhere('business_desc', 'like', "%$search%")
|
||||||
|
->orWhere('business_id_number', 'like', "%$search%")
|
||||||
|
->orWhere('owner_id', 'like', "%$search%")
|
||||||
|
->orWhere('owner_name', 'like', "%$search%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$umkm = $query->paginate($perPage);
|
$umkm = $query->paginate($perPage);
|
||||||
|
|
||||||
$umkm->getCollection()->transform(function ($umkm) {
|
$umkm->getCollection()->transform(function ($umkm) {
|
||||||
@@ -47,8 +58,14 @@ class UmkmController extends Controller
|
|||||||
return $umkm;
|
return $umkm;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$start = ($umkm->currentPage()-1) * $perPage + 1;
|
||||||
|
|
||||||
|
$data = $umkm->map(function ($item, $index) use ($start) {
|
||||||
|
return array_merge($item->toArray(), ['no' => $start + $index]);
|
||||||
|
});
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'data' => UmkmResource::collection($umkm),
|
'data' => $data,
|
||||||
'meta' => [
|
'meta' => [
|
||||||
'total' => $umkm->total(),
|
'total' => $umkm->total(),
|
||||||
'per_page' => $umkm->perPage(),
|
'per_page' => $umkm->perPage(),
|
||||||
@@ -176,7 +193,7 @@ class UmkmController extends Controller
|
|||||||
|
|
||||||
public function downloadExcelUmkm()
|
public function downloadExcelUmkm()
|
||||||
{
|
{
|
||||||
$filePath = storage_path('app/public/templates/template_umkm.xlsx');
|
$filePath = public_path('templates/template_umkm.xlsx');
|
||||||
|
|
||||||
// Cek apakah file ada
|
// Cek apakah file ada
|
||||||
if (!file_exists($filePath)) {
|
if (!file_exists($filePath)) {
|
||||||
|
|||||||
@@ -38,20 +38,20 @@ class UsersController extends Controller
|
|||||||
return response()->json(['message' => 'logged out successfully']);
|
return response()->json(['message' => 'logged out successfully']);
|
||||||
}
|
}
|
||||||
public function store(UsersRequest $request){
|
public function store(UsersRequest $request){
|
||||||
$validate_data = $request->validated();
|
$validate_data = $request->validated();
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
try{
|
try{
|
||||||
$user = User::create([
|
$user = User::create([
|
||||||
'name' => $validate_data->name,
|
'name' => $validate_data['name'],
|
||||||
'email' => $validate_data->email,
|
'email' => $validate_data['email'],
|
||||||
'password' => Hash::make($validate_data->password),
|
'password' => Hash::make($validate_data['password']),
|
||||||
'firstname' => $validate_data->firstname,
|
'firstname' => $validate_data['firstname'],
|
||||||
'lastname' => $validate_data->lastname,
|
'lastname' => $validate_data['lastname'],
|
||||||
'position' => $validate_data->position
|
'position' => $validate_data['position'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$user->roles()->attach($request->role_id);
|
$user->roles()->attach((int) $validate_data['role_id']);
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
return response()->json(['message' => 'Successfully created'],201);
|
return response()->json(['message' => 'Successfully created'],201);
|
||||||
@@ -60,4 +60,27 @@ class UsersController extends Controller
|
|||||||
return response()->json(['message' => $e->getMessage()],500);
|
return response()->json(['message' => $e->getMessage()],500);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
public function update(UsersRequest $request, $id){
|
||||||
|
try{
|
||||||
|
$validate_data = $request->validated();
|
||||||
|
$user = User::findOrFail($id);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
$user->update([
|
||||||
|
'name' => $validate_data['name'],
|
||||||
|
'email' => $validate_data['email'],
|
||||||
|
'firstname' => $validate_data['firstname'],
|
||||||
|
'lastname' => $validate_data['lastname'],
|
||||||
|
'position' => $validate_data['position']
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user->roles()->sync($request->role_id);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
return response()->json(['message' => 'Successfully updated'], 200);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
DB::rollBack();
|
||||||
|
return response()->json(['message' => $e->getMessage()],500);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
48
app/Http/Controllers/BigdataResumesController.php
Normal file
48
app/Http/Controllers/BigdataResumesController.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class BigdataResumesController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('bigdata-resumes.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*/
|
||||||
|
public function edit(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
26
app/Http/Controllers/CustomersController.php
Normal file
26
app/Http/Controllers/CustomersController.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Customer;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class CustomersController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('customers.index');
|
||||||
|
}
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('customers.create');
|
||||||
|
}
|
||||||
|
public function edit(string $id)
|
||||||
|
{
|
||||||
|
$data = Customer::findOrFail($id);
|
||||||
|
return view('customers.edit', compact('data'));
|
||||||
|
}
|
||||||
|
public function upload(){
|
||||||
|
return view('customers.upload');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,8 @@ class BigDataController extends Controller
|
|||||||
return view('dashboards.bigdata', compact('latest_created'));
|
return view('dashboards.bigdata', compact('latest_created'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pbg(){
|
public function pbg()
|
||||||
return view('index');
|
{
|
||||||
|
return view('dashboards.pbg');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
125
app/Http/Controllers/Data/SpatialPlanningController.php
Normal file
125
app/Http/Controllers/Data/SpatialPlanningController.php
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Data;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\SpatialPlanning;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class SpatialPlanningController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('data.spatialPlannings.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* show the form for creating a new resource.
|
||||||
|
*/
|
||||||
|
public function bulkCreate()
|
||||||
|
{
|
||||||
|
return view('data.spatialPlannings.form-upload');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$title = 'Rencana Tata Ruang';
|
||||||
|
$subtitle = "Create Data";
|
||||||
|
|
||||||
|
// Mengambil data untuk dropdown
|
||||||
|
$dropdownOptions = [];
|
||||||
|
|
||||||
|
$fields = $this->getFields();
|
||||||
|
$fieldTypes = $this->getFieldTypes();
|
||||||
|
|
||||||
|
$apiUrl = url('/api/spatial-plannings');
|
||||||
|
return view('data.spatialPlannings.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*/
|
||||||
|
public function edit(string $id)
|
||||||
|
{
|
||||||
|
$title = 'Rencana Tata Ruang';
|
||||||
|
$subtitle = 'Update Data';
|
||||||
|
|
||||||
|
$modelInstance = SpatialPlanning::find($id);
|
||||||
|
// Pastikan model ditemukan
|
||||||
|
if (!$modelInstance) {
|
||||||
|
return redirect()->route('spatialPlanning.index') ->with('error', 'Rencana tata ruang tidak ditemukan');
|
||||||
|
}
|
||||||
|
|
||||||
|
$dropdownOptions = [];
|
||||||
|
|
||||||
|
$fields = $this->getFields();
|
||||||
|
$fieldTypes = $this->getFieldTypes();
|
||||||
|
|
||||||
|
$apiUrl = url('/api/spatial-plannings');
|
||||||
|
return view('data.spatialPlannings.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(Request $request, string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getFields()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"name"=> "Nama",
|
||||||
|
"kbli"=> "KBLI",
|
||||||
|
"activities"=> "Kegiatan",
|
||||||
|
"area"=> "Luas (m2)",
|
||||||
|
"location"=> "Lokasi",
|
||||||
|
"number"=> "Nomor",
|
||||||
|
"date"=> "Tanggal",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getFieldTypes()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"name"=> "text",
|
||||||
|
"kbli"=> "text",
|
||||||
|
"activities"=> "text",
|
||||||
|
"area"=> "text",
|
||||||
|
"location"=> "text",
|
||||||
|
"number"=> "text",
|
||||||
|
"date"=> "date",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,7 +53,7 @@ class TourismController extends Controller
|
|||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
$title = 'Pariwisata';
|
$title = 'Pariwisata';
|
||||||
$subtitle = 'Create Data';
|
$subtitle = 'Update Data';
|
||||||
|
|
||||||
$modelInstance = Tourism::find($id);
|
$modelInstance = Tourism::find($id);
|
||||||
// Pastikan model ditemukan
|
// Pastikan model ditemukan
|
||||||
|
|||||||
12
app/Http/Controllers/GoogleApisController.php
Normal file
12
app/Http/Controllers/GoogleApisController.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class GoogleApisController extends Controller
|
||||||
|
{
|
||||||
|
public function index(){
|
||||||
|
return view('maps.google-api');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,4 +40,40 @@ class AdvertisementRequest extends FormRequest
|
|||||||
'contact' => 'required|string',
|
'contact' => 'required|string',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pesan error validasi
|
||||||
|
*/
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'no.required' => 'Nomor harus diisi.',
|
||||||
|
'business_name.required' => 'Nama usaha harus diisi.',
|
||||||
|
'business_name.string' => 'Nama usaha harus berupa teks.',
|
||||||
|
'npwpd.required' => 'NPWPD harus diisi.',
|
||||||
|
'npwpd.string' => 'NPWPD harus berupa teks.',
|
||||||
|
'advertisement_type.required' => 'Jenis reklame harus diisi.',
|
||||||
|
'advertisement_type.string' => 'Jenis reklame harus berupa teks.',
|
||||||
|
'advertisement_content.required' => 'Isi reklame harus diisi.',
|
||||||
|
'advertisement_content.string' => 'Isi reklame harus berupa teks.',
|
||||||
|
'business_address.required' => 'Alamat usaha harus diisi.',
|
||||||
|
'business_address.string' => 'Alamat usaha harus berupa teks.',
|
||||||
|
'advertisement_location.required' => 'Lokasi reklame harus diisi.',
|
||||||
|
'advertisement_location.string' => 'Lokasi reklame harus berupa teks.',
|
||||||
|
'village_name.required' => 'Nama desa harus diisi.',
|
||||||
|
'district_name.required' => 'Nama kecamatan harus diisi.',
|
||||||
|
'length.required' => 'Panjang harus diisi.',
|
||||||
|
'width.required' => 'Lebar harus diisi.',
|
||||||
|
'viewing_angle.required' => 'Sudut pandang harus diisi.',
|
||||||
|
'viewing_angle.string' => 'Sudut pandang harus berupa teks.',
|
||||||
|
'face.required' => 'Jumlah sisi harus diisi.',
|
||||||
|
'face.string' => 'Jumlah sisi harus berupa teks.',
|
||||||
|
'area.required' => 'Luas harus diisi.',
|
||||||
|
'area.string' => 'Luas harus berupa teks.',
|
||||||
|
'angle.required' => 'Sudut harus diisi.',
|
||||||
|
'angle.string' => 'Sudut harus berupa teks.',
|
||||||
|
'contact.required' => 'Kontak harus diisi.',
|
||||||
|
'contact.string' => 'Kontak harus berupa teks.',
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
33
app/Http/Requests/CustomersRequest.php
Normal file
33
app/Http/Requests/CustomersRequest.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class CustomersRequest 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 [
|
||||||
|
'nomor_pelanggan' => ['required', 'string'],
|
||||||
|
'kota_pelayanan' => ['required', 'string'],
|
||||||
|
'nama' => ['required', 'string'],
|
||||||
|
'alamat' => ['required', 'string'],
|
||||||
|
'latitude' => ['required', 'numeric', 'between:-90,90'],
|
||||||
|
'longitude' => ['required', 'numeric', 'between:-180,180'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ class DataSettingRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$id = $this->route('data_setting');
|
$id = $this->route('data_setting_id');
|
||||||
return [
|
return [
|
||||||
"key" => "required|unique:data_settings,key," . $id,
|
"key" => "required|unique:data_settings,key," . $id,
|
||||||
"value" => "required",
|
"value" => "required",
|
||||||
|
|||||||
28
app/Http/Requests/ExcelUploadRequest.php
Normal file
28
app/Http/Requests/ExcelUploadRequest.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class ExcelUploadRequest 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 [
|
||||||
|
"file" => "required|file|mimes:xlsx,xls|max:102400"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Http\Requests;
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
class MenuRequest extends FormRequest
|
class MenuRequest extends FormRequest
|
||||||
{
|
{
|
||||||
@@ -21,12 +22,14 @@ class MenuRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
|
$menuId = $this->route('menu_id'); // Get the menu ID if updating
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'name' => ['required','string','max:255'],
|
'name' => ['required', 'string', 'max:255', Rule::unique('menus', 'name')->ignore($menuId)],
|
||||||
'url' => ['nullable','string','max:255'],
|
'url' => ['nullable', 'string', 'max:255'],
|
||||||
'icon' => ['nullable','string','max:255'],
|
'icon' => ['nullable', 'string', 'max:255'],
|
||||||
'parent_id' => ['nullable','exists:menus,id'],
|
'parent_id' => ['nullable', 'exists:menus,id'],
|
||||||
'sort_order' => ['required','integer'],
|
'sort_order' => ['required', 'integer'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class RoleRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$roleId = $this->route('role');
|
$roleId = $this->route('role_id');
|
||||||
return [
|
return [
|
||||||
'name' => 'required|string|max:255|unique:roles,name,' . ($roleId ?? 'NULL') . ',id',
|
'name' => 'required|string|max:255|unique:roles,name,' . ($roleId ?? 'NULL') . ',id',
|
||||||
'description' => 'nullable|string',
|
'description' => 'nullable|string',
|
||||||
|
|||||||
52
app/Http/Requests/SpatialPlanningRequest.php
Normal file
52
app/Http/Requests/SpatialPlanningRequest.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class SpatialPlanningRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => 'string',
|
||||||
|
'kbli' => 'string',
|
||||||
|
'activities' => 'string',
|
||||||
|
'area' => 'string',
|
||||||
|
'location' => 'string',
|
||||||
|
'number' => 'string',
|
||||||
|
'date' => 'date_format:Y-m-d',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation messages for the defined validation rules.
|
||||||
|
*
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name.string' => 'Kolom Nama harus berupa teks.',
|
||||||
|
'kbli.string' => 'Kolom KBLI harus berupa teks.',
|
||||||
|
'activities.string' => 'Kolom Kegiatan harus berupa teks.',
|
||||||
|
'area.string' => 'Kolom Area harus berupa teks.',
|
||||||
|
'location.string' => 'Kolom Lokasi harus berupa teks.',
|
||||||
|
'number.string' => 'Kolom Nomor harus berupa teks.',
|
||||||
|
'date.date_format' => 'Format tanggal tidak valid, gunakan format Y-m-d H:i:s.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
35
app/Http/Requests/SpatialPlanningsRequest.php
Normal file
35
app/Http/Requests/SpatialPlanningsRequest.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class SpatialPlanningsRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required','string','max:255'],
|
||||||
|
'kbli' => ['required','string','max:255'],
|
||||||
|
'kegiatan' => ['required','string'],
|
||||||
|
'luas' => ['required','numeric','regex:/^\d{1,16}(\.\d{1,2})?$/'],
|
||||||
|
'lokasi' => ['required','string'],
|
||||||
|
'nomor' => ['required','string','max:255',Rule::unique('spatial_plannings')->ignore($this->id)],
|
||||||
|
'sp_date' => ['required','date'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,4 +49,85 @@ class TourismRequest extends FormRequest
|
|||||||
'tki' => 'required|string',
|
'tki' => 'required|string',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation messages for the defined validation rules.
|
||||||
|
*
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'project_id.required' => 'ID proyek harus diisi.',
|
||||||
|
'project_id.string' => 'ID proyek harus berupa teks.',
|
||||||
|
|
||||||
|
'project_type_id.required' => 'ID tipe proyek harus diisi.',
|
||||||
|
'project_type_id.string' => 'ID tipe proyek harus berupa teks.',
|
||||||
|
|
||||||
|
'nib.required' => 'NIB harus diisi.',
|
||||||
|
'nib.string' => 'NIB harus berupa teks.',
|
||||||
|
|
||||||
|
'business_name.required' => 'Nama usaha harus diisi.',
|
||||||
|
'business_name.string' => 'Nama usaha harus berupa teks.',
|
||||||
|
|
||||||
|
'oss_publication_date.required' => 'Tanggal publikasi OSS harus diisi.',
|
||||||
|
|
||||||
|
'investment_status_description.required' => 'Deskripsi status investasi harus diisi.',
|
||||||
|
'investment_status_description.string' => 'Deskripsi status investasi harus berupa teks.',
|
||||||
|
|
||||||
|
'business_form.required' => 'Bentuk usaha harus diisi.',
|
||||||
|
'business_form.string' => 'Bentuk usaha harus berupa teks.',
|
||||||
|
|
||||||
|
'project_risk.required' => 'Risiko proyek harus diisi.',
|
||||||
|
'project_risk.string' => 'Risiko proyek harus berupa teks.',
|
||||||
|
|
||||||
|
'project_name.required' => 'Nama proyek harus diisi.',
|
||||||
|
'project_name.string' => 'Nama proyek harus berupa teks.',
|
||||||
|
|
||||||
|
'business_scale.required' => 'Skala usaha harus diisi.',
|
||||||
|
'business_scale.string' => 'Skala usaha harus berupa teks.',
|
||||||
|
|
||||||
|
'business_address.required' => 'Alamat usaha harus diisi.',
|
||||||
|
'business_address.string' => 'Alamat usaha harus berupa teks.',
|
||||||
|
|
||||||
|
'district_name.required' => 'Nama kecamatan harus diisi.',
|
||||||
|
|
||||||
|
'village_name.required' => 'Nama desa harus diisi.',
|
||||||
|
|
||||||
|
'longitude.required' => 'Garis bujur harus diisi.',
|
||||||
|
'longitude.string' => 'Garis bujur harus berupa teks.',
|
||||||
|
|
||||||
|
'latitude.required' => 'Garis lintang harus diisi.',
|
||||||
|
'latitude.string' => 'Garis lintang harus berupa teks.',
|
||||||
|
|
||||||
|
'project_submission_date.required' => 'Tanggal pengajuan proyek harus diisi.',
|
||||||
|
|
||||||
|
'kbli.required' => 'Kode KBLI harus diisi.',
|
||||||
|
'kbli.string' => 'Kode KBLI harus berupa teks.',
|
||||||
|
|
||||||
|
'kbli_title.required' => 'Judul KBLI harus diisi.',
|
||||||
|
'kbli_title.string' => 'Judul KBLI harus berupa teks.',
|
||||||
|
|
||||||
|
'supervisory_sector.required' => 'Sektor pengawasan harus diisi.',
|
||||||
|
'supervisory_sector.string' => 'Sektor pengawasan harus berupa teks.',
|
||||||
|
|
||||||
|
'user_name.required' => 'Nama pengguna harus diisi.',
|
||||||
|
'user_name.string' => 'Nama pengguna harus berupa teks.',
|
||||||
|
|
||||||
|
'email.required' => 'Email harus diisi.',
|
||||||
|
'email.string' => 'Email harus berupa teks.',
|
||||||
|
|
||||||
|
'contact.required' => 'Kontak harus diisi.',
|
||||||
|
'contact.string' => 'Kontak harus berupa teks.',
|
||||||
|
|
||||||
|
'land_area_in_m2.required' => 'Luas lahan dalam m² harus diisi.',
|
||||||
|
'land_area_in_m2.string' => 'Luas lahan dalam m² harus berupa teks.',
|
||||||
|
|
||||||
|
'investment_amount.required' => 'Jumlah investasi harus diisi.',
|
||||||
|
'investment_amount.string' => 'Jumlah investasi harus berupa teks.',
|
||||||
|
|
||||||
|
'tki.required' => 'Jumlah tenaga kerja Indonesia harus diisi.',
|
||||||
|
'tki.string' => 'Jumlah tenaga kerja Indonesia harus berupa teks.',
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class UsersRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$userId = $this->route('user'); // Get user ID from route (used in update)
|
$userId = $this->route('users'); // Get user ID from route (used in update)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
@@ -31,7 +31,7 @@ class UsersRequest extends FormRequest
|
|||||||
'string',
|
'string',
|
||||||
'email',
|
'email',
|
||||||
'max:255',
|
'max:255',
|
||||||
Rule::unique('users')->ignore($userId), // Ignore the user's own email when updating
|
Rule::unique('users')->ignore($userId)
|
||||||
],
|
],
|
||||||
'password' => [$this->isMethod('post') ? 'required' : 'nullable', 'confirmed', 'max:255'],
|
'password' => [$this->isMethod('post') ? 'required' : 'nullable', 'confirmed', 'max:255'],
|
||||||
'firstname' => ['required', 'string', 'max:255'],
|
'firstname' => ['required', 'string', 'max:255'],
|
||||||
|
|||||||
42
app/Http/Resources/BigdataResumeResource.php
Normal file
42
app/Http/Resources/BigdataResumeResource.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class BigdataResumeResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'import_datasource_id' => $this->import_datasource_id,
|
||||||
|
'potention_count' => (int) $this->potention_count,
|
||||||
|
'potention_sum' => number_format((float) $this->potention_sum, 2, ',', '.'),
|
||||||
|
|
||||||
|
'non_verified_count' => (int) $this->non_verified_count,
|
||||||
|
'non_verified_sum' => number_format((float) $this->non_verified_sum, 2, ',', '.'),
|
||||||
|
|
||||||
|
'verified_count' => (int) $this->verified_count,
|
||||||
|
'verified_sum' => number_format((float) $this->verified_sum, 2, ',', '.'),
|
||||||
|
|
||||||
|
'business_count' => (int) $this->business_count,
|
||||||
|
'business_sum' => number_format((float) $this->business_sum, 2, ',', '.'),
|
||||||
|
|
||||||
|
'non_business_count' => (int) $this->non_business_count,
|
||||||
|
'non_business_sum' => number_format((float) $this->non_business_sum, 2, ',', '.'),
|
||||||
|
|
||||||
|
'spatial_count' => (int) $this->spatial_count,
|
||||||
|
'spatial_sum' => number_format((float) $this->spatial_sum, 2, ',', '.'),
|
||||||
|
|
||||||
|
'year' => $this->year,
|
||||||
|
'created_at' => $this->created_at->toDateTimeString(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/Http/Resources/CustomersResource.php
Normal file
19
app/Http/Resources/CustomersResource.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class CustomersResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return parent::toArray($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/Http/Resources/MenuResource.php
Normal file
19
app/Http/Resources/MenuResource.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class MenuResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return parent::toArray($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/Http/Resources/SpatialPlanningResource.php
Normal file
19
app/Http/Resources/SpatialPlanningResource.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class SpatialPlanningResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return parent::toArray($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/Http/Resources/SpatialPlanningsResource.php
Normal file
19
app/Http/Resources/SpatialPlanningsResource.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class SpatialPlanningsResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return parent::toArray($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,37 +3,105 @@
|
|||||||
namespace App\Imports;
|
namespace App\Imports;
|
||||||
|
|
||||||
use App\Models\BusinessOrIndustry;
|
use App\Models\BusinessOrIndustry;
|
||||||
use Maatwebsite\Excel\Concerns\ToModel;
|
|
||||||
use Maatwebsite\Excel\Concerns\ToCollection;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Maatwebsite\Excel\Concerns\ToCollection;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithChunkReading;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithBatchInserts;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class BusinessIndustriesImport implements ToCollection
|
class BusinessIndustriesImport implements ToCollection, WithMultipleSheets, WithChunkReading, WithBatchInserts, ShouldQueue, WithHeadingRow
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param array $row
|
* @param Collection $collection
|
||||||
*
|
*/
|
||||||
* @return \Illuminate\Database\Eloquent\Model|null
|
public function collection(Collection $collection)
|
||||||
*/
|
|
||||||
public function collection(Collection $rows)
|
|
||||||
{
|
{
|
||||||
foreach ($rows->skip(1) as $row){
|
try{
|
||||||
$clean_nop = preg_replace('/[^A-Za-z0-9]/', '', $row[2]);
|
$batchData = [];
|
||||||
if (!BusinessOrIndustry::where('nop', $clean_nop)->exists()) {
|
$batchSize = 1000;
|
||||||
BusinessOrIndustry::create([
|
|
||||||
'nama_kecamatan' => $row[0],
|
foreach ($collection as $row){
|
||||||
'nama_kelurahan' => $row[1],
|
if(!isset($row['nop']) || empty($row['nop'])){
|
||||||
'nop' => $clean_nop, // Store cleaned 'nop'
|
continue;
|
||||||
'nama_wajib_pajak' => $row[3],
|
}
|
||||||
'alamat_wajib_pajak' => $row[4],
|
|
||||||
'alamat_objek_pajak' => $row[5],
|
|
||||||
'luas_bumi' => $row[6],
|
$clean_nop = preg_replace('/[^A-Za-z0-9]/', '', $row['nop']);
|
||||||
'luas_bangunan' => $row[7],
|
|
||||||
'njop_bumi' => $row[8],
|
$batchData[] = [
|
||||||
'njop_bangunan' => $row[9],
|
'nama_kecamatan' => $row['nama_kecamatan'],
|
||||||
'ketetapan' => $row[10],
|
'nama_kelurahan' => $row['nama_kelurahan'],
|
||||||
'tahun_pajak' => $row[11],
|
'nop' => $clean_nop,
|
||||||
|
'nama_wajib_pajak' => $row['nama_wajib_pajak'],
|
||||||
|
'alamat_wajib_pajak' => $row['alamat_wajib_pajak'],
|
||||||
|
'alamat_objek_pajak' => $row['alamat_objek_pajak'],
|
||||||
|
'luas_bumi' => $row['luas_bumi'],
|
||||||
|
'luas_bangunan' => $row['luas_bangunan'],
|
||||||
|
'njop_bumi' => $row['njop_bumi'],
|
||||||
|
'njop_bangunan' => $row['njop_bangunan'],
|
||||||
|
'ketetapan' => $row['ketetapan'],
|
||||||
|
'tahun_pajak' => $row['tahun_pajak'],
|
||||||
|
];
|
||||||
|
|
||||||
|
if(count($batchData) >= $batchSize){
|
||||||
|
BusinessOrIndustry::upsert($batchData, ['nop'], [
|
||||||
|
'nama_kecamatan',
|
||||||
|
'nama_kelurahan',
|
||||||
|
'nama_wajib_pajak',
|
||||||
|
'alamat_wajib_pajak',
|
||||||
|
'alamat_objek_pajak',
|
||||||
|
'luas_bumi',
|
||||||
|
'luas_bangunan',
|
||||||
|
'njop_bumi',
|
||||||
|
'njop_bangunan',
|
||||||
|
'ketetapan',
|
||||||
|
'tahun_pajak',
|
||||||
|
]);
|
||||||
|
$batchData = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!empty($batchData)){
|
||||||
|
BusinessOrIndustry::upsert($batchData, ['nop'], [
|
||||||
|
'nama_kecamatan',
|
||||||
|
'nama_kelurahan',
|
||||||
|
'nama_wajib_pajak',
|
||||||
|
'alamat_wajib_pajak',
|
||||||
|
'alamat_objek_pajak',
|
||||||
|
'luas_bumi',
|
||||||
|
'luas_bangunan',
|
||||||
|
'njop_bumi',
|
||||||
|
'njop_bangunan',
|
||||||
|
'ketetapan',
|
||||||
|
'tahun_pajak',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
}catch(\Exception $exception){
|
||||||
|
Log::error('Error while importing Business Industries data:', ['error' => $exception->getMessage()]);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function sheets(): array {
|
||||||
|
return [
|
||||||
|
0 => $this
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function headingRow(): int
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function chunkSize(): int
|
||||||
|
{
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function batchSize(): int
|
||||||
|
{
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
92
app/Imports/CustomersImport.php
Normal file
92
app/Imports/CustomersImport.php
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Imports;
|
||||||
|
|
||||||
|
use App\Models\Customer;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Maatwebsite\Excel\Concerns\ToCollection;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithLimit;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithChunkReading;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithBatchInserts;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class CustomersImport implements ToCollection, WithMultipleSheets, WithChunkReading, WithBatchInserts, ShouldQueue, WithHeadingRow
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Collection $collection
|
||||||
|
*/
|
||||||
|
public function collection(Collection $collection)
|
||||||
|
{
|
||||||
|
$batchData = [];
|
||||||
|
$batchSize = 1000;
|
||||||
|
|
||||||
|
foreach ($collection as $row) {
|
||||||
|
if (!isset($row['nomor_pelanggan']) || empty($row['nomor_pelanggan'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$latitude = '0';
|
||||||
|
$longitude = '0';
|
||||||
|
|
||||||
|
if (isset($row['latkor']) && !empty(trim($row['latkor']))) {
|
||||||
|
$latitude = str_replace(',', '.', trim($row['latkor']));
|
||||||
|
if (is_numeric($latitude)) {
|
||||||
|
$latitude = bcadd($latitude, '0', 18);
|
||||||
|
} else {
|
||||||
|
$latitude = '0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$latitude = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($row['lonkor']) && !empty(trim($row['lonkor']))) {
|
||||||
|
$longitude = str_replace(',', '.', trim($row['lonkor']));
|
||||||
|
if (is_numeric($longitude)) {
|
||||||
|
$longitude = bcadd($longitude, '0', 18);
|
||||||
|
} else {
|
||||||
|
$longitude = '0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$longitude = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
$batchData[] = [
|
||||||
|
'nomor_pelanggan' => $row['nomor_pelanggan'] ?? '',
|
||||||
|
'kota_pelayanan' => $row['kota_pelayanan'] ?? '',
|
||||||
|
'nama' => $row['nama'] ?? '',
|
||||||
|
'alamat' => $row['alamat'] ?? '',
|
||||||
|
'latitude' => $latitude,
|
||||||
|
'longitude' => $longitude,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (count($batchData) >= $batchSize) {
|
||||||
|
Customer::upsert($batchData, ['nomor_pelanggan'], ['kota_pelayanan', 'nama', 'alamat', 'latitude', 'longitude']);
|
||||||
|
$batchData = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($batchData)) {
|
||||||
|
Customer::upsert($batchData, ['nomor_pelanggan'], ['kota_pelayanan', 'nama', 'alamat', 'latitude', 'longitude']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function sheets(): array {
|
||||||
|
return [
|
||||||
|
0 => $this
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function chunkSize(): int
|
||||||
|
{
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function batchSize(): int
|
||||||
|
{
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
63
app/Imports/SpatialPlanningImport.php
Normal file
63
app/Imports/SpatialPlanningImport.php
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Imports;
|
||||||
|
|
||||||
|
use App\Models\SpatialPlanning;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Maatwebsite\Excel\Concerns\ToCollection;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use DateTime;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class SpatialPlanningImport 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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) {
|
||||||
|
$dateValue = trim($row[7]);
|
||||||
|
info($dateValue);
|
||||||
|
$parsedDate = Carbon::createFromFormat('Y-m-d', $dateValue)->format('Y-m-d');
|
||||||
|
info($parsedDate);
|
||||||
|
|
||||||
|
$dataToInsert[] = [
|
||||||
|
'name'=>$row[1],
|
||||||
|
'kbli'=>$row[2],
|
||||||
|
'activities'=>$row[3],
|
||||||
|
'area'=>$row[4],
|
||||||
|
'location'=>$row[5],
|
||||||
|
'number'=>$row[6],
|
||||||
|
'date'=>$parsedDate,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!empty($dataToInsert)) {
|
||||||
|
SpatialPlanning::insert($dataToInsert);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -65,13 +65,6 @@ class TourismImport implements ToCollection
|
|||||||
// ambill village code yang village_name sama dengan $villageName
|
// ambill village code yang village_name sama dengan $villageName
|
||||||
$villageCode = $listTrueVillage[$villageName]['village_code'] ?? '000000';
|
$villageCode = $listTrueVillage[$villageName]['village_code'] ?? '000000';
|
||||||
|
|
||||||
|
|
||||||
// if (empty($row[16])) {
|
|
||||||
// info("Data kosong");
|
|
||||||
// } else {
|
|
||||||
// info("Baris ke- | Nilai: " . $row[16]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
$excelSerialDate = $row[16];
|
$excelSerialDate = $row[16];
|
||||||
if (is_numeric($excelSerialDate)) {
|
if (is_numeric($excelSerialDate)) {
|
||||||
$projectSubmissionDate = Carbon::createFromFormat('Y-m-d', '1899-12-30')
|
$projectSubmissionDate = Carbon::createFromFormat('Y-m-d', '1899-12-30')
|
||||||
@@ -82,8 +75,6 @@ class TourismImport implements ToCollection
|
|||||||
->format('Y-m-d H:i:s');
|
->format('Y-m-d H:i:s');
|
||||||
}
|
}
|
||||||
|
|
||||||
info("Tanggal dikonversi: " . $projectSubmissionDate);
|
|
||||||
|
|
||||||
$dataToInsert[] = [
|
$dataToInsert[] = [
|
||||||
'project_id' => $row[1],
|
'project_id' => $row[1],
|
||||||
'project_type_id' => $row[2],
|
'project_type_id' => $row[2],
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ class BigdataResume extends Model
|
|||||||
'business_sum',
|
'business_sum',
|
||||||
'non_business_count',
|
'non_business_count',
|
||||||
'non_business_sum',
|
'non_business_sum',
|
||||||
|
'spatial_count',
|
||||||
|
'spatial_sum',
|
||||||
|
'year'
|
||||||
];
|
];
|
||||||
|
|
||||||
public function importDatasource()
|
public function importDatasource()
|
||||||
@@ -28,88 +31,78 @@ class BigdataResume extends Model
|
|||||||
return $this->belongsTo(ImportDatasource::class, 'import_datasource_id');
|
return $this->belongsTo(ImportDatasource::class, 'import_datasource_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function generateResumeData($import_datasource_id){
|
public static function generateResumeData($import_datasource_id, $year){
|
||||||
$query_verified = once( function () {
|
$stats = PbgTask::with(['googleSheet', 'pbg_task_retributions'])
|
||||||
return DB::table('pbg_task AS pt')
|
->leftJoin('pbg_task_retributions as ptr', 'pbg_task.uuid', '=', 'ptr.pbg_task_uid')
|
||||||
->leftJoin('pbg_task_google_sheet AS ptgs', 'pt.registration_number', '=', 'ptgs.no_registrasi')
|
->leftJoin('pbg_task_google_sheet as ptgs', 'pbg_task.registration_number', '=', 'ptgs.no_registrasi')
|
||||||
->leftJoin('pbg_task_retributions AS ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid')
|
->when($year !== 'all', function ($query) use ($year) {
|
||||||
->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) = ?', [strtolower(trim('Selesai Verifikasi'))])
|
$query->whereYear('pbg_task.task_created_at', (int) $year);
|
||||||
->selectRaw('COUNT(pt.id) AS total_data,
|
|
||||||
SUM(ptr.nilai_retribusi_bangunan) AS total_retribution')
|
|
||||||
->first();
|
|
||||||
});
|
|
||||||
|
|
||||||
$verified_count = $query_verified->total_data ?? 0;
|
|
||||||
$verified_total = $query_verified->total_retribution ?? 0;
|
|
||||||
|
|
||||||
$query_business = once(function () {
|
|
||||||
return DB::table('pbg_task AS pt')
|
|
||||||
->leftJoin('pbg_task_google_sheet AS ptgs', 'pt.registration_number', '=', 'ptgs.no_registrasi')
|
|
||||||
->leftJoin('pbg_task_retributions AS ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid')
|
|
||||||
->where(function ($query) {
|
|
||||||
$query->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) != ?', [strtolower(trim('Selesai Verifikasi'))])
|
|
||||||
->orWhereNull('ptgs.status_verifikasi');
|
|
||||||
})
|
|
||||||
->where(function ($query) {
|
|
||||||
$query->whereRaw('LOWER(TRIM(pt.function_type)) = ?', [strtolower(trim('Sebagai Tempat Usaha'))]);
|
|
||||||
})
|
|
||||||
->selectRaw('COUNT(pt.id) AS total_data,
|
|
||||||
SUM(ptr.nilai_retribusi_bangunan) AS total_retribution')
|
|
||||||
->first();
|
|
||||||
});
|
|
||||||
|
|
||||||
$business_count = $query_business->total_data ?? 0;
|
|
||||||
$business_total = $query_business->total_retribution ?? 0;
|
|
||||||
|
|
||||||
$query_non_business = once( function () {
|
|
||||||
return DB::table('pbg_task AS pt')
|
|
||||||
->leftJoin('pbg_task_google_sheet AS ptgs', 'pt.registration_number', '=', 'ptgs.no_registrasi')
|
|
||||||
->leftJoin('pbg_task_retributions AS ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid') // Join ke pbg_task_retributions
|
|
||||||
->where(function ($query) {
|
|
||||||
$query->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) != ?', [strtolower(trim('Selesai Verifikasi'))])
|
|
||||||
->orWhereNull('ptgs.status_verifikasi'); // Include NULL values
|
|
||||||
})
|
})
|
||||||
->where(function ($query) {
|
->selectRaw("
|
||||||
$query->whereRaw('LOWER(TRIM(pt.function_type)) != ?', [strtolower(trim('Sebagai Tempat Usaha'))])
|
COUNT(CASE WHEN LOWER(TRIM(ptgs.status_verifikasi)) = 'selesai verifikasi' THEN 1 END) AS verified_count,
|
||||||
->orWhereNull('pt.function_type'); // Include NULL values
|
SUM(CASE WHEN LOWER(TRIM(ptgs.status_verifikasi)) = 'selesai verifikasi' THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS verified_total,
|
||||||
})
|
|
||||||
->selectRaw('COUNT(pt.id) AS total_data,
|
COUNT(CASE WHEN LOWER(TRIM(ptgs.status_verifikasi)) != 'selesai verifikasi' OR ptgs.status_verifikasi IS NULL THEN 1 END) AS non_verified_count,
|
||||||
SUM(ptr.nilai_retribusi_bangunan) AS total_retribution') // Menambahkan SUM dari pbg_task_retributions
|
SUM(CASE WHEN LOWER(TRIM(ptgs.status_verifikasi)) != 'selesai verifikasi' OR ptgs.status_verifikasi IS NULL THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS non_verified_total,
|
||||||
->first();
|
|
||||||
});
|
COUNT(CASE WHEN (LOWER(TRIM(ptgs.status_verifikasi)) != 'selesai verifikasi' OR ptgs.status_verifikasi IS NULL)
|
||||||
$non_business_count = $query_non_business->total_data ?? 0;
|
AND LOWER(TRIM(pbg_task.function_type)) = 'sebagai tempat usaha' THEN 1 END) AS business_count,
|
||||||
$non_business_total = $query_non_business->total_retribution ?? 0;
|
SUM(CASE WHEN (LOWER(TRIM(ptgs.status_verifikasi)) != 'selesai verifikasi' OR ptgs.status_verifikasi IS NULL)
|
||||||
|
AND LOWER(TRIM(pbg_task.function_type)) = 'sebagai tempat usaha' THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS business_total,
|
||||||
|
|
||||||
$query_non_verified = once(function () {
|
COUNT(CASE WHEN (LOWER(TRIM(ptgs.status_verifikasi)) != 'selesai verifikasi' OR ptgs.status_verifikasi IS NULL)
|
||||||
return DB::table('pbg_task AS pt')
|
AND (LOWER(TRIM(pbg_task.function_type)) != 'sebagai tempat usaha' OR pbg_task.function_type IS NULL) THEN 1 END) AS non_business_count,
|
||||||
->leftJoin('pbg_task_google_sheet AS ptgs', 'pt.registration_number', '=', 'ptgs.no_registrasi')
|
SUM(CASE WHEN (LOWER(TRIM(ptgs.status_verifikasi)) != 'selesai verifikasi' OR ptgs.status_verifikasi IS NULL)
|
||||||
->leftJoin('pbg_task_retributions AS ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid') // Join tabel pbg_task_retributions
|
AND (LOWER(TRIM(pbg_task.function_type)) != 'sebagai tempat usaha' OR pbg_task.function_type IS NULL) THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS non_business_total
|
||||||
->where(function ($query) {
|
")
|
||||||
$query->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) != ?', [strtolower(trim('Selesai Verifikasi'))])
|
|
||||||
->orWhereNull('ptgs.status_verifikasi'); // Include NULL values
|
|
||||||
})
|
|
||||||
->selectRaw('COUNT(pt.id) AS total_data,
|
|
||||||
SUM(ptr.nilai_retribusi_bangunan) AS total_retribution') // Menambahkan SUM dari pbg_task_retributions
|
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
|
// Assign Results
|
||||||
|
$verified_count = $stats->verified_count ?? 0;
|
||||||
|
$verified_total = $stats->verified_total ?? 0;
|
||||||
|
$non_verified_count = $stats->non_verified_count ?? 0;
|
||||||
|
$non_verified_total = $stats->non_verified_total ?? 0;
|
||||||
|
$business_count = $stats->business_count ?? 0;
|
||||||
|
$business_total = $stats->business_total ?? 0;
|
||||||
|
$non_business_count = $stats->non_business_count ?? 0;
|
||||||
|
$non_business_total = $stats->non_business_total ?? 0;
|
||||||
|
|
||||||
|
$query_potention = once(function () use ($year) {
|
||||||
|
$query = PbgTask::leftJoin('pbg_task_retributions as ptr', 'pbg_task.uuid', '=', 'ptr.pbg_task_uid')
|
||||||
|
->selectRaw('COUNT(DISTINCT pbg_task.id) as task_count, SUM(ptr.nilai_retribusi_bangunan) as total_retribution');
|
||||||
|
|
||||||
|
if ($year !== 'all') {
|
||||||
|
$query->whereYear('pbg_task.task_created_at', (int) $year);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query->first();
|
||||||
});
|
});
|
||||||
|
|
||||||
$non_verified_count = $query_non_verified->total_data ?? 0;
|
|
||||||
$non_verified_total = $query_non_verified->total_retribution ?? 0;
|
|
||||||
|
|
||||||
$query_potention = once( function () {
|
|
||||||
return DB::table('pbg_task as pt')
|
|
||||||
->leftJoin('pbg_task_retributions as ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid')
|
|
||||||
->select(
|
|
||||||
DB::raw('COUNT(DISTINCT pt.id) as task_count'),
|
|
||||||
DB::raw('SUM(ptr.nilai_retribusi_bangunan) as total_retribution')
|
|
||||||
)
|
|
||||||
->first();
|
|
||||||
});
|
|
||||||
$potention_count = $query_potention->task_count ?? 0;
|
$potention_count = $query_potention->task_count ?? 0;
|
||||||
$potention_total = $query_potention->total_retribution ?? 0;
|
$potention_total = $query_potention->total_retribution ?? 0;
|
||||||
|
|
||||||
|
$query_spatial_plannings = once(function () use ($year) {
|
||||||
|
$query = PbgTask::join('spatial_plannings as sp', 'pbg_task.document_number', '=', 'sp.number')
|
||||||
|
->join('pbg_task_retributions as ptr', 'ptr.pbg_task_uid', '=', 'pbg_task.uuid')
|
||||||
|
->selectRaw('COUNT(DISTINCT pbg_task.id) as task_count, SUM(ptr.nilai_retribusi_bangunan) as total_retribution');
|
||||||
|
|
||||||
|
if ($year !== 'all') {
|
||||||
|
$query->whereYear('pbg_task.task_created_at', (int) $year);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query->first();
|
||||||
|
});
|
||||||
|
|
||||||
|
$spatial_planning_count = $query_spatial_plannings->task_count ?? 0;
|
||||||
|
$spatial_planning_total = $query_spatial_plannings->total_retribution ?? 0;
|
||||||
|
|
||||||
|
$potention_count -= $spatial_planning_count;
|
||||||
|
$potention_total -= $spatial_planning_total;
|
||||||
|
|
||||||
return self::create([
|
return self::create([
|
||||||
'import_datasource_id' => $import_datasource_id,
|
'import_datasource_id' => $import_datasource_id,
|
||||||
|
'spatial_count' => $spatial_planning_count,
|
||||||
|
'spatial_sum' => $spatial_planning_total ?? 0.00,
|
||||||
'potention_count' => $potention_count ?? 0,
|
'potention_count' => $potention_count ?? 0,
|
||||||
'potention_sum' => $potention_total ?? 0.00,
|
'potention_sum' => $potention_total ?? 0.00,
|
||||||
'non_verified_count' => $non_verified_count ?? 0,
|
'non_verified_count' => $non_verified_count ?? 0,
|
||||||
@@ -120,6 +113,7 @@ class BigdataResume extends Model
|
|||||||
'business_sum' => $business_total ?? 0.00,
|
'business_sum' => $business_total ?? 0.00,
|
||||||
'non_business_count' => $non_business_count ?? 0,
|
'non_business_count' => $non_business_count ?? 0,
|
||||||
'non_business_sum' => $non_business_total ?? 0.00,
|
'non_business_sum' => $non_business_total ?? 0.00,
|
||||||
|
'year' => $year
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
app/Models/Customer.php
Normal file
20
app/Models/Customer.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Customer extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'customers';
|
||||||
|
protected $fillable = [
|
||||||
|
'nomor_pelanggan',
|
||||||
|
'kota_pelayanan',
|
||||||
|
'nama',
|
||||||
|
'alamat',
|
||||||
|
'latitude',
|
||||||
|
'longitude',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -37,4 +37,8 @@ class PbgTask extends Model
|
|||||||
public function pbg_task_index_integrations(){
|
public function pbg_task_index_integrations(){
|
||||||
return $this->hasOne(PbgTaskIndexIntegrations::class, 'pbg_task_uid', 'uuid');
|
return $this->hasOne(PbgTaskIndexIntegrations::class, 'pbg_task_uid', 'uuid');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function googleSheet(){
|
||||||
|
return $this->hasOne(PbgTaskGoogleSheet::class, 'no_registrasi', 'registration_number');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
37
app/Models/SpatialPlanning.php
Normal file
37
app/Models/SpatialPlanning.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SpatialPlanning
|
||||||
|
*
|
||||||
|
* @property $id
|
||||||
|
* @property $created_at
|
||||||
|
* @property $updated_at
|
||||||
|
* @property $name
|
||||||
|
* @property $kbli
|
||||||
|
* @property $activities
|
||||||
|
* @property $area
|
||||||
|
* @property $location
|
||||||
|
* @property $number
|
||||||
|
* @property $date
|
||||||
|
*
|
||||||
|
* @package App
|
||||||
|
* @mixin \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
class SpatialPlanning extends Model
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $perPage = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = ['name', 'kbli', 'activities', 'area', 'location', 'number', 'date'];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -61,32 +61,37 @@ class ServiceSIMBG
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function syncIndexIntegration($uuid, $token)
|
public function syncIndexIntegration($uuids, $token)
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
$url = "/api/pbg/v1/detail/" . $uuid . "/retribution/indeks-terintegrasi/";
|
if(empty($uuids)){
|
||||||
|
|
||||||
$headers = [
|
|
||||||
'Authorization' => "Bearer " . $token,
|
|
||||||
];
|
|
||||||
|
|
||||||
$res = $this->service_client->get($url, $headers);
|
|
||||||
|
|
||||||
if (empty($res->original['success']) || !$res->original['success']) {
|
|
||||||
// Log error
|
|
||||||
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$integrations = [];
|
||||||
|
foreach($uuids as $uuid){
|
||||||
|
$url = "/api/pbg/v1/detail/" . $uuid . "/retribution/indeks-terintegrasi/";
|
||||||
|
|
||||||
$data = $res->original['data']['data'] ?? null;
|
$headers = [
|
||||||
if (!$data) {
|
'Authorization' => "Bearer " . $token,
|
||||||
Log::error("No valid data returned from API", ['url' => $url, 'uuid' => $uuid]);
|
];
|
||||||
return false;
|
|
||||||
}
|
$res = $this->service_client->get($url, $headers);
|
||||||
|
|
||||||
$resultData = PbgTaskIndexIntegrations::updateOrCreate(
|
if (empty($res->original['success']) || !$res->original['success']) {
|
||||||
['pbg_task_uid' => $uuid],
|
// Log error
|
||||||
[
|
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $res->original['data']['data'] ?? null;
|
||||||
|
if (!$data) {
|
||||||
|
Log::error("No valid data returned from API", ['url' => $url, 'uuid' => $uuid]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$integrations[] = [
|
||||||
|
'pbg_task_uid' => $uuid,
|
||||||
'indeks_fungsi_bangunan' => $data['indeks_fungsi_bangunan'] ?? null,
|
'indeks_fungsi_bangunan' => $data['indeks_fungsi_bangunan'] ?? null,
|
||||||
'indeks_parameter_kompleksitas' => $data['indeks_parameter_kompleksitas'] ?? null,
|
'indeks_parameter_kompleksitas' => $data['indeks_parameter_kompleksitas'] ?? null,
|
||||||
'indeks_parameter_permanensi' => $data['indeks_parameter_permanensi'] ?? null,
|
'indeks_parameter_permanensi' => $data['indeks_parameter_permanensi'] ?? null,
|
||||||
@@ -94,8 +99,11 @@ class ServiceSIMBG
|
|||||||
'faktor_kepemilikan' => $data['faktor_kepemilikan'] ?? null,
|
'faktor_kepemilikan' => $data['faktor_kepemilikan'] ?? null,
|
||||||
'indeks_terintegrasi' => $data['indeks_terintegrasi'] ?? null,
|
'indeks_terintegrasi' => $data['indeks_terintegrasi'] ?? null,
|
||||||
'total' => $data['total'] ?? null,
|
'total' => $data['total'] ?? null,
|
||||||
]
|
];
|
||||||
);
|
}
|
||||||
|
|
||||||
|
PbgTaskIndexIntegrations::upsert($integrations, ['pbg_task_uid'], ['indeks_fungsi_bangunan',
|
||||||
|
'indeks_parameter_kompleksitas', 'indeks_parameter_permanensi', 'indeks_parameter_ketinggian', 'faktor_kepemilikan', 'indeks_terintegrasi', 'total']);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}catch (Exception $e){
|
}catch (Exception $e){
|
||||||
@@ -106,130 +114,136 @@ class ServiceSIMBG
|
|||||||
|
|
||||||
public function syncTaskList()
|
public function syncTaskList()
|
||||||
{
|
{
|
||||||
$initResToken = $this->getToken();
|
try {
|
||||||
|
$importDatasource = ImportDatasource::create([
|
||||||
$importDatasource = ImportDatasource::create([
|
'status' => ImportDatasourceStatus::Processing->value,
|
||||||
'status' => ImportDatasourceStatus::Processing->value,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (empty($initResToken->original['data']['token']['access'])) {
|
|
||||||
$importDatasource->update([
|
|
||||||
'status' => ImportDatasourceStatus::Failed->value,
|
|
||||||
'message' => 'Failed to retrieve token'
|
|
||||||
]);
|
]);
|
||||||
return $this->resError("Failed to retrieve token");
|
|
||||||
}
|
|
||||||
|
|
||||||
$apiToken = $initResToken->original['data']['token']['access'];
|
if (empty($initResToken->original['data']['token']['access'])) {
|
||||||
$headers = ['Authorization' => "Bearer " . $apiToken];
|
|
||||||
|
|
||||||
$url = "/api/pbg/v1/list/?page=1&size={$this->fetch_per_page}&sort=ASC";
|
|
||||||
$initialResponse = $this->service_client->get($url, $headers);
|
|
||||||
|
|
||||||
$totalPage = $initialResponse->original['data']['total_page'] ?? 0;
|
|
||||||
if ($totalPage == 0) {
|
|
||||||
$importDatasource->update([
|
|
||||||
'status' => ImportDatasourceStatus::Failed->value,
|
|
||||||
'message' => 'Invalid response: no total_page'
|
|
||||||
]);
|
|
||||||
return $this->resError("Invalid response from API");
|
|
||||||
}
|
|
||||||
|
|
||||||
$savedCount = $failedCount = 0;
|
|
||||||
|
|
||||||
for ($currentPage = 1; $currentPage <= $totalPage; $currentPage++) {
|
|
||||||
$pageUrl = "/api/pbg/v1/list/?page={$currentPage}&size={$this->fetch_per_page}&sort=ASC";
|
|
||||||
$getToken = $this->getToken();
|
|
||||||
Log::info("response index integration", ['currentPage' => $currentPage]);
|
|
||||||
if (empty($getToken->original['data']['token']['access'])) {
|
|
||||||
$importDatasource->update([
|
$importDatasource->update([
|
||||||
'status' => ImportDatasourceStatus::Failed->value,
|
'status' => ImportDatasourceStatus::Failed->value,
|
||||||
'message' => 'Failed to retrieve token'
|
'message' => 'Failed to retrieve token'
|
||||||
]);
|
]);
|
||||||
break;
|
return $this->resError("Failed to retrieve token");
|
||||||
}
|
}
|
||||||
$token = $getToken->original['data']['token']['access'];
|
|
||||||
$headers = ['Authorization' => "Bearer " . $token];
|
|
||||||
$response = $this->service_client->get($pageUrl, $headers);
|
|
||||||
$tasks = $response->original['data']['data'] ?? [];
|
|
||||||
|
|
||||||
if (empty($tasks)) {
|
$initResToken = $this->getToken();
|
||||||
|
$apiToken = $initResToken->original['data']['token']['access'];
|
||||||
|
$headers = ['Authorization' => "Bearer " . $apiToken];
|
||||||
|
|
||||||
|
$url = "/api/pbg/v1/list/?page=1&size={$this->fetch_per_page}&sort=ASC";
|
||||||
|
$initialResponse = $this->service_client->get($url, $headers);
|
||||||
|
|
||||||
|
$totalPage = $initialResponse->original['data']['total_page'] ?? 0;
|
||||||
|
if ($totalPage == 0) {
|
||||||
$importDatasource->update([
|
$importDatasource->update([
|
||||||
'status' => ImportDatasourceStatus::Failed->value,
|
'status' => ImportDatasourceStatus::Failed->value,
|
||||||
'message' => 'No data found on page'
|
'message' => 'Invalid response: no total_page'
|
||||||
]);
|
]);
|
||||||
Log::warning("No data found on page", ['page' => $currentPage]);
|
return $this->resError("Invalid response from API");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info("executed page", ['page' => $currentPage, 'total' => $totalPage]);
|
$savedCount = $failedCount = 0;
|
||||||
|
|
||||||
$tasksCollective = [];
|
for ($currentPage = 1; $currentPage <= $totalPage; $currentPage++) {
|
||||||
foreach ($tasks as $item) {
|
|
||||||
try {
|
try {
|
||||||
$tasksCollective[] = [
|
$pageUrl = "/api/pbg/v1/list/?page={$currentPage}&size={$this->fetch_per_page}&sort=ASC";
|
||||||
'uuid' => $item['uid'],
|
|
||||||
'name' => $item['name'],
|
|
||||||
'owner_name' => $item['owner_name'],
|
|
||||||
'application_type' => $item['application_type'],
|
|
||||||
'application_type_name' => $item['application_type_name'],
|
|
||||||
'condition' => $item['condition'],
|
|
||||||
'registration_number' => $item['registration_number'],
|
|
||||||
'document_number' => $item['document_number'],
|
|
||||||
'address' => $item['address'],
|
|
||||||
'status' => $item['status'],
|
|
||||||
'status_name' => $item['status_name'],
|
|
||||||
'slf_status' => $item['slf_status'] ?? null,
|
|
||||||
'slf_status_name' => $item['slf_status_name'] ?? null,
|
|
||||||
'function_type' => $item['function_type'],
|
|
||||||
'consultation_type' => $item['consultation_type'],
|
|
||||||
'due_date' => $item['due_date'],
|
|
||||||
'land_certificate_phase' => $item['land_certificate_phase'],
|
|
||||||
'task_created_at' => isset($item['created_at']) ? Carbon::parse($item['created_at'])->format('Y-m-d H:i:s') : null,
|
|
||||||
'updated_at' => now(),
|
|
||||||
'created_at' => now(),
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->syncIndexIntegration($item['uid'], $token);
|
Log::info("Fetching tasks", ['currentPage' => $currentPage]);
|
||||||
|
|
||||||
$this->syncTaskDetailSubmit($item['uid'], $token);
|
$response = $this->service_client->get($pageUrl, $headers);
|
||||||
|
$tasks = $response->original['data']['data'] ?? [];
|
||||||
$savedCount++;
|
|
||||||
|
if (empty($tasks)) {
|
||||||
|
Log::warning("No data found on page", ['page' => $currentPage]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tasksCollective = [];
|
||||||
|
foreach ($tasks as $item) {
|
||||||
|
try {
|
||||||
|
$tasksCollective[] = [
|
||||||
|
'uuid' => $item['uid'],
|
||||||
|
'name' => $item['name'],
|
||||||
|
'owner_name' => $item['owner_name'],
|
||||||
|
'application_type' => $item['application_type'],
|
||||||
|
'application_type_name' => $item['application_type_name'],
|
||||||
|
'condition' => $item['condition'],
|
||||||
|
'registration_number' => $item['registration_number'],
|
||||||
|
'document_number' => $item['document_number'],
|
||||||
|
'address' => $item['address'],
|
||||||
|
'status' => $item['status'],
|
||||||
|
'status_name' => $item['status_name'],
|
||||||
|
'slf_status' => $item['slf_status'] ?? null,
|
||||||
|
'slf_status_name' => $item['slf_status_name'] ?? null,
|
||||||
|
'function_type' => $item['function_type'],
|
||||||
|
'consultation_type' => $item['consultation_type'],
|
||||||
|
'due_date' => $item['due_date'],
|
||||||
|
'land_certificate_phase' => $item['land_certificate_phase'],
|
||||||
|
'task_created_at' => isset($item['created_at']) ? Carbon::parse($item['created_at'])->format('Y-m-d H:i:s') : null,
|
||||||
|
'updated_at' => now(),
|
||||||
|
'created_at' => now(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->syncTaskDetailSubmit($item['uid'], $apiToken);
|
||||||
|
$savedCount++;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$failedCount++;
|
||||||
|
Log::error("Failed to process task", [
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'task' => $item,
|
||||||
|
]);
|
||||||
|
continue; // Skip failed task, continue processing the rest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($tasksCollective)) {
|
||||||
|
PbgTask::upsert($tasksCollective, ['uuid'], [
|
||||||
|
'name', 'owner_name', 'application_type', 'application_type_name', 'condition',
|
||||||
|
'registration_number', 'document_number', 'address', 'status', 'status_name',
|
||||||
|
'slf_status', 'slf_status_name', 'function_type', 'consultation_type', 'due_date',
|
||||||
|
'land_certificate_phase', 'task_created_at', 'updated_at'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$uuids = array_column($tasksCollective, 'uuid');
|
||||||
|
$this->syncIndexIntegration($uuids, $apiToken);
|
||||||
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$failedCount++;
|
Log::error("Failed to process page", [
|
||||||
$importDatasource->update([
|
|
||||||
'status' => ImportDatasourceStatus::Failed->value,
|
|
||||||
'message' => "Successfully processed: $savedCount, Failed: $failedCount"
|
|
||||||
]);
|
|
||||||
Log::error("Failed to process task", [
|
|
||||||
'error' => $e->getMessage(),
|
'error' => $e->getMessage(),
|
||||||
'task' => $item,
|
'page' => $currentPage,
|
||||||
]);
|
]);
|
||||||
break;
|
continue; // Skip the failed page and move to the next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PbgTask::upsert($tasksCollective, ['uuid'], [
|
BigdataResume::generateResumeData($importDatasource->id, "all");
|
||||||
'name', 'owner_name', 'application_type', 'application_type_name', 'condition',
|
BigdataResume::generateResumeData($importDatasource->id, now()->year);
|
||||||
'registration_number', 'document_number', 'address', 'status', 'status_name',
|
|
||||||
'slf_status', 'slf_status_name', 'function_type', 'consultation_type', 'due_date',
|
// Final update after processing all pages
|
||||||
'land_certificate_phase', 'task_created_at', 'updated_at'
|
$importDatasource->update([
|
||||||
|
'status' => ImportDatasourceStatus::Success->value,
|
||||||
|
'message' => "Successfully processed: $savedCount, Failed: $failedCount"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
Log::info("syncTaskList completed", ['savedCount' => $savedCount, 'failedCount' => $failedCount]);
|
||||||
|
|
||||||
|
return $this->resSuccess(['savedCount' => $savedCount, 'failedCount' => $failedCount]);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error("syncTaskList failed", ['error' => $e->getMessage()]);
|
||||||
|
if (isset($importDatasource)) {
|
||||||
|
$importDatasource->update([
|
||||||
|
'status' => ImportDatasourceStatus::Failed->value,
|
||||||
|
'message' => 'Critical failure: ' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return $this->resError("Critical failure occurred: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$importDatasource->update([
|
|
||||||
'status' => ImportDatasourceStatus::Success->value,
|
|
||||||
'message' => "Successfully processed: $savedCount, Failed: $failedCount"
|
|
||||||
]);
|
|
||||||
|
|
||||||
BigdataResume::generateResumeData($importDatasource->id);
|
|
||||||
|
|
||||||
Log::info("syncTaskList completed", ['savedCount' => $savedCount, 'failedCount' => $failedCount]);
|
|
||||||
|
|
||||||
return $this->resSuccess(['savedCount' => $savedCount, 'failedCount' => $failedCount]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function syncTaskDetailSubmit($uuid, $token)
|
public function syncTaskDetailSubmit($uuid, $token)
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
@@ -311,5 +325,4 @@ class ServiceSIMBG
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
"ibex/crud-generator": "^2.1",
|
|
||||||
"laravel/pail": "^1.1",
|
"laravel/pail": "^1.1",
|
||||||
"laravel/pint": "^1.13",
|
"laravel/pint": "^1.13",
|
||||||
"laravel/sail": "^1.26",
|
"laravel/sail": "^1.26",
|
||||||
|
|||||||
@@ -109,4 +109,10 @@ return [
|
|||||||
'table' => 'failed_jobs',
|
'table' => 'failed_jobs',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// set timeout queue
|
||||||
|
|
||||||
|
'worker' => [
|
||||||
|
'timeout' => 300
|
||||||
|
]
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('spatial_planning', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
|
||||||
|
$table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
|
||||||
|
$table->string('name')->nullable();
|
||||||
|
$table->string('kbli')->nullable();
|
||||||
|
$table->string('activities')->nullable();
|
||||||
|
$table->string('area')->nullable();
|
||||||
|
$table->string('location')->nullable();
|
||||||
|
$table->string('number')->nullable();
|
||||||
|
$table->dateTime('date')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('spatial_planning');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::rename('spatial_planning', 'spatial_plannings');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::rename('spatial_plannings', 'spatial_planning');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?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('customers', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('nomor_pelanggan')->unique();
|
||||||
|
$table->string('kota_pelayanan');
|
||||||
|
$table->string('nama');
|
||||||
|
$table->text('alamat');
|
||||||
|
$table->decimal('latitude', 22,18);
|
||||||
|
$table->decimal('longitude', 22,18);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('customers');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -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('bigdata_resumes', function (Blueprint $table) {
|
||||||
|
$table->integer('spatial_count')->default(0);
|
||||||
|
$table->decimal('spatial_sum', 20,2)->default(0);
|
||||||
|
$table->string('year');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('bigdata_resumes', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('spatial_count');
|
||||||
|
$table->dropColumn('spatial_sum');
|
||||||
|
$table->dropColumn('year');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -71,7 +71,7 @@ class UsersRoleMenuSeeder extends Seeder
|
|||||||
[
|
[
|
||||||
"name" => "Laporan",
|
"name" => "Laporan",
|
||||||
"url" => "/laporan",
|
"url" => "/laporan",
|
||||||
"icon" => "mingcute:task-line",
|
"icon" => "mingcute:report-line",
|
||||||
"parent_id" => null,
|
"parent_id" => null,
|
||||||
"sort_order" => 6,
|
"sort_order" => 6,
|
||||||
]
|
]
|
||||||
@@ -116,6 +116,13 @@ class UsersRoleMenuSeeder extends Seeder
|
|||||||
"parent_id" => $dashboard->id,
|
"parent_id" => $dashboard->id,
|
||||||
"sort_order" => 3,
|
"sort_order" => 3,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"name" => "PETA",
|
||||||
|
"url" => "dashboard.maps",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $dashboard->id,
|
||||||
|
"sort_order" => 4,
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"name" => "Users",
|
"name" => "Users",
|
||||||
"url" => "users.index",
|
"url" => "users.index",
|
||||||
@@ -186,6 +193,20 @@ class UsersRoleMenuSeeder extends Seeder
|
|||||||
"parent_id" => $data->id,
|
"parent_id" => $data->id,
|
||||||
"sort_order" => 5,
|
"sort_order" => 5,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"name" => "Tata Ruang",
|
||||||
|
"url" => "spatial-plannings.index",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $data->id,
|
||||||
|
"sort_order" => 6,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "PDAM",
|
||||||
|
"url" => "customers",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $data->id,
|
||||||
|
"sort_order" => 7,
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"name" => "Lap Pariwisata",
|
"name" => "Lap Pariwisata",
|
||||||
"url" => "tourisms.index",
|
"url" => "tourisms.index",
|
||||||
@@ -193,6 +214,13 @@ class UsersRoleMenuSeeder extends Seeder
|
|||||||
"parent_id" => $laporan->id,
|
"parent_id" => $laporan->id,
|
||||||
"sort_order" => 1,
|
"sort_order" => 1,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"name" => "Lap Pimpinan",
|
||||||
|
"url" => "bigdata-resumes",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $laporan->id,
|
||||||
|
"sort_order" => 2,
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($children_menus as $child_menu) {
|
foreach ($children_menus as $child_menu) {
|
||||||
@@ -213,6 +241,10 @@ class UsersRoleMenuSeeder extends Seeder
|
|||||||
$laporan_pariwisata = Menu::where('name', 'Lap Pariwisata')->first();
|
$laporan_pariwisata = Menu::where('name', 'Lap Pariwisata')->first();
|
||||||
$umkm = Menu::where('name', 'UMKM')->first();
|
$umkm = Menu::where('name', 'UMKM')->first();
|
||||||
$lack_of_potentials = Menu::where('name', 'Dashboard Potensi')->first();
|
$lack_of_potentials = Menu::where('name', 'Dashboard Potensi')->first();
|
||||||
|
$spatial_plannings = Menu::where('name', 'Tata Ruang')->first();
|
||||||
|
$pdam = Menu::where('name', 'PDAM')->first();
|
||||||
|
$peta = Menu::where('name', 'PETA')->first();
|
||||||
|
$bigdata_resume = Menu::where('name', 'Lap Pimpinan')->first();
|
||||||
|
|
||||||
// Superadmin gets all menus
|
// Superadmin gets all menus
|
||||||
$superadmin->menus()->sync([
|
$superadmin->menus()->sync([
|
||||||
@@ -238,6 +270,10 @@ class UsersRoleMenuSeeder extends Seeder
|
|||||||
$laporan_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],
|
$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],
|
$lack_of_potentials->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||||
|
$spatial_plannings->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||||
|
$pdam->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||||
|
$peta->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||||
|
$bigdata_resume->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Admin gets limited menus
|
// Admin gets limited menus
|
||||||
@@ -252,6 +288,7 @@ class UsersRoleMenuSeeder extends Seeder
|
|||||||
$dashboard->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
$dashboard->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||||
$data->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
$data->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Attach User to role super admin
|
// Attach User to role super admin
|
||||||
User::findOrFail(1)->roles()->sync([$superadmin->id]);
|
User::findOrFail(1)->roles()->sync([$superadmin->id]);
|
||||||
}
|
}
|
||||||
|
|||||||
5851
package-lock.json
generated
5851
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
69
package.json
69
package.json
@@ -1,36 +1,37 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"dev": "vite"
|
"dev": "vite"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"axios": "^1.7.4",
|
"axios": "^1.7.4",
|
||||||
"concurrently": "^9.0.1",
|
"concurrently": "^9.0.1",
|
||||||
"laravel-vite-plugin": "^1.0",
|
"laravel-vite-plugin": "^1.0",
|
||||||
"postcss": "^8.4.47",
|
"postcss": "^8.4.47",
|
||||||
"sass": "^1.81.1",
|
"sass": "^1.81.1",
|
||||||
"tailwindcss": "^3.4.13",
|
"tailwindcss": "^3.4.13",
|
||||||
"vite": "^5.0"
|
"vite": "^5.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"apexcharts": "^3.44.2",
|
"apexcharts": "^3.44.2",
|
||||||
"big.js": "^6.2.2",
|
"big.js": "^6.2.2",
|
||||||
"bootstrap": "^5.3.3",
|
"bootstrap": "^5.3.3",
|
||||||
"countup.js": "^2.3.2",
|
"countup.js": "^2.3.2",
|
||||||
"dropzone": "^5.9.0",
|
"dropzone": "^5.9.0",
|
||||||
"flatpickr": "^4.6.13",
|
"flatpickr": "^4.6.13",
|
||||||
"gmaps": "^0.4.25",
|
"gmaps": "^0.4.25",
|
||||||
"gridjs": "^5.1.0",
|
"gridjs": "^5.1.0",
|
||||||
"iconify-icon": "^2.1.0",
|
"iconify-icon": "^2.1.0",
|
||||||
"jsvectormap": "^1.5.1",
|
"jsvectormap": "^1.5.1",
|
||||||
"moment": "^2.29.4",
|
"leaflet": "^1.9.4",
|
||||||
"node-waves": "^0.7.6",
|
"moment": "^2.29.4",
|
||||||
"quill": "^1.3.7",
|
"node-waves": "^0.7.6",
|
||||||
"simplebar": "^5.3.9",
|
"quill": "^1.3.7",
|
||||||
"sweetalert2": "^11.16.0",
|
"simplebar": "^5.3.9",
|
||||||
"wnumb": "^1.2.0"
|
"sweetalert2": "^11.16.0",
|
||||||
}
|
"wnumb": "^1.2.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
public/templates/template_pariwisata.xlsx
Normal file
BIN
public/templates/template_pariwisata.xlsx
Normal file
Binary file not shown.
BIN
public/templates/template_spatial_planning.xlsx
Normal file
BIN
public/templates/template_spatial_planning.xlsx
Normal file
Binary file not shown.
@@ -2,6 +2,30 @@ import bootstrap from "bootstrap/dist/js/bootstrap";
|
|||||||
window.bootstrap = bootstrap;
|
window.bootstrap = bootstrap;
|
||||||
import "iconify-icon";
|
import "iconify-icon";
|
||||||
import "simplebar/dist/simplebar";
|
import "simplebar/dist/simplebar";
|
||||||
|
// import flatpickr from "flatpickr";
|
||||||
|
// import "flatpickr/dist/flatpickr.min.css";
|
||||||
|
|
||||||
|
// class InitDatePicker {
|
||||||
|
// constructor(selector = ".datepicker") {
|
||||||
|
// this.selector = selector;
|
||||||
|
// }
|
||||||
|
// init() {
|
||||||
|
// const elements = document.querySelectorAll(this.selector);
|
||||||
|
// if (elements.length === 0) return; // Skip if no elements found
|
||||||
|
|
||||||
|
// const today = new Date();
|
||||||
|
// const minYear = today.getFullYear() - 5;
|
||||||
|
|
||||||
|
// elements.forEach((element) => {
|
||||||
|
// flatpickr(element, {
|
||||||
|
// enableTime: false,
|
||||||
|
// dateFormat: "Y-m-d",
|
||||||
|
// minDate: `${minYear}-01-01`,
|
||||||
|
// maxDate: today,
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
class Components {
|
class Components {
|
||||||
initBootstrapComponents() {
|
initBootstrapComponents() {
|
||||||
@@ -107,6 +131,7 @@ class FormValidation {
|
|||||||
}
|
}
|
||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
new Components().init(), new FormValidation().init();
|
new Components().init(), new FormValidation().init();
|
||||||
|
// new InitDatePicker().init();
|
||||||
});
|
});
|
||||||
class ThemeLayout {
|
class ThemeLayout {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|||||||
154
resources/js/bigdata-resumes/index.js
Normal file
154
resources/js/bigdata-resumes/index.js
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
import { Grid } from "gridjs/dist/gridjs.umd.js";
|
||||||
|
import gridjs from "gridjs/dist/gridjs.umd.js";
|
||||||
|
import "gridjs/dist/gridjs.umd.js";
|
||||||
|
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
|
class BigdataResume {
|
||||||
|
constructor() {
|
||||||
|
this.toastMessage = document.getElementById("toast-message");
|
||||||
|
this.toastElement = document.getElementById("toastNotification");
|
||||||
|
this.toast = new bootstrap.Toast(this.toastElement);
|
||||||
|
this.table = null;
|
||||||
|
|
||||||
|
// Initialize functions
|
||||||
|
this.initTableDataSettings();
|
||||||
|
// this.initEvents();
|
||||||
|
}
|
||||||
|
initEvents() {
|
||||||
|
document.body.addEventListener("click", async (event) => {
|
||||||
|
const deleteButton = event.target.closest(
|
||||||
|
".btn-delete-data-settings"
|
||||||
|
);
|
||||||
|
if (deleteButton) {
|
||||||
|
event.preventDefault();
|
||||||
|
await this.handleDelete(deleteButton);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initTableDataSettings() {
|
||||||
|
let tableContainer = document.getElementById("table-bigdata-resumes");
|
||||||
|
// Create a new Grid.js instance only if it doesn't exist
|
||||||
|
this.table = new Grid({
|
||||||
|
columns: [
|
||||||
|
{ name: "ID" },
|
||||||
|
{ name: "Potention Count" },
|
||||||
|
{ name: "Potention Sum" },
|
||||||
|
{ name: "Non Verified Count" },
|
||||||
|
{ name: "Non Verified Sum" },
|
||||||
|
{ name: "Verified Count" },
|
||||||
|
{ name: "Verified Sum" },
|
||||||
|
{ name: "Business Count" },
|
||||||
|
{ name: "Business Sum" },
|
||||||
|
{ name: "Non Business Count" },
|
||||||
|
{ name: "Non Business Sum" },
|
||||||
|
{ name: "Spatial Sum" },
|
||||||
|
{ name: "Spatial Count" },
|
||||||
|
{
|
||||||
|
name: "Created",
|
||||||
|
attributes: { style: "width: 200px; white-space: nowrap;" }, // Set width dynamically
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
limit: 15,
|
||||||
|
server: {
|
||||||
|
url: (prev, page) =>
|
||||||
|
`${prev}${prev.includes("?") ? "&" : "?"}page=${
|
||||||
|
page + 1
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sort: true,
|
||||||
|
search: {
|
||||||
|
server: {
|
||||||
|
url: (prev, keyword) => `${prev}?search=${keyword}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
url: `${GlobalConfig.apiHost}/api/bigdata-report`,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
then: (data) =>
|
||||||
|
data.data.map((item) => [
|
||||||
|
item.id,
|
||||||
|
item.potention_count,
|
||||||
|
addThousandSeparators(item.potention_sum),
|
||||||
|
item.non_verified_count,
|
||||||
|
addThousandSeparators(item.non_verified_sum),
|
||||||
|
item.verified_count,
|
||||||
|
addThousandSeparators(item.verified_sum),
|
||||||
|
item.business_count,
|
||||||
|
addThousandSeparators(item.business_sum),
|
||||||
|
item.non_business_count,
|
||||||
|
addThousandSeparators(item.non_business_sum),
|
||||||
|
item.spatial_count,
|
||||||
|
addThousandSeparators(item.spatial_sum),
|
||||||
|
moment(item.created_at).format("YYYY-MM-DD H:mm:ss"),
|
||||||
|
]),
|
||||||
|
total: (data) => data.total,
|
||||||
|
},
|
||||||
|
}).render(tableContainer);
|
||||||
|
}
|
||||||
|
async handleDelete(deleteButton) {
|
||||||
|
const id = deleteButton.getAttribute("data-id");
|
||||||
|
|
||||||
|
const result = await Swal.fire({
|
||||||
|
title: "Are you sure?",
|
||||||
|
text: "You won't be able to revert this!",
|
||||||
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: "Yes, delete it!",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
try {
|
||||||
|
let response = await fetch(
|
||||||
|
`${GlobalConfig.apiHost}/api/data-settings/${id}`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let result = await response.json();
|
||||||
|
this.toastMessage.innerText =
|
||||||
|
result.message || "Deleted successfully!";
|
||||||
|
this.toast.show();
|
||||||
|
|
||||||
|
// Refresh Grid.js table
|
||||||
|
if (typeof this.table !== "undefined") {
|
||||||
|
this.table.updateConfig({}).forceRender();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let error = await response.json();
|
||||||
|
console.error("Delete failed:", error);
|
||||||
|
this.toastMessage.innerText =
|
||||||
|
error.message || "Delete failed!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting item:", error);
|
||||||
|
this.toastMessage.innerText = "An error occurred!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
|
new BigdataResume();
|
||||||
|
});
|
||||||
@@ -5,9 +5,9 @@ Dropzone.autoDiscover = false;
|
|||||||
var previewTemplate,
|
var previewTemplate,
|
||||||
dropzone,
|
dropzone,
|
||||||
dropzonePreviewNode = document.querySelector("#dropzone-preview-list");
|
dropzonePreviewNode = document.querySelector("#dropzone-preview-list");
|
||||||
console.log(previewTemplate);
|
|
||||||
console.log(dropzone);
|
const uploadButton = document.getElementById("btnUploadBusinessIndustry");
|
||||||
console.log(dropzonePreviewNode);
|
const spinner = document.getElementById("spinner");
|
||||||
|
|
||||||
const toastNotification = document.getElementById("toastNotification");
|
const toastNotification = document.getElementById("toastNotification");
|
||||||
const toast = new bootstrap.Toast(toastNotification);
|
const toast = new bootstrap.Toast(toastNotification);
|
||||||
@@ -29,97 +29,50 @@ const toast = new bootstrap.Toast(toastNotification);
|
|||||||
.getAttribute("content")}`,
|
.getAttribute("content")}`,
|
||||||
},
|
},
|
||||||
init: function () {
|
init: function () {
|
||||||
// Listen for the success event
|
|
||||||
this.on("success", function (file, response) {
|
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 =
|
document.getElementById("toast-message").innerText =
|
||||||
response.message;
|
response.message;
|
||||||
toast.show();
|
toast.show();
|
||||||
document.getElementById("submit-upload").innerHTML =
|
|
||||||
"Upload Files";
|
|
||||||
// Tunggu sebentar lalu reload halaman
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = "/data/business-industries";
|
window.location.href = "/data/business-industries";
|
||||||
}, 2000);
|
}, 2000);
|
||||||
});
|
});
|
||||||
// Listen for the error event
|
|
||||||
this.on("error", function (file, errorMessage) {
|
this.on("error", function (file, errorMessage) {
|
||||||
console.error("Error uploading file:", file);
|
console.error("Error uploading file:", file);
|
||||||
console.error("Error message:", errorMessage);
|
console.error("Error message:", errorMessage);
|
||||||
// Handle the error response
|
|
||||||
|
|
||||||
// Show error toast
|
|
||||||
document.getElementById("toast-message").innerText =
|
document.getElementById("toast-message").innerText =
|
||||||
errorMessage.message;
|
errorMessage.message;
|
||||||
toast.show();
|
toast.show();
|
||||||
document.getElementById("submit-upload").innerHTML =
|
uploadButton.disabled = false;
|
||||||
"Upload Files";
|
spinner.classList.add("d-none");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
})));
|
})));
|
||||||
|
|
||||||
// Add event listener to control the submission manually
|
// Add event listener to control the submission manually
|
||||||
document.querySelector("#submit-upload").addEventListener("click", function () {
|
document
|
||||||
console.log("Ini adalah value dropzone", dropzone.files[0]);
|
.querySelector("#btnUploadBusinessIndustry")
|
||||||
const formData = new FormData();
|
.addEventListener("click", function () {
|
||||||
console.log("Dropzonefiles", dropzone.files);
|
console.log("Ini adalah value dropzone", dropzone.files[0]);
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
this.innerHTML =
|
if (dropzone.files.length > 0) {
|
||||||
'<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>Loading...';
|
formData.append("file", dropzone.files[0]);
|
||||||
|
dropzone.processQueue(); // Ini akan manual memicu upload
|
||||||
|
uploadButton.disabled = true;
|
||||||
|
spinner.classList.remove("d-none");
|
||||||
|
} else {
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
"Please add a file first.";
|
||||||
|
toast.show();
|
||||||
|
uploadButton.disabled = false;
|
||||||
|
spinner.classList.add("d-none");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Pastikan ada file dalam queue sebelum memprosesnya
|
dropzone.on("addedfile", function (file) {});
|
||||||
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.on("complete", function (file) {
|
||||||
dropzone.removeFile(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();
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -2,58 +2,36 @@ import { Grid } from "gridjs/dist/gridjs.umd.js";
|
|||||||
import gridjs from "gridjs/dist/gridjs.umd.js";
|
import gridjs from "gridjs/dist/gridjs.umd.js";
|
||||||
import "gridjs/dist/gridjs.umd.js";
|
import "gridjs/dist/gridjs.umd.js";
|
||||||
import GlobalConfig from "../global-config.js";
|
import GlobalConfig from "../global-config.js";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
|
||||||
class BusinessIndustries {
|
class BusinessIndustries {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.table = null; // Store Grid.js instance
|
this.toastMessage = document.getElementById("toast-message");
|
||||||
|
this.toastElement = document.getElementById("toastNotification");
|
||||||
|
this.toast = new bootstrap.Toast(this.toastElement);
|
||||||
|
this.table = null;
|
||||||
|
|
||||||
|
// Initialize functions
|
||||||
|
this.initTableBusinessIndustries();
|
||||||
|
this.initEvents();
|
||||||
}
|
}
|
||||||
init() {
|
initEvents() {
|
||||||
this.getFetchApiData();
|
document.body.addEventListener("click", async (event) => {
|
||||||
|
const deleteButton = event.target.closest(
|
||||||
|
".btn-delete-business-industry"
|
||||||
|
);
|
||||||
|
if (deleteButton) {
|
||||||
|
event.preventDefault();
|
||||||
|
await this.handleDelete(deleteButton);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getFetchApiData() {
|
initTableBusinessIndustries() {
|
||||||
let tableContainer = document.getElementById(
|
let tableContainer = document.getElementById(
|
||||||
"table-business-industries"
|
"table-business-industries"
|
||||||
);
|
);
|
||||||
|
// Create a new Grid.js instance only if it doesn't exist
|
||||||
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({
|
this.table = new Grid({
|
||||||
columns: [
|
columns: [
|
||||||
{ name: "ID", width: "80px", hidden: false },
|
{ name: "ID", width: "80px", hidden: false },
|
||||||
@@ -71,27 +49,20 @@ class BusinessIndustries {
|
|||||||
{ name: "Tahun Pajak", width: "120px" },
|
{ name: "Tahun Pajak", width: "120px" },
|
||||||
{ name: "Created", width: "180px" },
|
{ name: "Created", width: "180px" },
|
||||||
{
|
{
|
||||||
name: "Actions",
|
name: "Action",
|
||||||
width: "120px",
|
formatter: (cell) =>
|
||||||
formatter: function (cell) {
|
gridjs.html(`
|
||||||
return gridjs.html(`
|
<div class="d-flex justify-content-center gap-2">
|
||||||
<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">
|
||||||
<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>
|
||||||
<i class='bx bx-edit'></i>
|
</a>
|
||||||
</a>
|
<button data-id="${cell}" class="btn btn-sm btn-red btn-delete-business-industry d-inline-flex align-items-center justify-content-center">
|
||||||
<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>
|
||||||
<i class='bx bxs-trash'></i>
|
</button>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
`),
|
||||||
`);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
search: {
|
|
||||||
server: {
|
|
||||||
url: (prev, keyword) => `${prev}?search=${keyword}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pagination: {
|
pagination: {
|
||||||
limit: 15,
|
limit: 15,
|
||||||
server: {
|
server: {
|
||||||
@@ -102,6 +73,11 @@ class BusinessIndustries {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
sort: true,
|
sort: true,
|
||||||
|
search: {
|
||||||
|
server: {
|
||||||
|
url: (prev, keyword) => `${prev}?search=${keyword}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
url: `${GlobalConfig.apiHost}/api/api-business-industries`,
|
url: `${GlobalConfig.apiHost}/api/api-business-industries`,
|
||||||
headers: {
|
headers: {
|
||||||
@@ -131,98 +107,26 @@ class BusinessIndustries {
|
|||||||
total: (data) => data.total,
|
total: (data) => data.total,
|
||||||
},
|
},
|
||||||
}).render(tableContainer);
|
}).render(tableContainer);
|
||||||
|
|
||||||
document.addEventListener("click", this.handleDelete.bind(this));
|
|
||||||
}
|
}
|
||||||
handleDelete(event) {
|
async handleDelete(deleteButton) {
|
||||||
if (event.target.classList.contains("btn-delete-business-industries")) {
|
const id = deleteButton.getAttribute("data-id");
|
||||||
event.preventDefault();
|
|
||||||
const id = event.target.getAttribute("data-id");
|
|
||||||
let modalElement = document.getElementById("modalConfirmation");
|
|
||||||
let toastMessage = document.getElementById("toast-message");
|
|
||||||
|
|
||||||
if (!modalElement) {
|
const result = await Swal.fire({
|
||||||
console.error("Modal element not found!");
|
title: "Are you sure?",
|
||||||
return;
|
text: "You won't be able to revert this!",
|
||||||
}
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: "Yes, delete it!",
|
||||||
|
});
|
||||||
|
|
||||||
let modal = new bootstrap.Modal(modalElement);
|
if (result.isConfirmed) {
|
||||||
let btnSaveConfirmation = document.getElementById(
|
try {
|
||||||
"btnSaveConfirmation"
|
let response = await fetch(
|
||||||
);
|
`${GlobalConfig.apiHost}/api/api-business-industries/${id}`,
|
||||||
let toastElement = document.getElementById("toastNotification");
|
{
|
||||||
let toast = new bootstrap.Toast(toastElement);
|
method: "DELETE",
|
||||||
|
|
||||||
// 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",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${document
|
Authorization: `Bearer ${document
|
||||||
@@ -230,31 +134,34 @@ class BusinessIndustries {
|
|||||||
.getAttribute("content")}`,
|
.getAttribute("content")}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
then: (data) =>
|
}
|
||||||
data.data.map((item) => [
|
);
|
||||||
item.id,
|
|
||||||
item.nama_kecamatan,
|
if (response.ok) {
|
||||||
item.nama_kelurahan,
|
let result = await response.json();
|
||||||
item.nop,
|
this.toastMessage.innerText =
|
||||||
item.nama_wajib_pajak,
|
result.message || "Deleted successfully!";
|
||||||
item.alamat_wajib_pajak,
|
this.toast.show();
|
||||||
item.alamat_objek_pajak,
|
|
||||||
item.luas_bumi,
|
// Refresh Grid.js table
|
||||||
item.luas_bangunan,
|
if (typeof this.table !== "undefined") {
|
||||||
item.njop_bumi,
|
this.table.updateConfig({}).forceRender();
|
||||||
item.njop_bangunan,
|
}
|
||||||
item.ketetapan,
|
} else {
|
||||||
item.tahun_pajak,
|
let error = await response.json();
|
||||||
item.created_at,
|
console.error("Delete failed:", error);
|
||||||
item.id, // ID for Actions column
|
this.toastMessage.innerText =
|
||||||
]),
|
error.message || "Delete failed!";
|
||||||
total: (data) => data.total,
|
this.toast.show();
|
||||||
},
|
}
|
||||||
})
|
} catch (error) {
|
||||||
.forceRender();
|
console.error("Error deleting item:", error);
|
||||||
|
this.toastMessage.innerText = "An error occurred!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
new BusinessIndustries().init();
|
new BusinessIndustries();
|
||||||
});
|
});
|
||||||
|
|||||||
65
resources/js/customers/create.js
Normal file
65
resources/js/customers/create.js
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
class CreateCustomer {
|
||||||
|
constructor() {
|
||||||
|
this.initCreateCustomer();
|
||||||
|
}
|
||||||
|
|
||||||
|
initCreateCustomer() {
|
||||||
|
const toastNotification = document.getElementById("toastNotification");
|
||||||
|
const toast = new bootstrap.Toast(toastNotification);
|
||||||
|
document
|
||||||
|
.getElementById("btnCreateCustomer")
|
||||||
|
.addEventListener("click", async function () {
|
||||||
|
let submitButton = this;
|
||||||
|
let spinner = document.getElementById("spinner");
|
||||||
|
let form = document.getElementById("formCreateCustomer");
|
||||||
|
|
||||||
|
if (!form) {
|
||||||
|
console.error("Form element not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Get form data
|
||||||
|
let formData = new FormData(form);
|
||||||
|
|
||||||
|
// Disable button and show spinner
|
||||||
|
submitButton.disabled = true;
|
||||||
|
spinner.classList.remove("d-none");
|
||||||
|
|
||||||
|
try {
|
||||||
|
let response = await fetch(form.action, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
},
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let result = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
result.message;
|
||||||
|
toast.show();
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "/data/customers";
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
let error = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
error.message;
|
||||||
|
toast.show();
|
||||||
|
console.error("Error:", error);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Request failed:", error);
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
error.message;
|
||||||
|
toast.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
|
new CreateCustomer();
|
||||||
|
});
|
||||||
65
resources/js/customers/edit.js
Normal file
65
resources/js/customers/edit.js
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
class UpdateCustomer {
|
||||||
|
constructor() {
|
||||||
|
this.initUpdateCustomer();
|
||||||
|
}
|
||||||
|
|
||||||
|
initUpdateCustomer() {
|
||||||
|
const toastNotification = document.getElementById("toastNotification");
|
||||||
|
const toast = new bootstrap.Toast(toastNotification);
|
||||||
|
document
|
||||||
|
.getElementById("btnUpdateCustomer")
|
||||||
|
.addEventListener("click", async function () {
|
||||||
|
let submitButton = this;
|
||||||
|
let spinner = document.getElementById("spinner");
|
||||||
|
let form = document.getElementById("formUpdateCustomer");
|
||||||
|
|
||||||
|
if (!form) {
|
||||||
|
console.error("Form element not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Get form data
|
||||||
|
let formData = new FormData(form);
|
||||||
|
|
||||||
|
// Disable button and show spinner
|
||||||
|
submitButton.disabled = true;
|
||||||
|
spinner.classList.remove("d-none");
|
||||||
|
|
||||||
|
try {
|
||||||
|
let response = await fetch(form.action, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
},
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let result = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
result.message;
|
||||||
|
toast.show();
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "/data/customers";
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
let error = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
error.message;
|
||||||
|
toast.show();
|
||||||
|
console.error("Error:", error);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Request failed:", error);
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
error.message;
|
||||||
|
toast.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
|
new UpdateCustomer();
|
||||||
|
});
|
||||||
151
resources/js/customers/index.js
Normal file
151
resources/js/customers/index.js
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
import { Grid } from "gridjs/dist/gridjs.umd.js";
|
||||||
|
import gridjs from "gridjs/dist/gridjs.umd.js";
|
||||||
|
import "gridjs/dist/gridjs.umd.js";
|
||||||
|
import GlobalConfig from "../global-config";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
|
||||||
|
class Customers {
|
||||||
|
constructor() {
|
||||||
|
this.toastMessage = document.getElementById("toast-message");
|
||||||
|
this.toastElement = document.getElementById("toastNotification");
|
||||||
|
this.toast = new bootstrap.Toast(this.toastElement);
|
||||||
|
this.table = null;
|
||||||
|
|
||||||
|
// Initialize functions
|
||||||
|
this.initTableCustomers();
|
||||||
|
this.initEvents();
|
||||||
|
}
|
||||||
|
initEvents() {
|
||||||
|
document.body.addEventListener("click", async (event) => {
|
||||||
|
const deleteButton = event.target.closest(".btn-delete-customers");
|
||||||
|
if (deleteButton) {
|
||||||
|
event.preventDefault();
|
||||||
|
await this.handleDelete(deleteButton);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initTableCustomers() {
|
||||||
|
let tableContainer = document.getElementById("table-customers");
|
||||||
|
// Create a new Grid.js instance only if it doesn't exist
|
||||||
|
this.table = new Grid({
|
||||||
|
columns: [
|
||||||
|
"ID",
|
||||||
|
"Nomor Pelanggan",
|
||||||
|
"Nama",
|
||||||
|
"Kota Pelayanan",
|
||||||
|
"Alamat",
|
||||||
|
"Latitude",
|
||||||
|
"Longitude",
|
||||||
|
{
|
||||||
|
name: "Action",
|
||||||
|
formatter: (cell) =>
|
||||||
|
gridjs.html(`
|
||||||
|
<div class="d-flex justify-content-center gap-2">
|
||||||
|
<a href="/data/customers/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
|
||||||
|
<i class='bx bx-edit'></i>
|
||||||
|
</a>
|
||||||
|
<button data-id="${cell}" class="btn btn-sm btn-red btn-delete-customers d-inline-flex align-items-center justify-content-center">
|
||||||
|
<i class='bx bxs-trash' ></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
limit: 15,
|
||||||
|
server: {
|
||||||
|
url: (prev, page) =>
|
||||||
|
`${prev}${prev.includes("?") ? "&" : "?"}page=${
|
||||||
|
page + 1
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sort: true,
|
||||||
|
search: {
|
||||||
|
server: {
|
||||||
|
url: (prev, keyword) => `${prev}?search=${keyword}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
url: `${GlobalConfig.apiHost}/api/customers`,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
then: (data) =>
|
||||||
|
data.data.map((item) => [
|
||||||
|
item.id,
|
||||||
|
item.nomor_pelanggan,
|
||||||
|
item.nama,
|
||||||
|
item.kota_pelayanan,
|
||||||
|
item.alamat,
|
||||||
|
item.latitude,
|
||||||
|
item.longitude,
|
||||||
|
item.id,
|
||||||
|
]),
|
||||||
|
total: (data) => data.meta.total,
|
||||||
|
},
|
||||||
|
}).render(tableContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleDelete(deleteButton) {
|
||||||
|
const id = deleteButton.getAttribute("data-id");
|
||||||
|
|
||||||
|
const result = await Swal.fire({
|
||||||
|
title: "Are you sure?",
|
||||||
|
text: "You won't be able to revert this!",
|
||||||
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: "Yes, delete it!",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
try {
|
||||||
|
let response = await fetch(
|
||||||
|
`${GlobalConfig.apiHost}/api/customers/${id}`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let result = await response.json();
|
||||||
|
this.toastMessage.innerText =
|
||||||
|
result.message || "Deleted successfully!";
|
||||||
|
this.toast.show();
|
||||||
|
|
||||||
|
// Refresh Grid.js table
|
||||||
|
if (typeof this.table !== "undefined") {
|
||||||
|
this.table.updateConfig({}).forceRender();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let error = await response.json();
|
||||||
|
console.error("Delete failed:", error);
|
||||||
|
this.toastMessage.innerText =
|
||||||
|
error.message || "Delete failed!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting item:", error);
|
||||||
|
this.toastMessage.innerText = "An error occurred!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
|
new Customers();
|
||||||
|
});
|
||||||
78
resources/js/customers/upload.js
Normal file
78
resources/js/customers/upload.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { Dropzone } from "dropzone";
|
||||||
|
Dropzone.autoDiscover = false;
|
||||||
|
|
||||||
|
class UploadCustomers {
|
||||||
|
constructor() {
|
||||||
|
this.spatialDropzone = null;
|
||||||
|
this.formElement = document.getElementById("formUploadCustomers");
|
||||||
|
this.uploadButton = document.getElementById("submit-upload");
|
||||||
|
this.spinner = document.getElementById("spinner");
|
||||||
|
if (!this.formElement) {
|
||||||
|
console.error("Element formUploadCustomers tidak ditemukan!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.initDropzone();
|
||||||
|
this.setupUploadButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
initDropzone() {
|
||||||
|
const toastNotification = document.getElementById("toastNotification");
|
||||||
|
const toast = new bootstrap.Toast(toastNotification);
|
||||||
|
var previewTemplate,
|
||||||
|
dropzonePreviewNode = document.querySelector(
|
||||||
|
"#dropzone-preview-list"
|
||||||
|
);
|
||||||
|
(dropzonePreviewNode.id = ""),
|
||||||
|
dropzonePreviewNode &&
|
||||||
|
((previewTemplate = dropzonePreviewNode.parentNode.innerHTML),
|
||||||
|
dropzonePreviewNode.parentNode.removeChild(dropzonePreviewNode),
|
||||||
|
(this.spatialDropzone = new Dropzone(".dropzone", {
|
||||||
|
url: this.formElement.action,
|
||||||
|
method: "post",
|
||||||
|
acceptedFiles: ".xls,.xlsx",
|
||||||
|
previewTemplate: previewTemplate,
|
||||||
|
previewsContainer: "#dropzone-preview",
|
||||||
|
autoProcessQueue: false,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
},
|
||||||
|
init: function () {
|
||||||
|
this.on("success", function (file, response) {
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
response.message;
|
||||||
|
toast.show();
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "/data/customers";
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
this.on("error", function (file, errorMessage) {
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
errorMessage.message;
|
||||||
|
toast.show();
|
||||||
|
this.uploadButton.disabled = false;
|
||||||
|
this.spinner.classList.add("d-none");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
setupUploadButton() {
|
||||||
|
this.uploadButton.addEventListener("click", (e) => {
|
||||||
|
if (this.spatialDropzone.files.length > 0) {
|
||||||
|
this.spatialDropzone.processQueue();
|
||||||
|
this.uploadButton.disabled = true;
|
||||||
|
this.spinner.classList.remove("d-none");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
|
new UploadCustomers().init();
|
||||||
|
});
|
||||||
@@ -1,167 +1,31 @@
|
|||||||
import Big from "big.js";
|
import Big from "big.js";
|
||||||
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
|
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
|
||||||
import flatpickr from "flatpickr";
|
import InitDatePicker from "../utils/InitDatePicker.js";
|
||||||
import "flatpickr/dist/flatpickr.min.css";
|
|
||||||
|
|
||||||
class BigData {
|
class BigData {
|
||||||
async init() {
|
async init() {
|
||||||
try {
|
try {
|
||||||
this.filterYear = new Date().getFullYear(); // Set initial year
|
new InitDatePicker(
|
||||||
|
"#datepicker-dashboard-bigdata",
|
||||||
let yearSelect = document.querySelector("#yearPicker");
|
this.handleChangeDate.bind(this)
|
||||||
let filterButton = document.querySelector("#btnFilterYear");
|
).init();
|
||||||
|
|
||||||
if (!yearSelect || !filterButton) {
|
|
||||||
console.error(
|
|
||||||
"Element #yearPicker or #btnFilterYear not found."
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set default value for input
|
|
||||||
yearSelect.value = this.filterYear;
|
|
||||||
|
|
||||||
yearSelect.addEventListener("change", () => {
|
|
||||||
this.updateYear(yearSelect.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle button click
|
|
||||||
filterButton.addEventListener("click", () => {
|
|
||||||
this.updateYear(yearSelect.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("init filter this year", this.filterYear);
|
|
||||||
|
|
||||||
// Load initial data
|
// Load initial data
|
||||||
await this.updateData(this.filterYear);
|
this.updateData("latest");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error initializing data:", error);
|
console.error("Error initializing data:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateYear(value) {
|
|
||||||
let inputYear = parseInt(value, 10);
|
handleChangeDate(filterDate) {
|
||||||
if (!isNaN(inputYear)) {
|
if (!filterDate) return;
|
||||||
this.filterYear = inputYear;
|
this.updateData(filterDate);
|
||||||
this.updateData(this.filterYear);
|
|
||||||
} else {
|
|
||||||
console.error("Invalid year input");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async updateData(year) {
|
async updateData(filterDate) {
|
||||||
try {
|
try {
|
||||||
this.totalTargetPAD = await this.getDataSettings("TARGET_PAD");
|
this.resumeBigData = await this.getBigDataResume(filterDate);
|
||||||
this.resultDataTotal = await this.getDataTotalPotensi(year);
|
|
||||||
this.dataVerification = await this.getDataVerfication(year);
|
|
||||||
this.dataNonVerification = await this.getDataNonVerfication(year);
|
|
||||||
this.dataBusiness = await this.getDataBusiness(year);
|
|
||||||
this.dataNonBusiness = await this.getDataNonBusiness(year);
|
|
||||||
this.dataTataRuang = await this.getDataSettings("TATA_RUANG");
|
|
||||||
this.dataSumRealisasiTerbit = await this.getDataSettings(
|
|
||||||
"REALISASI_TERBIT_PBG_SUM"
|
|
||||||
);
|
|
||||||
this.dataCountRealisasiTerbit = await this.getDataSettings(
|
|
||||||
"REALISASI_TERBIT_PBG_COUNT"
|
|
||||||
);
|
|
||||||
this.dataSumMenungguKlikDPMPTSP = await this.getDataSettings(
|
|
||||||
"MENUNGGU_KLIK_DPMPTSP_SUM"
|
|
||||||
);
|
|
||||||
this.dataCountMenungguKlikDPMPTSP = await this.getDataSettings(
|
|
||||||
"MENUNGGU_KLIK_DPMPTSP_COUNT"
|
|
||||||
);
|
|
||||||
this.dataSumProsesDinasTeknis = await this.getDataSettings(
|
|
||||||
"PROSES_DINAS_TEKNIS_SUM"
|
|
||||||
);
|
|
||||||
this.dataCountProsesDinasTeknis = await this.getDataSettings(
|
|
||||||
"PROSES_DINAS_TEKNIS_COUNT"
|
|
||||||
);
|
|
||||||
|
|
||||||
// total potensi
|
this.initChartTargetPAD(filterDate);
|
||||||
this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0);
|
|
||||||
this.bigTotalPotensi = new Big(this.resultDataTotal.totalData ?? 0);
|
|
||||||
|
|
||||||
this.resultPercentage = 0;
|
|
||||||
if (this.bigTotalPotensi > 0 && this.bigTargetPAD > 0) {
|
|
||||||
this.resultPercentage = this.bigTotalPotensi
|
|
||||||
.div(this.bigTargetPAD)
|
|
||||||
.times(100)
|
|
||||||
.toFixed(2);
|
|
||||||
if (this.resultPercentage > 100) {
|
|
||||||
this.resultPercentage = 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// tata ruang
|
|
||||||
this.bigTotalTataRuang = new Big(this.dataTataRuang);
|
|
||||||
this.percentageResultTataRuang =
|
|
||||||
this.bigTotalTataRuang <= 0 || this.bigTotalPotensi <= 0
|
|
||||||
? 0
|
|
||||||
: this.bigTotalTataRuang
|
|
||||||
.div(this.bigTotalPotensi)
|
|
||||||
.times(100)
|
|
||||||
.toFixed(2);
|
|
||||||
|
|
||||||
// kekurangan potensi
|
|
||||||
this.totalKekuranganPotensi = new Big(
|
|
||||||
this.bigTargetPAD - this.bigTotalPotensi
|
|
||||||
);
|
|
||||||
|
|
||||||
this.percentageKekuranganPotensi =
|
|
||||||
this.totalKekuranganPotensi <= 0 || this.bigTargetPAD <= 0
|
|
||||||
? 0
|
|
||||||
: this.totalKekuranganPotensi
|
|
||||||
.div(this.bigTargetPAD)
|
|
||||||
.times(100)
|
|
||||||
.toFixed(2);
|
|
||||||
|
|
||||||
// non-verification documents
|
|
||||||
this.bigTotalNonVerification = new Big(
|
|
||||||
this.dataNonVerification.total
|
|
||||||
);
|
|
||||||
this.percentageResultNonVerification =
|
|
||||||
this.bigTotalNonVerification <= 0 || this.bigTotalPotensi <= 0
|
|
||||||
? 0
|
|
||||||
: this.bigTotalNonVerification
|
|
||||||
.div(this.bigTotalPotensi)
|
|
||||||
.times(100)
|
|
||||||
.toFixed(2);
|
|
||||||
|
|
||||||
// verification documents
|
|
||||||
this.bigTotalVerification = new Big(this.dataVerification.total);
|
|
||||||
this.percetageResultVerification =
|
|
||||||
this.bigTotalVerification <= 0 || this.bigTotalPotensi <= 0
|
|
||||||
? 0
|
|
||||||
: this.bigTotalVerification
|
|
||||||
.div(this.bigTargetPAD)
|
|
||||||
.times(100)
|
|
||||||
.toFixed(2);
|
|
||||||
|
|
||||||
// business documents
|
|
||||||
this.bigTotalBusiness = new Big(this.dataBusiness.total);
|
|
||||||
this.percentageResultBusiness =
|
|
||||||
this.bigTotalNonVerification <= 0 || this.bigTotalBusiness <= 0
|
|
||||||
? 0
|
|
||||||
: this.bigTotalBusiness
|
|
||||||
.div(this.bigTotalNonVerification)
|
|
||||||
.times(100)
|
|
||||||
.toFixed(2);
|
|
||||||
|
|
||||||
// non-business documents
|
|
||||||
this.bigTotalNonBusiness = new Big(this.dataNonBusiness.total);
|
|
||||||
this.percentageResultNonBusiness =
|
|
||||||
this.bigTotalNonBusiness <= 0 ||
|
|
||||||
this.bigTotalNonVerification <= 0
|
|
||||||
? 0
|
|
||||||
: this.bigTotalNonBusiness
|
|
||||||
.div(this.bigTotalNonVerification)
|
|
||||||
.times(100)
|
|
||||||
.toFixed(2);
|
|
||||||
|
|
||||||
if (!this.bigTargetPAD) {
|
|
||||||
console.error("Failed to load chart data");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.initChartTargetPAD();
|
|
||||||
this.initChartUsaha();
|
this.initChartUsaha();
|
||||||
this.initChartNonUsaha();
|
this.initChartNonUsaha();
|
||||||
this.initChartTotalPotensi();
|
this.initChartTotalPotensi();
|
||||||
@@ -177,10 +41,10 @@ class BigData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDataTotalPotensi(year) {
|
async getBigDataResume(filterByDate) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${GlobalConfig.apiHost}/api/all-task-documents?year=${year}`,
|
`${GlobalConfig.apiHost}/api/bigdata-resume?filterByDate=${filterByDate}`,
|
||||||
{
|
{
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -198,169 +62,23 @@ class BigData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return {
|
return data;
|
||||||
countData: data.data.count,
|
|
||||||
totalData: data.data.total,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching chart data:", error);
|
console.error("Error fetching chart data:", error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDataVerfication(year) {
|
initChartTargetPAD(filterDate) {
|
||||||
try {
|
const year =
|
||||||
const response = await fetch(
|
filterDate === "latest"
|
||||||
`${GlobalConfig.apiHost}/api/verification-documents?year=${year}`,
|
? new Date().getFullYear()
|
||||||
{
|
: new Date(filterDate).getFullYear();
|
||||||
credentials: "include",
|
document
|
||||||
headers: {
|
.querySelectorAll(".document-title.chart-target-pad")
|
||||||
Authorization: `Bearer ${
|
.forEach((element) => {
|
||||||
document.querySelector("meta[name='api-token']")
|
element.innerText = `Target PAD ${year}`;
|
||||||
.content
|
});
|
||||||
}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
console.error("Network response was not ok", response);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
return {
|
|
||||||
count: data.data.count,
|
|
||||||
total: data.data.total,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching chart data:", error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getDataNonVerfication(year) {
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`${GlobalConfig.apiHost}/api/non-verification-documents?year=${year}`,
|
|
||||||
{
|
|
||||||
credentials: "include",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${
|
|
||||||
document.querySelector("meta[name='api-token']")
|
|
||||||
.content
|
|
||||||
}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
console.error("Network response was not ok", response);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
return {
|
|
||||||
count: data.data.count,
|
|
||||||
total: data.data.total,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching chart data:", error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getDataBusiness(year) {
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`${GlobalConfig.apiHost}/api/business-documents?year=${year}`,
|
|
||||||
{
|
|
||||||
credentials: "include",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${
|
|
||||||
document.querySelector("meta[name='api-token']")
|
|
||||||
.content
|
|
||||||
}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
console.error("Network response was not ok", response);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
return {
|
|
||||||
count: data.data.count,
|
|
||||||
total: data.data.total,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching chart data:", error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getDataNonBusiness(year) {
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`${GlobalConfig.apiHost}/api/non-business-documents?year=${year}`,
|
|
||||||
{
|
|
||||||
credentials: "include",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${
|
|
||||||
document.querySelector("meta[name='api-token']")
|
|
||||||
.content
|
|
||||||
}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
console.error("Network response was not ok", response);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
return {
|
|
||||||
count: data.data.count,
|
|
||||||
total: data.data.total,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching chart data:", error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
initChartTargetPAD() {
|
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-count.chart-target-pad")
|
.querySelectorAll(".document-count.chart-target-pad")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
@@ -370,53 +88,59 @@ class BigData {
|
|||||||
.querySelectorAll(".document-total.chart-target-pad")
|
.querySelectorAll(".document-total.chart-target-pad")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.bigTargetPAD.toString()
|
this.resumeBigData.target_pad.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".small-percentage.chart-target-pad")
|
.querySelectorAll(".small-percentage.chart-target-pad")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${100}%`;
|
element.innerText = `${this.resumeBigData.target_pad.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initChartTotalPotensi() {
|
initChartTotalPotensi() {
|
||||||
const countAll = this.resultDataTotal.countData ?? 0;
|
// const countAll = this.resultDataTotal.countData ?? 0;
|
||||||
|
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-count.chart-total-potensi")
|
.querySelectorAll(".document-count.chart-total-potensi")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${countAll}`;
|
// element.innerText = `${countAll}`;
|
||||||
|
element.innerText = `${this.resumeBigData.total_potensi.count}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-total.chart-total-potensi")
|
.querySelectorAll(".document-total.chart-total-potensi")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.bigTotalPotensi.toString()
|
// this.bigTotalPotensi.toString()
|
||||||
|
this.resumeBigData.total_potensi.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".small-percentage.chart-total-potensi")
|
.querySelectorAll(".small-percentage.chart-total-potensi")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.resultPercentage}%`;
|
// element.innerText = `${this.resultPercentage}%`;
|
||||||
|
element.innerText = `${this.resumeBigData.total_potensi.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initChartVerificationDocuments() {
|
initChartVerificationDocuments() {
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-count.chart-berkas-terverifikasi")
|
.querySelectorAll(".document-count.chart-berkas-terverifikasi")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.dataVerification.count}`;
|
// element.innerText = `${this.dataVerification.count}`;
|
||||||
|
element.innerText = `${this.resumeBigData.verified_document.count}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-total.chart-berkas-terverifikasi")
|
.querySelectorAll(".document-total.chart-berkas-terverifikasi")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.bigTotalVerification.toString()
|
// this.bigTotalVerification.toString()
|
||||||
|
this.resumeBigData.verified_document.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".small-percentage.chart-berkas-terverifikasi")
|
.querySelectorAll(".small-percentage.chart-berkas-terverifikasi")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.percetageResultVerification}%`;
|
// element.innerText = `${this.percetageResultVerification}%`;
|
||||||
|
element.innerText = `${this.resumeBigData.verified_document.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initChartNonVerificationDocuments() {
|
initChartNonVerificationDocuments() {
|
||||||
@@ -425,7 +149,8 @@ class BigData {
|
|||||||
".document-count.chart-berkas-belum-terverifikasi"
|
".document-count.chart-berkas-belum-terverifikasi"
|
||||||
)
|
)
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.dataNonVerification.count}`;
|
// element.innerText = `${this.dataNonVerification.count}`;
|
||||||
|
element.innerText = `${this.resumeBigData.non_verified_document.count}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(
|
.querySelectorAll(
|
||||||
@@ -433,7 +158,8 @@ class BigData {
|
|||||||
)
|
)
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.bigTotalNonVerification.toString()
|
// this.bigTotalNonVerification.toString()
|
||||||
|
this.resumeBigData.non_verified_document.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
@@ -441,45 +167,52 @@ class BigData {
|
|||||||
".small-percentage.chart-berkas-belum-terverifikasi"
|
".small-percentage.chart-berkas-belum-terverifikasi"
|
||||||
)
|
)
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.percentageResultNonVerification}%`;
|
// element.innerText = `${this.percentageResultNonVerification}%`;
|
||||||
|
element.innerText = `${this.resumeBigData.non_verified_document.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initChartUsaha() {
|
initChartUsaha() {
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-count.chart-business")
|
.querySelectorAll(".document-count.chart-business")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.dataBusiness.count}`;
|
// element.innerText = `${this.dataBusiness.count}`;
|
||||||
|
element.innerText = `${this.resumeBigData.business_document.count}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-total.chart-business")
|
.querySelectorAll(".document-total.chart-business")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.bigTotalBusiness.toString()
|
// this.bigTotalBusiness.toString()
|
||||||
|
this.resumeBigData.business_document.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".small-percentage.chart-business")
|
.querySelectorAll(".small-percentage.chart-business")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.percentageResultBusiness}%`;
|
// element.innerText = `${this.percentageResultBusiness}%`;
|
||||||
|
element.innerText = `${this.resumeBigData.business_document.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initChartNonUsaha() {
|
initChartNonUsaha() {
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-count.chart-non-business")
|
.querySelectorAll(".document-count.chart-non-business")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.dataNonBusiness.count}`;
|
// element.innerText = `${this.dataNonBusiness.count}`;
|
||||||
|
element.innerText = `${this.resumeBigData.non_business_document.count}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-total.chart-non-business")
|
.querySelectorAll(".document-total.chart-non-business")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.bigTotalNonBusiness.toString()
|
// this.bigTotalNonBusiness.toString()
|
||||||
|
this.resumeBigData.non_business_document.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".small-percentage.chart-non-business")
|
.querySelectorAll(".small-percentage.chart-non-business")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.percentageResultNonBusiness}%`;
|
// element.innerText = `${this.percentageResultNonBusiness}%`;
|
||||||
|
element.innerText = `${this.resumeBigData.non_business_document.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initChartKekuranganPotensi() {
|
initChartKekuranganPotensi() {
|
||||||
@@ -492,89 +225,97 @@ class BigData {
|
|||||||
.querySelectorAll(".document-total.chart-kekurangan-potensi")
|
.querySelectorAll(".document-total.chart-kekurangan-potensi")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.totalKekuranganPotensi.toString()
|
// this.totalKekuranganPotensi.toString()
|
||||||
|
this.resumeBigData.kekurangan_potensi.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".small-percentage.chart-kekurangan-potensi")
|
.querySelectorAll(".small-percentage.chart-kekurangan-potensi")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.percentageKekuranganPotensi}%`;
|
// element.innerText = `${this.percentageKekuranganPotensi}%`;
|
||||||
|
element.innerText = `${this.resumeBigData.kekurangan_potensi.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initChartRealisasiTerbitPBG() {
|
initChartRealisasiTerbitPBG() {
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-count.chart-realisasi-tebit-pbg")
|
.querySelectorAll(".document-count.chart-realisasi-tebit-pbg")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.dataCountRealisasiTerbit}`;
|
// element.innerText = `${this.dataCountRealisasiTerbit}`;
|
||||||
|
element.innerText = `${this.resumeBigData.realisasi_terbit.count}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-total.chart-realisasi-tebit-pbg")
|
.querySelectorAll(".document-total.chart-realisasi-tebit-pbg")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.dataSumRealisasiTerbit
|
// this.dataSumRealisasiTerbit
|
||||||
|
this.resumeBigData.realisasi_terbit.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".small-percentage.chart-realisasi-tebit-pbg")
|
.querySelectorAll(".small-percentage.chart-realisasi-tebit-pbg")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `0.00%`;
|
element.innerText = `${this.resumeBigData.realisasi_terbit.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initChartMenungguKlikDPMPTSP() {
|
initChartMenungguKlikDPMPTSP() {
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-count.chart-menunggu-klik-dpmptsp")
|
.querySelectorAll(".document-count.chart-menunggu-klik-dpmptsp")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.dataCountMenungguKlikDPMPTSP}`;
|
// element.innerText = `${this.dataCountMenungguKlikDPMPTSP}`;
|
||||||
|
element.innerText = `${this.resumeBigData.menunggu_klik_dpmptsp.count}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-total.chart-menunggu-klik-dpmptsp")
|
.querySelectorAll(".document-total.chart-menunggu-klik-dpmptsp")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.dataSumMenungguKlikDPMPTSP
|
// this.dataSumMenungguKlikDPMPTSP
|
||||||
|
this.resumeBigData.menunggu_klik_dpmptsp.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".small-percentage.chart-menunggu-klik-dpmptsp")
|
.querySelectorAll(".small-percentage.chart-menunggu-klik-dpmptsp")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `0.00%`;
|
element.innerText = `${this.resumeBigData.menunggu_klik_dpmptsp.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initChartProsesDinasTeknis() {
|
initChartProsesDinasTeknis() {
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-count.chart-proses-dinas-teknis")
|
.querySelectorAll(".document-count.chart-proses-dinas-teknis")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.dataCountProsesDinasTeknis}`;
|
// element.innerText = `${this.dataCountProsesDinasTeknis}`;
|
||||||
|
element.innerText = `${this.resumeBigData.proses_dinas_teknis.count}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-total.chart-proses-dinas-teknis")
|
.querySelectorAll(".document-total.chart-proses-dinas-teknis")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.dataSumProsesDinasTeknis
|
// this.dataSumProsesDinasTeknis
|
||||||
|
this.resumeBigData.proses_dinas_teknis.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".small-percentage.chart-proses-dinas-teknis")
|
.querySelectorAll(".small-percentage.chart-proses-dinas-teknis")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `0.00%`;
|
element.innerText = `${this.resumeBigData.proses_dinas_teknis.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
initChartPotensiTataRuang() {
|
initChartPotensiTataRuang() {
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-count.chart-potensi-tata-ruang")
|
.querySelectorAll(".document-count.chart-potensi-tata-ruang")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = "";
|
element.innerText = `${this.resumeBigData.tata_ruang.count}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-total.chart-potensi-tata-ruang")
|
.querySelectorAll(".document-total.chart-potensi-tata-ruang")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `Rp.${addThousandSeparators(
|
element.innerText = `Rp.${addThousandSeparators(
|
||||||
this.bigTotalTataRuang.toString()
|
this.resumeBigData.tata_ruang.sum.toString()
|
||||||
)}`;
|
)}`;
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
.querySelectorAll(".small-percentage.chart-potensi-tata-ruang")
|
.querySelectorAll(".small-percentage.chart-potensi-tata-ruang")
|
||||||
.forEach((element) => {
|
.forEach((element) => {
|
||||||
element.innerText = `${this.percentageResultTataRuang}%`;
|
element.innerText = `${this.resumeBigData.tata_ruang.percentage}%`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,42 @@
|
|||||||
import Big from "big.js";
|
import Big from "big.js";
|
||||||
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
|
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
|
||||||
|
import InitDatePicker from "../utils/InitDatePicker.js";
|
||||||
|
|
||||||
class LackOfPotential {
|
class LackOfPotential {
|
||||||
async init() {
|
async init() {
|
||||||
|
new InitDatePicker(
|
||||||
|
"#datepicker-lack-of-potential",
|
||||||
|
this.handleChangedDate.bind(this)
|
||||||
|
).init();
|
||||||
this.bigTotalLackPotential = 0;
|
this.bigTotalLackPotential = 0;
|
||||||
this.totalPotensi = await this.getDataTotalPotensi(2025);
|
this.totalPotensi = await this.getDataTotalPotensi("latest");
|
||||||
this.totalTargetPAD = await this.getDataSettings("TARGET_PAD");
|
this.totalTargetPAD = await this.getDataSettings("TARGET_PAD");
|
||||||
|
this.allCountData = await this.getValueDashboard();
|
||||||
|
this.reklameCount = this.allCountData.total_reklame ?? 0;
|
||||||
|
this.pdamCount = this.allCountData.total_pdam ?? 0;
|
||||||
|
this.tataRuangCount = this.allCountData.total_tata_ruang ?? 0;
|
||||||
|
|
||||||
this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0);
|
this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0);
|
||||||
this.bigTotalPotensi = new Big(this.totalPotensi.totalData ?? 0);
|
this.bigTotalPotensi = new Big(this.totalPotensi.total ?? 0);
|
||||||
this.bigTotalLackPotential = this.bigTargetPAD - this.bigTotalPotensi;
|
this.bigTotalLackPotential = this.bigTargetPAD.minus(
|
||||||
|
this.bigTotalPotensi
|
||||||
|
);
|
||||||
|
this.initChartKekuranganPotensi();
|
||||||
|
this.initDataValueDashboard();
|
||||||
|
}
|
||||||
|
async handleChangedDate(filterDate) {
|
||||||
|
const totalPotensi = await this.getDataTotalPotensi(filterDate);
|
||||||
|
this.bigTotalPotensi = new Big(totalPotensi.total ?? 0);
|
||||||
|
this.bigTotalLackPotential = this.bigTargetPAD.minus(
|
||||||
|
this.bigTotalPotensi
|
||||||
|
);
|
||||||
|
|
||||||
this.initChartKekuranganPotensi();
|
this.initChartKekuranganPotensi();
|
||||||
}
|
}
|
||||||
async getDataTotalPotensi(year) {
|
async getDataTotalPotensi(filterDate) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${GlobalConfig.apiHost}/api/all-task-documents?year=${year}`,
|
`${GlobalConfig.apiHost}/api/bigdata-resume?filterByDate=${filterDate}`,
|
||||||
{
|
{
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -34,8 +55,7 @@ class LackOfPotential {
|
|||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return {
|
return {
|
||||||
countData: data.data.count,
|
total: data.total_potensi.sum,
|
||||||
totalData: data.data.total,
|
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching chart data:", error);
|
console.error("Error fetching chart data:", error);
|
||||||
@@ -45,7 +65,7 @@ class LackOfPotential {
|
|||||||
async getDataSettings(string_key) {
|
async getDataSettings(string_key) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${GlobalConfig.apiHost}/api/api-data-settings?search=${string_key}`,
|
`${GlobalConfig.apiHost}/api/data-settings?search=${string_key}`,
|
||||||
{
|
{
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -69,6 +89,33 @@ class LackOfPotential {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async getValueDashboard() {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${GlobalConfig.apiHost}/api/dashboard-potential-count`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${
|
||||||
|
document.querySelector("meta[name='api-token']")
|
||||||
|
.content
|
||||||
|
}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("Network response was not ok", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching chart data:", error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
initChartKekuranganPotensi() {
|
initChartKekuranganPotensi() {
|
||||||
document
|
document
|
||||||
.querySelectorAll(".document-count.chart-lack-of-potential")
|
.querySelectorAll(".document-count.chart-lack-of-potential")
|
||||||
@@ -88,6 +135,12 @@ class LackOfPotential {
|
|||||||
element.innerText = ``;
|
element.innerText = ``;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
initDataValueDashboard() {
|
||||||
|
document.getElementById("reklame-count").innerText = this.reklameCount;
|
||||||
|
document.getElementById("pdam-count").innerText = this.pdamCount;
|
||||||
|
document.getElementById("pbb-bangunan-count").innerText =
|
||||||
|
this.tataRuangCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener("DOMContentLoaded", async function (e) {
|
document.addEventListener("DOMContentLoaded", async function (e) {
|
||||||
await new LackOfPotential().init();
|
await new LackOfPotential().init();
|
||||||
|
|||||||
543
resources/js/dashboards/pbg.js
Normal file
543
resources/js/dashboards/pbg.js
Normal file
@@ -0,0 +1,543 @@
|
|||||||
|
import Big from "big.js";
|
||||||
|
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
|
||||||
|
import ApexCharts from "apexcharts";
|
||||||
|
import "gridjs/dist/gridjs.umd.js";
|
||||||
|
import GeneralTable from "../table-generator.js";
|
||||||
|
|
||||||
|
var chart;
|
||||||
|
document.addEventListener("DOMContentLoaded", async function () {
|
||||||
|
await initChart();
|
||||||
|
const yearPicker = document.getElementById("yearPicker");
|
||||||
|
|
||||||
|
async function updateDataByYear(selectedYear) {
|
||||||
|
// Target PAD Element
|
||||||
|
const targetPadElement = document.getElementById("target-pad");
|
||||||
|
if (!targetPadElement) return;
|
||||||
|
const targetPadValue = await getDataSettings("TARGET_PAD");
|
||||||
|
targetPadElement.textContent = formatCurrency(targetPadValue);
|
||||||
|
|
||||||
|
// Total Potensi Berkas
|
||||||
|
const totalPotensiBerkas = document.getElementById(
|
||||||
|
"total-potensi-berkas"
|
||||||
|
);
|
||||||
|
if (!totalPotensiBerkas) return;
|
||||||
|
const totalPotensiBerkasValue = await getDataTotalPotensi(selectedYear);
|
||||||
|
totalPotensiBerkas.textContent = formatCurrency(
|
||||||
|
totalPotensiBerkasValue.totalData
|
||||||
|
);
|
||||||
|
|
||||||
|
// Total Berkas Terverifikasi
|
||||||
|
const totalBerkasTerverifikasi = document.getElementById(
|
||||||
|
"total-berkas-terverifikasi"
|
||||||
|
);
|
||||||
|
if (!totalBerkasTerverifikasi) return;
|
||||||
|
const totalBerkasTerverifikasiValue = await getDataVerification(
|
||||||
|
selectedYear
|
||||||
|
);
|
||||||
|
totalBerkasTerverifikasi.textContent = formatCurrency(
|
||||||
|
totalBerkasTerverifikasiValue.totalData
|
||||||
|
);
|
||||||
|
|
||||||
|
// Total Kekurangan potensi
|
||||||
|
const totalKekuranganPotensi = document.getElementById(
|
||||||
|
"total-kekurangan-potensi"
|
||||||
|
);
|
||||||
|
if (!totalKekuranganPotensi) return;
|
||||||
|
const totalKekuranganPotensiValue =
|
||||||
|
new Big(targetPadValue) -
|
||||||
|
new Big(totalPotensiBerkasValue.totalData);
|
||||||
|
totalKekuranganPotensi.textContent = formatCurrency(
|
||||||
|
totalKekuranganPotensiValue
|
||||||
|
);
|
||||||
|
|
||||||
|
// Total Potensi PBG dari tata ruang
|
||||||
|
const totalPotensiPBGTataRuang = document.getElementById(
|
||||||
|
"total-potensi-pbd-tata-ruang"
|
||||||
|
);
|
||||||
|
if (!totalPotensiPBGTataRuang) return;
|
||||||
|
const totalPotensiPBGTataRuangValue = await getDataSettings(
|
||||||
|
"TATA_RUANG"
|
||||||
|
);
|
||||||
|
totalPotensiPBGTataRuang.textContent = formatCurrency(
|
||||||
|
totalPotensiPBGTataRuangValue
|
||||||
|
);
|
||||||
|
|
||||||
|
// Total Berkas Belum terverifikasi
|
||||||
|
const totalBerkasBelumTerverifikasi = document.getElementById(
|
||||||
|
"total-berkas-belum-terverifikasi"
|
||||||
|
);
|
||||||
|
if (!totalBerkasBelumTerverifikasi) return;
|
||||||
|
const totalBerkasBelumTerverifikasiValue = await getDataNonVerification(
|
||||||
|
selectedYear
|
||||||
|
);
|
||||||
|
const totalBerkasBelumTerverifikasiCount =
|
||||||
|
totalBerkasBelumTerverifikasiValue.countData;
|
||||||
|
totalBerkasBelumTerverifikasi.textContent = formatCurrency(
|
||||||
|
totalBerkasBelumTerverifikasiValue.totalData
|
||||||
|
);
|
||||||
|
|
||||||
|
// Total Berkas Usaha
|
||||||
|
const totalBerkasUsahaValue = await getDataBusiness(selectedYear);
|
||||||
|
const totalBerkasUsahaCount = totalBerkasUsahaValue.countData;
|
||||||
|
const totalBerkasUsahaTotalData = totalBerkasUsahaValue.totalData;
|
||||||
|
|
||||||
|
// Total Berkas Non Usaha
|
||||||
|
const totalBerkasNonUsahaValue = await getDataNonBusiness(selectedYear);
|
||||||
|
const totalBerkasNonUsahaCount = totalBerkasNonUsahaValue.countData;
|
||||||
|
const totalBerkasNonUsahaTotalData = totalBerkasNonUsahaValue.totalData;
|
||||||
|
|
||||||
|
// Pie Chart Section
|
||||||
|
let persenUsaha =
|
||||||
|
totalBerkasBelumTerverifikasiCount > 0
|
||||||
|
? (
|
||||||
|
(totalBerkasUsahaCount /
|
||||||
|
totalBerkasBelumTerverifikasiCount) *
|
||||||
|
100
|
||||||
|
).toFixed(2)
|
||||||
|
: "0";
|
||||||
|
|
||||||
|
let persenNonUsaha =
|
||||||
|
totalBerkasBelumTerverifikasiCount > 0
|
||||||
|
? (
|
||||||
|
(totalBerkasNonUsahaCount /
|
||||||
|
totalBerkasBelumTerverifikasiCount) *
|
||||||
|
100
|
||||||
|
).toFixed(2)
|
||||||
|
: "0";
|
||||||
|
|
||||||
|
const dataSeriesPieChart = [
|
||||||
|
Number(persenUsaha),
|
||||||
|
Number(persenNonUsaha),
|
||||||
|
];
|
||||||
|
const labelsPieChart = ["Berkas Usaha", "Berkas Non Usaha"];
|
||||||
|
document.querySelector("td[data-category='non-usaha']").textContent =
|
||||||
|
formatCurrency(totalBerkasNonUsahaTotalData).toLocaleString();
|
||||||
|
document.querySelector(
|
||||||
|
"td[data-category='non-usaha-percentage']"
|
||||||
|
).textContent = persenNonUsaha + "%";
|
||||||
|
|
||||||
|
document.querySelector("td[data-category='usaha']").textContent =
|
||||||
|
formatCurrency(totalBerkasUsahaTotalData).toLocaleString();
|
||||||
|
document.querySelector(
|
||||||
|
"td[data-category='usaha-percentage']"
|
||||||
|
).textContent = persenUsaha + "%";
|
||||||
|
|
||||||
|
updatePieChart(dataSeriesPieChart, labelsPieChart);
|
||||||
|
|
||||||
|
// Load all Tourism location
|
||||||
|
const allLocation = await getAllLocation();
|
||||||
|
console.log(allLocation);
|
||||||
|
|
||||||
|
// Filter hanya data yang memiliki angka valid
|
||||||
|
let validLocations = allLocation.dataLocation.filter((loc) => {
|
||||||
|
return (
|
||||||
|
!isNaN(parseFloat(loc.longitude)) &&
|
||||||
|
!isNaN(parseFloat(loc.latitude))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ubah string ke float
|
||||||
|
validLocations = validLocations.map((loc) => ({
|
||||||
|
name: loc.project_name,
|
||||||
|
longitude: parseFloat(loc.longitude),
|
||||||
|
latitude: parseFloat(loc.latitude),
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.log(validLocations.name);
|
||||||
|
|
||||||
|
// Inisialisasi peta
|
||||||
|
var map = L.map("map").setView([-7.023, 107.5275], 10);
|
||||||
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||||
|
attribution: "© OpenStreetMap contributors",
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
// Tambahkan marker ke peta
|
||||||
|
validLocations.forEach(function (loc) {
|
||||||
|
L.marker([loc.latitude, loc.longitude])
|
||||||
|
.addTo(map)
|
||||||
|
.bindPopup(`<b>${loc.name}</b>`) // Popup saat diklik
|
||||||
|
.bindTooltip(loc.name, { permanent: false, direction: "top" }); // Tooltip saat di-hover
|
||||||
|
});
|
||||||
|
|
||||||
|
// Realisasi terbit PBG
|
||||||
|
const totalRealisasiTerbitPBG = document.getElementById(
|
||||||
|
"realisasi-terbit-pbg"
|
||||||
|
);
|
||||||
|
if (!totalRealisasiTerbitPBG) return;
|
||||||
|
const totalRealisasiTerbitPBGValue = await getDataSettings(
|
||||||
|
"REALISASI_TERBIT_PBG_SUM"
|
||||||
|
);
|
||||||
|
totalRealisasiTerbitPBG.textContent = formatCurrency(
|
||||||
|
totalRealisasiTerbitPBGValue
|
||||||
|
);
|
||||||
|
|
||||||
|
// Menunggu Klik DPMPTSP
|
||||||
|
const totalMenungguKlikDpmptsp = document.getElementById(
|
||||||
|
"waiting-click-dpmptsp"
|
||||||
|
);
|
||||||
|
if (!totalMenungguKlikDpmptsp) return;
|
||||||
|
const totalMenungguKlikDpmptspValue = await getDataSettings(
|
||||||
|
"MENUNGGU_KLIK_DPMPTSP_SUM"
|
||||||
|
);
|
||||||
|
totalMenungguKlikDpmptsp.textContent = formatCurrency(
|
||||||
|
totalMenungguKlikDpmptspValue
|
||||||
|
);
|
||||||
|
|
||||||
|
// Proses Dinas Teknis
|
||||||
|
const totalProsesDinasTeknis = document.getElementById(
|
||||||
|
"processing-technical-services"
|
||||||
|
);
|
||||||
|
if (!totalProsesDinasTeknis) return;
|
||||||
|
const totalProsesDinasTeknisValue = await getDataSettings(
|
||||||
|
"PROSES_DINAS_TEKNIS_SUM"
|
||||||
|
);
|
||||||
|
totalProsesDinasTeknis.textContent = formatCurrency(
|
||||||
|
totalProsesDinasTeknisValue
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load Tabel Baru di Update
|
||||||
|
const tableLastUpdated = new GeneralTable(
|
||||||
|
"pbg-filter-by-updated-at",
|
||||||
|
`${GlobalConfig.apiHost}/api/api-pbg-task?isLastUpdated=true`,
|
||||||
|
`${GlobalConfig.apiHost}`,
|
||||||
|
pbgTaskColumns
|
||||||
|
);
|
||||||
|
|
||||||
|
tableLastUpdated.processData = function (data) {
|
||||||
|
console.log("Response Data:", data);
|
||||||
|
return data.data.map((item) => {
|
||||||
|
return [
|
||||||
|
item.no,
|
||||||
|
item.name,
|
||||||
|
item.registration_number,
|
||||||
|
item.document_number,
|
||||||
|
item.address,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
tableLastUpdated.init();
|
||||||
|
|
||||||
|
// Load Tabel Status SK Terbit
|
||||||
|
const tableSKPBGTerbit = new GeneralTable(
|
||||||
|
"pbg-filter-by-status",
|
||||||
|
`${GlobalConfig.apiHost}/api/api-pbg-task?isLastUpdated=false`,
|
||||||
|
`${GlobalConfig.apiHost}`,
|
||||||
|
pbgTaskColumns
|
||||||
|
);
|
||||||
|
|
||||||
|
tableSKPBGTerbit.processData = function (data) {
|
||||||
|
console.log("Response Data:", data);
|
||||||
|
return data.data.map((item) => {
|
||||||
|
return [
|
||||||
|
item.no,
|
||||||
|
item.name,
|
||||||
|
item.registration_number,
|
||||||
|
item.document_number,
|
||||||
|
item.address,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
tableSKPBGTerbit.init();
|
||||||
|
|
||||||
|
document.querySelector(
|
||||||
|
"#pbg-filter-by-updated-at .gridjs-search"
|
||||||
|
).hidden = true;
|
||||||
|
document.querySelector(
|
||||||
|
"#pbg-filter-by-updated-at .gridjs-footer"
|
||||||
|
).hidden = true;
|
||||||
|
document.querySelector(
|
||||||
|
"#pbg-filter-by-status .gridjs-search"
|
||||||
|
).hidden = true;
|
||||||
|
document.querySelector(
|
||||||
|
"#pbg-filter-by-status .gridjs-footer"
|
||||||
|
).hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateDataByYear(yearPicker.value);
|
||||||
|
|
||||||
|
yearPicker.addEventListener("change", async function () {
|
||||||
|
console.log("event change dropdown");
|
||||||
|
await updateDataByYear(yearPicker.value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function getDataSettings(string_key) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${GlobalConfig.apiHost}/api/data-settings?search=${string_key}`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${
|
||||||
|
document.querySelector("meta[name='api-token']").content
|
||||||
|
}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("Network response was not ok", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return data.data?.[0]?.value ?? 0; // Pastikan tidak error jika data kosong
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching data:", error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataTotalPotensi(year) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${GlobalConfig.apiHost}/api/all-task-documents?year=${year}`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${
|
||||||
|
document.querySelector("meta[name='api-token']").content
|
||||||
|
}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("Network response was not ok", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return {
|
||||||
|
totalData: data.data.total,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching chart data:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataVerification(year) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${GlobalConfig.apiHost}/api/verification-documents?year=${year}`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${
|
||||||
|
document.querySelector("meta[name='api-token']").content
|
||||||
|
}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("Network response was not ok", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return {
|
||||||
|
totalData: data.data.total,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching chart data:", error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataNonVerification(year) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${GlobalConfig.apiHost}/api/non-verification-documents?year=${year}`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${
|
||||||
|
document.querySelector("meta[name='api-token']").content
|
||||||
|
}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("Network response was not ok", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return {
|
||||||
|
countData: data.data.count,
|
||||||
|
totalData: data.data.total,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching chart data:", error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataBusiness(year) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${GlobalConfig.apiHost}/api/business-documents?year=${year}`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${
|
||||||
|
document.querySelector("meta[name='api-token']").content
|
||||||
|
}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("Network response was not ok", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return {
|
||||||
|
countData: data.data.count,
|
||||||
|
totalData: data.data.total,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching chart data:", error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataNonBusiness(year) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${GlobalConfig.apiHost}/api/non-business-documents?year=${year}`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${
|
||||||
|
document.querySelector("meta[name='api-token']").content
|
||||||
|
}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("Network response was not ok", response);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
return {
|
||||||
|
countData: data.data.count,
|
||||||
|
totalData: data.data.total,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching chart data:", error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllLocation() {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${GlobalConfig.apiHost}/api/get-all-location`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${
|
||||||
|
document.querySelector("meta[name='api-token']").content
|
||||||
|
}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("Network response was not ok", response);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
return {
|
||||||
|
dataLocation: data.data,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching chart data:", error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initChart() {
|
||||||
|
var options = {
|
||||||
|
chart: {
|
||||||
|
height: 180,
|
||||||
|
type: "donut",
|
||||||
|
},
|
||||||
|
series: [0, 0], // Inisialisasi dengan nilai awal
|
||||||
|
labels: ["Berkas Usaha", "Berkas Non Usaha"],
|
||||||
|
legend: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
stroke: {
|
||||||
|
width: 0,
|
||||||
|
},
|
||||||
|
plotOptions: {
|
||||||
|
pie: {
|
||||||
|
donut: {
|
||||||
|
size: "60%",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
colors: ["#7e67fe", "#17c553"],
|
||||||
|
dataLabels: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
responsive: [
|
||||||
|
{
|
||||||
|
breakpoint: 480,
|
||||||
|
options: {
|
||||||
|
chart: {
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
fill: {
|
||||||
|
type: "gradient",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
chart = new ApexCharts(document.querySelector("#conversions"), options);
|
||||||
|
chart.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updatePieChart(dataSeries, labels) {
|
||||||
|
if (!Array.isArray(dataSeries) || dataSeries.length === 0) {
|
||||||
|
console.error("Data series tidak valid:", dataSeries);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perbarui data series chart
|
||||||
|
chart.updateSeries(dataSeries);
|
||||||
|
|
||||||
|
// Perbarui label jika diperlukan
|
||||||
|
if (Array.isArray(labels) && labels.length === dataSeries.length) {
|
||||||
|
chart.updateOptions({
|
||||||
|
labels: labels,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fungsi untuk format angka ke Rupiah
|
||||||
|
function formatCurrency(number) {
|
||||||
|
return new Intl.NumberFormat("id-ID", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "IDR",
|
||||||
|
minimumFractionDigits: 0,
|
||||||
|
}).format(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pbgTaskColumns = [
|
||||||
|
"No",
|
||||||
|
"Name",
|
||||||
|
"Nomor Registrasi",
|
||||||
|
"Nomor Dokumen",
|
||||||
|
"Alamat",
|
||||||
|
];
|
||||||
@@ -24,10 +24,9 @@ document.addEventListener("DOMContentLoaded", function (e) {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
"X-CSRF-TOKEN": document
|
Authorization: `Bearer ${document
|
||||||
.querySelector('meta[name="csrf-token"]')
|
.querySelector('meta[name="api-token"]')
|
||||||
.getAttribute("content"),
|
.getAttribute("content")}`,
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
},
|
||||||
body: formData,
|
body: formData,
|
||||||
});
|
});
|
||||||
@@ -35,7 +34,7 @@ document.addEventListener("DOMContentLoaded", function (e) {
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
let result = await response.json();
|
let result = await response.json();
|
||||||
document.getElementById("toast-message").innerText =
|
document.getElementById("toast-message").innerText =
|
||||||
result.message;
|
result.data.message;
|
||||||
toast.show();
|
toast.show();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = "/data-settings";
|
window.location.href = "/data-settings";
|
||||||
@@ -46,6 +45,8 @@ document.addEventListener("DOMContentLoaded", function (e) {
|
|||||||
error.message;
|
error.message;
|
||||||
toast.show();
|
toast.show();
|
||||||
console.error("Error:", error);
|
console.error("Error:", error);
|
||||||
|
submitButton.disabled = false;
|
||||||
|
spinner.classList.add("d-none");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Request failed:", error);
|
console.error("Request failed:", error);
|
||||||
|
|||||||
@@ -2,46 +2,34 @@ import { Grid } from "gridjs/dist/gridjs.umd.js";
|
|||||||
import gridjs from "gridjs/dist/gridjs.umd.js";
|
import gridjs from "gridjs/dist/gridjs.umd.js";
|
||||||
import "gridjs/dist/gridjs.umd.js";
|
import "gridjs/dist/gridjs.umd.js";
|
||||||
import GlobalConfig from "../global-config.js";
|
import GlobalConfig from "../global-config.js";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
|
||||||
class DataSettings {
|
class DataSettings {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.table = null; // Store Grid.js instance
|
this.toastMessage = document.getElementById("toast-message");
|
||||||
|
this.toastElement = document.getElementById("toastNotification");
|
||||||
|
this.toast = new bootstrap.Toast(this.toastElement);
|
||||||
|
this.table = null;
|
||||||
|
|
||||||
|
// Initialize functions
|
||||||
|
this.initTableDataSettings();
|
||||||
|
this.initEvents();
|
||||||
}
|
}
|
||||||
init() {
|
initEvents() {
|
||||||
this.getFetchApiData();
|
document.body.addEventListener("click", async (event) => {
|
||||||
|
const deleteButton = event.target.closest(
|
||||||
|
".btn-delete-data-settings"
|
||||||
|
);
|
||||||
|
if (deleteButton) {
|
||||||
|
event.preventDefault();
|
||||||
|
await this.handleDelete(deleteButton);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getFetchApiData() {
|
initTableDataSettings() {
|
||||||
let tableContainer = document.getElementById("table-data-settings");
|
let tableContainer = document.getElementById("table-data-settings");
|
||||||
|
// Create a new Grid.js instance only if it doesn't exist
|
||||||
if (this.table) {
|
|
||||||
// If table exists, update its data instead of recreating
|
|
||||||
this.table
|
|
||||||
.updateConfig({
|
|
||||||
server: {
|
|
||||||
url: `${GlobalConfig.apiHost}/api/api-data-settings`,
|
|
||||||
credentials: "include",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${document
|
|
||||||
.querySelector('meta[name="api-token"]')
|
|
||||||
.getAttribute("content")}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
then: (data) =>
|
|
||||||
data.data.map((item) => [
|
|
||||||
item.id,
|
|
||||||
item.key,
|
|
||||||
item.value,
|
|
||||||
item.created_at,
|
|
||||||
item.id,
|
|
||||||
]),
|
|
||||||
total: (data) => data.meta.total,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.forceRender();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.table = new Grid({
|
this.table = new Grid({
|
||||||
columns: [
|
columns: [
|
||||||
"ID",
|
"ID",
|
||||||
@@ -65,11 +53,6 @@ class DataSettings {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
search: {
|
|
||||||
server: {
|
|
||||||
url: (prev, keyword) => `${prev}?search=${keyword}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pagination: {
|
pagination: {
|
||||||
limit: 15,
|
limit: 15,
|
||||||
server: {
|
server: {
|
||||||
@@ -80,8 +63,13 @@ class DataSettings {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
sort: true,
|
sort: true,
|
||||||
|
search: {
|
||||||
|
server: {
|
||||||
|
url: (prev, keyword) => `${prev}?search=${keyword}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
url: `${GlobalConfig.apiHost}/api/api-data-settings`,
|
url: `${GlobalConfig.apiHost}/api/data-settings`,
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${document
|
Authorization: `Bearer ${document
|
||||||
.querySelector('meta[name="api-token"]')
|
.querySelector('meta[name="api-token"]')
|
||||||
@@ -99,94 +87,26 @@ class DataSettings {
|
|||||||
total: (data) => data.meta.total,
|
total: (data) => data.meta.total,
|
||||||
},
|
},
|
||||||
}).render(tableContainer);
|
}).render(tableContainer);
|
||||||
|
|
||||||
document.addEventListener("click", this.handleDelete.bind(this));
|
|
||||||
}
|
}
|
||||||
handleDelete(event) {
|
async handleDelete(deleteButton) {
|
||||||
if (event.target.classList.contains("btn-delete-data-settings")) {
|
const id = deleteButton.getAttribute("data-id");
|
||||||
event.preventDefault();
|
|
||||||
const id = event.target.getAttribute("data-id");
|
|
||||||
let modalElement = document.getElementById("modalConfirmation");
|
|
||||||
let toastMessage = document.getElementById("toast-message");
|
|
||||||
|
|
||||||
if (!modalElement) {
|
const result = await Swal.fire({
|
||||||
console.error("Modal element not found!");
|
title: "Are you sure?",
|
||||||
return;
|
text: "You won't be able to revert this!",
|
||||||
}
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: "Yes, delete it!",
|
||||||
|
});
|
||||||
|
|
||||||
let modal = new bootstrap.Modal(modalElement);
|
if (result.isConfirmed) {
|
||||||
let btnSaveConfirmation = document.getElementById(
|
try {
|
||||||
"btnSaveConfirmation"
|
let response = await fetch(
|
||||||
);
|
`${GlobalConfig.apiHost}/api/data-settings/${id}`,
|
||||||
let toastElement = document.getElementById("toastNotification");
|
{
|
||||||
let toast = new bootstrap.Toast(toastElement);
|
method: "DELETE",
|
||||||
|
|
||||||
// Remove previous event listeners to avoid multiple bindings
|
|
||||||
btnSaveConfirmation.replaceWith(
|
|
||||||
btnSaveConfirmation.cloneNode(true)
|
|
||||||
);
|
|
||||||
btnSaveConfirmation = document.getElementById(
|
|
||||||
"btnSaveConfirmation"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set the role ID on the confirm button inside the modal
|
|
||||||
btnSaveConfirmation.setAttribute("data-settings-id", id);
|
|
||||||
|
|
||||||
// Show the modal
|
|
||||||
modal.show();
|
|
||||||
|
|
||||||
btnSaveConfirmation.addEventListener("click", async () => {
|
|
||||||
let dataSettingId =
|
|
||||||
btnSaveConfirmation.getAttribute("data-settings-id");
|
|
||||||
|
|
||||||
try {
|
|
||||||
let response = await fetch(
|
|
||||||
`/data-settings/${dataSettingId}`,
|
|
||||||
{
|
|
||||||
method: "DELETE",
|
|
||||||
credentials: "include",
|
|
||||||
headers: {
|
|
||||||
"X-CSRF-TOKEN": document
|
|
||||||
.querySelector('meta[name="csrf-token"]')
|
|
||||||
.getAttribute("content"),
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
let result = await response.json();
|
|
||||||
toastMessage.innerText =
|
|
||||||
result.message || "Deleted successfully!";
|
|
||||||
toast.show();
|
|
||||||
|
|
||||||
// Hide modal
|
|
||||||
modal.hide();
|
|
||||||
|
|
||||||
// Refresh Grid.js table
|
|
||||||
this.refreshDataSettings();
|
|
||||||
} else {
|
|
||||||
let error = await response.json();
|
|
||||||
console.error("Delete failed:", error);
|
|
||||||
toastMessage.innerText =
|
|
||||||
error.message || "Delete failed!";
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error deleting item:", error);
|
|
||||||
toastMessage.innerText = "An error occurred!";
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshDataSettings() {
|
|
||||||
if (this.table) {
|
|
||||||
this.table
|
|
||||||
.updateConfig({
|
|
||||||
server: {
|
|
||||||
url: `${GlobalConfig.apiHost}/api/api-data-settings`,
|
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${document
|
Authorization: `Bearer ${document
|
||||||
@@ -194,21 +114,34 @@ class DataSettings {
|
|||||||
.getAttribute("content")}`,
|
.getAttribute("content")}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
then: (data) =>
|
}
|
||||||
data.data.map((item) => [
|
);
|
||||||
item.id,
|
|
||||||
item.key,
|
if (response.ok) {
|
||||||
item.value,
|
let result = await response.json();
|
||||||
item.created_at,
|
this.toastMessage.innerText =
|
||||||
item.id,
|
result.message || "Deleted successfully!";
|
||||||
]),
|
this.toast.show();
|
||||||
total: (data) => data.meta.total,
|
|
||||||
},
|
// Refresh Grid.js table
|
||||||
})
|
if (typeof this.table !== "undefined") {
|
||||||
.forceRender();
|
this.table.updateConfig({}).forceRender();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let error = await response.json();
|
||||||
|
console.error("Delete failed:", error);
|
||||||
|
this.toastMessage.innerText =
|
||||||
|
error.message || "Delete failed!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting item:", error);
|
||||||
|
this.toastMessage.innerText = "An error occurred!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
new DataSettings().init();
|
new DataSettings();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -24,16 +24,16 @@ document.addEventListener("DOMContentLoaded", function (e) {
|
|||||||
let response = await fetch(form.action, {
|
let response = await fetch(form.action, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"X-CSRF-TOKEN": document
|
Authorization: `Bearer ${document
|
||||||
.querySelector('meta[name="csrf-token"]')
|
.querySelector('meta[name="api-token"]')
|
||||||
.getAttribute("content"),
|
.getAttribute("content")}`,
|
||||||
},
|
},
|
||||||
body: formData,
|
body: formData,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
let result = await response.json();
|
let result = await response.json();
|
||||||
toastMessage.innerText = result.message;
|
toastMessage.innerText = result.data.message;
|
||||||
toast.show();
|
toast.show();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = "/data-settings";
|
window.location.href = "/data-settings";
|
||||||
@@ -43,6 +43,8 @@ document.addEventListener("DOMContentLoaded", function (e) {
|
|||||||
toastMessage.innerText = error.message;
|
toastMessage.innerText = error.message;
|
||||||
toast.show();
|
toast.show();
|
||||||
console.error("Error:", error);
|
console.error("Error:", error);
|
||||||
|
submitButton.disabled = false;
|
||||||
|
spinner.classList.add("d-none");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Request failed:", error);
|
console.error("Request failed:", error);
|
||||||
|
|||||||
@@ -28,12 +28,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
data[key] = value;
|
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");
|
const url = form.getAttribute("action");
|
||||||
console.log("Ini adalah url dari form action", url);
|
|
||||||
|
|
||||||
const method = isEdit ? "PUT" : "POST";
|
const method = isEdit ? "PUT" : "POST";
|
||||||
|
|
||||||
@@ -49,7 +44,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
console.log("Response data:", data);
|
|
||||||
if (!data.errors) {
|
if (!data.errors) {
|
||||||
// Remove existing icon (if any) before adding the new one
|
// Remove existing icon (if any) before adding the new one
|
||||||
if (authLogo) {
|
if (authLogo) {
|
||||||
@@ -74,11 +68,11 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
toast.classList.add('show'); // Show the toast
|
toast.classList.add('show'); // Show the toast
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||||
}, 3000);
|
}, 2000);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = '/data/advertisements';
|
window.location.href = '/data/advertisements';
|
||||||
}, 3000);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
if (authLogo) {
|
if (authLogo) {
|
||||||
// Hapus ikon yang sudah ada jika ada
|
// Hapus ikon yang sudah ada jika ada
|
||||||
@@ -96,21 +90,21 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
// Tambahkan ikon ke dalam auth-logo
|
// Tambahkan ikon ke dalam auth-logo
|
||||||
authLogo.appendChild(icon);
|
authLogo.appendChild(icon);
|
||||||
}
|
}
|
||||||
// Set error message for the toast
|
|
||||||
toastBody.textContent = "Error: " + (responseData.message || "Something went wrong");
|
|
||||||
toast.classList.add('show'); // Show the toast
|
|
||||||
|
|
||||||
// Enable button and reset its text on error
|
// Enable button and reset its text on error
|
||||||
modalButton.disabled = false;
|
modalButton.disabled = false;
|
||||||
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
||||||
|
|
||||||
|
// Set error message for the toast
|
||||||
|
toastBody.textContent = "Failed: " + (data.message || "Something went wrong");
|
||||||
|
toast.classList.add('show'); // Show the toast
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(errors => {
|
||||||
console.error("Error:", error);
|
|
||||||
if (authLogo) {
|
if (authLogo) {
|
||||||
// Hapus ikon yang sudah ada jika ada
|
// Hapus ikon yang sudah ada jika ada
|
||||||
const existingIcon = authLogo.querySelector('.bx');
|
const existingIcon = authLogo.querySelector('.bx');
|
||||||
@@ -127,14 +121,14 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
// Tambahkan ikon ke dalam auth-logo
|
// Tambahkan ikon ke dalam auth-logo
|
||||||
authLogo.appendChild(icon);
|
authLogo.appendChild(icon);
|
||||||
}
|
}
|
||||||
|
// Enable button and reset its text on error
|
||||||
|
modalButton.disabled = false;
|
||||||
|
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
||||||
|
|
||||||
// Set error message for the toast
|
// Set error message for the toast
|
||||||
toastBody.textContent = "An error occurred while processing your request.";
|
toastBody.textContent = "An error occurred while processing your request.";
|
||||||
toast.classList.add('show'); // Show the toast
|
toast.classList.add('show'); // Show the toast
|
||||||
|
|
||||||
// Enable button and reset its text on error
|
|
||||||
modalButton.disabled = false;
|
|
||||||
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||||
}, 3000);
|
}, 3000);
|
||||||
@@ -144,7 +138,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
// Fungsi fetchOptions untuk autocomplete server-side
|
// Fungsi fetchOptions untuk autocomplete server-side
|
||||||
window.fetchOptions = function (field) {
|
window.fetchOptions = function (field) {
|
||||||
let inputValue = document.getElementById(field).value;
|
let inputValue = document.getElementById(field).value;
|
||||||
console.log("Query Value:", inputValue); // Debugging log
|
|
||||||
if (inputValue.length < 2) return;
|
if (inputValue.length < 2) return;
|
||||||
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
||||||
|
|
||||||
|
|||||||
63
resources/js/data/spatialPlannings/data-spatialPlannings.js
Normal file
63
resources/js/data/spatialPlannings/data-spatialPlannings.js
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { Grid } from "gridjs/dist/gridjs.umd.js";
|
||||||
|
import gridjs from "gridjs/dist/gridjs.umd.js";
|
||||||
|
import "gridjs/dist/gridjs.umd.js";
|
||||||
|
import GlobalConfig from "../../global-config.js";
|
||||||
|
import GeneralTable from "../../table-generator.js";
|
||||||
|
|
||||||
|
const dataSpatialPlanningColumns = [
|
||||||
|
"No",
|
||||||
|
"Nama",
|
||||||
|
"KBLI",
|
||||||
|
"Kegiatan",
|
||||||
|
"Luas",
|
||||||
|
"Lokasi",
|
||||||
|
"Nomor",
|
||||||
|
"Tanggal",
|
||||||
|
{
|
||||||
|
name: "Actions",
|
||||||
|
widht: "120px",
|
||||||
|
formatter: function (cell, row) {
|
||||||
|
const id = row.cells[8].data;
|
||||||
|
const model = "data/spatial-plannings";
|
||||||
|
return gridjs.html(`
|
||||||
|
<div class="d-flex justify-items-end gap-10">
|
||||||
|
<button class="btn btn-warning me-2 btn-edit"
|
||||||
|
data-id="${id}"
|
||||||
|
data-model="${model}">
|
||||||
|
<i class='bx bx-edit'></i></button>
|
||||||
|
|
||||||
|
<button class="btn btn-red btn-delete"
|
||||||
|
data-id="${id}">
|
||||||
|
<i class='bx bxs-trash'></i></button>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const table = new GeneralTable(
|
||||||
|
"spatial-planning-data-table",
|
||||||
|
`${GlobalConfig.apiHost}/api/spatial-plannings`,
|
||||||
|
`${GlobalConfig.apiHost}`,
|
||||||
|
dataSpatialPlanningColumns
|
||||||
|
);
|
||||||
|
|
||||||
|
table.processData = function (data) {
|
||||||
|
return data.data.map((item) => {
|
||||||
|
return [
|
||||||
|
item.no,
|
||||||
|
item.name,
|
||||||
|
item.kbli,
|
||||||
|
item.activities,
|
||||||
|
item.area,
|
||||||
|
item.location,
|
||||||
|
item.number,
|
||||||
|
item.date,
|
||||||
|
item.id,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
table.init();
|
||||||
|
});
|
||||||
185
resources/js/data/spatialPlannings/form-create-update.js
Normal file
185
resources/js/data/spatialPlannings/form-create-update.js
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
import GlobalConfig from "../../global-config";
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
const saveButton = document.querySelector(".modal-footer .btn-primary");
|
||||||
|
const modalButton = document.querySelector(".btn-modal");
|
||||||
|
const form = document.querySelector("form#create-update-form");
|
||||||
|
var authLogo = document.querySelector(".auth-logo");
|
||||||
|
|
||||||
|
if (!saveButton || !form) return;
|
||||||
|
|
||||||
|
saveButton.addEventListener("click", function () {
|
||||||
|
// Disable tombol dan tampilkan spinner
|
||||||
|
modalButton.disabled = true;
|
||||||
|
modalButton.innerHTML = `
|
||||||
|
<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>
|
||||||
|
Loading...
|
||||||
|
`;
|
||||||
|
const isEdit = saveButton.classList.contains("btn-edit");
|
||||||
|
const formData = new FormData(form);
|
||||||
|
const toast = document.getElementById("toastEditUpdate");
|
||||||
|
const toastBody = toast.querySelector(".toast-body");
|
||||||
|
const toastHeader = toast.querySelector(".toast-header small");
|
||||||
|
|
||||||
|
const data = {};
|
||||||
|
|
||||||
|
// Mengonversi FormData ke dalam JSON
|
||||||
|
formData.forEach((value, key) => {
|
||||||
|
data[key] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = form.getAttribute("action");
|
||||||
|
|
||||||
|
const method = isEdit ? "PUT" : "POST";
|
||||||
|
|
||||||
|
fetch(url, {
|
||||||
|
method: method,
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
if (!data.errors) {
|
||||||
|
// Remove existing icon (if any) before adding the new one
|
||||||
|
if (authLogo) {
|
||||||
|
// Hapus ikon yang sudah ada jika ada
|
||||||
|
const existingIcon = authLogo.querySelector(".bx");
|
||||||
|
if (existingIcon) {
|
||||||
|
authLogo.removeChild(existingIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat ikon baru
|
||||||
|
const icon = document.createElement("i");
|
||||||
|
icon.classList.add("bx", "bxs-check-square");
|
||||||
|
icon.style.fontSize = "25px";
|
||||||
|
icon.style.color = "green"; // Pastikan 'green' dalam bentuk string
|
||||||
|
|
||||||
|
// Tambahkan ikon ke dalam auth-logo
|
||||||
|
authLogo.appendChild(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set success message for the toast
|
||||||
|
toastBody.textContent = isEdit
|
||||||
|
? "Data updated successfully!"
|
||||||
|
: "Data created successfully!";
|
||||||
|
toast.classList.add("show"); // Show the toast
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.classList.remove("show"); // Hide the toast after 3 seconds
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "/data/spatial-plannings";
|
||||||
|
}, 3000);
|
||||||
|
} else {
|
||||||
|
if (authLogo) {
|
||||||
|
// Hapus ikon yang sudah ada jika ada
|
||||||
|
const existingIcon = authLogo.querySelector(".bx");
|
||||||
|
if (existingIcon) {
|
||||||
|
authLogo.removeChild(existingIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat ikon baru
|
||||||
|
const icon = document.createElement("i");
|
||||||
|
icon.classList.add("bx", "bxs-error-alt");
|
||||||
|
icon.style.fontSize = "25px";
|
||||||
|
icon.style.color = "red"; // Pastikan 'green' dalam bentuk string
|
||||||
|
|
||||||
|
// Tambahkan ikon ke dalam auth-logo
|
||||||
|
authLogo.appendChild(icon);
|
||||||
|
}
|
||||||
|
// Set error message for the toast
|
||||||
|
toastBody.textContent =
|
||||||
|
"Error: " + (data.message || "Something went wrong");
|
||||||
|
toast.classList.add("show"); // Show the toast
|
||||||
|
|
||||||
|
// Enable button and reset its text on error
|
||||||
|
modalButton.disabled = false;
|
||||||
|
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.classList.remove("show"); // Hide the toast after 3 seconds
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
if (authLogo) {
|
||||||
|
// Hapus ikon yang sudah ada jika ada
|
||||||
|
const existingIcon = authLogo.querySelector(".bx");
|
||||||
|
if (existingIcon) {
|
||||||
|
authLogo.removeChild(existingIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat ikon baru
|
||||||
|
const icon = document.createElement("i");
|
||||||
|
icon.classList.add("bx", "bxs-error-alt");
|
||||||
|
icon.style.fontSize = "25px";
|
||||||
|
icon.style.color = "red"; // Pastikan 'green' dalam bentuk string
|
||||||
|
|
||||||
|
// Tambahkan ikon ke dalam auth-logo
|
||||||
|
authLogo.appendChild(icon);
|
||||||
|
}
|
||||||
|
// Set error message for the toast
|
||||||
|
toastBody.textContent =
|
||||||
|
"An error occurred while processing your request.";
|
||||||
|
toast.classList.add("show"); // Show the toast
|
||||||
|
|
||||||
|
// Enable button and reset its text on error
|
||||||
|
modalButton.disabled = false;
|
||||||
|
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.classList.remove("show"); // Hide the toast after 3 seconds
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fungsi fetchOptions untuk autocomplete server-side
|
||||||
|
window.fetchOptions = function (field) {
|
||||||
|
let inputValue = document.getElementById(field).value;
|
||||||
|
if (inputValue.length < 2) return;
|
||||||
|
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
||||||
|
|
||||||
|
let url = `${
|
||||||
|
GlobalConfig.apiHost
|
||||||
|
}/api/combobox/search-options?query=${encodeURIComponent(
|
||||||
|
inputValue
|
||||||
|
)}&field=${field}`;
|
||||||
|
|
||||||
|
// Jika field desa, tambahkan kecamatan sebagai filter
|
||||||
|
if (field === "village_name") {
|
||||||
|
url += `&district=${encodeURIComponent(districtValue)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
let dataList = document.getElementById(field + "Options");
|
||||||
|
dataList.innerHTML = "";
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
let option = document.createElement("option");
|
||||||
|
option.value = item.name;
|
||||||
|
option.dataset.code = item.code;
|
||||||
|
dataList.appendChild(option);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => console.error("Error fetching options:", error));
|
||||||
|
};
|
||||||
|
|
||||||
|
document.querySelector(".btn-back").addEventListener("click", function () {
|
||||||
|
window.history.back();
|
||||||
|
});
|
||||||
|
});
|
||||||
150
resources/js/data/spatialPlannings/form-upload.js
Normal file
150
resources/js/data/spatialPlannings/form-upload.js
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
import { Dropzone } from "dropzone";
|
||||||
|
import GlobalConfig from "../../global-config.js";
|
||||||
|
|
||||||
|
Dropzone.autoDiscover = false;
|
||||||
|
|
||||||
|
var previewTemplate,
|
||||||
|
dropzone,
|
||||||
|
dropzonePreviewNode = document.querySelector("#dropzone-preview-list");
|
||||||
|
console.log(previewTemplate);
|
||||||
|
console.log(dropzone);
|
||||||
|
console.log(dropzonePreviewNode);
|
||||||
|
|
||||||
|
(dropzonePreviewNode.id = ""),
|
||||||
|
dropzonePreviewNode &&
|
||||||
|
((previewTemplate = dropzonePreviewNode.parentNode.innerHTML),
|
||||||
|
dropzonePreviewNode.parentNode.removeChild(dropzonePreviewNode),
|
||||||
|
(dropzone = new Dropzone(".dropzone", {
|
||||||
|
url: `${GlobalConfig.apiHost}/api/spatial-plannings/import`,
|
||||||
|
// url: "https://httpbin.org/post",
|
||||||
|
method: "post",
|
||||||
|
acceptedFiles: ".xls,.xlsx", // Use acceptedFiles for better validation
|
||||||
|
previewTemplate: previewTemplate,
|
||||||
|
previewsContainer: "#dropzone-preview",
|
||||||
|
autoProcessQueue: false, // Disable auto post
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`
|
||||||
|
},
|
||||||
|
init: function() {
|
||||||
|
// Listen for the success event
|
||||||
|
this.on("success", function(file, response) {
|
||||||
|
console.log("File successfully uploaded:", file);
|
||||||
|
console.log("API Response:", response);
|
||||||
|
|
||||||
|
// Show success toast
|
||||||
|
showToast('bxs-check-square', 'green', response.message);
|
||||||
|
document.getElementById("submit-upload").innerHTML = "Upload Files";
|
||||||
|
// Tunggu sebentar lalu reload halaman
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "/data/spatial-plannings";
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
// Listen for the error event
|
||||||
|
this.on("error", function(file, errorMessage) {
|
||||||
|
console.error("Error uploading file:", file);
|
||||||
|
console.error("Error message:", errorMessage);
|
||||||
|
// Handle the error response
|
||||||
|
|
||||||
|
// Show error toast
|
||||||
|
showToast('bxs-error-alt', 'red', errorMessage.message);
|
||||||
|
document.getElementById("submit-upload").innerHTML = "Upload Files";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})));
|
||||||
|
|
||||||
|
// Add event listener to control the submission manually
|
||||||
|
document.querySelector("#submit-upload").addEventListener("click", function() {
|
||||||
|
console.log("Ini adalah value dropzone", dropzone.files[0]);
|
||||||
|
const formData = new FormData()
|
||||||
|
console.log("Dropzonefiles",dropzone.files);
|
||||||
|
|
||||||
|
this.innerHTML = '<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>Loading...';
|
||||||
|
|
||||||
|
// Pastikan ada file dalam queue sebelum memprosesnya
|
||||||
|
if (dropzone.files.length > 0) {
|
||||||
|
formData.append('file', dropzone.files[0])
|
||||||
|
console.log("ini adalah form data on submit", ...formData);
|
||||||
|
dropzone.processQueue(); // Ini akan manual memicu upload
|
||||||
|
} else {
|
||||||
|
// Show error toast when no file is selected
|
||||||
|
showToast('bxs-error-alt', 'red', "Please add a file first.");
|
||||||
|
document.getElementById("submit-upload").innerHTML = "Upload Files";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Optional: Listen for the 'addedfile' event to log or control file add behavior
|
||||||
|
dropzone.on("addedfile", function (file) {
|
||||||
|
console.log("File ditambahkan:", file);
|
||||||
|
console.log("Nama File:", file.name);
|
||||||
|
console.log("Tipe File:", file.type);
|
||||||
|
console.log("Ukuran File:", (file.size / 1024).toFixed(2) + " KB");
|
||||||
|
});
|
||||||
|
|
||||||
|
dropzone.on("complete", function(file) {
|
||||||
|
dropzone.removeFile(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add event listener to download file template
|
||||||
|
document.getElementById('downloadtempspatialPlannings').addEventListener('click', function() {
|
||||||
|
var url = `${GlobalConfig.apiHost}/api/download-template-spatialPlannings`;
|
||||||
|
fetch(url, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.blob(); // Jika respons OK, konversi menjadi blob
|
||||||
|
} else {
|
||||||
|
return response.json(); // Jika respons gagal, konversi menjadi JSON untuk menangani pesan error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
console.log(blob);
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.style.display = 'none';
|
||||||
|
a.href = url;
|
||||||
|
a.download = 'template_rencana_tata_ruang.xlsx';
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Gagal mendownload file:", error);
|
||||||
|
showToast('bxs-error-alt', 'red', "Template file is not already exist.");
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Function to show toast
|
||||||
|
function showToast(iconClass, iconColor, message) {
|
||||||
|
const toastElement = document.getElementById('toastUploadSpatialPlannings');
|
||||||
|
const toastBody = toastElement.querySelector('.toast-body');
|
||||||
|
const toastHeader = toastElement.querySelector('.toast-header');
|
||||||
|
|
||||||
|
// Remove existing icon (if any) before adding the new one
|
||||||
|
const existingIcon = toastHeader.querySelector('.bx');
|
||||||
|
if (existingIcon) {
|
||||||
|
toastHeader.querySelector('.auth-logo').removeChild(existingIcon); // Remove the existing icon
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the new icon to the toast header
|
||||||
|
const icon = document.createElement('i');
|
||||||
|
icon.classList.add('bx', iconClass);
|
||||||
|
icon.style.fontSize = '25px';
|
||||||
|
icon.style.color = iconColor;
|
||||||
|
toastHeader.querySelector('.auth-logo').appendChild(icon);
|
||||||
|
|
||||||
|
// Set the toast message
|
||||||
|
toastBody.textContent = message;
|
||||||
|
|
||||||
|
// Show the toast
|
||||||
|
const toast = new bootstrap.Toast(toastElement); // Inisialisasi Bootstrap Toast
|
||||||
|
toast.show();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@ import GlobalConfig from "../../global-config.js";
|
|||||||
import GeneralTable from "../../table-generator.js";
|
import GeneralTable from "../../table-generator.js";
|
||||||
|
|
||||||
const dataTourismsColumns = [
|
const dataTourismsColumns = [
|
||||||
|
"No",
|
||||||
"Nama Perusahaan",
|
"Nama Perusahaan",
|
||||||
"Nama Proyek",
|
"Nama Proyek",
|
||||||
"Alamat Usaha",
|
"Alamat Usaha",
|
||||||
@@ -19,9 +20,9 @@ const dataTourismsColumns = [
|
|||||||
name: "Actions",
|
name: "Actions",
|
||||||
widht: "120px",
|
widht: "120px",
|
||||||
formatter: function (cell, row) {
|
formatter: function (cell, row) {
|
||||||
const id = row.cells[10].data;
|
const id = row.cells[11].data;
|
||||||
const long = row.cells[8].data;
|
const long = row.cells[9].data;
|
||||||
const lat = row.cells[9].data;
|
const lat = row.cells[10].data;
|
||||||
const model = "data/tourisms";
|
const model = "data/tourisms";
|
||||||
return gridjs.html(`
|
return gridjs.html(`
|
||||||
<div class="d-flex justify-items-end gap-10">
|
<div class="d-flex justify-items-end gap-10">
|
||||||
@@ -54,6 +55,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
table.processData = function (data) {
|
table.processData = function (data) {
|
||||||
return data.data.map((item) => {
|
return data.data.map((item) => {
|
||||||
return [
|
return [
|
||||||
|
item.no,
|
||||||
item.business_name,
|
item.business_name,
|
||||||
item.project_name,
|
item.project_name,
|
||||||
item.business_address,
|
item.business_address,
|
||||||
|
|||||||
@@ -28,12 +28,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
data[key] = value;
|
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");
|
const url = form.getAttribute("action");
|
||||||
console.log("Ini adalah url dari form action", url);
|
|
||||||
|
|
||||||
const method = isEdit ? "PUT" : "POST";
|
const method = isEdit ? "PUT" : "POST";
|
||||||
|
|
||||||
@@ -49,7 +44,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
})
|
})
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
console.log("Response data:", data);
|
|
||||||
if (!data.errors) {
|
if (!data.errors) {
|
||||||
// Remove existing icon (if any) before adding the new one
|
// Remove existing icon (if any) before adding the new one
|
||||||
if (authLogo) {
|
if (authLogo) {
|
||||||
@@ -113,7 +107,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("Error:", error);
|
|
||||||
if (authLogo) {
|
if (authLogo) {
|
||||||
// Hapus ikon yang sudah ada jika ada
|
// Hapus ikon yang sudah ada jika ada
|
||||||
const existingIcon = authLogo.querySelector(".bx");
|
const existingIcon = authLogo.querySelector(".bx");
|
||||||
@@ -148,7 +141,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
// Fungsi fetchOptions untuk autocomplete server-side
|
// Fungsi fetchOptions untuk autocomplete server-side
|
||||||
window.fetchOptions = function (field) {
|
window.fetchOptions = function (field) {
|
||||||
let inputValue = document.getElementById(field).value;
|
let inputValue = document.getElementById(field).value;
|
||||||
console.log("Query Value:", inputValue); // Debugging log
|
|
||||||
if (inputValue.length < 2) return;
|
if (inputValue.length < 2) return;
|
||||||
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ dropzone.on("complete", function(file) {
|
|||||||
|
|
||||||
// Add event listener to download file template
|
// Add event listener to download file template
|
||||||
document.getElementById('downloadtemptourisms').addEventListener('click', function() {
|
document.getElementById('downloadtemptourisms').addEventListener('click', function() {
|
||||||
var url = `${GlobalConfig.apiHost}/api/download-template-umkm`;
|
var url = `${GlobalConfig.apiHost}/api/download-template-tourism`;
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
@@ -105,11 +105,12 @@ document.getElementById('downloadtemptourisms').addEventListener('click', functi
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((blob) => {
|
.then((blob) => {
|
||||||
|
console.log(blob);
|
||||||
const url = window.URL.createObjectURL(blob);
|
const url = window.URL.createObjectURL(blob);
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.style.display = 'none';
|
a.style.display = 'none';
|
||||||
a.href = url;
|
a.href = url;
|
||||||
a.download = 'template_tourisms.xlsx';
|
a.download = 'template_pariwisata.xlsx';
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
window.URL.revokeObjectURL(url);
|
window.URL.revokeObjectURL(url);
|
||||||
@@ -122,7 +123,7 @@ document.getElementById('downloadtemptourisms').addEventListener('click', functi
|
|||||||
|
|
||||||
// Function to show toast
|
// Function to show toast
|
||||||
function showToast(iconClass, iconColor, message) {
|
function showToast(iconClass, iconColor, message) {
|
||||||
const toastElement = document.getElementById('toastUploadUmkm');
|
const toastElement = document.getElementById('toastUploadTourisms');
|
||||||
const toastBody = toastElement.querySelector('.toast-body');
|
const toastBody = toastElement.querySelector('.toast-body');
|
||||||
const toastHeader = toastElement.querySelector('.toast-header');
|
const toastHeader = toastElement.querySelector('.toast-header');
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import GlobalConfig from "../../global-config.js";
|
|||||||
import GeneralTable from "../../table-generator.js";
|
import GeneralTable from "../../table-generator.js";
|
||||||
|
|
||||||
const dataUMKMColumns = [
|
const dataUMKMColumns = [
|
||||||
|
"No",
|
||||||
"Nama Usaha",
|
"Nama Usaha",
|
||||||
"Alamat Usaha",
|
"Alamat Usaha",
|
||||||
"Deskripsi Usaha",
|
"Deskripsi Usaha",
|
||||||
@@ -26,7 +27,7 @@ const dataUMKMColumns = [
|
|||||||
name: "Actions",
|
name: "Actions",
|
||||||
widht: "120px",
|
widht: "120px",
|
||||||
formatter: function(cell, row) {
|
formatter: function(cell, row) {
|
||||||
const id = row.cells[18].data;
|
const id = row.cells[19].data;
|
||||||
const model = "data/umkm";
|
const model = "data/umkm";
|
||||||
return gridjs.html(`
|
return gridjs.html(`
|
||||||
<div class="d-flex justify-items-end gap-10">
|
<div class="d-flex justify-items-end gap-10">
|
||||||
@@ -54,6 +55,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
table.processData = function (data) {
|
table.processData = function (data) {
|
||||||
return data.data.map((item) => {
|
return data.data.map((item) => {
|
||||||
return [
|
return [
|
||||||
|
item.no,
|
||||||
item.business_name,
|
item.business_name,
|
||||||
item.business_address,
|
item.business_address,
|
||||||
item.business_desc,
|
item.business_desc,
|
||||||
|
|||||||
@@ -28,12 +28,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
data[key] = value;
|
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");
|
const url = form.getAttribute("action");
|
||||||
console.log("Ini adalah url dari form action", url);
|
|
||||||
|
|
||||||
const method = isEdit ? "PUT" : "POST";
|
const method = isEdit ? "PUT" : "POST";
|
||||||
|
|
||||||
@@ -74,11 +69,11 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
toast.classList.add('show'); // Show the toast
|
toast.classList.add('show'); // Show the toast
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||||
}, 3000);
|
}, 2000);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = '/data/umkm';
|
window.location.href = '/data/umkm';
|
||||||
}, 3000);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
if (authLogo) {
|
if (authLogo) {
|
||||||
// Hapus ikon yang sudah ada jika ada
|
// Hapus ikon yang sudah ada jika ada
|
||||||
@@ -96,14 +91,16 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
// Tambahkan ikon ke dalam auth-logo
|
// Tambahkan ikon ke dalam auth-logo
|
||||||
authLogo.appendChild(icon);
|
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
|
// Enable button and reset its text on error
|
||||||
modalButton.disabled = false;
|
modalButton.disabled = false;
|
||||||
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
||||||
|
|
||||||
|
|
||||||
|
// Set error message for the toast
|
||||||
|
toastBody.textContent = "Error: " + (data.message || "Something went wrong");
|
||||||
|
toast.classList.add('show'); // Show the toast
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||||
}, 3000);
|
}, 3000);
|
||||||
@@ -127,14 +124,15 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
// Tambahkan ikon ke dalam auth-logo
|
// Tambahkan ikon ke dalam auth-logo
|
||||||
authLogo.appendChild(icon);
|
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
|
// Enable button and reset its text on error
|
||||||
modalButton.disabled = false;
|
modalButton.disabled = false;
|
||||||
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
modalButton.innerHTML = isEdit ? "Update" : "Create";
|
||||||
|
|
||||||
|
// Set error message for the toast
|
||||||
|
toastBody.textContent = "An error occurred while processing your request.";
|
||||||
|
toast.classList.add('show'); // Show the toast
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
toast.classList.remove('show'); // Hide the toast after 3 seconds
|
||||||
}, 3000);
|
}, 3000);
|
||||||
@@ -144,7 +142,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
// Fungsi fetchOptions untuk autocomplete server-side
|
// Fungsi fetchOptions untuk autocomplete server-side
|
||||||
window.fetchOptions = function (field) {
|
window.fetchOptions = function (field) {
|
||||||
let inputValue = document.getElementById(field).value;
|
let inputValue = document.getElementById(field).value;
|
||||||
console.log("Query Value:", inputValue); // Debugging log
|
|
||||||
if (inputValue.length < 2) return;
|
if (inputValue.length < 2) return;
|
||||||
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
|
||||||
|
|
||||||
|
|||||||
79
resources/js/maps/maps-kml.js
Normal file
79
resources/js/maps/maps-kml.js
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import L from "leaflet";
|
||||||
|
import "leaflet/dist/leaflet.css";
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
var map = L.map("map").setView([-6.9175, 107.6191], 10); // Bandung
|
||||||
|
|
||||||
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||||
|
attribution: "© OpenStreetMap contributors",
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
// Dapatkan elemen loading
|
||||||
|
const loadingDiv = document.getElementById("loading");
|
||||||
|
loadingDiv.style.display = "flex"; // Tampilkan loading
|
||||||
|
|
||||||
|
fetch("/storage/maps/rencana-polaruang.geojson")
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((geojson) => {
|
||||||
|
let colorMapping = {
|
||||||
|
BJ: "rgb(235, 30, 30)",
|
||||||
|
BA: "rgb(151, 219, 242)",
|
||||||
|
CA: "rgb(70, 70, 165)",
|
||||||
|
"P-2": "rgb(230, 255, 75)",
|
||||||
|
HL: "rgb(50, 95, 40)",
|
||||||
|
HPT: "rgb(75, 155, 55)",
|
||||||
|
HP: "rgb(125, 180, 55)",
|
||||||
|
W: "rgb(255, 165, 255)",
|
||||||
|
PTL: "rgb(0, 255, 205)",
|
||||||
|
"IK-2": "rgb(130, 185, 210)",
|
||||||
|
"P-3": "rgb(175, 175, 55)",
|
||||||
|
PS: "rgb(5, 215, 215)",
|
||||||
|
PD: "rgb(235, 155, 60)",
|
||||||
|
PK: "rgb(245, 155, 30)",
|
||||||
|
HK: "rgb(155, 0, 255)",
|
||||||
|
KPI: "rgb(105, 0, 0)",
|
||||||
|
MBT: "rgb(95, 115, 145)",
|
||||||
|
"P-4": "rgb(185, 235, 185)",
|
||||||
|
TB: "rgb(70, 150, 255)",
|
||||||
|
"P-1": "rgb(200, 245, 70)",
|
||||||
|
TR: "rgb(215, 55, 0)",
|
||||||
|
THR: "rgb(185, 165, 255)",
|
||||||
|
TWA: "rgb(210, 190, 255)",
|
||||||
|
};
|
||||||
|
var geoLayer = L.geoJSON(geojson, {
|
||||||
|
style: function (feature) {
|
||||||
|
let htmlString = feature.properties.description.toString();
|
||||||
|
|
||||||
|
let match = htmlString.match(
|
||||||
|
/<td>Kode Kawasan<\/td>\s*<td>(.*?)<\/td>/
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("Kode Kawasan ", match[1]);
|
||||||
|
|
||||||
|
let color_code = match[1];
|
||||||
|
|
||||||
|
return {
|
||||||
|
color: colorMapping[color_code],
|
||||||
|
fillColor: colorMapping[color_code] || "#cccccc",
|
||||||
|
fillOpacity: 0.6,
|
||||||
|
weight: 1.5,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onEachFeature: function (feature, layer) {
|
||||||
|
if (feature.properties && feature.properties.name) {
|
||||||
|
layer.bindPopup(feature.properties.name);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
map.fitBounds(geoLayer.getBounds());
|
||||||
|
|
||||||
|
// Sembunyikan loading setelah selesai render
|
||||||
|
loadingDiv.style.display = "none";
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error loading GeoJSON:", error);
|
||||||
|
loadingDiv.innerHTML =
|
||||||
|
"<div class='loading-text' style='background: red;'>Failed to load data!</div>";
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -19,15 +19,24 @@ document.addEventListener("DOMContentLoaded", function (e) {
|
|||||||
submitButton.disabled = true;
|
submitButton.disabled = true;
|
||||||
spinner.classList.remove("d-none");
|
spinner.classList.remove("d-none");
|
||||||
|
|
||||||
|
let jsonData = {};
|
||||||
|
formData.forEach((value, key) => {
|
||||||
|
jsonData[key] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(jsonData);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let response = await fetch(form.action, {
|
let response = await fetch(form.action, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"X-CSRF-TOKEN": document
|
"Content-Type": "application/json",
|
||||||
.querySelector('meta[name="csrf-token"]')
|
Accept: "application/json",
|
||||||
.getAttribute("content"),
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
},
|
},
|
||||||
body: formData,
|
body: JSON.stringify(jsonData),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
|||||||
@@ -1,55 +1,67 @@
|
|||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
class CreateMenu {
|
||||||
const toastNotification = document.getElementById("toastNotification");
|
constructor() {
|
||||||
const toast = new bootstrap.Toast(toastNotification);
|
this.initCreateMenu();
|
||||||
document
|
}
|
||||||
.getElementById("btnCreateMenus")
|
|
||||||
.addEventListener("click", async function () {
|
|
||||||
let submitButton = this;
|
|
||||||
let spinner = document.getElementById("spinner");
|
|
||||||
let form = document.getElementById("formCreateMenus");
|
|
||||||
|
|
||||||
if (!form) {
|
initCreateMenu() {
|
||||||
console.error("Form element not found!");
|
const toastNotification = document.getElementById("toastNotification");
|
||||||
return;
|
const toast = new bootstrap.Toast(toastNotification);
|
||||||
}
|
document
|
||||||
// Get form data
|
.getElementById("btnCreateMenus")
|
||||||
let formData = new FormData(form);
|
.addEventListener("click", async function () {
|
||||||
|
let submitButton = this;
|
||||||
|
let spinner = document.getElementById("spinner");
|
||||||
|
let form = document.getElementById("formCreateMenus");
|
||||||
|
|
||||||
// Disable button and show spinner
|
if (!form) {
|
||||||
submitButton.disabled = true;
|
console.error("Form element not found!");
|
||||||
spinner.classList.remove("d-none");
|
return;
|
||||||
|
}
|
||||||
|
// Get form data
|
||||||
|
let formData = new FormData(form);
|
||||||
|
|
||||||
try {
|
// Disable button and show spinner
|
||||||
let response = await fetch(form.action, {
|
submitButton.disabled = true;
|
||||||
method: "POST",
|
spinner.classList.remove("d-none");
|
||||||
headers: {
|
|
||||||
"X-CSRF-TOKEN": document
|
|
||||||
.querySelector('meta[name="csrf-token"]')
|
|
||||||
.getAttribute("content"),
|
|
||||||
},
|
|
||||||
body: formData,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
try {
|
||||||
let result = await response.json();
|
let response = await fetch(form.action, {
|
||||||
document.getElementById("toast-message").innerText =
|
method: "POST",
|
||||||
result.message;
|
headers: {
|
||||||
toast.show();
|
Authorization: `Bearer ${document
|
||||||
setTimeout(() => {
|
.querySelector('meta[name="api-token"]')
|
||||||
window.location.href = "/menus";
|
.getAttribute("content")}`,
|
||||||
}, 2000);
|
},
|
||||||
} else {
|
body: formData,
|
||||||
let error = await response.json();
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let result = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
result.message;
|
||||||
|
toast.show();
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "/menus";
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
let error = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
error.message;
|
||||||
|
toast.show();
|
||||||
|
console.error("Error:", error);
|
||||||
|
submitButton.disabled = false;
|
||||||
|
spinner.classList.add("d-none");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Request failed:", error);
|
||||||
document.getElementById("toast-message").innerText =
|
document.getElementById("toast-message").innerText =
|
||||||
error.message;
|
error.message;
|
||||||
toast.show();
|
toast.show();
|
||||||
console.error("Error:", error);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
});
|
||||||
console.error("Request failed:", error);
|
}
|
||||||
document.getElementById("toast-message").innerText =
|
}
|
||||||
error.message;
|
|
||||||
toast.show();
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
}
|
new CreateMenu();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,13 +2,27 @@ import { Grid } from "gridjs/dist/gridjs.umd.js";
|
|||||||
import gridjs from "gridjs/dist/gridjs.umd.js";
|
import gridjs from "gridjs/dist/gridjs.umd.js";
|
||||||
import "gridjs/dist/gridjs.umd.js";
|
import "gridjs/dist/gridjs.umd.js";
|
||||||
import GlobalConfig from "../global-config";
|
import GlobalConfig from "../global-config";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
|
||||||
class Menus {
|
class Menus {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.toastMessage = document.getElementById("toast-message");
|
||||||
|
this.toastElement = document.getElementById("toastNotification");
|
||||||
|
this.toast = new bootstrap.Toast(this.toastElement);
|
||||||
this.table = null;
|
this.table = null;
|
||||||
}
|
|
||||||
init() {
|
// Initialize functions
|
||||||
this.initTableMenus();
|
this.initTableMenus();
|
||||||
|
this.initEvents();
|
||||||
|
}
|
||||||
|
initEvents() {
|
||||||
|
document.body.addEventListener("click", async (event) => {
|
||||||
|
const deleteButton = event.target.closest(".btn-delete-menu");
|
||||||
|
if (deleteButton) {
|
||||||
|
event.preventDefault();
|
||||||
|
await this.handleDelete(deleteButton);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
initTableMenus() {
|
initTableMenus() {
|
||||||
@@ -19,7 +33,7 @@ class Menus {
|
|||||||
this.table
|
this.table
|
||||||
.updateConfig({
|
.updateConfig({
|
||||||
server: {
|
server: {
|
||||||
url: `${GlobalConfig.apiHost}/api/api-menus`,
|
url: `${GlobalConfig.apiHost}/api/menus`,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${document
|
Authorization: `Bearer ${document
|
||||||
@@ -60,7 +74,8 @@ class Menus {
|
|||||||
<a href="/menus/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
|
<a href="/menus/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
|
||||||
<i class='bx bx-edit'></i>
|
<i class='bx bx-edit'></i>
|
||||||
</a>
|
</a>
|
||||||
<button data-id="${cell}" class="btn btn-red btn-sm btn-delete-menu d-inline-flex align-items-center justify-content-center">
|
<button data-id="${cell}"
|
||||||
|
class="btn btn-red btn-sm btn-delete-menu d-inline-flex align-items-center justify-content-center">
|
||||||
<i class='bx bxs-trash' ></i>
|
<i class='bx bxs-trash' ></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,7 +98,7 @@ class Menus {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
url: `${GlobalConfig.apiHost}/api/api-menus`,
|
url: `${GlobalConfig.apiHost}/api/menus`,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${document
|
Authorization: `Bearer ${document
|
||||||
@@ -104,118 +119,63 @@ class Menus {
|
|||||||
total: (data) => data.total,
|
total: (data) => data.total,
|
||||||
},
|
},
|
||||||
}).render(tableContainer);
|
}).render(tableContainer);
|
||||||
|
|
||||||
document.addEventListener("click", this.handleDelete.bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDelete(event) {
|
async handleDelete(button) {
|
||||||
if (event.target.classList.contains("btn-delete-menu")) {
|
const id = button.getAttribute("data-id");
|
||||||
event.preventDefault();
|
|
||||||
const id = event.target.getAttribute("data-id");
|
|
||||||
let modalElement = document.getElementById("modalConfirmation");
|
|
||||||
let toastMessage = document.getElementById("toast-message");
|
|
||||||
|
|
||||||
if (!modalElement) {
|
const result = await Swal.fire({
|
||||||
console.error("Modal element not found!");
|
title: "Are you sure?",
|
||||||
return;
|
text: "You won't be able to revert this!",
|
||||||
}
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: "Yes, delete it!",
|
||||||
|
});
|
||||||
|
|
||||||
let modal = new bootstrap.Modal(modalElement);
|
if (result.isConfirmed) {
|
||||||
let btnSaveConfirmation = document.getElementById(
|
try {
|
||||||
"btnSaveConfirmation"
|
let response = await fetch(
|
||||||
);
|
`${GlobalConfig.apiHost}/api/menus/${id}`,
|
||||||
let toastElement = document.getElementById("toastNotification");
|
{
|
||||||
let toast = new bootstrap.Toast(toastElement);
|
|
||||||
|
|
||||||
// Remove previous event listeners to avoid multiple bindings
|
|
||||||
btnSaveConfirmation.replaceWith(
|
|
||||||
btnSaveConfirmation.cloneNode(true)
|
|
||||||
);
|
|
||||||
btnSaveConfirmation = document.getElementById(
|
|
||||||
"btnSaveConfirmation"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set the role ID on the confirm button inside the modal
|
|
||||||
btnSaveConfirmation.setAttribute("data-menu-id", id);
|
|
||||||
|
|
||||||
// Show the modal
|
|
||||||
modal.show();
|
|
||||||
|
|
||||||
btnSaveConfirmation.addEventListener("click", async () => {
|
|
||||||
let menuId = btnSaveConfirmation.getAttribute("data-menu-id");
|
|
||||||
|
|
||||||
try {
|
|
||||||
let response = await fetch(`/menus/${menuId}`, {
|
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
|
||||||
"X-CSRF-TOKEN": document
|
|
||||||
.querySelector('meta[name="csrf-token"]')
|
|
||||||
.getAttribute("content"),
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
let result = await response.json();
|
|
||||||
toastMessage.innerText =
|
|
||||||
result.message || "Deleted successfully!";
|
|
||||||
toast.show();
|
|
||||||
|
|
||||||
// Hide modal
|
|
||||||
modal.hide();
|
|
||||||
|
|
||||||
// Refresh Grid.js table
|
|
||||||
this.refreshTableMenus();
|
|
||||||
} else {
|
|
||||||
let error = await response.json();
|
|
||||||
console.error("Delete failed:", error);
|
|
||||||
toastMessage.innerText =
|
|
||||||
error.message || "Delete failed!";
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error deleting item:", error);
|
|
||||||
toastMessage.innerText = "An error occurred!";
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshTableMenus() {
|
|
||||||
if (this.table) {
|
|
||||||
this.table
|
|
||||||
.updateConfig({
|
|
||||||
server: {
|
|
||||||
url: `${GlobalConfig.apiHost}/api/api-menus`,
|
|
||||||
credentials: "include",
|
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${document
|
Authorization: `Bearer ${document
|
||||||
.querySelector('meta[name="api-token"]')
|
.querySelector('meta[name="api-token"]')
|
||||||
.getAttribute("content")}`,
|
.getAttribute("content")}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
then: (data) =>
|
}
|
||||||
data.data.map((item) => [
|
);
|
||||||
item.id,
|
|
||||||
item.name,
|
if (response.ok) {
|
||||||
item.url,
|
let result = await response.json();
|
||||||
item.icon,
|
this.toastMessage.innerText =
|
||||||
item.parent_id,
|
result.message || "Deleted successfully!";
|
||||||
item.sort_order,
|
this.toast.show();
|
||||||
item.id,
|
|
||||||
]),
|
// Refresh Grid.js table
|
||||||
total: (data) => data.total,
|
if (typeof this.table !== "undefined") {
|
||||||
},
|
this.table.updateConfig({}).forceRender();
|
||||||
})
|
}
|
||||||
.forceRender();
|
} else {
|
||||||
} else {
|
let error = await response.json();
|
||||||
this.initTableMenus(); // If no table exists, reinitialize it
|
console.error("Delete failed:", error);
|
||||||
|
this.toastMessage.innerText =
|
||||||
|
error.message || "Delete failed!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting item:", error);
|
||||||
|
this.toastMessage.innerText = "An error occurred!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
new Menus().init();
|
new Menus();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,53 +1,67 @@
|
|||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
class UpdateMenu {
|
||||||
let form = document.getElementById("formUpdateMenus");
|
constructor() {
|
||||||
let submitButton = document.getElementById("btnUpdateMenus");
|
this.initUpdateMenu();
|
||||||
let spinner = document.getElementById("spinner");
|
}
|
||||||
let toastMessage = document.getElementById("toast-message");
|
|
||||||
let toast = new bootstrap.Toast(
|
|
||||||
document.getElementById("toastNotification")
|
|
||||||
);
|
|
||||||
submitButton.addEventListener("click", async function () {
|
|
||||||
let submitButton = this;
|
|
||||||
|
|
||||||
if (!form) {
|
initUpdateMenu() {
|
||||||
console.error("Form element not found!");
|
const toastNotification = document.getElementById("toastNotification");
|
||||||
return;
|
const toast = new bootstrap.Toast(toastNotification);
|
||||||
}
|
document
|
||||||
// Get form data
|
.getElementById("btnUpdateMenus")
|
||||||
let formData = new FormData(form);
|
.addEventListener("click", async function () {
|
||||||
|
let submitButton = this;
|
||||||
|
let spinner = document.getElementById("spinner");
|
||||||
|
let form = document.getElementById("formUpdateMenus");
|
||||||
|
|
||||||
// Disable button and show spinner
|
if (!form) {
|
||||||
submitButton.disabled = true;
|
console.error("Form element not found!");
|
||||||
spinner.classList.remove("d-none");
|
return;
|
||||||
|
}
|
||||||
|
// Get form data
|
||||||
|
let formData = new FormData(form);
|
||||||
|
|
||||||
try {
|
// Disable button and show spinner
|
||||||
let response = await fetch(form.action, {
|
submitButton.disabled = true;
|
||||||
method: "POST",
|
spinner.classList.remove("d-none");
|
||||||
headers: {
|
|
||||||
"X-CSRF-TOKEN": document
|
try {
|
||||||
.querySelector('meta[name="csrf-token"]')
|
let response = await fetch(form.action, {
|
||||||
.getAttribute("content"),
|
method: "POST",
|
||||||
},
|
headers: {
|
||||||
body: formData,
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
},
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let result = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
result.message;
|
||||||
|
toast.show();
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "/menus";
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
let error = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
error.message;
|
||||||
|
toast.show();
|
||||||
|
console.error("Error:", error);
|
||||||
|
submitButton.disabled = false;
|
||||||
|
spinner.classList.add("d-none");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Request failed:", error);
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
error.message;
|
||||||
|
toast.show();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (response.ok) {
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
let result = await response.json();
|
new UpdateMenu();
|
||||||
toastMessage.innerText = result.message;
|
|
||||||
toast.show();
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.href = "/menus";
|
|
||||||
}, 2000);
|
|
||||||
} else {
|
|
||||||
let error = await response.json();
|
|
||||||
toastMessage.innerText = error.message;
|
|
||||||
toast.show();
|
|
||||||
console.error("Error:", error);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Request failed:", error);
|
|
||||||
toastMessage.innerText = error.message;
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,55 +1,67 @@
|
|||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
class CreateRoles {
|
||||||
const toastNotification = document.getElementById("toastNotification");
|
constructor() {
|
||||||
const toast = new bootstrap.Toast(toastNotification);
|
this.initCreateRole();
|
||||||
document
|
}
|
||||||
.getElementById("btnCreateRole")
|
|
||||||
.addEventListener("click", async function () {
|
|
||||||
let submitButton = this;
|
|
||||||
let spinner = document.getElementById("spinner");
|
|
||||||
let form = document.getElementById("formCreateRole");
|
|
||||||
|
|
||||||
if (!form) {
|
initCreateRole() {
|
||||||
console.error("Form element not found!");
|
const toastNotification = document.getElementById("toastNotification");
|
||||||
return;
|
const toast = new bootstrap.Toast(toastNotification);
|
||||||
}
|
document
|
||||||
// Get form data
|
.getElementById("btnCreateRole")
|
||||||
let formData = new FormData(form);
|
.addEventListener("click", async function () {
|
||||||
|
let submitButton = this;
|
||||||
|
let spinner = document.getElementById("spinner");
|
||||||
|
let form = document.getElementById("formCreateRole");
|
||||||
|
|
||||||
// Disable button and show spinner
|
if (!form) {
|
||||||
submitButton.disabled = true;
|
console.error("Form element not found!");
|
||||||
spinner.classList.remove("d-none");
|
return;
|
||||||
|
}
|
||||||
|
// Get form data
|
||||||
|
let formData = new FormData(form);
|
||||||
|
|
||||||
try {
|
// Disable button and show spinner
|
||||||
let response = await fetch(form.action, {
|
submitButton.disabled = true;
|
||||||
method: "POST",
|
spinner.classList.remove("d-none");
|
||||||
headers: {
|
|
||||||
"X-CSRF-TOKEN": document
|
|
||||||
.querySelector('meta[name="csrf-token"]')
|
|
||||||
.getAttribute("content"),
|
|
||||||
},
|
|
||||||
body: formData,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
try {
|
||||||
let result = await response.json();
|
let response = await fetch(form.action, {
|
||||||
document.getElementById("toast-message").innerText =
|
method: "POST",
|
||||||
result.message;
|
headers: {
|
||||||
toast.show();
|
Authorization: `Bearer ${document
|
||||||
setTimeout(() => {
|
.querySelector('meta[name="api-token"]')
|
||||||
window.location.href = "/roles";
|
.getAttribute("content")}`,
|
||||||
}, 2000);
|
},
|
||||||
} else {
|
body: formData,
|
||||||
let error = await response.json();
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let result = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
result.message;
|
||||||
|
toast.show();
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "/roles";
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
let error = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
error.message;
|
||||||
|
toast.show();
|
||||||
|
console.error("Error:", error);
|
||||||
|
submitButton.disabled = false;
|
||||||
|
spinner.classList.add("d-none");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Request failed:", error);
|
||||||
document.getElementById("toast-message").innerText =
|
document.getElementById("toast-message").innerText =
|
||||||
error.message;
|
error.message;
|
||||||
toast.show();
|
toast.show();
|
||||||
console.error("Error:", error);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
});
|
||||||
console.error("Request failed:", error);
|
}
|
||||||
document.getElementById("toast-message").innerText =
|
}
|
||||||
error.message;
|
|
||||||
toast.show();
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
}
|
new CreateRoles();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,46 +2,31 @@ import { Grid } from "gridjs/dist/gridjs.umd.js";
|
|||||||
import gridjs from "gridjs/dist/gridjs.umd.js";
|
import gridjs from "gridjs/dist/gridjs.umd.js";
|
||||||
import "gridjs/dist/gridjs.umd.js";
|
import "gridjs/dist/gridjs.umd.js";
|
||||||
import GlobalConfig from "../global-config";
|
import GlobalConfig from "../global-config";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
|
||||||
class Roles {
|
class Roles {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.table = null; // Store Grid.js instance
|
this.toastMessage = document.getElementById("toast-message");
|
||||||
}
|
this.toastElement = document.getElementById("toastNotification");
|
||||||
|
this.toast = new bootstrap.Toast(this.toastElement);
|
||||||
|
this.table = null;
|
||||||
|
|
||||||
init() {
|
// Initialize functions
|
||||||
this.initTableRoles();
|
this.initTableRoles();
|
||||||
|
this.initEvents();
|
||||||
|
}
|
||||||
|
initEvents() {
|
||||||
|
document.body.addEventListener("click", async (event) => {
|
||||||
|
const deleteButton = event.target.closest(".btn-delete-role");
|
||||||
|
if (deleteButton) {
|
||||||
|
event.preventDefault();
|
||||||
|
await this.handleDelete(deleteButton);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
initTableRoles() {
|
initTableRoles() {
|
||||||
let tableContainer = document.getElementById("table-roles");
|
let tableContainer = document.getElementById("table-roles");
|
||||||
|
|
||||||
// If table instance already exists, update it instead of re-creating
|
|
||||||
if (this.table) {
|
|
||||||
this.table
|
|
||||||
.updateConfig({
|
|
||||||
server: {
|
|
||||||
url: `${GlobalConfig.apiHost}/api/api-roles`,
|
|
||||||
credentials: "include",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${document
|
|
||||||
.querySelector('meta[name="api-token"]')
|
|
||||||
.getAttribute("content")}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
then: (data) =>
|
|
||||||
data.data.map((item) => [
|
|
||||||
item.id,
|
|
||||||
item.name,
|
|
||||||
item.description,
|
|
||||||
item.id,
|
|
||||||
]),
|
|
||||||
total: (data) => data.total,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.forceRender();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new Grid.js instance only if it doesn't exist
|
// Create a new Grid.js instance only if it doesn't exist
|
||||||
this.table = new gridjs.Grid({
|
this.table = new gridjs.Grid({
|
||||||
columns: [
|
columns: [
|
||||||
@@ -82,7 +67,7 @@ class Roles {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
url: `${GlobalConfig.apiHost}/api/api-roles`,
|
url: `${GlobalConfig.apiHost}/api/roles`,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${document
|
Authorization: `Bearer ${document
|
||||||
@@ -100,116 +85,63 @@ class Roles {
|
|||||||
total: (data) => data.total,
|
total: (data) => data.total,
|
||||||
},
|
},
|
||||||
}).render(tableContainer);
|
}).render(tableContainer);
|
||||||
|
|
||||||
document.addEventListener("click", this.handleDelete.bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDelete(event) {
|
async handleDelete(deleteButton) {
|
||||||
if (event.target.classList.contains("btn-delete-role")) {
|
const id = deleteButton.getAttribute("data-id");
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
const id = event.target.getAttribute("data-id");
|
const result = await Swal.fire({
|
||||||
let modalElement = document.getElementById("modalConfirmation");
|
title: "Are you sure?",
|
||||||
let toastMessage = document.getElementById("toast-message");
|
text: "You won't be able to revert this!",
|
||||||
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: "Yes, delete it!",
|
||||||
|
});
|
||||||
|
|
||||||
if (!modalElement) {
|
if (result.isConfirmed) {
|
||||||
console.error("Modal element not found!");
|
try {
|
||||||
return;
|
let response = await fetch(
|
||||||
}
|
`${GlobalConfig.apiHost}/api/roles/${id}`,
|
||||||
|
{
|
||||||
let modal = new bootstrap.Modal(modalElement);
|
|
||||||
let btnSaveConfirmation = document.getElementById(
|
|
||||||
"btnSaveConfirmation"
|
|
||||||
);
|
|
||||||
let toastElement = document.getElementById("toastNotification");
|
|
||||||
let toast = new bootstrap.Toast(toastElement);
|
|
||||||
|
|
||||||
// Remove previous event listeners to avoid multiple bindings
|
|
||||||
btnSaveConfirmation.replaceWith(
|
|
||||||
btnSaveConfirmation.cloneNode(true)
|
|
||||||
);
|
|
||||||
btnSaveConfirmation = document.getElementById(
|
|
||||||
"btnSaveConfirmation"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set the role ID on the confirm button inside the modal
|
|
||||||
btnSaveConfirmation.setAttribute("data-role-id", id);
|
|
||||||
|
|
||||||
// Show the modal
|
|
||||||
modal.show();
|
|
||||||
|
|
||||||
btnSaveConfirmation.addEventListener("click", async () => {
|
|
||||||
let roleId = btnSaveConfirmation.getAttribute("data-role-id");
|
|
||||||
|
|
||||||
try {
|
|
||||||
let response = await fetch(`/roles/${roleId}`, {
|
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
|
||||||
"X-CSRF-TOKEN": document
|
|
||||||
.querySelector('meta[name="csrf-token"]')
|
|
||||||
.getAttribute("content"),
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
let result = await response.json();
|
|
||||||
toastMessage.innerText =
|
|
||||||
result.message || "Deleted successfully!";
|
|
||||||
toast.show();
|
|
||||||
|
|
||||||
// Hide modal
|
|
||||||
modal.hide();
|
|
||||||
|
|
||||||
// Refresh Grid.js table
|
|
||||||
this.refreshRolesTable();
|
|
||||||
} else {
|
|
||||||
let error = await response.json();
|
|
||||||
console.error("Delete failed:", error);
|
|
||||||
toastMessage.innerText =
|
|
||||||
error.message || "Delete failed!";
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error deleting item:", error);
|
|
||||||
toastMessage.innerText = "An error occurred!";
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshRolesTable() {
|
|
||||||
if (this.table) {
|
|
||||||
this.table
|
|
||||||
.updateConfig({
|
|
||||||
server: {
|
|
||||||
url: `${GlobalConfig.apiHost}/api/api-roles`,
|
|
||||||
credentials: "include",
|
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${document
|
Authorization: `Bearer ${document
|
||||||
.querySelector('meta[name="api-token"]')
|
.querySelector('meta[name="api-token"]')
|
||||||
.getAttribute("content")}`,
|
.getAttribute("content")}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
then: (data) =>
|
}
|
||||||
data.data.map((item) => [
|
);
|
||||||
item.id,
|
|
||||||
item.name,
|
if (response.ok) {
|
||||||
item.description,
|
let result = await response.json();
|
||||||
item.id,
|
this.toastMessage.innerText =
|
||||||
]),
|
result.message || "Deleted successfully!";
|
||||||
total: (data) => data.total,
|
this.toast.show();
|
||||||
},
|
|
||||||
})
|
// Refresh Grid.js table
|
||||||
.forceRender();
|
if (typeof this.table !== "undefined") {
|
||||||
} else {
|
this.table.updateConfig({}).forceRender();
|
||||||
this.initTableRoles(); // If the table is null, reinitialize
|
}
|
||||||
|
} else {
|
||||||
|
let error = await response.json();
|
||||||
|
console.error("Delete failed:", error);
|
||||||
|
this.toastMessage.innerText =
|
||||||
|
error.message || "Delete failed!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting item:", error);
|
||||||
|
this.toastMessage.innerText = "An error occurred!";
|
||||||
|
this.toast.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
new Roles().init();
|
new Roles();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,53 +1,67 @@
|
|||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
class UpdateRoles {
|
||||||
let form = document.getElementById("formUpdateRole");
|
constructor() {
|
||||||
let submitButton = document.getElementById("btnUpdateRole");
|
this.initUpdateRole();
|
||||||
let spinner = document.getElementById("spinner");
|
}
|
||||||
let toastMessage = document.getElementById("toast-message");
|
|
||||||
let toast = new bootstrap.Toast(
|
|
||||||
document.getElementById("toastNotification")
|
|
||||||
);
|
|
||||||
submitButton.addEventListener("click", async function () {
|
|
||||||
let submitButton = this;
|
|
||||||
|
|
||||||
if (!form) {
|
initUpdateRole() {
|
||||||
console.error("Form element not found!");
|
const toastNotification = document.getElementById("toastNotification");
|
||||||
return;
|
const toast = new bootstrap.Toast(toastNotification);
|
||||||
}
|
document
|
||||||
// Get form data
|
.getElementById("btnUpdateRole")
|
||||||
let formData = new FormData(form);
|
.addEventListener("click", async function () {
|
||||||
|
let submitButton = this;
|
||||||
|
let spinner = document.getElementById("spinner");
|
||||||
|
let form = document.getElementById("formUpdateRole");
|
||||||
|
|
||||||
// Disable button and show spinner
|
if (!form) {
|
||||||
submitButton.disabled = true;
|
console.error("Form element not found!");
|
||||||
spinner.classList.remove("d-none");
|
return;
|
||||||
|
}
|
||||||
|
// Get form data
|
||||||
|
let formData = new FormData(form);
|
||||||
|
|
||||||
try {
|
// Disable button and show spinner
|
||||||
let response = await fetch(form.action, {
|
submitButton.disabled = true;
|
||||||
method: "POST",
|
spinner.classList.remove("d-none");
|
||||||
headers: {
|
|
||||||
"X-CSRF-TOKEN": document
|
try {
|
||||||
.querySelector('meta[name="csrf-token"]')
|
let response = await fetch(form.action, {
|
||||||
.getAttribute("content"),
|
method: "POST",
|
||||||
},
|
headers: {
|
||||||
body: formData,
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
},
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
let result = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
result.message;
|
||||||
|
toast.show();
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "/roles";
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
let error = await response.json();
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
error.message;
|
||||||
|
toast.show();
|
||||||
|
console.error("Error:", error);
|
||||||
|
submitButton.disabled = false;
|
||||||
|
spinner.classList.add("d-none");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Request failed:", error);
|
||||||
|
document.getElementById("toast-message").innerText =
|
||||||
|
error.message;
|
||||||
|
toast.show();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (response.ok) {
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
let result = await response.json();
|
new UpdateRoles();
|
||||||
toastMessage.innerText = result.message;
|
|
||||||
toast.show();
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.href = "/roles";
|
|
||||||
}, 2000);
|
|
||||||
} else {
|
|
||||||
let error = await response.json();
|
|
||||||
toastMessage.innerText = error.message;
|
|
||||||
toast.show();
|
|
||||||
console.error("Error:", error);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Request failed:", error);
|
|
||||||
toastMessage.innerText = error.message;
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
34
resources/js/utils/InitDatePicker.js
Normal file
34
resources/js/utils/InitDatePicker.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import flatpickr from "flatpickr";
|
||||||
|
import "flatpickr/dist/flatpickr.min.css";
|
||||||
|
|
||||||
|
class InitDatePicker {
|
||||||
|
constructor(selector = ".datepicker", onChangeCallback = null) {
|
||||||
|
this.selector = selector;
|
||||||
|
this.onChangeCallback = onChangeCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
const today = new Date();
|
||||||
|
|
||||||
|
document.querySelectorAll(this.selector).forEach((element) => {
|
||||||
|
flatpickr(element, {
|
||||||
|
enableTime: false,
|
||||||
|
dateFormat: "Y-m-d",
|
||||||
|
maxDate: today,
|
||||||
|
onChange: (selectedDates, dateStr) => {
|
||||||
|
if (this.onChangeCallback) {
|
||||||
|
this.onChangeCallback(dateStr); // Call callback with selected date
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onReady: (selectedDates, dateStr, instance) => {
|
||||||
|
// Call the callback with the default date when initialized
|
||||||
|
if (this.onChangeCallback && dateStr) {
|
||||||
|
this.onChangeCallback(dateStr);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InitDatePicker;
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace [% namespace %];
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
|
||||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
|
||||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
|
||||||
use Illuminate\Routing\Controller as BaseController;
|
|
||||||
|
|
||||||
class Controller extends BaseController
|
|
||||||
{
|
|
||||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
|
||||||
|
|
||||||
[% response_methods %]
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
return new [% api_resource_class %]($[% model_name_singular_variable %], [% model_was_deleted %]);
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
return $this->successResponse(
|
|
||||||
[% model_was_deleted %],
|
|
||||||
$this->transform($[% model_name_singular_variable %])
|
|
||||||
);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
return new [% api_resource_collection_class %]($[% model_name_plural_variable %], [% models_were_retrieved %]);
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
$[% data_variable %] = $[% model_name_plural_variable %]->transform(function ($[% model_name_singular_variable %]) {
|
|
||||||
return $this->transform($[% model_name_singular_variable %]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return $this->successResponse(
|
|
||||||
[% models_were_retrieved %],
|
|
||||||
$[% data_variable %],
|
|
||||||
[
|
|
||||||
'links' => [
|
|
||||||
'first' => $[% model_name_plural_variable %]->url(1),
|
|
||||||
'last' => $[% model_name_plural_variable %]->url($[% model_name_plural_variable %]->lastPage()),
|
|
||||||
'prev' => $[% model_name_plural_variable %]->previousPageUrl(),
|
|
||||||
'next' => $[% model_name_plural_variable %]->nextPageUrl(),
|
|
||||||
],
|
|
||||||
'meta' =>
|
|
||||||
[
|
|
||||||
'current_page' => $[% model_name_plural_variable %]->currentPage(),
|
|
||||||
'from' => $[% model_name_plural_variable %]->firstItem(),
|
|
||||||
'last_page' => $[% model_name_plural_variable %]->lastPage(),
|
|
||||||
'path' => $[% model_name_plural_variable %]->resolveCurrentPath(),
|
|
||||||
'per_page' => $[% model_name_plural_variable %]->perPage(),
|
|
||||||
'to' => $[% model_name_plural_variable %]->lastItem(),
|
|
||||||
'total' => $[% model_name_plural_variable %]->total(),
|
|
||||||
],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
return new [% api_resource_class %]($[% model_name_singular_variable %], [% model_was_retrieved %]);
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
return $this->successResponse(
|
|
||||||
[% model_was_retrieved %],
|
|
||||||
$this->transform($[% model_name_singular_variable %])
|
|
||||||
);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
return new [% api_resource_class %]($[% model_name_singular_variable %], [% model_was_added %]);
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
return $this->successResponse(
|
|
||||||
[% model_was_added %],
|
|
||||||
$this->transform($[% model_name_singular_variable %])
|
|
||||||
);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
return new [% api_resource_class %]($[% model_name_singular_variable %], [% model_was_updated %]);
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
return $this->successResponse(
|
|
||||||
[% model_was_updated %],
|
|
||||||
$this->transform($[% model_name_singular_variable %])
|
|
||||||
);
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/**
|
|
||||||
* Get an error response
|
|
||||||
*
|
|
||||||
* @param mix $message
|
|
||||||
*
|
|
||||||
* @return Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
protected function errorResponse($message)
|
|
||||||
{
|
|
||||||
return response()->json([
|
|
||||||
'errors' => (array) $message,
|
|
||||||
'success' => false,
|
|
||||||
], 422);
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* Gets a new validator instance with the defined rules.
|
|
||||||
*
|
|
||||||
* @param [% request_fullname %] $request
|
|
||||||
*
|
|
||||||
* @return Illuminate\Support\Facades\Validator
|
|
||||||
*/
|
|
||||||
protected function getValidator(Request $request)
|
|
||||||
{
|
|
||||||
$rules = [
|
|
||||||
[% validation_rules %]
|
|
||||||
];
|
|
||||||
[% file_validation_snippet %]
|
|
||||||
return Validator::make($request->all(), $rules);
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
/**
|
|
||||||
* Get a success response
|
|
||||||
*
|
|
||||||
* @param mix $message
|
|
||||||
* @param mix $data
|
|
||||||
* @param array $meta
|
|
||||||
*
|
|
||||||
* @return Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
protected function successResponse($message, $data, array $meta = [])
|
|
||||||
{
|
|
||||||
return response()->json(
|
|
||||||
array_merge([
|
|
||||||
'data' => $data,
|
|
||||||
'message' => $message,
|
|
||||||
'success' => true,
|
|
||||||
], $meta), 200);
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user