Compare commits

...

14 Commits

Author SHA1 Message Date
arifal 625d182d81 fix service google sheet, add uemail to profile, fix detail pbg view, backupdb local last migrate, create menu and role request 2025-02-14 16:22:34 +07:00
arifal 4d32d4a110 fix button and fix service sync simbg 2025-02-14 00:23:50 +07:00
arifal ac2f37d549 add js builk create 2025-02-13 01:50:14 +07:00
arifal a9afb47f08 change filter year on dashboard to dropdown 2025-02-13 01:17:22 +07:00
arifal 9efb6c346e fix conflict and add seeder vilages 2025-02-12 23:50:16 +07:00
arifal 6ba62da5ca merge with feat reklame 2025-02-12 22:24:23 +07:00
arifal ba95c185de create filter and bigdata resume sync 2025-02-12 21:28:08 +07:00
arifal b4b34b503e fix loading all pages 2025-02-12 01:53:40 +07:00
arifal 1a15bc03f8 create loading and handle from js create edit and delete roles 2025-02-11 23:40:31 +07:00
arifal 2bf4b8b327 create feat management role menu 2025-02-11 17:59:03 +07:00
@jamaludinarifrohman6661 ecf9096149 feature: form upload reklame 2025-02-11 16:57:53 +07:00
arifal cb90f69d1e create user role and menu, create seeder for first user and create crud role, menu and user 2025-02-11 02:35:53 +07:00
@jamaludinarifrohman6661 9c41fad232 Feature: crud reklame 2025-02-07 18:11:33 +07:00
@jamaludinarifrohman6661 a7b6f13d8c feature: create seeder master data 2025-02-06 00:28:55 +07:00
108 changed files with 107509 additions and 1615 deletions
+9 -3
View File
@@ -2,7 +2,7 @@
namespace App\Console\Commands;
use App\ServiceSIMBG;
use App\Services\ServiceSIMBG;
use Illuminate\Console\Command;
use \Illuminate\Support\Facades\Log;
@@ -25,10 +25,16 @@ class ExecuteScraping extends Command
/**
* Execute the console command.
*/
private $service_simbg;
public function __construct(ServiceSIMBG $service_simbg){
$this->service_simbg = $service_simbg;
parent::__construct();
}
public function handle()
{
Log::info("running scheduler daily scraping");
$service = new ServiceSIMBG();
$service->syncTaskList();
$this->service_simbg->syncTaskList();
}
}
@@ -0,0 +1,199 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\Advertisement;
use Illuminate\Http\Request;
use App\Http\Requests\AdvertisementRequest;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use App\Http\Resources\AdvertisementResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\AdvertisementImport;
class AdvertisementController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$perPage = $request->input('per_page', 15); // Default 15 jika tidak dikirim oleh client
$search = $request->input('search', ''); // Ambil parameter 'search' jika ada
// Query dasar untuk mengambil iklan
$query = Advertisement::query();
// Jika ada pencarian, filter berdasarkan kolom yang diinginkan
if ($search) {
$query->where(function ($q) use ($search) {
$q->where('business_name', 'like', "%$search%")
->orWhere('npwpd', 'like', "%$search%")
->orWhere('advertisement_content', 'like', "%$search%")
->orWhere('business_address', 'like', "%$search%")
->orWhere('advertisement_location', 'like', "%$search%")
->orWhereIn('village_code', function ($subQuery) use ($search) {
$subQuery->select('village_code')
->from('villages')
->where('village_name', 'like', "%$search%");
})
->orWhereIn('district_code', function ($subQuery) use ($search) {
$subQuery->select('district_code')
->from('districts')
->where('district_name', 'like', "%$search%");
});
});
}
$advertisements = $query->paginate($perPage);
$advertisements->getCollection()->transform(function ($advertisement) {
$village = DB::table('villages')->where('village_code', $advertisement->village_code)->first();
$advertisement->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $advertisement->district_code)->first();
$advertisement->district_name = $district ? $district->district_name : null;
return $advertisement;
});
return response()->json([
'data' => AdvertisementResource::collection($advertisements),
'meta' => [
'total' => $advertisements->total(),
'per_page' => $advertisements->perPage(),
'current_page' => $advertisements->currentPage(),
'last_page' => $advertisements->lastPage(),
]
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(AdvertisementRequest $request): Advertisement
{
$data = $request->validated();
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->value('village_code');
// Cari district_code berdasarkan district_name
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
// Tambahkan village_code dan district_code ke data
$data['village_code'] = $village_code;
$data['district_code'] = $district_code;
// Log data setelah transformasi
info($data);
return Advertisement::create($data);
}
/**
* Import advertisements from Excel or CSV.
*/
public function importFromFile(Request $request)
{
// Validasi file
info($request);
$validator = Validator::make($request->all(), [
'file' => 'required|mimes:xlsx,xls|max:10240', // Max 10MB
]);
if ($validator->fails()) {
return response()->json([
'message' => 'File validation failed.',
'errors' => $validator->errors()
], 400);
}
try {
// Ambil file dari request
$file = $request->file('file');
// Menggunakan Laravel Excel untuk mengimpor file
Excel::import(new AdvertisementImport, $file);
// Jika sukses, kembalikan respons sukses
return response()->json([
'message' => 'File uploaded and imported successfully!'
], 200);
} catch (\Exception $e) {
// Jika ada error, kembalikan error response
return response()->json([
'message' => 'Error during file import.',
'error' => $e->getMessage()
], 500);
}
}
/**
* Display the specified resource.
*/
public function show(Advertisement $advertisement): Advertisement
{
return $advertisement;
}
/**
* Update the specified resource in storage.
*/
public function update(AdvertisementRequest $request, Advertisement $advertisement): Advertisement
{
$data = $request->validated();
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->value('village_code');
// Cari district_code berdasarkan district_name
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
// Tambahkan village_code dan district_code ke data
$data['village_code'] = $village_code;
$data['district_code'] = $district_code;
// Log data setelah transformasi
info($data);
$advertisement->update($data);
return $advertisement;
}
public function destroy(Advertisement $advertisement): Response
{
$advertisement->delete();
return response()->noContent();
}
public function searchOptionsInAdvertisements(Request $request)
{
$query = $request->input('query');
$field = $request->input('field');
$district = $request->input('district'); // Ambil kecamatan jika ada
info("Query: $query, Field: $field, District: $district");
if ($field === 'district_name') {
$results = DB::table('districts')
->where('district_name', 'like', '%' . $query . '%')
->limit(10)
->get(['district_name AS name', 'district_code AS code']);
} elseif ($field === 'village_name' && $district) {
$results = DB::table('villages')
->where('village_name', 'like', '%' . $query . '%')
->whereExists(function ($query) use ($district) {
$query->select(DB::raw(1))
->from('districts')
->whereColumn('villages.district_code', 'districts.district_code')
->where('districts.district_name', $district);
})
->limit(10)
->get(['village_name AS name', 'village_code AS code']);
} else {
$results = collect();
}
return response()->json($results);
}
}
@@ -11,11 +11,21 @@ class DashboardController extends Controller
{
use GlobalApiResponse;
public function businnessDocument(Request $request){
$query = once(function () {
public function businnessDocument(Request $request)
{
$request->validate([
"year" => "required|integer"
]);
$current_year = $request->get('year');
$startOfYear = "$current_year-01-01 00:00:00";
$endOfYear = "$current_year-12-31 23:59:59";
$query = once(function () use ($startOfYear, $endOfYear) {
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')
->whereBetween("pt.task_created_at", [$startOfYear, $endOfYear])
->where(function ($query) {
$query->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) != ?', [strtolower(trim('Selesai Verifikasi'))])
->orWhereNull('ptgs.status_verifikasi');
@@ -37,11 +47,20 @@ class DashboardController extends Controller
]);
}
public function nonBusinnessDocument(Request $request){
$request->validate([
"year" => "required|integer"
]);
$query = once( function () {
$current_year = $request->get('year');
$startOfYear = "$current_year-01-01 00:00:00";
$endOfYear = "$current_year-12-31 23:59:59";
$query = once( function () use ($startOfYear, $endOfYear) {
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
->whereBetween("pt.task_created_at", [$startOfYear, $endOfYear])
->where(function ($query) {
$query->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) != ?', [strtolower(trim('Selesai Verifikasi'))])
->orWhereNull('ptgs.status_verifikasi'); // Include NULL values
@@ -61,13 +80,22 @@ class DashboardController extends Controller
"total" => $taskTotal
]);
}
public function allTaskDocuments(){
$query = once( function () {
return DB::table('pbg_task')
->leftJoin('pbg_task_retributions', 'pbg_task.uuid', '=', 'pbg_task_retributions.pbg_task_uid')
public function allTaskDocuments(Request $request){
$request->validate([
"year" => "required|integer"
]);
$current_year = $request->get('year');
$startOfYear = "$current_year-01-01 00:00:00";
$endOfYear = "$current_year-12-31 23:59:59";
$query = once( function () use ($startOfYear, $endOfYear) {
return DB::table('pbg_task as pt')
->leftJoin('pbg_task_retributions as ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid')
->whereBetween("pt.task_created_at", [$startOfYear, $endOfYear])
->select(
DB::raw('COUNT(DISTINCT pbg_task.id) as task_count'),
DB::raw('SUM(pbg_task_retributions.nilai_retribusi_bangunan) as total_retribution')
DB::raw('COUNT(DISTINCT pt.id) as task_count'),
DB::raw('SUM(ptr.nilai_retribusi_bangunan) as total_retribution')
)
->first();
});
@@ -79,11 +107,20 @@ class DashboardController extends Controller
]);
}
public function verificationDocuments(){
$query = once( function (){
public function verificationDocuments(Request $request){
$request->validate([
"year" => "required|integer"
]);
$current_year = $request->get('year');
$startOfYear = "$current_year-01-01 00:00:00";
$endOfYear = "$current_year-12-31 23:59:59";
$query = once( function () use ($startOfYear, $endOfYear){
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') // Menambahkan join ke pbg_task_retributions
->leftJoin('pbg_task_retributions AS ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid')
->whereBetween("pt.task_created_at", [$startOfYear, $endOfYear])
->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) = ?', [strtolower(trim('Selesai Verifikasi'))])
->selectRaw('COUNT(pt.id) AS total_data,
SUM(ptr.nilai_retribusi_bangunan) AS total_retribution')
@@ -99,11 +136,21 @@ class DashboardController extends Controller
]);
}
public function nonVerificationDocuments(){
$query = once(function () {
public function nonVerificationDocuments(Request $request){
$request->validate([
"year" => "required|integer"
]);
$current_year = $request->get('year');
$startOfYear = "$current_year-01-01 00:00:00";
$endOfYear = "$current_year-12-31 23:59:59";
$query = once(function () use ($startOfYear, $endOfYear) {
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 tabel pbg_task_retributions
->whereBetween("pt.task_created_at", [$startOfYear, $endOfYear])
->where(function ($query) {
$query->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) != ?', [strtolower(trim('Selesai Verifikasi'))])
->orWhereNull('ptgs.status_verifikasi'); // Include NULL values
@@ -0,0 +1,56 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Menu;
use Illuminate\Http\Request;
class MenusController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$query = Menu::query();
if($request->has("search") && !empty($request->get("search"))){
$query = $query->where("name", "like", "%".$request->get("search")."%");
}
return response()->json($query->paginate());
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}
@@ -242,7 +242,7 @@ class PbgTaskController extends Controller
$total_data = count($mapToUpsert);
$import_datasource->update([
"message" => "Successfully imported {$total_data}",
"message" => "Successfully processed: {$total_data}",
"status" => ImportDatasourceStatus::Success->value,
]);
@@ -0,0 +1,56 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Role;
use Illuminate\Http\Request;
class RolesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$query = Role::query();
if($request->has('search') && !empty($request->get('search'))){
$query = $query->where('name', 'like', '%'. $request->get('search') . '%');
}
return response()->json($query->paginate());
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}
@@ -0,0 +1,135 @@
<?php
namespace App\Http\Controllers\Data;
use App\Http\Controllers\Controller;
use App\Models\Advertisement;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AdvertisementController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('data.advertisements.index');
}
/**
* Show the form for uploading a file.
*/
public function bulkCreate()
{
// Mengembalikan view form-upload
return view('data.advertisements.form-upload');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$title = 'Advertisement';
$subtitle = 'Create Data';
// Mengambil data untuk dropdown
$dropdownOptions = [
'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'),
'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'),
];
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/advertisements');
// $route = 'advertisements.create';
// info("AdvertisementController@edit diakses dengan ID: $title");
return view('data.advertisements.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
info("AdvertisementController@edit diakses dengan ID: $id");
$title = 'Advertisement';
$subtitle = 'Update Data';
$modelInstance = Advertisement::find($id);
// Pastikan model ditemukan
if (!$modelInstance) {
info("AdvertisementController@edit: Model tidak ditemukan.");
return redirect()->route('advertisements.index')->with('error', 'Advertisement not found');
}
// Mengambil dan memetakan village_name dan district_name
$village = DB::table('villages')->where('village_code', $modelInstance->village_code)->first();
$modelInstance->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $modelInstance->district_code)->first();
$modelInstance->district_name = $district ? $district->district_name : null;
// Mengambil data untuk dropdown
$dropdownOptions = [
'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'),
'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'),
];
info("AdvertisementController@edit diakses dengan Model Instance: $modelInstance");
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/advertisements');
// $route = 'advertisements.update'; // Menggunakan route update untuk form edit
// info("AdvertisementController@edit diakses dengan route: $route");
return view('data.advertisements.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
}
private function getFields()
{
return [
"no" => "No",
"business_name" => "Nama Wajib Pajak",
"npwpd" => "NPWPD",
"advertisement_type" => "Jenis Reklame",
"advertisement_content" => "Isi Reklame",
"business_address" => "Alamat Wajib Pajak",
"advertisement_location" => "Lokasi Reklame",
"district_name" => "Kecamatan",
"village_name" => "Desa",
"length" => "Panjang",
"width" => "Lebar",
"viewing_angle" => "Sudut Pandang",
"face" => "Muka",
"area" => "Luas",
"angle" => "Sudut",
"contact" => "Kontak",
];
}
private function getFieldTypes()
{
return [
"no" => "text",
"business_name" => "text",
"npwpd" => "text",
"advertisement_type" => "text",
"advertisement_content" => "textarea",
"business_address" => "text",
"advertisement_location" => "text",
"village_name" => "combobox",
"district_name" => "combobox",
"length" => "text",
"width" => "text",
"viewing_angle" => "text",
"face" => "text",
"area" => "text",
"angle" => "text",
"contact" => "text",
];
}
}
@@ -36,12 +36,13 @@ class DataSettingController extends Controller
DB::beginTransaction();
DataSetting::create($request->validated());
DB::commit();
return redirect()->route("data-settings.index")->with("success","Successfully created");
return response()->json(['message' => 'Successfully created'],201);
}catch(Exception $ex){
DB::rollBack();
return redirect()->back()
->withInput()
->with('error', 'Something went wrong while saving data. ' . $ex->getMessage());
return response()->json([
'message' => 'Failed to create data setting',
'error' => $ex->getMessage()
], 500);
}
}
@@ -79,12 +80,10 @@ class DataSettingController extends Controller
$data = DataSetting::findOrFail($id);
$data->update($request->validated());
DB::commit();
return redirect()->route("data-settings.index")->with("success","Successfully updated");
return response()->json(['message' => 'Successfully updated'], 200);
}catch(Exception $ex){
DB::rollBack();
return redirect()->back()
->withInput()
->with('error', 'Something went wrong while saving data. ' . $ex->getMessage());
return response()->json(['message' => $ex->getMessage()],500);
}
}
@@ -97,7 +96,7 @@ class DataSettingController extends Controller
DB::beginTransaction();
DataSetting::findOrFail($id)->delete();
DB::commit();
return response()->json(['success' => true, 'message' => 'Item deleted successfully.']);
return response()->json(['success' => true, 'message' => 'Item deleted successfully.'], 200);
}catch(Exception $e){
DB::rollBack();
Log::error($e->getMessage());
+41 -13
View File
@@ -3,7 +3,10 @@
namespace App\Http\Controllers\Master;
use App\Http\Controllers\Controller;
use App\Models\Role;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
@@ -22,7 +25,8 @@ class UsersController extends Controller
return view('master.users.index', compact('users'));
}
public function create(){
return view('master.users.create');
$roles = Role::all();
return view('master.users.create', compact('roles'));
}
public function store(Request $request){
$request->validate([
@@ -31,11 +35,12 @@ class UsersController extends Controller
'password' => ['required', 'confirmed', 'max:255'],
'firstname' => ['required', 'string', 'max:255'],
'lastname' => ['required', 'string', 'max:255'],
'position' => ['required', 'string', 'max:255']
'position' => ['required', 'string', 'max:255'],
'role_id' => 'required|exists:roles,id'
]);
// dd($request);
DB::beginTransaction();
try{
$user = User::create([
'name' => $request->name,
'email' => $request->email,
@@ -45,7 +50,14 @@ class UsersController extends Controller
'position' => $request->position
]);
return redirect()->route('users.index')->with('success','Successfully registered');
$user->roles()->attach($request->role_id);
DB::commit();
return response()->json(['message' => 'Successfully created'],201);
}catch(\Exception $e){
DB::rollBack();
return response()->json(['message' => $e->getMessage()],500);
};
}
public function show($id){
$user = User::find($id);
@@ -53,24 +65,40 @@ class UsersController extends Controller
}
public function edit($id){
$user = User::find($id);
return view('master.users.edit', compact('user'));
$roles = Role::all();
return view('master.users.edit', compact('user', 'roles'));
}
public function update(Request $request, $id){
$user = User::find($id);
$validate = $request->validate([
$validatedData = $request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
'email' => ['required', 'string', 'email', 'max:255', Rule::unique('users')->ignore($id)],
'firstname' => ['required', 'string', 'max:255'],
'lastname' => ['required', 'string', 'max:255'],
'position' => ['required', 'string', 'max:255']
'position' => ['required', 'string', 'max:255'],
'role_id' => ['required', 'exists:roles,id'],
]);
$user->update($validate);
return redirect()->route('master.users')->with('success', 'Successfully');
try{
DB::beginTransaction();
$updateData = [
'name' => $validatedData['name'],
'email' => $validatedData['email'],
'firstname' => $validatedData['firstname'],
'lastname' => $validatedData['lastname'],
'position' => $validatedData['position'],
];
$user->update($updateData);
$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);
}
}
public function destroy($id){
$user = User::find($id);
$user->delete();
return redirect()->route('master.users')->with('success','Successfully deleted');
return redirect()->route('users.index')->with('success','Successfully deleted');
}
}
+113
View File
@@ -0,0 +1,113 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\MenuRequest;
use App\Models\Menu;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class MenusController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('menus.index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$parent_menus = Menu::whereNull('parent_id')->get();
return view("menus.create", compact('parent_menus'));
}
/**
* Store a newly created resource in storage.
*/
public function store(MenuRequest $request)
{
try{
$validated_menu = $request->validated();
DB::beginTransaction();
Menu::create($validated_menu);
DB::commit();
return response()->json(['message' => 'Successfully created'], 200);
}catch(\Exception $e){
DB::rollBack();
\Log::error('Menu creation failed: ' . $e->getMessage()); // Log the error for debugging
return response()->json(['message'=> $e->getMessage()],500);
}
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$menu = Menu::findOrFail($id);
$parent_menus = Menu::whereNull('parent_id')->where('id','!=',$id)->get();
return view("menus.edit", compact('menu','parent_menus'));
}
/**
* Update the specified resource in storage.
*/
public function update(MenuRequest $request, string $id)
{
try{
$validate_menu = $request->validated();
$menu = Menu::findOrFail($id);
DB::beginTransaction();
$menu->update($validate_menu);
DB::commit();
return response()->json(['message' => 'Successfully updated'], 200);
}catch(\Exception $e){
DB::rollBack();
\Log::error('Menu update failed: '. $e->getMessage()); // Log the error for debugging
return response()->json(['message' => $e->getMessage()],500);
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
try{
DB::beginTransaction();
$menu = Menu::findOrFail($id);
$this->deleteChildren($menu);
$menu->roles()->detach();
$menu->delete();
DB::commit();
return response()->json(['success' => true, 'message' => 'Successfully deleted']);
}catch(\Exception $e){
DB::rollBack();
\Log::error('failed delete menu'. $e->getMessage());
return response()->json(['success' => false, 'message' => 'Something went wrong! Please try again.']);
}
}
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();
}
}
}
+146
View File
@@ -0,0 +1,146 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\RoleRequest;
use App\Models\Menu;
use App\Models\Role;
use App\Models\RoleMenu;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
class RolesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view("roles.index");
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view("roles.create");
}
/**
* Store a newly created resource in storage.
*/
public function store(RoleRequest $request)
{
try{
$validate_role = $request->validated();
DB::beginTransaction();
Role::create($validate_role);
DB::commit();
return response()->json(['message' => 'Role created successfully'], 201);
}
catch(\Exception $e){
DB::rollBack();
return response()->json(['message' => $e->getMessage()], 500);
}
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$role = Role::findOrFail($id);
return view("roles.edit", compact('role'));
}
/**
* Update the specified resource in storage.
*/
public function update(RoleRequest $request, string $id)
{
try{
$validate_role = $request->validated();
$role = Role::findOrFail($id);
DB::beginTransaction();
$role->update($validate_role);
DB::commit();
return response()->json(['message' => 'Role updated successfully'], 200);
}catch(\Exception $e){
DB::rollBack();
return response()->json(['message' => $e->getMessage()], 500);
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
try{
DB::beginTransaction();
Role::findOrFail($id)->delete();
DB::commit();
return response()->json(['success' => true, "message" => "Successfully deleted"]);
}catch(\Exception $e){
DB::rollBack();
return response()->json(['success' => false, "message" => $e->getMessage()]);
}
}
public function menu_permission(string $role_id){
try{
$role = Role::findOrFail($role_id);
$menus = Menu::all();
$role_menus = RoleMenu::where('role_id', $role_id)->get() ?? collect();
return view('roles.role_menu', compact('role', 'menus', 'role_menus'));
}catch(\Exception $e){
return redirect()->back()->with("error", $e->getMessage());
}
}
public function update_menu_permission(Request $request, string $role_id){
try{
$validateData = $request->validate([
"permissions" => "array",
"permissions.*.allow_show" => "nullable|boolean",
"permissions.*.allow_create" => "nullable|boolean",
"permissions.*.allow_update" => "nullable|boolean",
"permissions.*.allow_destroy" => "nullable|boolean"
]);
$role = Role::find($role_id);
$permissionsArray = [];
foreach ($validateData['permissions'] as $menu_id => $permission) {
$permissionsArray[$menu_id] = [
"allow_show" => (int) ($permission["allow_show"] ?? 0),
"allow_create" => (int) ($permission["allow_create"] ?? 0),
"allow_update" => (int) ($permission["allow_update"] ?? 0),
"allow_destroy" => (int) ($permission["allow_destroy"] ?? 0),
"updated_at" => now(),
];
}
// Sync will update existing records and insert new ones
$role->menus()->sync($permissionsArray);
return redirect()->route("role-menu.permission", $role_id)->with('success','Menu Permission updated successfully');
}catch(\Exception $e){
Log::error("Error updating role_menu:", ["error" => $e->getMessage()]);
return redirect()->route("role-menu.permission", $role_id)->with("error", $e->getMessage());
}
}
}
@@ -3,7 +3,7 @@
namespace App\Http\Controllers\Settings;
use App\Http\Controllers\Controller;
use App\ServiceSIMBG;
use App\Services\ServiceSIMBG;
use Illuminate\Http\Request;
use Exception;
class SyncronizeController extends Controller
@@ -0,0 +1,43 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class AdvertisementRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'no' => 'required',
'business_name' => 'required|string',
'npwpd' => 'required|string',
'advertisement_type' => 'required|string',
'advertisement_content' => 'required|string',
'business_address' => 'required|string',
'advertisement_location' => 'required|string',
'village_name' => 'required',
'district_name' => 'required',
'length' => 'required',
'width' => 'required',
'viewing_angle' => 'required|string',
'face' => 'required|string',
'area' => 'required|string',
'angle' => 'required|string',
'contact' => 'required|string',
];
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class MenuRequest 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'],
'url' => ['nullable','string','max:255'],
'icon' => ['nullable','string','max:255'],
'parent_id' => ['nullable','exists:menus,id'],
'sort_order' => ['required','integer'],
];
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class RoleRequest 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
{
$roleId = $this->route('role');
return [
'name' => 'required|string|max:255|unique:roles,name,' . ($roleId ?? 'NULL') . ',id',
'description' => 'nullable|string',
];
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class AdvertisementResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
}
+1
View File
@@ -23,6 +23,7 @@ class UserResource extends JsonResource
'position' => $this->position,
'firstname' => $this->firstname,
'lastname' => $this->lastname,
'roles' => $this->roles->pluck('name'),
];
}
}
+92
View File
@@ -0,0 +1,92 @@
<?php
namespace App\Imports;
use App\Models\Advertisement;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Illuminate\Support\Facades\DB;
class AdvertisementImport implements ToCollection
{
/**
* Process each row in the file.
*/
public function collection(Collection $rows)
{
if ($rows->isEmpty())
{
return;
}
// Ambil data districts dengan normalisasi nama
$districts = DB::table('districts')
->get()
->mapWithKeys(function ($item) {
return [strtolower(trim($item->district_name)) => $item->district_code];
})
->toArray();
// Cari header secara otomatis
$header = $rows->first();
$headerIndex = collect($header)->search(fn($value) => !empty($value));
// Pastikan header ditemukan
if ($headerIndex === false) {
return;
}
$dataToInsert = [];
foreach ($rows->skip(1) as $row) {
// Normalisasi nama kecamatan dan desa
$districtName = strtolower(trim(str_replace('Kecamatan ', '', $row[8])));
$villageName = strtolower(trim($row[7]));
// Cari district_code dari tabel districts
$districtCode = $districts[$districtName] ?? null;
$listTrueVillage = DB::table('villages')
->where('district_code', $districtCode) // Perbaikan pada where()
->get()
->mapWithKeys(function ($item) {
return [strtolower(trim($item->village_name)) => [
'village_code' => $item->village_code,
'district_code' => $item->district_code
]];
})
->toArray();
// ambil village code yang village_name sama dengan $villageName
$villageCode = $listTrueVillage[$villageName]['village_code'] ?? '0000';
$dataToInsert[] = [
'no' => $row[0],
'business_name' => $row[1],
'npwpd' => $row[2],
'advertisement_type' => $row[3],
'advertisement_content' => $row[4],
'business_address' => $row[5],
'advertisement_location' => $row[6],
'village_code' => $villageCode,
'district_code' => $districtCode,
'length' => $row[9],
'width' => $row[10],
'viewing_angle' => $row[11],
'face' => $row[12],
'area' => $row[13],
'angle' => $row[14],
'contact' => $row[15] ?? "-",
'created_at' => now(),
'updated_at' => now()
];
}
// Bulk insert untuk efisiensi
if (!empty($dataToInsert)) {
Advertisement::insert($dataToInsert);
} else {
return;
}
}
}
+46
View File
@@ -0,0 +1,46 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Class Advertisement
*
* @property $id
* @property $created_at
* @property $updated_at
* @property $no
* @property $business_name
* @property $npwpd
* @property $advertisement_type
* @property $advertisement_content
* @property $business_address
* @property $advertisement_location
* @property $village_code
* @property $district_code
* @property $length
* @property $width
* @property $viewing_angle
* @property $face
* @property $area
* @property $angle
* @property $contact
*
* @package App
* @mixin \Illuminate\Database\Eloquent\Builder
*/
class Advertisement extends Model
{
protected $perPage = 20;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = ['no', 'business_name', 'npwpd', 'advertisement_type', 'advertisement_content', 'business_address', 'advertisement_location', 'village_code', 'district_code', 'length', 'width', 'viewing_angle', 'face', 'area', 'angle', 'contact'];
}
+125
View File
@@ -0,0 +1,125 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class BigdataResume extends Model
{
protected $table = "bigdata_resumes";
protected $fillable = [
'import_datasource_id',
'potention_count',
'potention_sum',
'non_verified_count',
'non_verified_sum',
'verified_count',
'verified_sum',
'business_count',
'business_sum',
'non_business_count',
'non_business_sum',
];
public function importDatasource()
{
return $this->belongsTo(ImportDatasource::class, 'import_datasource_id');
}
public static function generateResumeData($import_datasource_id){
$query_verified = 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')
->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) = ?', [strtolower(trim('Selesai Verifikasi'))])
->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) {
$query->whereRaw('LOWER(TRIM(pt.function_type)) != ?', [strtolower(trim('Sebagai Tempat Usaha'))])
->orWhereNull('pt.function_type'); // 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();
});
$non_business_count = $query_non_business->total_data ?? 0;
$non_business_total = $query_non_business->total_retribution ?? 0;
$query_non_verified = 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 tabel pbg_task_retributions
->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();
});
$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_total = $query_potention->total_retribution ?? 0;
return self::create([
'import_datasource_id' => $import_datasource_id,
'potention_count' => $potention_count ?? 0,
'potention_sum' => $potention_total ?? 0.00,
'non_verified_count' => $non_verified_count ?? 0,
'non_verified_sum' => $non_verified_total ?? 0.00,
'verified_count' => $verified_count ?? 0,
'verified_sum' => $verified_total ?? 0.00,
'business_count' => $business_count ?? 0,
'business_sum' => $business_total ?? 0.00,
'non_business_count' => $non_business_count ?? 0,
'non_business_sum' => $non_business_total ?? 0.00,
]);
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Menu extends Model
{
protected $table = 'menus';
protected $fillable = [
'name',
'url',
'icon',
'parent_id',
'sort_order'
];
public function roles(){
return $this->belongsToMany(Role::class, 'role_menu')->withTimestamps();
}
public function children(){
return $this->hasMany(Menu::class,'parent_id');
}
}
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
protected $table = 'roles';
protected $fillable = [
'name',
'description'
];
public function users(){
return $this->belongsToMany(User::class,'user_role')->withTimestamps();
}
public function menus(){
return $this->belongsToMany(Menu::class,'role_menu')->withTimestamps();
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class RoleMenu extends Model
{
protected $table = 'role_menu';
protected $primary = ['role_id', 'menu_id'];
public $incrementing = false;
protected $fillable = [
'role_id',
'menu_id',
'allow_show',
'allow_create',
'allow_update',
'allow_destroy',
];
public $timestamps = true;
public function role(){
return $this->belongsTo(Role::class, 'role_id');
}
public function menu(){
return $this->belongsTo(Menu::class,'menu_id');
}
}
+4
View File
@@ -49,4 +49,8 @@ class User extends Authenticatable
'password' => 'hashed',
];
}
public function roles(){
return $this->belongsToMany(Role::class, 'user_role')->withTimestamps();
}
}
+24
View File
@@ -2,8 +2,11 @@
namespace App\Providers;
use App\Models\Menu;
use App\View\Components\Circle;
use Auth;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Carbon\Carbon;
@@ -23,5 +26,26 @@ class AppServiceProvider extends ServiceProvider
public function boot(): void
{
Blade::component('circle', Circle::class);
View::composer('layouts.partials.sidebar', function ($view){
$user = Auth::user();
if($user){
$menus = Menu::whereHas('roles', function ($query) use ($user){
$query->where('roles.id', $user->roles->pluck('id'));
})
->with(['children' => function ($query) {
$query->whereHas('roles', function ($subQuery) {
$subQuery->where('role_menu.allow_show', 1);
});
}])
->orderBy('sort_order', 'asc')
->get();
}else{
$menus = collect();
}
$view->with('menus', $menus);
});
}
}
+12
View File
@@ -34,6 +34,7 @@ class GoogleSheetService
public function getLastRowByColumn($column = "A")
{
try{
// Ambil spreadsheet
$spreadsheet = $this->service->spreadsheets->get($this->spreadsheetID);
$sheets = $spreadsheet->getSheets();
@@ -63,9 +64,13 @@ class GoogleSheetService
}
return 0;
}catch(\Exception $e){
throw $e;
}
}
public function getHeader()
{
try{
$spreadsheet = $this->service->spreadsheets->get($this->spreadsheetID);
$sheets = $spreadsheet->getSheets();
@@ -79,6 +84,9 @@ class GoogleSheetService
// Kembalikan header (baris pertama)
return !empty($values) ? $values[0] : [];
}catch(\Exception $e){
throw $e;
}
}
public function getLastColumn()
@@ -99,6 +107,7 @@ class GoogleSheetService
}
public function getSheetDataCollection($totalRow = 10){
try{
$spreadsheet = $this->service->spreadsheets->get($this->spreadsheetID);
$sheets = $spreadsheet->getSheets();
$firstSheetTitle = $sheets[0]->getProperties()->getTitle();
@@ -127,5 +136,8 @@ class GoogleSheetService
}
return $mappedData;
}catch(\Exception $e){
throw $e;
}
}
}
@@ -1,6 +1,6 @@
<?php
namespace App;
namespace App\Services;
use App\Traits\GlobalApiResponse;
use GuzzleHttp\Client;
use Exception;
@@ -42,10 +42,17 @@ class ServiceClient
}
$response = $this->client->request($method, $this->baseUrl . $url, $options);
$responseBody = (string) $response->getBody();
$resultResponse = json_decode($response->getBody(), true);
if (!str_contains($response->getHeaderLine('Content-Type'), 'application/json')) {
\Log::error('Unexpected response format: ' . $responseBody);
return $this->resError('API response is not JSON');
}
$resultResponse = json_decode($responseBody, true, 512, JSON_THROW_ON_ERROR);
return $this->resSuccess($resultResponse);
} catch (Exception $e) {
\Log::error('error from client service'. $e->getMessage());
return $this->resError($e->getMessage());
}
}
@@ -1,8 +1,9 @@
<?php
namespace App;
namespace App\Services;
use App\Enums\ImportDatasourceStatus;
use App\Models\BigdataResume;
use App\Models\GlobalSetting;
use App\Models\ImportDatasource;
use App\Models\PbgTaskIndexIntegrations;
@@ -13,6 +14,7 @@ use App\Models\PbgTask;
use App\Traits\GlobalApiResponse;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;
use App\Services\ServiceClient;
class ServiceSIMBG
{
@@ -25,16 +27,17 @@ class ServiceSIMBG
/**
* Create a new class instance.
*/
public function __construct(ServiceClient $service_client)
public function __construct()
{
$this->email = trim((string) GlobalSetting::where('key','SIMBG_EMAIL')->first()->value);
$this->password = trim((string) GlobalSetting::where('key','SIMBG_PASSWORD')->first()->value);
$this->simbg_host = trim((string)GlobalSetting::where('key','SIMBG_HOST')->first()->value);
$this->fetch_per_page = trim((string)GlobalSetting::where('key','FETCH_PER_PAGE')->first()->value);
$this->email = trim((string) GlobalSetting::where('key','SIMBG_EMAIL')->firstOrFail()->value);
$this->password = trim((string) GlobalSetting::where('key','SIMBG_PASSWORD')->firstOrFail()->value);
$this->simbg_host = trim((string)GlobalSetting::where('key','SIMBG_HOST')->firstOrFail()->value);
$this->fetch_per_page = trim((string)GlobalSetting::where('key','FETCH_PER_PAGE')->firstOrFail()->value);
$this->service_client = new ServiceClient($this->simbg_host);
}
public function getToken(){
try{
$url = "/api/user/v1/auth/login/";
$body = [
'email' => $this->email,
@@ -44,13 +47,18 @@ class ServiceSIMBG
$res = $this->service_client->post($url, $body);
if(!$res->original['success']){
Log::error("Token not retrieved ", ['response' => $res]);
return null;
throw new Exception("Token not retrieved.");
}
return $res;
}catch(Exception $e){
Log::error("Error on method get token ", ['response' => $e->getMessage()]);
throw $e;
}
}
public function syncIndexIntegration($uuid, $token)
{
try{
$url = "/api/pbg/v1/detail/" . $uuid . "/retribution/indeks-terintegrasi/";
$headers = [
@@ -59,8 +67,6 @@ class ServiceSIMBG
$res = $this->service_client->get($url, $headers);
Log::info("response index integration", ['res' => $res]);
if (empty($res->original['success']) || !$res->original['success']) {
// Log error
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
@@ -86,14 +92,11 @@ class ServiceSIMBG
]
);
// Log success
if ($resultData->wasRecentlyCreated) {
Log::info("integration created successfully", ['uuid' => $uuid]);
} else {
Log::info("integration updated successfully", ['uuid' => $uuid]);
}
return true;
}catch (Exception $e){
Log::error('error when sync index integration ', ['index integration'=> $e->getMessage()]);
throw $e;
}
}
public function syncTaskList()
@@ -183,7 +186,9 @@ class ServiceSIMBG
];
$this->syncIndexIntegration($item['uid'], $token);
$this->syncTaskDetailSubmit($item['uid'], $token);
$savedCount++;
} catch (Exception $e) {
$failedCount++;
@@ -212,6 +217,8 @@ class ServiceSIMBG
'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]);
@@ -220,6 +227,7 @@ class ServiceSIMBG
public function syncTaskDetailSubmit($uuid, $token)
{
try{
$url = "/api/pbg/v1/detail/" . $uuid . "/retribution/submit/";
$headers = [
'Authorization' => "Bearer " . $token,
@@ -290,9 +298,12 @@ class ServiceSIMBG
// Use bulk insert or upsert for faster database operation
PbgTaskPrasarana::upsert($insertData, ['prasarana_id']);
}
Log::info("retribution and prasarana successfully", ['uuid' => $uuid]);
return true;
}catch(Exception $e){
Log::error("Failed to sync task detail submit", ['error' => $e->getMessage(), 'uuid' => $uuid]);
throw $e;
}
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class ModalConfirmation extends Component
{
/**
* Create a new component instance.
*/
public function __construct()
{
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.modal-confirmation');
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class ToastNotification extends Component
{
/**
* Create a new component instance.
*/
public function __construct()
{
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.toast-notification');
}
}
+8 -9
View File
@@ -3,7 +3,10 @@
"name": "laravel/laravel",
"type": "project",
"description": "The skeleton application for the Laravel framework.",
"keywords": ["laravel", "framework"],
"keywords": [
"laravel",
"framework"
],
"license": "MIT",
"require": {
"php": "^8.2",
@@ -11,10 +14,12 @@
"guzzlehttp/guzzle": "^7.9",
"laravel/framework": "^11.31",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.9"
"laravel/tinker": "^2.9",
"maatwebsite/excel": "^3.1"
},
"require-dev": {
"fakerphp/faker": "^1.23",
"ibex/crud-generator": "^2.1",
"laravel/pail": "^1.1",
"laravel/pint": "^1.13",
"laravel/sail": "^1.26",
@@ -70,11 +75,5 @@
}
},
"minimum-stability": "stable",
"prefer-stable": true,
"repositories": {
"grocery-crud": {
"type": "composer",
"url": "https://composer.grocerycrud.com/"
}
}
"prefer-stable": true
}
Generated Executable → Regular
+716 -55
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3fea2988b5efebfd50ec7c29aeae3830",
"content-hash": "52617d098d62b15c6ce8538cc8aea775",
"packages": [
{
"name": "brick/math",
@@ -135,6 +135,166 @@
],
"time": "2024-02-09T16:56:22+00:00"
},
{
"name": "composer/pcre",
"version": "3.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<1.11.10"
},
"require-dev": {
"phpstan/phpstan": "^1.12 || ^2",
"phpstan/phpstan-strict-rules": "^1 || ^2",
"phpunit/phpunit": "^8 || ^9"
},
"type": "library",
"extra": {
"phpstan": {
"includes": [
"extension.neon"
]
},
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Pcre\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
"keywords": [
"PCRE",
"preg",
"regex",
"regular expression"
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.3.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2024-11-12T16:29:46+00:00"
},
{
"name": "composer/semver",
"version": "3.4.3",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
"reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.11",
"symfony/phpunit-bridge": "^3 || ^7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.4.3"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2024-09-19T14:15:21+00:00"
},
{
"name": "dflydev/dot-access-data",
"version": "v3.0.3",
@@ -510,6 +670,67 @@
],
"time": "2024-12-27T00:36:43+00:00"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.18.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "cb56001e54359df7ae76dc522d08845dc741621b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b",
"reference": "cb56001e54359df7ae76dc522d08845dc741621b",
"shasum": ""
},
"require": {
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
},
"require-dev": {
"cerdic/css-tidy": "^1.7 || ^2.0",
"simpletest/simpletest": "dev-master"
},
"suggest": {
"cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
"ext-bcmath": "Used for unit conversion and imagecrash protection",
"ext-iconv": "Converts text to and from non-UTF-8 encodings",
"ext-tidy": "Used for pretty-printing HTML"
},
"type": "library",
"autoload": {
"files": [
"library/HTMLPurifier.composer.php"
],
"psr-0": {
"HTMLPurifier": "library/"
},
"exclude-from-classmap": [
"/library/HTMLPurifier/Language/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-or-later"
],
"authors": [
{
"name": "Edward Z. Yang",
"email": "admin@htmlpurifier.org",
"homepage": "http://ezyang.com"
}
],
"description": "Standards compliant HTML filter written in PHP",
"homepage": "http://htmlpurifier.org/",
"keywords": [
"html"
],
"support": {
"issues": "https://github.com/ezyang/htmlpurifier/issues",
"source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0"
},
"time": "2024-11-01T03:51:45+00:00"
},
{
"name": "firebase/php-jwt",
"version": "v6.11.0",
@@ -715,16 +936,16 @@
},
{
"name": "google/apiclient-services",
"version": "v0.393.0",
"version": "v0.394.0",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-api-php-client-services.git",
"reference": "ed24c09584df8ef0cdcfb9d4305abf66fc17e609"
"reference": "17fa8210d62c02c398fb4985ed4bc461d18989c1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/ed24c09584df8ef0cdcfb9d4305abf66fc17e609",
"reference": "ed24c09584df8ef0cdcfb9d4305abf66fc17e609",
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/17fa8210d62c02c398fb4985ed4bc461d18989c1",
"reference": "17fa8210d62c02c398fb4985ed4bc461d18989c1",
"shasum": ""
},
"require": {
@@ -753,22 +974,22 @@
],
"support": {
"issues": "https://github.com/googleapis/google-api-php-client-services/issues",
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.393.0"
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.394.0"
},
"time": "2025-02-03T00:54:21+00:00"
"time": "2025-02-10T01:06:23+00:00"
},
{
"name": "google/auth",
"version": "v1.45.3",
"version": "v1.45.4",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-auth-library-php.git",
"reference": "000d9439f430c6e56cba105c5ab750f5f7d69ea8"
"reference": "c70b987a3c2685c78e5e86280f9d259d4603839b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/000d9439f430c6e56cba105c5ab750f5f7d69ea8",
"reference": "000d9439f430c6e56cba105c5ab750f5f7d69ea8",
"url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/c70b987a3c2685c78e5e86280f9d259d4603839b",
"reference": "c70b987a3c2685c78e5e86280f9d259d4603839b",
"shasum": ""
},
"require": {
@@ -812,11 +1033,11 @@
"oauth2"
],
"support": {
"docs": "https://googleapis.github.io/google-auth-library-php/main/",
"docs": "https://cloud.google.com/php/docs/reference/auth/latest",
"issues": "https://github.com/googleapis/google-auth-library-php/issues",
"source": "https://github.com/googleapis/google-auth-library-php/tree/v1.45.3"
"source": "https://github.com/googleapis/google-auth-library-php/tree/v1.45.4"
},
"time": "2025-01-29T18:17:08+00:00"
"time": "2025-02-10T18:04:06+00:00"
},
{
"name": "graham-campbell/result-type",
@@ -1293,16 +1514,16 @@
},
{
"name": "laravel/framework",
"version": "v11.41.3",
"version": "v11.42.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "3ef433d5865f30a19b6b1be247586068399b59cc"
"reference": "006375ba67e830e87daa7b52ab65163ba3508d26"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/3ef433d5865f30a19b6b1be247586068399b59cc",
"reference": "3ef433d5865f30a19b6b1be247586068399b59cc",
"url": "https://api.github.com/repos/laravel/framework/zipball/006375ba67e830e87daa7b52ab65163ba3508d26",
"reference": "006375ba67e830e87daa7b52ab65163ba3508d26",
"shasum": ""
},
"require": {
@@ -1410,11 +1631,11 @@
"league/flysystem-read-only": "^3.25.1",
"league/flysystem-sftp-v3": "^3.25.1",
"mockery/mockery": "^1.6.10",
"orchestra/testbench-core": "^9.6",
"orchestra/testbench-core": "^9.9.4",
"pda/pheanstalk": "^5.0.6",
"php-http/discovery": "^1.15",
"phpstan/phpstan": "^1.11.5",
"phpunit/phpunit": "^10.5.35|^11.3.6",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^10.5.35|^11.3.6|^12.0.1",
"predis/predis": "^2.3",
"resend/resend-php": "^0.10.0",
"symfony/cache": "^7.0.3",
@@ -1446,7 +1667,7 @@
"mockery/mockery": "Required to use mocking (^1.6).",
"pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).",
"php-http/discovery": "Required to use PSR-7 bridging features (^1.15).",
"phpunit/phpunit": "Required to use assertions and run tests (^10.5|^11.0).",
"phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1).",
"predis/predis": "Required to use the predis connector (^2.3).",
"psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).",
@@ -1504,20 +1725,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2025-01-30T13:25:22+00:00"
"time": "2025-02-11T17:17:56+00:00"
},
{
"name": "laravel/prompts",
"version": "v0.3.4",
"version": "v0.3.5",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
"reference": "abeaa2ba4294247d5409490d1ca1bc6248087011"
"reference": "57b8f7efe40333cdb925700891c7d7465325d3b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/prompts/zipball/abeaa2ba4294247d5409490d1ca1bc6248087011",
"reference": "abeaa2ba4294247d5409490d1ca1bc6248087011",
"url": "https://api.github.com/repos/laravel/prompts/zipball/57b8f7efe40333cdb925700891c7d7465325d3b1",
"reference": "57b8f7efe40333cdb925700891c7d7465325d3b1",
"shasum": ""
},
"require": {
@@ -1561,9 +1782,9 @@
"description": "Add beautiful and user-friendly forms to your command-line applications.",
"support": {
"issues": "https://github.com/laravel/prompts/issues",
"source": "https://github.com/laravel/prompts/tree/v0.3.4"
"source": "https://github.com/laravel/prompts/tree/v0.3.5"
},
"time": "2025-01-24T15:41:01+00:00"
"time": "2025-02-11T13:34:40+00:00"
},
{
"name": "laravel/sanctum",
@@ -1631,16 +1852,16 @@
},
{
"name": "laravel/serializable-closure",
"version": "v2.0.2",
"version": "v2.0.3",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
"reference": "2e1a362527783bcab6c316aad51bf36c5513ae44"
"reference": "f379c13663245f7aa4512a7869f62eb14095f23f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/2e1a362527783bcab6c316aad51bf36c5513ae44",
"reference": "2e1a362527783bcab6c316aad51bf36c5513ae44",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f379c13663245f7aa4512a7869f62eb14095f23f",
"reference": "f379c13663245f7aa4512a7869f62eb14095f23f",
"shasum": ""
},
"require": {
@@ -1688,7 +1909,7 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
"time": "2025-01-24T15:42:37+00:00"
"time": "2025-02-11T15:03:05+00:00"
},
{
"name": "laravel/tinker",
@@ -2307,6 +2528,272 @@
],
"time": "2024-12-08T08:18:47+00:00"
},
{
"name": "maatwebsite/excel",
"version": "3.1.62",
"source": {
"type": "git",
"url": "https://github.com/SpartnerNL/Laravel-Excel.git",
"reference": "decfb9140161fcc117571e47e35ddf27983189ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/decfb9140161fcc117571e47e35ddf27983189ce",
"reference": "decfb9140161fcc117571e47e35ddf27983189ce",
"shasum": ""
},
"require": {
"composer/semver": "^3.3",
"ext-json": "*",
"illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0",
"php": "^7.0||^8.0",
"phpoffice/phpspreadsheet": "^1.29.7",
"psr/simple-cache": "^1.0||^2.0||^3.0"
},
"require-dev": {
"laravel/scout": "^7.0||^8.0||^9.0||^10.0",
"orchestra/testbench": "^6.0||^7.0||^8.0||^9.0",
"predis/predis": "^1.1"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Excel": "Maatwebsite\\Excel\\Facades\\Excel"
},
"providers": [
"Maatwebsite\\Excel\\ExcelServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Maatwebsite\\Excel\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Patrick Brouwers",
"email": "patrick@spartner.nl"
}
],
"description": "Supercharged Excel exports and imports in Laravel",
"keywords": [
"PHPExcel",
"batch",
"csv",
"excel",
"export",
"import",
"laravel",
"php",
"phpspreadsheet"
],
"support": {
"issues": "https://github.com/SpartnerNL/Laravel-Excel/issues",
"source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.62"
},
"funding": [
{
"url": "https://laravel-excel.com/commercial-support",
"type": "custom"
},
{
"url": "https://github.com/patrickbrouwers",
"type": "github"
}
],
"time": "2025-01-04T12:14:36+00:00"
},
{
"name": "maennchen/zipstream-php",
"version": "3.1.2",
"source": {
"type": "git",
"url": "https://github.com/maennchen/ZipStream-PHP.git",
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f",
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"ext-zlib": "*",
"php-64bit": "^8.2"
},
"require-dev": {
"brianium/paratest": "^7.7",
"ext-zip": "*",
"friendsofphp/php-cs-fixer": "^3.16",
"guzzlehttp/guzzle": "^7.5",
"mikey179/vfsstream": "^1.6",
"php-coveralls/php-coveralls": "^2.5",
"phpunit/phpunit": "^11.0",
"vimeo/psalm": "^6.0"
},
"suggest": {
"guzzlehttp/psr7": "^2.4",
"psr/http-message": "^2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"ZipStream\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paul Duncan",
"email": "pabs@pablotron.org"
},
{
"name": "Jonatan Männchen",
"email": "jonatan@maennchen.ch"
},
{
"name": "Jesse Donat",
"email": "donatj@gmail.com"
},
{
"name": "András Kolesár",
"email": "kolesar@kolesar.hu"
}
],
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
"keywords": [
"stream",
"zip"
],
"support": {
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2"
},
"funding": [
{
"url": "https://github.com/maennchen",
"type": "github"
}
],
"time": "2025-01-27T12:07:53+00:00"
},
{
"name": "markbaker/complex",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPComplex.git",
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
"phpcompatibility/php-compatibility": "^9.3",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"squizlabs/php_codesniffer": "^3.7"
},
"type": "library",
"autoload": {
"psr-4": {
"Complex\\": "classes/src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@lange.demon.co.uk"
}
],
"description": "PHP Class for working with complex numbers",
"homepage": "https://github.com/MarkBaker/PHPComplex",
"keywords": [
"complex",
"mathematics"
],
"support": {
"issues": "https://github.com/MarkBaker/PHPComplex/issues",
"source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
},
"time": "2022-12-06T16:21:08+00:00"
},
{
"name": "markbaker/matrix",
"version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPMatrix.git",
"reference": "728434227fe21be27ff6d86621a1b13107a2562c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c",
"reference": "728434227fe21be27ff6d86621a1b13107a2562c",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
"phpcompatibility/php-compatibility": "^9.3",
"phpdocumentor/phpdocumentor": "2.*",
"phploc/phploc": "^4.0",
"phpmd/phpmd": "2.*",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"sebastian/phpcpd": "^4.0",
"squizlabs/php_codesniffer": "^3.7"
},
"type": "library",
"autoload": {
"psr-4": {
"Matrix\\": "classes/src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@demon-angel.eu"
}
],
"description": "PHP Class for working with matrices",
"homepage": "https://github.com/MarkBaker/PHPMatrix",
"keywords": [
"mathematics",
"matrix",
"vector"
],
"support": {
"issues": "https://github.com/MarkBaker/PHPMatrix/issues",
"source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
},
"time": "2022-12-02T22:17:43+00:00"
},
{
"name": "monolog/monolog",
"version": "3.8.1",
@@ -2412,16 +2899,16 @@
},
{
"name": "nesbot/carbon",
"version": "3.8.4",
"version": "3.8.5",
"source": {
"type": "git",
"url": "https://github.com/CarbonPHP/carbon.git",
"reference": "129700ed449b1f02d70272d2ac802357c8c30c58"
"reference": "b1a53a27898639579a67de42e8ced5d5386aa9a4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/129700ed449b1f02d70272d2ac802357c8c30c58",
"reference": "129700ed449b1f02d70272d2ac802357c8c30c58",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/b1a53a27898639579a67de42e8ced5d5386aa9a4",
"reference": "b1a53a27898639579a67de42e8ced5d5386aa9a4",
"shasum": ""
},
"require": {
@@ -2497,8 +2984,8 @@
],
"support": {
"docs": "https://carbon.nesbot.com/docs",
"issues": "https://github.com/briannesbitt/Carbon/issues",
"source": "https://github.com/briannesbitt/Carbon"
"issues": "https://github.com/CarbonPHP/carbon/issues",
"source": "https://github.com/CarbonPHP/carbon"
},
"funding": [
{
@@ -2514,7 +3001,7 @@
"type": "tidelift"
}
],
"time": "2024-12-27T09:25:35+00:00"
"time": "2025-02-11T16:28:45+00:00"
},
{
"name": "nette/schema",
@@ -2926,6 +3413,112 @@
},
"time": "2020-10-15T08:29:30+00:00"
},
{
"name": "phpoffice/phpspreadsheet",
"version": "1.29.10",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "c80041b1628c4f18030407134fe88303661d4e4e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/c80041b1628c4f18030407134fe88303661d4e4e",
"reference": "c80041b1628c4f18030407134fe88303661d4e4e",
"shasum": ""
},
"require": {
"composer/pcre": "^1||^2||^3",
"ext-ctype": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"ezyang/htmlpurifier": "^4.15",
"maennchen/zipstream-php": "^2.1 || ^3.0",
"markbaker/complex": "^3.0",
"markbaker/matrix": "^3.0",
"php": "^7.4 || ^8.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-main",
"dompdf/dompdf": "^1.0 || ^2.0 || ^3.0",
"friendsofphp/php-cs-fixer": "^3.2",
"mitoteam/jpgraph": "^10.3",
"mpdf/mpdf": "^8.1.1",
"phpcompatibility/php-compatibility": "^9.3",
"phpstan/phpstan": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^8.5 || ^9.0",
"squizlabs/php_codesniffer": "^3.7",
"tecnickcom/tcpdf": "^6.5"
},
"suggest": {
"dompdf/dompdf": "Option for rendering PDF with PDF Writer",
"ext-intl": "PHP Internationalization Functions",
"mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
},
"type": "library",
"autoload": {
"psr-4": {
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maarten Balliauw",
"homepage": "https://blog.maartenballiauw.be"
},
{
"name": "Mark Baker",
"homepage": "https://markbakeruk.net"
},
{
"name": "Franck Lefevre",
"homepage": "https://rootslabs.net"
},
{
"name": "Erik Tilt"
},
{
"name": "Adrien Crivelli"
}
],
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
"keywords": [
"OpenXML",
"excel",
"gnumeric",
"ods",
"php",
"spreadsheet",
"xls",
"xlsx"
],
"support": {
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.10"
},
"time": "2025-02-08T02:56:14+00:00"
},
{
"name": "phpoption/phpoption",
"version": "1.9.3",
@@ -6562,6 +7155,74 @@
},
"time": "2020-07-09T08:09:16+00:00"
},
{
"name": "ibex/crud-generator",
"version": "v2.1.2",
"source": {
"type": "git",
"url": "https://github.com/awais-vteams/laravel-crud-generator.git",
"reference": "3906f4a702c91bbe3a84d940c3021d1511834320"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/awais-vteams/laravel-crud-generator/zipball/3906f4a702c91bbe3a84d940c3021d1511834320",
"reference": "3906f4a702c91bbe3a84d940c3021d1511834320",
"shasum": ""
},
"require": {
"laravel/framework": "^10.30|^11.0",
"php": "^8.2"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Ibex\\CrudGenerator\\CrudServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Ibex\\CrudGenerator\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "M Awais",
"email": "asargodha@gmail.com"
}
],
"description": "Laravel CRUD Generator",
"keywords": [
"alpine js",
"bootstrap css",
"crud",
"crud generator",
"laravel",
"laravel crud generator",
"laravel package",
"tailwind css"
],
"support": {
"issues": "https://github.com/awais-vteams/laravel-crud-generator/issues",
"source": "https://github.com/awais-vteams/laravel-crud-generator/tree/v2.1.2"
},
"funding": [
{
"url": "https://github.com/awais-vteams",
"type": "github"
},
{
"url": "https://ko-fi.com/mawais",
"type": "ko_fi"
}
],
"time": "2024-12-09T06:01:54+00:00"
},
{
"name": "laravel/pail",
"version": "v1.2.2",
@@ -6854,16 +7515,16 @@
},
{
"name": "myclabs/deep-copy",
"version": "1.12.1",
"version": "1.13.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "123267b2c49fbf30d78a7b2d333f6be754b94845"
"reference": "024473a478be9df5fdaca2c793f2232fe788e414"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845",
"reference": "123267b2c49fbf30d78a7b2d333f6be754b94845",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
"reference": "024473a478be9df5fdaca2c793f2232fe788e414",
"shasum": ""
},
"require": {
@@ -6902,7 +7563,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.12.1"
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
},
"funding": [
{
@@ -6910,7 +7571,7 @@
"type": "tidelift"
}
],
"time": "2024-11-08T17:47:46+00:00"
"time": "2025-02-12T12:17:51+00:00"
},
{
"name": "nunomaduro/collision",
@@ -7453,16 +8114,16 @@
},
{
"name": "phpunit/phpunit",
"version": "11.5.6",
"version": "11.5.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3c3ae14c90f244cdda95028c3e469028e8d1c02c"
"reference": "e1cb706f019e2547039ca2c839898cd5f557ee5d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3c3ae14c90f244cdda95028c3e469028e8d1c02c",
"reference": "3c3ae14c90f244cdda95028c3e469028e8d1c02c",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e1cb706f019e2547039ca2c839898cd5f557ee5d",
"reference": "e1cb706f019e2547039ca2c839898cd5f557ee5d",
"shasum": ""
},
"require": {
@@ -7534,7 +8195,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.6"
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.7"
},
"funding": [
{
@@ -7550,7 +8211,7 @@
"type": "tidelift"
}
],
"time": "2025-01-31T07:03:30+00:00"
"time": "2025-02-06T16:10:05+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -8655,12 +9316,12 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"stability-flags": [],
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
"php": "^8.2"
},
"platform-dev": {},
"platform-dev": [],
"plugin-api-version": "2.6.0"
}
+81
View File
@@ -0,0 +1,81 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Stubs Path
|--------------------------------------------------------------------------
|
| The stubs path directory to generate crud. You may configure your
| stubs paths here, allowing you to customize the own stubs of the
| model,controller or view. Or, you may simply stick with the CrudGenerator defaults!
|
| Example: 'stub_path' => resource_path('stubs/')
| Default: "default"
| Files:
| Controller.stub
| Model.stub
| Request.stub
| views/
| bootstrap/
| create.stub
| edit.stub
| form.stub
| form-field.stub
| index.stub
| show.stub
| view-field.stub
*/
'stub_path' => 'default',
/*
|--------------------------------------------------------------------------
| Application Layout
|--------------------------------------------------------------------------
|
| This value is the name of your application layout. This value is used when creating
| views for crud. Default will be the "layouts.app".
|
| layout = false or layout = null will not create the layout files.
*/
'layout' => 'layouts.app',
'model' => [
'namespace' => 'App\Models',
/*
* Do not make these columns $fillable in Model or views
*/
'unwantedColumns' => [
'id',
'uuid',
'ulid',
'password',
'email_verified_at',
'remember_token',
'created_at',
'updated_at',
'deleted_at',
],
],
'controller' => [
'namespace' => 'App\Http\Controllers',
'apiNamespace' => 'App\Http\Controllers\Api',
],
'resources' => [
'namespace' => 'App\Http\Resources',
],
'livewire' => [
'namespace' => 'App\Livewire',
],
'request' => [
'namespace' => 'App\Http\Requests',
],
];
+380
View File
@@ -0,0 +1,380 @@
<?php
use Maatwebsite\Excel\Excel;
use PhpOffice\PhpSpreadsheet\Reader\Csv;
return [
'exports' => [
/*
|--------------------------------------------------------------------------
| Chunk size
|--------------------------------------------------------------------------
|
| When using FromQuery, the query is automatically chunked.
| Here you can specify how big the chunk should be.
|
*/
'chunk_size' => 1000,
/*
|--------------------------------------------------------------------------
| Pre-calculate formulas during export
|--------------------------------------------------------------------------
*/
'pre_calculate_formulas' => false,
/*
|--------------------------------------------------------------------------
| Enable strict null comparison
|--------------------------------------------------------------------------
|
| When enabling strict null comparison empty cells ('') will
| be added to the sheet.
*/
'strict_null_comparison' => false,
/*
|--------------------------------------------------------------------------
| CSV Settings
|--------------------------------------------------------------------------
|
| Configure e.g. delimiter, enclosure and line ending for CSV exports.
|
*/
'csv' => [
'delimiter' => ',',
'enclosure' => '"',
'line_ending' => PHP_EOL,
'use_bom' => false,
'include_separator_line' => false,
'excel_compatibility' => false,
'output_encoding' => '',
'test_auto_detect' => true,
],
/*
|--------------------------------------------------------------------------
| Worksheet properties
|--------------------------------------------------------------------------
|
| Configure e.g. default title, creator, subject,...
|
*/
'properties' => [
'creator' => '',
'lastModifiedBy' => '',
'title' => '',
'description' => '',
'subject' => '',
'keywords' => '',
'category' => '',
'manager' => '',
'company' => '',
],
],
'imports' => [
/*
|--------------------------------------------------------------------------
| Read Only
|--------------------------------------------------------------------------
|
| When dealing with imports, you might only be interested in the
| data that the sheet exists. By default we ignore all styles,
| however if you want to do some logic based on style data
| you can enable it by setting read_only to false.
|
*/
'read_only' => true,
/*
|--------------------------------------------------------------------------
| Ignore Empty
|--------------------------------------------------------------------------
|
| When dealing with imports, you might be interested in ignoring
| rows that have null values or empty strings. By default rows
| containing empty strings or empty values are not ignored but can be
| ignored by enabling the setting ignore_empty to true.
|
*/
'ignore_empty' => false,
/*
|--------------------------------------------------------------------------
| Heading Row Formatter
|--------------------------------------------------------------------------
|
| Configure the heading row formatter.
| Available options: none|slug|custom
|
*/
'heading_row' => [
'formatter' => 'slug',
],
/*
|--------------------------------------------------------------------------
| CSV Settings
|--------------------------------------------------------------------------
|
| Configure e.g. delimiter, enclosure and line ending for CSV imports.
|
*/
'csv' => [
'delimiter' => null,
'enclosure' => '"',
'escape_character' => '\\',
'contiguous' => false,
'input_encoding' => Csv::GUESS_ENCODING,
],
/*
|--------------------------------------------------------------------------
| Worksheet properties
|--------------------------------------------------------------------------
|
| Configure e.g. default title, creator, subject,...
|
*/
'properties' => [
'creator' => '',
'lastModifiedBy' => '',
'title' => '',
'description' => '',
'subject' => '',
'keywords' => '',
'category' => '',
'manager' => '',
'company' => '',
],
/*
|--------------------------------------------------------------------------
| Cell Middleware
|--------------------------------------------------------------------------
|
| Configure middleware that is executed on getting a cell value
|
*/
'cells' => [
'middleware' => [
//\Maatwebsite\Excel\Middleware\TrimCellValue::class,
//\Maatwebsite\Excel\Middleware\ConvertEmptyCellValuesToNull::class,
],
],
],
/*
|--------------------------------------------------------------------------
| Extension detector
|--------------------------------------------------------------------------
|
| Configure here which writer/reader type should be used when the package
| needs to guess the correct type based on the extension alone.
|
*/
'extension_detector' => [
'xlsx' => Excel::XLSX,
'xlsm' => Excel::XLSX,
'xltx' => Excel::XLSX,
'xltm' => Excel::XLSX,
'xls' => Excel::XLS,
'xlt' => Excel::XLS,
'ods' => Excel::ODS,
'ots' => Excel::ODS,
'slk' => Excel::SLK,
'xml' => Excel::XML,
'gnumeric' => Excel::GNUMERIC,
'htm' => Excel::HTML,
'html' => Excel::HTML,
'csv' => Excel::CSV,
'tsv' => Excel::TSV,
/*
|--------------------------------------------------------------------------
| PDF Extension
|--------------------------------------------------------------------------
|
| Configure here which Pdf driver should be used by default.
| Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF
|
*/
'pdf' => Excel::DOMPDF,
],
/*
|--------------------------------------------------------------------------
| Value Binder
|--------------------------------------------------------------------------
|
| PhpSpreadsheet offers a way to hook into the process of a value being
| written to a cell. In there some assumptions are made on how the
| value should be formatted. If you want to change those defaults,
| you can implement your own default value binder.
|
| Possible value binders:
|
| [x] Maatwebsite\Excel\DefaultValueBinder::class
| [x] PhpOffice\PhpSpreadsheet\Cell\StringValueBinder::class
| [x] PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder::class
|
*/
'value_binder' => [
'default' => Maatwebsite\Excel\DefaultValueBinder::class,
],
'cache' => [
/*
|--------------------------------------------------------------------------
| Default cell caching driver
|--------------------------------------------------------------------------
|
| By default PhpSpreadsheet keeps all cell values in memory, however when
| dealing with large files, this might result into memory issues. If you
| want to mitigate that, you can configure a cell caching driver here.
| When using the illuminate driver, it will store each value in the
| cache store. This can slow down the process, because it needs to
| store each value. You can use the "batch" store if you want to
| only persist to the store when the memory limit is reached.
|
| Drivers: memory|illuminate|batch
|
*/
'driver' => 'memory',
/*
|--------------------------------------------------------------------------
| Batch memory caching
|--------------------------------------------------------------------------
|
| When dealing with the "batch" caching driver, it will only
| persist to the store when the memory limit is reached.
| Here you can tweak the memory limit to your liking.
|
*/
'batch' => [
'memory_limit' => 60000,
],
/*
|--------------------------------------------------------------------------
| Illuminate cache
|--------------------------------------------------------------------------
|
| When using the "illuminate" caching driver, it will automatically use
| your default cache store. However if you prefer to have the cell
| cache on a separate store, you can configure the store name here.
| You can use any store defined in your cache config. When leaving
| at "null" it will use the default store.
|
*/
'illuminate' => [
'store' => null,
],
/*
|--------------------------------------------------------------------------
| Cache Time-to-live (TTL)
|--------------------------------------------------------------------------
|
| The TTL of items written to cache. If you want to keep the items cached
| indefinitely, set this to null. Otherwise, set a number of seconds,
| a \DateInterval, or a callable.
|
| Allowable types: callable|\DateInterval|int|null
|
*/
'default_ttl' => 10800,
],
/*
|--------------------------------------------------------------------------
| Transaction Handler
|--------------------------------------------------------------------------
|
| By default the import is wrapped in a transaction. This is useful
| for when an import may fail and you want to retry it. With the
| transactions, the previous import gets rolled-back.
|
| You can disable the transaction handler by setting this to null.
| Or you can choose a custom made transaction handler here.
|
| Supported handlers: null|db
|
*/
'transactions' => [
'handler' => 'db',
'db' => [
'connection' => null,
],
],
'temporary_files' => [
/*
|--------------------------------------------------------------------------
| Local Temporary Path
|--------------------------------------------------------------------------
|
| When exporting and importing files, we use a temporary file, before
| storing reading or downloading. Here you can customize that path.
| permissions is an array with the permission flags for the directory (dir)
| and the create file (file).
|
*/
'local_path' => storage_path('framework/cache/laravel-excel'),
/*
|--------------------------------------------------------------------------
| Local Temporary Path Permissions
|--------------------------------------------------------------------------
|
| Permissions is an array with the permission flags for the directory (dir)
| and the create file (file).
| If omitted the default permissions of the filesystem will be used.
|
*/
'local_permissions' => [
// 'dir' => 0755,
// 'file' => 0644,
],
/*
|--------------------------------------------------------------------------
| Remote Temporary Disk
|--------------------------------------------------------------------------
|
| When dealing with a multi server setup with queues in which you
| cannot rely on having a shared local temporary path, you might
| want to store the temporary file on a shared disk. During the
| queue executing, we'll retrieve the temporary file from that
| location instead. When left to null, it will always use
| the local path. This setting only has effect when using
| in conjunction with queued imports and exports.
|
*/
'remote_disk' => null,
'remote_prefix' => null,
/*
|--------------------------------------------------------------------------
| Force Resync
|--------------------------------------------------------------------------
|
| When dealing with a multi server setup as above, it's possible
| for the clean up that occurs after entire queue has been run to only
| cleanup the server that the last AfterImportJob runs on. The rest of the server
| would still have the local temporary file stored on it. In this case your
| local storage limits can be exceeded and future imports won't be processed.
| To mitigate this you can set this config value to be true, so that after every
| queued chunk is processed the local temporary file is deleted on the server that
| processed it.
|
*/
'force_resync_remote' => null,
],
];
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('provincies', function (Blueprint $table) {
$table->id();
$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
$table->integer('province_code');
$table->string('province_name');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('provincies');
}
};
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('regencies', function (Blueprint $table) {
$table->id();
$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
$table->integer('province_code');
$table->integer('regency_code');
$table->string('regency_name');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('regencies');
}
};
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('districts', function (Blueprint $table) {
$table->id();
$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
$table->integer('regency_code');
$table->integer('district_code');
$table->string('district_name');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('districts');
}
};
@@ -0,0 +1,43 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('advertisements', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->integer('no');
$table->string('business_name');
$table->string('npwpd');
$table->string('advertisement_type');
$table->string('advertisement_content');
$table->string('business_address');
$table->string('advertisement_location');
$table->integer('village_code');
$table->integer('district_code');
$table->float('length');
$table->float('width');
$table->string('viewing_angle');
$table->string('face');
$table->string('area');
$table->string('angle');
$table->string('contact');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('advertisements');
}
};
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('villages', function (Blueprint $table) {
$table->id();
$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
$table->integer('district_code');
$table->string('village_code');
$table->string('village_name');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('villages');
}
};
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
//
Schema::table('advertisements', function (Blueprint $table) {
// Mengubah tipe data kolom 'village_code' menjadi BIGINT
$table->string('village_code')->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
Schema::table('advertisements', function (Blueprint $table) {
// Mengubah kembali tipe data kolom 'village_code' ke tipe sebelumnya (misalnya INT)
$table->integer('village_code')->change();
});
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->text('description')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('roles');
}
};
@@ -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('menus', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('url');
$table->string('icon')->nullable();
$table->unsignedBigInteger('parent_id')->nullable();
$table->integer('sort_order')->default(0);
$table->foreign('parent_id')->references('id')->on('menus')->onDelete('set null');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('menus');
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('user_role', function (Blueprint $table) {
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('role_id')->constrained()->onDelete('cascade');
$table->primary(['user_id', 'role_id']);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('user_role');
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('role_menu', function (Blueprint $table) {
$table->foreignId('role_id')->constrained()->cascadeOnDelete();
$table->foreignId('menu_id')->constrained()->cascadeOnDelete();
$table->primary(['role_id', 'menu_id']);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('role_menu');
}
};
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('role_menu', function (Blueprint $table) {
$table->boolean('allow_show')->default(true)->after('menu_id');
$table->boolean('allow_create')->default(true)->after('allow_show');
$table->boolean('allow_update')->default(true)->after('allow_create');
$table->boolean('allow_destroy')->default(true)->after('allow_update');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('role_menu', function (Blueprint $table) {
$table->dropColumn(['allow_show','allow_create', 'allow_update', 'allow_destroy']);
});
}
};
@@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('bigdata_resumes', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('import_datasource_id');
$table->integer('potention_count')->default(0);
$table->decimal('potention_sum', 20, 2)->default(0);
$table->integer('non_verified_count')->default(0);
$table->decimal('non_verified_sum', 20, 2)->default(0);
$table->integer('verified_count')->default(0);
$table->decimal('verified_sum', 20, 2)->default(0);
$table->integer('business_count')->default(0);
$table->decimal('business_sum', 20, 2)->default(0);
$table->integer('non_business_count')->default(0);
$table->decimal('non_business_sum', 20, 2)->default(0);
$table->timestamps();
$table->foreign('import_datasource_id')->references('id')->on('import_datasources')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('bigdata_resumes');
}
};
File diff suppressed because it is too large Load Diff
+56
View File
@@ -0,0 +1,56 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class ProvinceSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
DB::table('provincies')->insert([
['province_code' => 11, 'province_name' => 'ACEH'],
['province_code' => 12, 'province_name' => 'SUMATERA UTARA'],
['province_code' => 13, 'province_name' => 'SUMATERA BARAT'],
['province_code' => 14, 'province_name' => 'RIAU'],
['province_code' => 15, 'province_name' => 'JAMBI'],
['province_code' => 16, 'province_name' => 'SUMATERA SELATAN'],
['province_code' => 17, 'province_name' => 'BENGKULU'],
['province_code' => 18, 'province_name' => 'LAMPUNG'],
['province_code' => 19, 'province_name' => 'KEPULAUAN BANGKA BELITUNG'],
['province_code' => 21, 'province_name' => 'KEPULAUAN RIAU'],
['province_code' => 31, 'province_name' => 'DKI JAKARTA'],
['province_code' => 32, 'province_name' => 'JAWA BARAT'],
['province_code' => 33, 'province_name' => 'JAWA TENGAH'],
['province_code' => 34, 'province_name' => 'DAERAH ISTIMEWA YOGYAKARTA'],
['province_code' => 35, 'province_name' => 'JAWA TIMUR'],
['province_code' => 36, 'province_name' => 'BANTEN'],
['province_code' => 51, 'province_name' => 'BALI'],
['province_code' => 52, 'province_name' => 'NUSA TENGGARA BARAT'],
['province_code' => 53, 'province_name' => 'NUSA TENGGARA TIMUR'],
['province_code' => 61, 'province_name' => 'KALIMANTAN BARAT'],
['province_code' => 62, 'province_name' => 'KALIMANTAN TENGAH'],
['province_code' => 63, 'province_name' => 'KALIMANTAN SELATAN'],
['province_code' => 64, 'province_name' => 'KALIMANTAN TIMUR'],
['province_code' => 65, 'province_name' => 'KALIMANTAN UTARA'],
['province_code' => 71, 'province_name' => 'SULAWESI UTARA'],
['province_code' => 72, 'province_name' => 'SULAWESI TENGAH'],
['province_code' => 73, 'province_name' => 'SULAWESI SELATAN'],
['province_code' => 74, 'province_name' => 'SULAWESI TENGGARA'],
['province_code' => 75, 'province_name' => 'GORONTALO'],
['province_code' => 76, 'province_name' => 'SULAWESI BARAT'],
['province_code' => 81, 'province_name' => 'MALUKU'],
['province_code' => 82, 'province_name' => 'MALUKU UTARA'],
['province_code' => 91, 'province_name' => 'PAPUA'],
['province_code' => 92, 'province_name' => 'PAPUA BARAT'],
['province_code' => 93, 'province_name' => 'PAPUA SELATAN'],
['province_code' => 94, 'province_name' => 'PAPUA TENGAH'],
['province_code' => 95, 'province_name' => 'PAPUA PEGUNUNGAN'],
]);
}
}
+533
View File
@@ -0,0 +1,533 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class RegenciesSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
DB::table('regencies')->insert([
['regency_code' => '1101', 'province_code' => '11', 'regency_name' => 'KAB. ACEH SELATAN'],
['regency_code' => '1102', 'province_code' => '11', 'regency_name' => 'KAB. ACEH TENGGARA'],
['regency_code' => '1103', 'province_code' => '11', 'regency_name' => 'KAB. ACEH TIMUR'],
['regency_code' => '1104', 'province_code' => '11', 'regency_name' => 'KAB. ACEH TENGAH'],
['regency_code' => '1105', 'province_code' => '11', 'regency_name' => 'KAB. ACEH BARAT'],
['regency_code' => '1106', 'province_code' => '11', 'regency_name' => 'KAB. ACEH BESAR'],
['regency_code' => '1107', 'province_code' => '11', 'regency_name' => 'KAB. PIDIE'],
['regency_code' => '1108', 'province_code' => '11', 'regency_name' => 'KAB. ACEH UTARA'],
['regency_code' => '1109', 'province_code' => '11', 'regency_name' => 'KAB. SIMEULUE'],
['regency_code' => '1110', 'province_code' => '11', 'regency_name' => 'KAB. ACEH SINGKIL'],
['regency_code' => '1111', 'province_code' => '11', 'regency_name' => 'KAB. BIREUEN'],
['regency_code' => '1112', 'province_code' => '11', 'regency_name' => 'KAB. ACEH BARAT DAYA'],
['regency_code' => '1113', 'province_code' => '11', 'regency_name' => 'KAB. GAYO LUES'],
['regency_code' => '1114', 'province_code' => '11', 'regency_name' => 'KAB. ACEH JAYA'],
['regency_code' => '1115', 'province_code' => '11', 'regency_name' => 'KAB. NAGAN RAYA'],
['regency_code' => '1116', 'province_code' => '11', 'regency_name' => 'KAB. ACEH TAMIANG'],
['regency_code' => '1117', 'province_code' => '11', 'regency_name' => 'KAB. BENER MERIAH'],
['regency_code' => '1118', 'province_code' => '11', 'regency_name' => 'KAB. PIDIE JAYA'],
['regency_code' => '1171', 'province_code' => '11', 'regency_name' => 'KOTA BANDA ACEH'],
['regency_code' => '1172', 'province_code' => '11', 'regency_name' => 'KOTA SABANG'],
['regency_code' => '1173', 'province_code' => '11', 'regency_name' => 'KOTA LHOKSEUMAWE'],
['regency_code' => '1174', 'province_code' => '11', 'regency_name' => 'KOTA LANGSA'],
['regency_code' => '1175', 'province_code' => '11', 'regency_name' => 'KOTA SUBULUSSALAM'],
['regency_code' => '1201', 'province_code' => '12', 'regency_name' => 'KAB. TAPANULI TENGAH'],
['regency_code' => '1202', 'province_code' => '12', 'regency_name' => 'KAB. TAPANULI UTARA'],
['regency_code' => '1203', 'province_code' => '12', 'regency_name' => 'KAB. TAPANULI SELATAN'],
['regency_code' => '1204', 'province_code' => '12', 'regency_name' => 'KAB. NIAS'],
['regency_code' => '1205', 'province_code' => '12', 'regency_name' => 'KAB. LANGKAT'],
['regency_code' => '1206', 'province_code' => '12', 'regency_name' => 'KAB. KARO'],
['regency_code' => '1207', 'province_code' => '12', 'regency_name' => 'KAB. DELI SERDANG'],
['regency_code' => '1208', 'province_code' => '12', 'regency_name' => 'KAB. SIMALUNGUN'],
['regency_code' => '1209', 'province_code' => '12', 'regency_name' => 'KAB. ASAHAN'],
['regency_code' => '1210', 'province_code' => '12', 'regency_name' => 'KAB. LABUHANBATU'],
['regency_code' => '1211', 'province_code' => '12', 'regency_name' => 'KAB. DAIRI'],
['regency_code' => '1212', 'province_code' => '12', 'regency_name' => 'KAB. TOBA'],
['regency_code' => '1213', 'province_code' => '12', 'regency_name' => 'KAB. MANDAILING NATAL'],
['regency_code' => '1214', 'province_code' => '12', 'regency_name' => 'KAB. NIAS SELATAN'],
['regency_code' => '1215', 'province_code' => '12', 'regency_name' => 'KAB. PAKPAK BHARAT'],
['regency_code' => '1216', 'province_code' => '12', 'regency_name' => 'KAB. HUMBANG HASUNDUTAN'],
['regency_code' => '1217', 'province_code' => '12', 'regency_name' => 'KAB. SAMOSIR'],
['regency_code' => '1218', 'province_code' => '12', 'regency_name' => 'KAB. SERDANG BEDAGAI'],
['regency_code' => '1219', 'province_code' => '12', 'regency_name' => 'KAB. BATU BARA'],
['regency_code' => '1220', 'province_code' => '12', 'regency_name' => 'KAB. PADANG LAWAS UTARA'],
['regency_code' => '1221', 'province_code' => '12', 'regency_name' => 'KAB. PADANG LAWAS'],
['regency_code' => '1222', 'province_code' => '12', 'regency_name' => 'KAB. LABUHANBATU SELATAN'],
['regency_code' => '1223', 'province_code' => '12', 'regency_name' => 'KAB. LABUHANBATU UTARA'],
['regency_code' => '1224', 'province_code' => '12', 'regency_name' => 'KAB. NIAS UTARA'],
['regency_code' => '1225', 'province_code' => '12', 'regency_name' => 'KAB. NIAS BARAT'],
['regency_code' => '1271', 'province_code' => '12', 'regency_name' => 'KOTA MEDAN'],
['regency_code' => '1272', 'province_code' => '12', 'regency_name' => 'KOTA PEMATANGSIANTAR'],
['regency_code' => '1273', 'province_code' => '12', 'regency_name' => 'KOTA SIBOLGA'],
['regency_code' => '1274', 'province_code' => '12', 'regency_name' => 'KOTA TANJUNG BALAI'],
['regency_code' => '1275', 'province_code' => '12', 'regency_name' => 'KOTA BINJAI'],
['regency_code' => '1276', 'province_code' => '12', 'regency_name' => 'KOTA TEBING TINGGI'],
['regency_code' => '1277', 'province_code' => '12', 'regency_name' => 'KOTA PADANGSIDIMPUAN'],
['regency_code' => '1278', 'province_code' => '12', 'regency_name' => 'KOTA GUNUNGSITOLI'],
['regency_code' => '1301', 'province_code' => '13', 'regency_name' => 'KAB. PESISIR SELATAN'],
['regency_code' => '1302', 'province_code' => '13', 'regency_name' => 'KAB. SOLOK'],
['regency_code' => '1303', 'province_code' => '13', 'regency_name' => 'KAB. SIJUNJUNG'],
['regency_code' => '1304', 'province_code' => '13', 'regency_name' => 'KAB. TANAH DATAR'],
['regency_code' => '1305', 'province_code' => '13', 'regency_name' => 'KAB. PADANG PARIAMAN'],
['regency_code' => '1306', 'province_code' => '13', 'regency_name' => 'KAB. AGAM'],
['regency_code' => '1307', 'province_code' => '13', 'regency_name' => 'KAB. LIMA PULUH KOTA'],
['regency_code' => '1308', 'province_code' => '13', 'regency_name' => 'KAB. PASAMAN'],
['regency_code' => '1309', 'province_code' => '13', 'regency_name' => 'KAB. KEPULAUAN MENTAWAI'],
['regency_code' => '1310', 'province_code' => '13', 'regency_name' => 'KAB. DHARMASRAYA'],
['regency_code' => '1311', 'province_code' => '13', 'regency_name' => 'KAB. SOLOK SELATAN'],
['regency_code' => '1312', 'province_code' => '13', 'regency_name' => 'KAB. PASAMAN BARAT'],
['regency_code' => '1371', 'province_code' => '13', 'regency_name' => 'KOTA PADANG'],
['regency_code' => '1372', 'province_code' => '13', 'regency_name' => 'KOTA SOLOK'],
['regency_code' => '1373', 'province_code' => '13', 'regency_name' => 'KOTA SAWAHLUNTO'],
['regency_code' => '1374', 'province_code' => '13', 'regency_name' => 'KOTA PADANG PANJANG'],
['regency_code' => '1375', 'province_code' => '13', 'regency_name' => 'KOTA BUKITTINGGI'],
['regency_code' => '1376', 'province_code' => '13', 'regency_name' => 'KOTA PAYAKUMBUH'],
['regency_code' => '1377', 'province_code' => '13', 'regency_name' => 'KOTA PARIAMAN'],
['regency_code' => '1401', 'province_code' => '14', 'regency_name' => 'KAB. KAMPAR'],
['regency_code' => '1402', 'province_code' => '14', 'regency_name' => 'KAB. INDRAGIRI HULU'],
['regency_code' => '1403', 'province_code' => '14', 'regency_name' => 'KAB. BENGKALIS'],
['regency_code' => '1404', 'province_code' => '14', 'regency_name' => 'KAB. INDRAGIRI HILIR'],
['regency_code' => '1405', 'province_code' => '14', 'regency_name' => 'KAB. PELALAWAN'],
['regency_code' => '1406', 'province_code' => '14', 'regency_name' => 'KAB. ROKAN HULU'],
['regency_code' => '1407', 'province_code' => '14', 'regency_name' => 'KAB. ROKAN HILIR'],
['regency_code' => '1408', 'province_code' => '14', 'regency_name' => 'KAB. SIAK'],
['regency_code' => '1409', 'province_code' => '14', 'regency_name' => 'KAB. KUANTAN SINGINGI'],
['regency_code' => '1410', 'province_code' => '14', 'regency_name' => 'KAB. KEPULAUAN MERANTI'],
['regency_code' => '1471', 'province_code' => '14', 'regency_name' => 'KOTA PEKANBARU'],
['regency_code' => '1472', 'province_code' => '14', 'regency_name' => 'KOTA DUMAI'],
['regency_code' => '1501', 'province_code' => '15', 'regency_name' => 'KAB. KERINCI'],
['regency_code' => '1502', 'province_code' => '15', 'regency_name' => 'KAB. MERANGIN'],
['regency_code' => '1503', 'province_code' => '15', 'regency_name' => 'KAB. SAROLANGUN'],
['regency_code' => '1504', 'province_code' => '15', 'regency_name' => 'KAB. BATANGHARI'],
['regency_code' => '1505', 'province_code' => '15', 'regency_name' => 'KAB. MUARO JAMBI'],
['regency_code' => '1506', 'province_code' => '15', 'regency_name' => 'KAB. TANJUNG JABUNG BARAT'],
['regency_code' => '1507', 'province_code' => '15', 'regency_name' => 'KAB. TANJUNG JABUNG TIMUR'],
['regency_code' => '1508', 'province_code' => '15', 'regency_name' => 'KAB. BUNGO'],
['regency_code' => '1509', 'province_code' => '15', 'regency_name' => 'KAB. TEBO'],
['regency_code' => '1571', 'province_code' => '15', 'regency_name' => 'KOTA JAMBI'],
['regency_code' => '1572', 'province_code' => '15', 'regency_name' => 'KOTA SUNGAI PENUH'],
['regency_code' => '1601', 'province_code' => '16', 'regency_name' => 'KAB. OGAN KOMERING ULU'],
['regency_code' => '1602', 'province_code' => '16', 'regency_name' => 'KAB. OGAN KOMERING ILIR'],
['regency_code' => '1603', 'province_code' => '16', 'regency_name' => 'KAB. MUARA ENIM'],
['regency_code' => '1604', 'province_code' => '16', 'regency_name' => 'KAB. LAHAT'],
['regency_code' => '1605', 'province_code' => '16', 'regency_name' => 'KAB. MUSI RAWAS'],
['regency_code' => '1606', 'province_code' => '16', 'regency_name' => 'KAB. MUSI BANYUASIN'],
['regency_code' => '1607', 'province_code' => '16', 'regency_name' => 'KAB. BANYUASIN'],
['regency_code' => '1608', 'province_code' => '16', 'regency_name' => 'KAB. OGAN KOMERING ULU TIMUR'],
['regency_code' => '1609', 'province_code' => '16', 'regency_name' => 'KAB. OGAN KOMERING ULU SELATAN'],
['regency_code' => '1610', 'province_code' => '16', 'regency_name' => 'KAB. OGAN ILIR'],
['regency_code' => '1611', 'province_code' => '16', 'regency_name' => 'KAB. EMPAT LAWANG'],
['regency_code' => '1612', 'province_code' => '16', 'regency_name' => 'KAB. PENUKAL ABAB LEMATANG ILIR'],
['regency_code' => '1613', 'province_code' => '16', 'regency_name' => 'KAB. MUSI RAWAS UTARA'],
['regency_code' => '1671', 'province_code' => '16', 'regency_name' => 'KOTA PALEMBANG'],
['regency_code' => '1672', 'province_code' => '16', 'regency_name' => 'KOTA PAGAR ALAM'],
['regency_code' => '1673', 'province_code' => '16', 'regency_name' => 'KOTA LUBUK LINGGAU'],
['regency_code' => '1674', 'province_code' => '16', 'regency_name' => 'KOTA PRABUMULIH'],
['regency_code' => '1701', 'province_code' => '17', 'regency_name' => 'KAB. BENGKULU SELATAN'],
['regency_code' => '1702', 'province_code' => '17', 'regency_name' => 'KAB. REJANG LEBONG'],
['regency_code' => '1703', 'province_code' => '17', 'regency_name' => 'KAB. BENGKULU UTARA'],
['regency_code' => '1704', 'province_code' => '17', 'regency_name' => 'KAB. KAUR'],
['regency_code' => '1705', 'province_code' => '17', 'regency_name' => 'KAB. SELUMA'],
['regency_code' => '1706', 'province_code' => '17', 'regency_name' => 'KAB. MUKO MUKO'],
['regency_code' => '1707', 'province_code' => '17', 'regency_name' => 'KAB. LEBONG'],
['regency_code' => '1708', 'province_code' => '17', 'regency_name' => 'KAB. KEPAHIANG'],
['regency_code' => '1709', 'province_code' => '17', 'regency_name' => 'KAB. BENGKULU TENGAH'],
['regency_code' => '1771', 'province_code' => '17', 'regency_name' => 'KOTA BENGKULU'],
['regency_code' => '1801', 'province_code' => '18', 'regency_name' => 'KAB. LAMPUNG SELATAN'],
['regency_code' => '1802', 'province_code' => '18', 'regency_name' => 'KAB. LAMPUNG TENGAH'],
['regency_code' => '1803', 'province_code' => '18', 'regency_name' => 'KAB. LAMPUNG UTARA'],
['regency_code' => '1804', 'province_code' => '18', 'regency_name' => 'KAB. LAMPUNG BARAT'],
['regency_code' => '1805', 'province_code' => '18', 'regency_name' => 'KAB. TULANG BAWANG'],
['regency_code' => '1806', 'province_code' => '18', 'regency_name' => 'KAB. TANGGAMUS'],
['regency_code' => '1807', 'province_code' => '18', 'regency_name' => 'KAB. LAMPUNG TIMUR'],
['regency_code' => '1808', 'province_code' => '18', 'regency_name' => 'KAB. WAY KANAN'],
['regency_code' => '1809', 'province_code' => '18', 'regency_name' => 'KAB. PESAWARAN'],
['regency_code' => '1810', 'province_code' => '18', 'regency_name' => 'KAB. PRINGSEWU'],
['regency_code' => '1811', 'province_code' => '18', 'regency_name' => 'KAB. MESUJI'],
['regency_code' => '1812', 'province_code' => '18', 'regency_name' => 'KAB. TULANG BAWANG BARAT'],
['regency_code' => '1813', 'province_code' => '18', 'regency_name' => 'KAB. PESISIR BARAT'],
['regency_code' => '1871', 'province_code' => '18', 'regency_name' => 'KOTA BANDAR LAMPUNG'],
['regency_code' => '1872', 'province_code' => '18', 'regency_name' => 'KOTA METRO'],
['regency_code' => '1901', 'province_code' => '19', 'regency_name' => 'KAB. BANGKA'],
['regency_code' => '1902', 'province_code' => '19', 'regency_name' => 'KAB. BELITUNG'],
['regency_code' => '1903', 'province_code' => '19', 'regency_name' => 'KAB. BANGKA SELATAN'],
['regency_code' => '1904', 'province_code' => '19', 'regency_name' => 'KAB. BANGKA TENGAH'],
['regency_code' => '1905', 'province_code' => '19', 'regency_name' => 'KAB. BANGKA BARAT'],
['regency_code' => '1906', 'province_code' => '19', 'regency_name' => 'KAB. BELITUNG TIMUR'],
['regency_code' => '1971', 'province_code' => '19', 'regency_name' => 'KOTA PANGKAL PINANG'],
['regency_code' => '2101', 'province_code' => '21', 'regency_name' => 'KAB. BINTAN'],
['regency_code' => '2102', 'province_code' => '21', 'regency_name' => 'KAB. KARIMUN'],
['regency_code' => '2103', 'province_code' => '21', 'regency_name' => 'KAB. NATUNA'],
['regency_code' => '2104', 'province_code' => '21', 'regency_name' => 'KAB. LINGGA'],
['regency_code' => '2105', 'province_code' => '21', 'regency_name' => 'KAB. KEPULAUAN ANAMBAS'],
['regency_code' => '2171', 'province_code' => '21', 'regency_name' => 'KOTA BATAM'],
['regency_code' => '2172', 'province_code' => '21', 'regency_name' => 'KOTA TANJUNG PINANG'],
['regency_code' => '3101', 'province_code' => '31', 'regency_name' => 'KAB. ADM. KEP. SERIBU'],
['regency_code' => '3171', 'province_code' => '31', 'regency_name' => 'KOTA ADM. JAKARTA PUSAT'],
['regency_code' => '3172', 'province_code' => '31', 'regency_name' => 'KOTA ADM. JAKARTA UTARA'],
['regency_code' => '3173', 'province_code' => '31', 'regency_name' => 'KOTA ADM. JAKARTA BARAT'],
['regency_code' => '3174', 'province_code' => '31', 'regency_name' => 'KOTA ADM. JAKARTA SELATAN'],
['regency_code' => '3175', 'province_code' => '31', 'regency_name' => 'KOTA ADM. JAKARTA TIMUR'],
['regency_code' => '3201', 'province_code' => '32', 'regency_name' => 'KAB. BOGOR'],
['regency_code' => '3202', 'province_code' => '32', 'regency_name' => 'KAB. SUKABUMI'],
['regency_code' => '3203', 'province_code' => '32', 'regency_name' => 'KAB. CIANJUR'],
['regency_code' => '3204', 'province_code' => '32', 'regency_name' => 'KAB. BANDUNG'],
['regency_code' => '3205', 'province_code' => '32', 'regency_name' => 'KAB. GARUT'],
['regency_code' => '3206', 'province_code' => '32', 'regency_name' => 'KAB. TASIKMALAYA'],
['regency_code' => '3207', 'province_code' => '32', 'regency_name' => 'KAB. CIAMIS'],
['regency_code' => '3208', 'province_code' => '32', 'regency_name' => 'KAB. KUNINGAN'],
['regency_code' => '3209', 'province_code' => '32', 'regency_name' => 'KAB. CIREBON'],
['regency_code' => '3210', 'province_code' => '32', 'regency_name' => 'KAB. MAJALENGKA'],
['regency_code' => '3211', 'province_code' => '32', 'regency_name' => 'KAB. SUMEDANG'],
['regency_code' => '3212', 'province_code' => '32', 'regency_name' => 'KAB. INDRAMAYU'],
['regency_code' => '3213', 'province_code' => '32', 'regency_name' => 'KAB. SUBANG'],
['regency_code' => '3214', 'province_code' => '32', 'regency_name' => 'KAB. PURWAKARTA'],
['regency_code' => '3215', 'province_code' => '32', 'regency_name' => 'KAB. KARAWANG'],
['regency_code' => '3216', 'province_code' => '32', 'regency_name' => 'KAB. BEKASI'],
['regency_code' => '3217', 'province_code' => '32', 'regency_name' => 'KAB. BANDUNG BARAT'],
['regency_code' => '3218', 'province_code' => '32', 'regency_name' => 'KAB. PANGANDARAN'],
['regency_code' => '3271', 'province_code' => '32', 'regency_name' => 'KOTA BOGOR'],
['regency_code' => '3272', 'province_code' => '32', 'regency_name' => 'KOTA SUKABUMI'],
['regency_code' => '3273', 'province_code' => '32', 'regency_name' => 'KOTA BANDUNG'],
['regency_code' => '3274', 'province_code' => '32', 'regency_name' => 'KOTA CIREBON'],
['regency_code' => '3275', 'province_code' => '32', 'regency_name' => 'KOTA BEKASI'],
['regency_code' => '3276', 'province_code' => '32', 'regency_name' => 'KOTA DEPOK'],
['regency_code' => '3277', 'province_code' => '32', 'regency_name' => 'KOTA CIMAHI'],
['regency_code' => '3278', 'province_code' => '32', 'regency_name' => 'KOTA TASIKMALAYA'],
['regency_code' => '3279', 'province_code' => '32', 'regency_name' => 'KOTA BANJAR'],
['regency_code' => '3301', 'province_code' => '33', 'regency_name' => 'KAB. CILACAP'],
['regency_code' => '3302', 'province_code' => '33', 'regency_name' => 'KAB. BANYUMAS'],
['regency_code' => '3303', 'province_code' => '33', 'regency_name' => 'KAB. PURBALINGGA'],
['regency_code' => '3304', 'province_code' => '33', 'regency_name' => 'KAB. BANJARNEGARA'],
['regency_code' => '3305', 'province_code' => '33', 'regency_name' => 'KAB. KEBUMEN'],
['regency_code' => '3306', 'province_code' => '33', 'regency_name' => 'KAB. PURWOREJO'],
['regency_code' => '3307', 'province_code' => '33', 'regency_name' => 'KAB. WONOSOBO'],
['regency_code' => '3308', 'province_code' => '33', 'regency_name' => 'KAB. MAGELANG'],
['regency_code' => '3309', 'province_code' => '33', 'regency_name' => 'KAB. BOYOLALI'],
['regency_code' => '3310', 'province_code' => '33', 'regency_name' => 'KAB. KLATEN'],
['regency_code' => '3311', 'province_code' => '33', 'regency_name' => 'KAB. SUKOHARJO'],
['regency_code' => '3312', 'province_code' => '33', 'regency_name' => 'KAB. WONOGIRI'],
['regency_code' => '3313', 'province_code' => '33', 'regency_name' => 'KAB. KARANGANYAR'],
['regency_code' => '3314', 'province_code' => '33', 'regency_name' => 'KAB. SRAGEN'],
['regency_code' => '3315', 'province_code' => '33', 'regency_name' => 'KAB. GROBOGAN'],
['regency_code' => '3316', 'province_code' => '33', 'regency_name' => 'KAB. BLORA'],
['regency_code' => '3317', 'province_code' => '33', 'regency_name' => 'KAB. REMBANG'],
['regency_code' => '3318', 'province_code' => '33', 'regency_name' => 'KAB. PATI'],
['regency_code' => '3319', 'province_code' => '33', 'regency_name' => 'KAB. KUDUS'],
['regency_code' => '3320', 'province_code' => '33', 'regency_name' => 'KAB. JEPARA'],
['regency_code' => '3321', 'province_code' => '33', 'regency_name' => 'KAB. DEMAK'],
['regency_code' => '3322', 'province_code' => '33', 'regency_name' => 'KAB. SEMARANG'],
['regency_code' => '3323', 'province_code' => '33', 'regency_name' => 'KAB. TEMANGGUNG'],
['regency_code' => '3324', 'province_code' => '33', 'regency_name' => 'KAB. KENDAL'],
['regency_code' => '3325', 'province_code' => '33', 'regency_name' => 'KAB. BATANG'],
['regency_code' => '3326', 'province_code' => '33', 'regency_name' => 'KAB. PEKALONGAN'],
['regency_code' => '3327', 'province_code' => '33', 'regency_name' => 'KAB. PEMALANG'],
['regency_code' => '3328', 'province_code' => '33', 'regency_name' => 'KAB. TEGAL'],
['regency_code' => '3329', 'province_code' => '33', 'regency_name' => 'KAB. BREBES'],
['regency_code' => '3371', 'province_code' => '33', 'regency_name' => 'KOTA MAGELANG'],
['regency_code' => '3372', 'province_code' => '33', 'regency_name' => 'KOTA SURAKARTA'],
['regency_code' => '3373', 'province_code' => '33', 'regency_name' => 'KOTA SALATIGA'],
['regency_code' => '3374', 'province_code' => '33', 'regency_name' => 'KOTA SEMARANG'],
['regency_code' => '3375', 'province_code' => '33', 'regency_name' => 'KOTA PEKALONGAN'],
['regency_code' => '3376', 'province_code' => '33', 'regency_name' => 'KOTA TEGAL'],
['regency_code' => '3401', 'province_code' => '34', 'regency_name' => 'KAB. KULON PROGO'],
['regency_code' => '3402', 'province_code' => '34', 'regency_name' => 'KAB. BANTUL'],
['regency_code' => '3403', 'province_code' => '34', 'regency_name' => 'KAB. GUNUNGKIDUL'],
['regency_code' => '3404', 'province_code' => '34', 'regency_name' => 'KAB. SLEMAN'],
['regency_code' => '3471', 'province_code' => '34', 'regency_name' => 'KOTA YOGYAKARTA'],
['regency_code' => '3501', 'province_code' => '35', 'regency_name' => 'KAB. PACITAN'],
['regency_code' => '3502', 'province_code' => '35', 'regency_name' => 'KAB. PONOROGO'],
['regency_code' => '3503', 'province_code' => '35', 'regency_name' => 'KAB. TRENGGALEK'],
['regency_code' => '3504', 'province_code' => '35', 'regency_name' => 'KAB. TULUNGAGUNG'],
['regency_code' => '3505', 'province_code' => '35', 'regency_name' => 'KAB. BLITAR'],
['regency_code' => '3506', 'province_code' => '35', 'regency_name' => 'KAB. KEDIRI'],
['regency_code' => '3507', 'province_code' => '35', 'regency_name' => 'KAB. MALANG'],
['regency_code' => '3508', 'province_code' => '35', 'regency_name' => 'KAB. LUMAJANG'],
['regency_code' => '3509', 'province_code' => '35', 'regency_name' => 'KAB. JEMBER'],
['regency_code' => '3510', 'province_code' => '35', 'regency_name' => 'KAB. BANYUWANGI'],
['regency_code' => '3511', 'province_code' => '35', 'regency_name' => 'KAB. BONDOWOSO'],
['regency_code' => '3512', 'province_code' => '35', 'regency_name' => 'KAB. SITUBONDO'],
['regency_code' => '3513', 'province_code' => '35', 'regency_name' => 'KAB. PROBOLINGGO'],
['regency_code' => '3514', 'province_code' => '35', 'regency_name' => 'KAB. PASURUAN'],
['regency_code' => '3515', 'province_code' => '35', 'regency_name' => 'KAB. SIDOARJO'],
['regency_code' => '3516', 'province_code' => '35', 'regency_name' => 'KAB. MOJOKERTO'],
['regency_code' => '3517', 'province_code' => '35', 'regency_name' => 'KAB. JOMBANG'],
['regency_code' => '3518', 'province_code' => '35', 'regency_name' => 'KAB. NGANJUK'],
['regency_code' => '3519', 'province_code' => '35', 'regency_name' => 'KAB. MADIUN'],
['regency_code' => '3520', 'province_code' => '35', 'regency_name' => 'KAB. MAGETAN'],
['regency_code' => '3521', 'province_code' => '35', 'regency_name' => 'KAB. NGAWI'],
['regency_code' => '3522', 'province_code' => '35', 'regency_name' => 'KAB. BOJONEGORO'],
['regency_code' => '3523', 'province_code' => '35', 'regency_name' => 'KAB. TUBAN'],
['regency_code' => '3524', 'province_code' => '35', 'regency_name' => 'KAB. LAMONGAN'],
['regency_code' => '3525', 'province_code' => '35', 'regency_name' => 'KAB. GRESIK'],
['regency_code' => '3526', 'province_code' => '35', 'regency_name' => 'KAB. BANGKALAN'],
['regency_code' => '3527', 'province_code' => '35', 'regency_name' => 'KAB. SAMPANG'],
['regency_code' => '3528', 'province_code' => '35', 'regency_name' => 'KAB. PAMEKASAN'],
['regency_code' => '3529', 'province_code' => '35', 'regency_name' => 'KAB. SUMENEP'],
['regency_code' => '3571', 'province_code' => '35', 'regency_name' => 'KOTA KEDIRI'],
['regency_code' => '3572', 'province_code' => '35', 'regency_name' => 'KOTA BLITAR'],
['regency_code' => '3573', 'province_code' => '35', 'regency_name' => 'KOTA MALANG'],
['regency_code' => '3574', 'province_code' => '35', 'regency_name' => 'KOTA PROBOLINGGO'],
['regency_code' => '3575', 'province_code' => '35', 'regency_name' => 'KOTA PASURUAN'],
['regency_code' => '3576', 'province_code' => '35', 'regency_name' => 'KOTA MOJOKERTO'],
['regency_code' => '3577', 'province_code' => '35', 'regency_name' => 'KOTA MADIUN'],
['regency_code' => '3578', 'province_code' => '35', 'regency_name' => 'KOTA SURABAYA'],
['regency_code' => '3579', 'province_code' => '35', 'regency_name' => 'KOTA BATU'],
['regency_code' => '3601', 'province_code' => '36', 'regency_name' => 'KAB. PANDEGLANG'],
['regency_code' => '3602', 'province_code' => '36', 'regency_name' => 'KAB. LEBAK'],
['regency_code' => '3603', 'province_code' => '36', 'regency_name' => 'KAB. TANGERANG'],
['regency_code' => '3604', 'province_code' => '36', 'regency_name' => 'KAB. SERANG'],
['regency_code' => '3671', 'province_code' => '36', 'regency_name' => 'KOTA TANGERANG'],
['regency_code' => '3672', 'province_code' => '36', 'regency_name' => 'KOTA CILEGON'],
['regency_code' => '3673', 'province_code' => '36', 'regency_name' => 'KOTA SERANG'],
['regency_code' => '3674', 'province_code' => '36', 'regency_name' => 'KOTA TANGERANG SELATAN'],
['regency_code' => '5101', 'province_code' => '51', 'regency_name' => 'KAB. JEMBRANA'],
['regency_code' => '5102', 'province_code' => '51', 'regency_name' => 'KAB. TABANAN'],
['regency_code' => '5103', 'province_code' => '51', 'regency_name' => 'KAB. BADUNG'],
['regency_code' => '5104', 'province_code' => '51', 'regency_name' => 'KAB. GIANYAR'],
['regency_code' => '5105', 'province_code' => '51', 'regency_name' => 'KAB. KLUNGKUNG'],
['regency_code' => '5106', 'province_code' => '51', 'regency_name' => 'KAB. BANGLI'],
['regency_code' => '5107', 'province_code' => '51', 'regency_name' => 'KAB. KARANGASEM'],
['regency_code' => '5108', 'province_code' => '51', 'regency_name' => 'KAB. BULELENG'],
['regency_code' => '5171', 'province_code' => '51', 'regency_name' => 'KOTA DENPASAR'],
['regency_code' => '5201', 'province_code' => '52', 'regency_name' => 'KAB. LOMBOK BARAT'],
['regency_code' => '5202', 'province_code' => '52', 'regency_name' => 'KAB. LOMBOK TENGAH'],
['regency_code' => '5203', 'province_code' => '52', 'regency_name' => 'KAB. LOMBOK TIMUR'],
['regency_code' => '5204', 'province_code' => '52', 'regency_name' => 'KAB. SUMBAWA'],
['regency_code' => '5205', 'province_code' => '52', 'regency_name' => 'KAB. DOMPU'],
['regency_code' => '5206', 'province_code' => '52', 'regency_name' => 'KAB. BIMA'],
['regency_code' => '5207', 'province_code' => '52', 'regency_name' => 'KAB. SUMBAWA BARAT'],
['regency_code' => '5208', 'province_code' => '52', 'regency_name' => 'KAB. LOMBOK UTARA'],
['regency_code' => '5271', 'province_code' => '52', 'regency_name' => 'KOTA MATARAM'],
['regency_code' => '5272', 'province_code' => '52', 'regency_name' => 'KOTA BIMA'],
['regency_code' => '5301', 'province_code' => '53', 'regency_name' => 'KAB. KUPANG'],
['regency_code' => '5302', 'province_code' => '53', 'regency_name' => 'KAB TIMOR TENGAH SELATAN'],
['regency_code' => '5303', 'province_code' => '53', 'regency_name' => 'KAB. TIMOR TENGAH UTARA'],
['regency_code' => '5304', 'province_code' => '53', 'regency_name' => 'KAB. BELU'],
['regency_code' => '5305', 'province_code' => '53', 'regency_name' => 'KAB. ALOR'],
['regency_code' => '5306', 'province_code' => '53', 'regency_name' => 'KAB. FLORES TIMUR'],
['regency_code' => '5307', 'province_code' => '53', 'regency_name' => 'KAB. SIKKA'],
['regency_code' => '5308', 'province_code' => '53', 'regency_name' => 'KAB. ENDE'],
['regency_code' => '5309', 'province_code' => '53', 'regency_name' => 'KAB. NGADA'],
['regency_code' => '5310', 'province_code' => '53', 'regency_name' => 'KAB. MANGGARAI'],
['regency_code' => '5311', 'province_code' => '53', 'regency_name' => 'KAB. SUMBA TIMUR'],
['regency_code' => '5312', 'province_code' => '53', 'regency_name' => 'KAB. SUMBA BARAT'],
['regency_code' => '5313', 'province_code' => '53', 'regency_name' => 'KAB. LEMBATA'],
['regency_code' => '5314', 'province_code' => '53', 'regency_name' => 'KAB. ROTE NDAO'],
['regency_code' => '5315', 'province_code' => '53', 'regency_name' => 'KAB. MANGGARAI BARAT'],
['regency_code' => '5316', 'province_code' => '53', 'regency_name' => 'KAB. NAGEKEO'],
['regency_code' => '5317', 'province_code' => '53', 'regency_name' => 'KAB. SUMBA TENGAH'],
['regency_code' => '5318', 'province_code' => '53', 'regency_name' => 'KAB. SUMBA BARAT DAYA'],
['regency_code' => '5319', 'province_code' => '53', 'regency_name' => 'KAB. MANGGARAI TIMUR'],
['regency_code' => '5320', 'province_code' => '53', 'regency_name' => 'KAB. SABU RAIJUA'],
['regency_code' => '5321', 'province_code' => '53', 'regency_name' => 'KAB. MALAKA'],
['regency_code' => '5371', 'province_code' => '53', 'regency_name' => 'KOTA KUPANG'],
['regency_code' => '6101', 'province_code' => '61', 'regency_name' => 'KAB. SAMBAS'],
['regency_code' => '6102', 'province_code' => '61', 'regency_name' => 'KAB. MEMPAWAH'],
['regency_code' => '6103', 'province_code' => '61', 'regency_name' => 'KAB. SANGGAU'],
['regency_code' => '6104', 'province_code' => '61', 'regency_name' => 'KAB. KETAPANG'],
['regency_code' => '6105', 'province_code' => '61', 'regency_name' => 'KAB. SINTANG'],
['regency_code' => '6106', 'province_code' => '61', 'regency_name' => 'KAB. KAPUAS HULU'],
['regency_code' => '6107', 'province_code' => '61', 'regency_name' => 'KAB. BENGKAYANG'],
['regency_code' => '6108', 'province_code' => '61', 'regency_name' => 'KAB. LANDAK'],
['regency_code' => '6109', 'province_code' => '61', 'regency_name' => 'KAB. SEKADAU'],
['regency_code' => '6110', 'province_code' => '61', 'regency_name' => 'KAB. MELAWI'],
['regency_code' => '6111', 'province_code' => '61', 'regency_name' => 'KAB. KAYONG UTARA'],
['regency_code' => '6112', 'province_code' => '61', 'regency_name' => 'KAB. KUBU RAYA'],
['regency_code' => '6171', 'province_code' => '61', 'regency_name' => 'KOTA PONTIANAK'],
['regency_code' => '6172', 'province_code' => '61', 'regency_name' => 'KOTA SINGKAWANG'],
['regency_code' => '6201', 'province_code' => '62', 'regency_name' => 'KAB. KOTAWARINGIN BARAT'],
['regency_code' => '6202', 'province_code' => '62', 'regency_name' => 'KAB. KOTAWARINGIN TIMUR'],
['regency_code' => '6203', 'province_code' => '62', 'regency_name' => 'KAB. KAPUAS'],
['regency_code' => '6204', 'province_code' => '62', 'regency_name' => 'KAB. BARITO SELATAN'],
['regency_code' => '6205', 'province_code' => '62', 'regency_name' => 'KAB. BARITO UTARA'],
['regency_code' => '6206', 'province_code' => '62', 'regency_name' => 'KAB. KATINGAN'],
['regency_code' => '6207', 'province_code' => '62', 'regency_name' => 'KAB. SERUYAN'],
['regency_code' => '6208', 'province_code' => '62', 'regency_name' => 'KAB. SUKAMARA'],
['regency_code' => '6209', 'province_code' => '62', 'regency_name' => 'KAB. LAMANDAU'],
['regency_code' => '6210', 'province_code' => '62', 'regency_name' => 'KAB. GUNUNG MAS'],
['regency_code' => '6211', 'province_code' => '62', 'regency_name' => 'KAB. PULANG PISAU'],
['regency_code' => '6212', 'province_code' => '62', 'regency_name' => 'KAB. MURUNG RAYA'],
['regency_code' => '6213', 'province_code' => '62', 'regency_name' => 'KAB. BARITO TIMUR'],
['regency_code' => '6271', 'province_code' => '62', 'regency_name' => 'KOTA PALANGKARAYA'],
['regency_code' => '6301', 'province_code' => '63', 'regency_name' => 'KAB. TANAH LAUT'],
['regency_code' => '6302', 'province_code' => '63', 'regency_name' => 'KAB. KOTABARU'],
['regency_code' => '6303', 'province_code' => '63', 'regency_name' => 'KAB. BANJAR'],
['regency_code' => '6304', 'province_code' => '63', 'regency_name' => 'KAB. BARITO KUALA'],
['regency_code' => '6305', 'province_code' => '63', 'regency_name' => 'KAB. TAPIN'],
['regency_code' => '6306', 'province_code' => '63', 'regency_name' => 'KAB. HULU SUNGAI SELATAN'],
['regency_code' => '6307', 'province_code' => '63', 'regency_name' => 'KAB. HULU SUNGAI TENGAH'],
['regency_code' => '6308', 'province_code' => '63', 'regency_name' => 'KAB. HULU SUNGAI UTARA'],
['regency_code' => '6309', 'province_code' => '63', 'regency_name' => 'KAB. TABALONG'],
['regency_code' => '6310', 'province_code' => '63', 'regency_name' => 'KAB. TANAH BUMBU'],
['regency_code' => '6311', 'province_code' => '63', 'regency_name' => 'KAB. BALANGAN'],
['regency_code' => '6371', 'province_code' => '63', 'regency_name' => 'KOTA BANJARMASIN'],
['regency_code' => '6372', 'province_code' => '63', 'regency_name' => 'KOTA BANJARBARU'],
['regency_code' => '6401', 'province_code' => '64', 'regency_name' => 'KAB. PASER'],
['regency_code' => '6402', 'province_code' => '64', 'regency_name' => 'KAB. KUTAI KARTANEGARA'],
['regency_code' => '6403', 'province_code' => '64', 'regency_name' => 'KAB. BERAU'],
['regency_code' => '6407', 'province_code' => '64', 'regency_name' => 'KAB. KUTAI BARAT'],
['regency_code' => '6408', 'province_code' => '64', 'regency_name' => 'KAB. KUTAI TIMUR'],
['regency_code' => '6409', 'province_code' => '64', 'regency_name' => 'KAB. PENAJAM PASER UTARA'],
['regency_code' => '6411', 'province_code' => '64', 'regency_name' => 'KAB. MAHAKAM ULU'],
['regency_code' => '6471', 'province_code' => '64', 'regency_name' => 'KOTA BALIKPAPAN'],
['regency_code' => '6472', 'province_code' => '64', 'regency_name' => 'KOTA SAMARINDA'],
['regency_code' => '6474', 'province_code' => '64', 'regency_name' => 'KOTA BONTANG'],
['regency_code' => '6501', 'province_code' => '65', 'regency_name' => 'KAB. BULUNGAN'],
['regency_code' => '6502', 'province_code' => '65', 'regency_name' => 'KAB. MALINAU'],
['regency_code' => '6503', 'province_code' => '65', 'regency_name' => 'KAB. NUNUKAN'],
['regency_code' => '6504', 'province_code' => '65', 'regency_name' => 'KAB. TANA TIDUNG'],
['regency_code' => '6571', 'province_code' => '65', 'regency_name' => 'KOTA TARAKAN'],
['regency_code' => '7101', 'province_code' => '71', 'regency_name' => 'KAB. BOLAANG MONGONDOW'],
['regency_code' => '7102', 'province_code' => '71', 'regency_name' => 'KAB. MINAHASA'],
['regency_code' => '7103', 'province_code' => '71', 'regency_name' => 'KAB. KEPULAUAN SANGIHE'],
['regency_code' => '7104', 'province_code' => '71', 'regency_name' => 'KAB. KEPULAUAN TALAUD'],
['regency_code' => '7105', 'province_code' => '71', 'regency_name' => 'KAB. MINAHASA SELATAN'],
['regency_code' => '7106', 'province_code' => '71', 'regency_name' => 'KAB. MINAHASA UTARA'],
['regency_code' => '7107', 'province_code' => '71', 'regency_name' => 'KAB. MINAHASA TENGGARA'],
['regency_code' => '7108', 'province_code' => '71', 'regency_name' => 'KAB. BOLAANG MONGONDOW UTARA'],
['regency_code' => '7109', 'province_code' => '71', 'regency_name' => 'KAB. KEP. SIAU TAGULANDANG BIARO'],
['regency_code' => '7110', 'province_code' => '71', 'regency_name' => 'KAB. BOLAANG MONGONDOW TIMUR'],
['regency_code' => '7111', 'province_code' => '71', 'regency_name' => 'KAB. BOLAANG MONGONDOW SELATAN'],
['regency_code' => '7171', 'province_code' => '71', 'regency_name' => 'KOTA MANADO'],
['regency_code' => '7172', 'province_code' => '71', 'regency_name' => 'KOTA BITUNG'],
['regency_code' => '7173', 'province_code' => '71', 'regency_name' => 'KOTA TOMOHON'],
['regency_code' => '7174', 'province_code' => '71', 'regency_name' => 'KOTA KOTAMOBAGU'],
['regency_code' => '7201', 'province_code' => '72', 'regency_name' => 'KAB. BANGGAI'],
['regency_code' => '7202', 'province_code' => '72', 'regency_name' => 'KAB. POSO'],
['regency_code' => '7203', 'province_code' => '72', 'regency_name' => 'KAB. DONGGALA'],
['regency_code' => '7204', 'province_code' => '72', 'regency_name' => 'KAB. TOLI TOLI'],
['regency_code' => '7205', 'province_code' => '72', 'regency_name' => 'KAB. BUOL'],
['regency_code' => '7206', 'province_code' => '72', 'regency_name' => 'KAB. MOROWALI'],
['regency_code' => '7207', 'province_code' => '72', 'regency_name' => 'KAB. BANGGAI KEPULAUAN'],
['regency_code' => '7208', 'province_code' => '72', 'regency_name' => 'KAB. PARIGI MOUTONG'],
['regency_code' => '7209', 'province_code' => '72', 'regency_name' => 'KAB. TOJO UNA UNA'],
['regency_code' => '7210', 'province_code' => '72', 'regency_name' => 'KAB. SIGI'],
['regency_code' => '7211', 'province_code' => '72', 'regency_name' => 'KAB. BANGGAI LAUT'],
['regency_code' => '7212', 'province_code' => '72', 'regency_name' => 'KAB. MOROWALI UTARA'],
['regency_code' => '7271', 'province_code' => '72', 'regency_name' => 'KOTA PALU'],
['regency_code' => '7301', 'province_code' => '73', 'regency_name' => 'KAB. KEPULAUAN SELAYAR'],
['regency_code' => '7302', 'province_code' => '73', 'regency_name' => 'KAB. BULUKUMBA'],
['regency_code' => '7303', 'province_code' => '73', 'regency_name' => 'KAB. BANTAENG'],
['regency_code' => '7304', 'province_code' => '73', 'regency_name' => 'KAB. JENEPONTO'],
['regency_code' => '7305', 'province_code' => '73', 'regency_name' => 'KAB. TAKALAR'],
['regency_code' => '7306', 'province_code' => '73', 'regency_name' => 'KAB. GOWA'],
['regency_code' => '7307', 'province_code' => '73', 'regency_name' => 'KAB. SINJAI'],
['regency_code' => '7308', 'province_code' => '73', 'regency_name' => 'KAB. BONE'],
['regency_code' => '7309', 'province_code' => '73', 'regency_name' => 'KAB. MAROS'],
['regency_code' => '7310', 'province_code' => '73', 'regency_name' => 'KAB. PANGKAJENE KEPULAUAN'],
['regency_code' => '7311', 'province_code' => '73', 'regency_name' => 'KAB. BARRU'],
['regency_code' => '7312', 'province_code' => '73', 'regency_name' => 'KAB. SOPPENG'],
['regency_code' => '7313', 'province_code' => '73', 'regency_name' => 'KAB. WAJO'],
['regency_code' => '7314', 'province_code' => '73', 'regency_name' => 'KAB. SIDENRENG RAPPANG'],
['regency_code' => '7315', 'province_code' => '73', 'regency_name' => 'KAB. PINRANG'],
['regency_code' => '7316', 'province_code' => '73', 'regency_name' => 'KAB. ENREKANG'],
['regency_code' => '7317', 'province_code' => '73', 'regency_name' => 'KAB. LUWU'],
['regency_code' => '7318', 'province_code' => '73', 'regency_name' => 'KAB. TANA TORAJA'],
['regency_code' => '7322', 'province_code' => '73', 'regency_name' => 'KAB. LUWU UTARA'],
['regency_code' => '7324', 'province_code' => '73', 'regency_name' => 'KAB. LUWU TIMUR'],
['regency_code' => '7326', 'province_code' => '73', 'regency_name' => 'KAB. TORAJA UTARA'],
['regency_code' => '7371', 'province_code' => '73', 'regency_name' => 'KOTA MAKASSAR'],
['regency_code' => '7372', 'province_code' => '73', 'regency_name' => 'KOTA PARE PARE'],
['regency_code' => '7373', 'province_code' => '73', 'regency_name' => 'KOTA PALOPO'],
['regency_code' => '7401', 'province_code' => '74', 'regency_name' => 'KAB. KOLAKA'],
['regency_code' => '7402', 'province_code' => '74', 'regency_name' => 'KAB. KONAWE'],
['regency_code' => '7403', 'province_code' => '74', 'regency_name' => 'KAB. MUNA'],
['regency_code' => '7404', 'province_code' => '74', 'regency_name' => 'KAB. BUTON'],
['regency_code' => '7405', 'province_code' => '74', 'regency_name' => 'KAB. KONAWE SELATAN'],
['regency_code' => '7406', 'province_code' => '74', 'regency_name' => 'KAB. BOMBANA'],
['regency_code' => '7407', 'province_code' => '74', 'regency_name' => 'KAB. WAKATOBI'],
['regency_code' => '7408', 'province_code' => '74', 'regency_name' => 'KAB. KOLAKA UTARA'],
['regency_code' => '7409', 'province_code' => '74', 'regency_name' => 'KAB. KONAWE UTARA'],
['regency_code' => '7410', 'province_code' => '74', 'regency_name' => 'KAB. BUTON UTARA'],
['regency_code' => '7411', 'province_code' => '74', 'regency_name' => 'KAB. KOLAKA TIMUR'],
['regency_code' => '7412', 'province_code' => '74', 'regency_name' => 'KAB. KONAWE KEPULAUAN'],
['regency_code' => '7413', 'province_code' => '74', 'regency_name' => 'KAB. MUNA BARAT'],
['regency_code' => '7414', 'province_code' => '74', 'regency_name' => 'KAB. BUTON TENGAH'],
['regency_code' => '7415', 'province_code' => '74', 'regency_name' => 'KAB. BUTON SELATAN'],
['regency_code' => '7471', 'province_code' => '74', 'regency_name' => 'KOTA KENDARI'],
['regency_code' => '7472', 'province_code' => '74', 'regency_name' => 'KOTA BAU BAU'],
['regency_code' => '7501', 'province_code' => '75', 'regency_name' => 'KAB. GORONTALO'],
['regency_code' => '7502', 'province_code' => '75', 'regency_name' => 'KAB. BOALEMO'],
['regency_code' => '7503', 'province_code' => '75', 'regency_name' => 'KAB. BONE BOLANGO'],
['regency_code' => '7504', 'province_code' => '75', 'regency_name' => 'KAB. POHUWATO'],
['regency_code' => '7505', 'province_code' => '75', 'regency_name' => 'KAB. GORONTALO UTARA'],
['regency_code' => '7571', 'province_code' => '75', 'regency_name' => 'KOTA GORONTALO'],
['regency_code' => '7601', 'province_code' => '76', 'regency_name' => 'KAB. PASANGKAYU'],
['regency_code' => '7602', 'province_code' => '76', 'regency_name' => 'KAB. MAMUJU'],
['regency_code' => '7603', 'province_code' => '76', 'regency_name' => 'KAB. MAMASA'],
['regency_code' => '7604', 'province_code' => '76', 'regency_name' => 'KAB. POLEWALI MANDAR'],
['regency_code' => '7605', 'province_code' => '76', 'regency_name' => 'KAB. MAJENE'],
['regency_code' => '7606', 'province_code' => '76', 'regency_name' => 'KAB. MAMUJU TENGAH'],
['regency_code' => '8101', 'province_code' => '81', 'regency_name' => 'KAB. MALUKU TENGAH'],
['regency_code' => '8102', 'province_code' => '81', 'regency_name' => 'KAB. MALUKU TENGGARA'],
['regency_code' => '8103', 'province_code' => '81', 'regency_name' => 'KAB. KEPULAUAN TANIMBAR'],
['regency_code' => '8104', 'province_code' => '81', 'regency_name' => 'KAB. BURU'],
['regency_code' => '8105', 'province_code' => '81', 'regency_name' => 'KAB. SERAM BAGIAN TIMUR'],
['regency_code' => '8106', 'province_code' => '81', 'regency_name' => 'KAB. SERAM BAGIAN BARAT'],
['regency_code' => '8107', 'province_code' => '81', 'regency_name' => 'KAB. KEPULAUAN ARU'],
['regency_code' => '8108', 'province_code' => '81', 'regency_name' => 'KAB. MALUKU BARAT DAYA'],
['regency_code' => '8109', 'province_code' => '81', 'regency_name' => 'KAB. BURU SELATAN'],
['regency_code' => '8171', 'province_code' => '81', 'regency_name' => 'KOTA AMBON'],
['regency_code' => '8172', 'province_code' => '81', 'regency_name' => 'KOTA TUAL'],
['regency_code' => '8201', 'province_code' => '82', 'regency_name' => 'KAB. HALMAHERA BARAT'],
['regency_code' => '8202', 'province_code' => '82', 'regency_name' => 'KAB. HALMAHERA TENGAH'],
['regency_code' => '8203', 'province_code' => '82', 'regency_name' => 'KAB. HALMAHERA UTARA'],
['regency_code' => '8204', 'province_code' => '82', 'regency_name' => 'KAB. HALMAHERA SELATAN'],
['regency_code' => '8205', 'province_code' => '82', 'regency_name' => 'KAB. KEPULAUAN SULA'],
['regency_code' => '8206', 'province_code' => '82', 'regency_name' => 'KAB. HALMAHERA TIMUR'],
['regency_code' => '8207', 'province_code' => '82', 'regency_name' => 'KAB. PULAU MOROTAI'],
['regency_code' => '8208', 'province_code' => '82', 'regency_name' => 'KAB. PULAU TALIABU'],
['regency_code' => '8271', 'province_code' => '82', 'regency_name' => 'KOTA TERNATE'],
['regency_code' => '8272', 'province_code' => '82', 'regency_name' => 'KOTA TIDORE KEPULAUAN'],
['regency_code' => '9103', 'province_code' => '91', 'regency_name' => 'KAB. JAYAPURA'],
['regency_code' => '9105', 'province_code' => '91', 'regency_name' => 'KAB. KEPULAUAN YAPEN'],
['regency_code' => '9106', 'province_code' => '91', 'regency_name' => 'KAB. BIAK NUMFOR'],
['regency_code' => '9110', 'province_code' => '91', 'regency_name' => 'KAB. SARMI'],
['regency_code' => '9111', 'province_code' => '91', 'regency_name' => 'KAB. KEEROM'],
['regency_code' => '9115', 'province_code' => '91', 'regency_name' => 'KAB. WAROPEN'],
['regency_code' => '9119', 'province_code' => '91', 'regency_name' => 'KAB. SUPIORI'],
['regency_code' => '9120', 'province_code' => '91', 'regency_name' => 'KAB. MAMBERAMO RAYA'],
['regency_code' => '9171', 'province_code' => '91', 'regency_name' => 'KOTA JAYAPURA'],
['regency_code' => '9201', 'province_code' => '92', 'regency_name' => 'KAB. SORONG'],
['regency_code' => '9202', 'province_code' => '92', 'regency_name' => 'KAB. MANOKWARI'],
['regency_code' => '9203', 'province_code' => '92', 'regency_name' => 'KAB. FAK FAK'],
['regency_code' => '9204', 'province_code' => '92', 'regency_name' => 'KAB. SORONG SELATAN'],
['regency_code' => '9205', 'province_code' => '92', 'regency_name' => 'KAB. RAJA AMPAT'],
['regency_code' => '9206', 'province_code' => '92', 'regency_name' => 'KAB. TELUK BINTUNI'],
['regency_code' => '9207', 'province_code' => '92', 'regency_name' => 'KAB. TELUK WONDAMA'],
['regency_code' => '9208', 'province_code' => '92', 'regency_name' => 'KAB. KAIMANA'],
['regency_code' => '9209', 'province_code' => '92', 'regency_name' => 'KAB. TAMBRAUW'],
['regency_code' => '9210', 'province_code' => '92', 'regency_name' => 'KAB. MAYBRAT'],
['regency_code' => '9211', 'province_code' => '92', 'regency_name' => 'KAB. MANOKWARI SELATAN'],
['regency_code' => '9212', 'province_code' => '92', 'regency_name' => 'KAB. PEGUNUNGAN ARFAK'],
['regency_code' => '9271', 'province_code' => '92', 'regency_name' => 'KOTA SORONG'],
['regency_code' => '9301', 'province_code' => '93', 'regency_name' => 'KAB. MERAUKE'],
['regency_code' => '9302', 'province_code' => '93', 'regency_name' => 'KAB. BOVEN DIGOEL'],
['regency_code' => '9303', 'province_code' => '93', 'regency_name' => 'KAB. MAPPI'],
['regency_code' => '9304', 'province_code' => '93', 'regency_name' => 'KAB. ASMAT'],
['regency_code' => '9401', 'province_code' => '94', 'regency_name' => 'KAB. NABIRE'],
['regency_code' => '9402', 'province_code' => '94', 'regency_name' => 'KAB. PUNCAK JAYA'],
['regency_code' => '9403', 'province_code' => '94', 'regency_name' => 'KAB. PANIAI'],
['regency_code' => '9404', 'province_code' => '94', 'regency_name' => 'KAB. MIMIKA'],
['regency_code' => '9405', 'province_code' => '94', 'regency_name' => 'KAB. PUNCAK'],
['regency_code' => '9406', 'province_code' => '94', 'regency_name' => 'KAB. DOGIYAI'],
['regency_code' => '9407', 'province_code' => '94', 'regency_name' => 'KAB. INTAN JAYA'],
['regency_code' => '9408', 'province_code' => '94', 'regency_name' => 'KAB. DEIYAI'],
['regency_code' => '9501', 'province_code' => '95', 'regency_name' => 'KAB. JAYAWIJAYA'],
['regency_code' => '9502', 'province_code' => '95', 'regency_name' => 'KAB. PEGUNUNGAN BINTANG'],
['regency_code' => '9503', 'province_code' => '95', 'regency_name' => 'KAB. YAHUKIMO'],
['regency_code' => '9504', 'province_code' => '95', 'regency_name' => 'KAB. TOLIKARA'],
['regency_code' => '9505', 'province_code' => '95', 'regency_name' => 'KAB. MAMBERAMO TENGAH'],
['regency_code' => '9506', 'province_code' => '95', 'regency_name' => 'KAB. YALIMO'],
['regency_code' => '9507', 'province_code' => '95', 'regency_name' => 'KAB. LANNY JAYA'],
['regency_code' => '9508', 'province_code' => '95', 'regency_name' => 'KAB. NDUGA'],
]);
}
}
+204
View File
@@ -0,0 +1,204 @@
<?php
namespace Database\Seeders;
use App\Models\Menu;
use App\Models\Role;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class UsersRoleMenuSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$roles = [
[
"name" => "superadmin",
"description" => "show all menus for super admins",
],
[
"name" => "admin",
"description" => "show only necessary menus for admins",
],
[
"name" => "operator",
"description" => "show only necessary menus for operators",
]
];
Role::upsert($roles, ['name']);
$parent_menus = [
[
"name" => "Dashboard",
"url" => "/dashboard",
"icon" => "mingcute:home-3-line",
"parent_id" => null,
"sort_order" => 1,
],
[
"name" => "Master",
"url" => "/master",
"icon" => "mingcute:cylinder-line",
"parent_id" => null,
"sort_order" => 2,
],
[
"name" => "Settings",
"url" => "/settings",
"icon" => "mingcute:settings-6-line",
"parent_id" => null,
"sort_order" => 3,
],
[
"name" => "Data Settings",
"url" => "/data-settings",
"icon" => "mingcute:settings-1-line",
"parent_id" => null,
"sort_order" => 4,
],
[
"name" => "Data",
"url" => "/data",
"icon" => "mingcute:task-line",
"parent_id" => null,
"sort_order" => 5,
]
];
foreach ($parent_menus as $parent_menu) {
Menu::firstOrCreate(['name' => $parent_menu['name']], $parent_menu);
}
// Attach Menus to Roles
$superadmin = Role::where('name', 'superadmin')->first();
$admin = Role::where('name', 'admin')->first();
$operator = Role::where('name', 'operator')->first();
$dashboard = Menu::where('name', 'Dashboard')->first();
$master = Menu::where('name', 'Master')->first();
$settings = Menu::where('name', 'Settings')->first();
$dataSettings = Menu::where('name', 'Data Settings')->first();
$data = Menu::where('name', 'Data')->first();
// create children menu
$children_menus = [
[
"name" => "Dashboard Pimpinan",
"url" => "dashboard.home",
"icon" => null,
"parent_id" => $dashboard->id,
"sort_order" => 1,
],
[
"name" => "Dashboard PBG",
"url" => "dashboard.pbg",
"icon" => null,
"parent_id" => $dashboard->id,
"sort_order" => 2,
],
[
"name" => "Users",
"url" => "users.index",
"icon" => null,
"parent_id" => $master->id,
"sort_order" => 1,
],
[
"name" => "Syncronize",
"url" => "settings.syncronize",
"icon" => null,
"parent_id" => $settings->id,
"sort_order" => 1,
],
[
"name" => "Menu",
"url" => "menus.index",
"icon" => null,
"parent_id" => $settings->id,
"sort_order" => 2,
],
[
"name" => "Role",
"url" => "roles.index",
"icon" => null,
"parent_id" => $settings->id,
"sort_order" => 3,
],
[
"name" => "Setting Dashboard",
"url" => "data-settings.index",
"icon" => null,
"parent_id" => $dataSettings->id,
"sort_order" => 1,
],
[
"name" => "PBG",
"url" => "pbg-task.index",
"icon" => null,
"parent_id" => $data->id,
"sort_order" => 1,
],
[
"name" => "Reklame",
"url" => "advertisements.index",
"icon" => null,
"parent_id" => $data->id,
"sort_order" => 1,
],
];
foreach ($children_menus as $child_menu) {
Menu::firstOrCreate(['name' => $child_menu['name']], $child_menu);
}
$dashboard_pimpinan = Menu::where('name', 'Dashboard Pimpinan')->first();
$dashboard_pbg = Menu::where('name', 'Dashboard PBG')->first();
$users = Menu::where('name', 'Users')->first();
$syncronize = Menu::where('name', 'Syncronize')->first();
$setting_menu = Menu::where('name', 'Menu')->first();
$setting_role = Menu::where('name', 'Role')->first();
$setting_dashboard = Menu::where('name', 'Setting Dashboard')->first();
$setting_pbg = Menu::where('name', 'PBG')->first();
$reklame = Menu::where('name', 'Reklame')->first();
// Superadmin gets all menus
$superadmin->menus()->sync([
// parent
$dashboard->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
$master->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
$settings->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
$dataSettings->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
$data->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
// children
$dashboard_pimpinan->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$dashboard_pbg->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$users->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$syncronize->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$setting_menu->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$setting_role->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$setting_dashboard->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$setting_pbg->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$reklame->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
]);
// Admin gets limited menus
$admin->menus()->sync([
$dashboard->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$master->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$settings->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
]);
// Operator gets only basic menus with full permissions
$operator->menus()->sync([
$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],
]);
// Attach User to role super admin
User::findOrFail(1)->roles()->sync([$superadmin->id]);
}
}
+132 -8
View File
@@ -10,6 +10,10 @@
"__commonjsHelpers-C4iS2aBk.js"
]
},
"_dropzone-B5tMhgFp.js": {
"file": "assets/dropzone-B5tMhgFp.js",
"name": "dropzone"
},
"_global-config-9uDKFQ8j.js": {
"file": "assets/global-config-9uDKFQ8j.js",
"name": "global-config"
@@ -58,6 +62,10 @@
"src": "node_modules/quill/dist/quill.snow.css",
"isEntry": true
},
"public/images/bg-dashboard.jpg": {
"file": "assets/bg-dashboard-CUwt8_jP.jpg",
"src": "public/images/bg-dashboard.jpg"
},
"resources/fonts/boxicons.eot": {
"file": "assets/boxicons-0t2gX1vj.eot",
"src": "resources/fonts/boxicons.eot"
@@ -94,16 +102,25 @@
"isEntry": true
},
"resources/js/dashboards/bigdata.js": {
"file": "assets/bigdata-C1y9KS-u.js",
"file": "assets/bigdata-DYDUaCEC.js",
"name": "bigdata",
"src": "resources/js/dashboards/bigdata.js",
"isEntry": true,
"imports": [
"_global-config-9uDKFQ8j.js"
],
"css": [
"assets/flatpickr-CksuuEqD.css"
]
},
"resources/js/data-settings/create.js": {
"file": "assets/create-C1IbeTHP.js",
"name": "create",
"src": "resources/js/data-settings/create.js",
"isEntry": true
},
"resources/js/data-settings/index.js": {
"file": "assets/index-CzuDcG6g.js",
"file": "assets/index-BOfsbw53.js",
"name": "index",
"src": "resources/js/data-settings/index.js",
"isEntry": true,
@@ -113,8 +130,55 @@
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/data-settings/update.js": {
"file": "assets/update-nNw3P4hj.js",
"name": "update",
"src": "resources/js/data-settings/update.js",
"isEntry": true
},
"resources/js/data/advertisements/data-advertisements.js": {
"file": "assets/data-advertisements-C_ZfB4RA.js",
"name": "data-advertisements",
"src": "resources/js/data/advertisements/data-advertisements.js",
"isEntry": true,
"imports": [
"_gridjs.umd-BiCNXlqL.js",
"_global-config-9uDKFQ8j.js",
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/data/advertisements/form-create-update.js": {
"file": "assets/form-create-update-CyN97GsU.js",
"name": "form-create-update",
"src": "resources/js/data/advertisements/form-create-update.js",
"isEntry": true,
"imports": [
"_global-config-9uDKFQ8j.js"
]
},
"resources/js/data/advertisements/form-upload.js": {
"file": "assets/form-upload-Ci7Kyzc7.js",
"name": "form-upload",
"src": "resources/js/data/advertisements/form-upload.js",
"isEntry": true,
"imports": [
"_dropzone-B5tMhgFp.js"
]
},
"resources/js/master/users/create.js": {
"file": "assets/create-RO4xgm-f.js",
"name": "create",
"src": "resources/js/master/users/create.js",
"isEntry": true
},
"resources/js/master/users/update.js": {
"file": "assets/update-DhoG4v8r.js",
"name": "update",
"src": "resources/js/master/users/update.js",
"isEntry": true
},
"resources/js/master/users/users.js": {
"file": "assets/users-BoDXPe3W.js",
"file": "assets/users-jfWUOWyP.js",
"name": "users",
"src": "resources/js/master/users/users.js",
"isEntry": true,
@@ -124,6 +188,29 @@
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/menus/create.js": {
"file": "assets/create-ChUgh-yc.js",
"name": "create",
"src": "resources/js/menus/create.js",
"isEntry": true
},
"resources/js/menus/index.js": {
"file": "assets/index-C4xA1kYa.js",
"name": "index",
"src": "resources/js/menus/index.js",
"isEntry": true,
"imports": [
"_gridjs.umd-BiCNXlqL.js",
"_global-config-9uDKFQ8j.js",
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/menus/update.js": {
"file": "assets/update-8JQOGES4.js",
"name": "update",
"src": "resources/js/menus/update.js",
"isEntry": true
},
"resources/js/pages/chart.js": {
"file": "assets/chart-DQBoD9wk.js",
"name": "chart",
@@ -146,10 +233,13 @@
]
},
"resources/js/pages/form-fileupload.js": {
"file": "assets/form-fileupload-mrxZaoHv.js",
"file": "assets/form-fileupload-DGbdX8GT.js",
"name": "form-fileupload",
"src": "resources/js/pages/form-fileupload.js",
"isEntry": true
"isEntry": true,
"imports": [
"_dropzone-B5tMhgFp.js"
]
},
"resources/js/pages/form-flatepicker.js": {
"file": "assets/form-flatepicker-ChSlk6xC.js",
@@ -223,7 +313,7 @@
]
},
"resources/js/pbg-task/index.js": {
"file": "assets/index-BW29TEbh.js",
"file": "assets/index-CqcfkvSL.js",
"name": "index",
"src": "resources/js/pbg-task/index.js",
"isEntry": true,
@@ -233,6 +323,35 @@
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/roles/create.js": {
"file": "assets/create-Dd-lHOwF.js",
"name": "create",
"src": "resources/js/roles/create.js",
"isEntry": true
},
"resources/js/roles/index.js": {
"file": "assets/index-C_kI_q7O.js",
"name": "index",
"src": "resources/js/roles/index.js",
"isEntry": true,
"imports": [
"_gridjs.umd-BiCNXlqL.js",
"_global-config-9uDKFQ8j.js",
"__commonjsHelpers-C4iS2aBk.js"
]
},
"resources/js/roles/role_menu.js": {
"file": "assets/role_menu-BuFAi1wM.js",
"name": "role_menu",
"src": "resources/js/roles/role_menu.js",
"isEntry": true
},
"resources/js/roles/update.js": {
"file": "assets/update-CapXnAP8.js",
"name": "update",
"src": "resources/js/roles/update.js",
"isEntry": true
},
"resources/js/settings/general/general-settings.js": {
"file": "assets/general-settings-BoJeYQk1.js",
"name": "general-settings",
@@ -267,17 +386,22 @@
]
},
"resources/scss/components/_circle.scss": {
"file": "assets/_circle-ByHaR-XI.css",
"file": "assets/_circle-DgPqpfJw.css",
"src": "resources/scss/components/_circle.scss",
"isEntry": true
},
"resources/scss/dashboards/_bigdata.scss": {
"file": "assets/_bigdata-0hCjAhYp.css",
"src": "resources/scss/dashboards/_bigdata.scss",
"isEntry": true
},
"resources/scss/icons.scss": {
"file": "assets/icons-CHxf0fE3.css",
"src": "resources/scss/icons.scss",
"isEntry": true
},
"resources/scss/style.scss": {
"file": "assets/style-B2v4WMju.css",
"file": "assets/style-DUYVmgAM.css",
"src": "resources/scss/style.scss",
"isEntry": true
}
File diff suppressed because one or more lines are too long
-643
View File
File diff suppressed because one or more lines are too long
+117 -42
View File
@@ -1,16 +1,61 @@
import Big from "big.js";
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
import flatpickr from "flatpickr";
import "flatpickr/dist/flatpickr.min.css";
class BigData {
async init() {
try {
this.totalTargetPAD = await this.getTargetPAD();
this.resultDataTotal = await this.getDataTotalPotensi();
this.dataVerification = await this.getDataVerfication();
this.dataNonVerification = await this.getDataNonVerfication();
this.dataBusiness = await this.getDataBusiness();
this.dataNonBusiness = await this.getDataNonBusiness();
this.dataTataRuang = await this.getDataTataRuang();
this.filterYear = new Date().getFullYear(); // Set initial year
let yearSelect = document.querySelector("#yearPicker");
let filterButton = document.querySelector("#btnFilterYear");
if (!yearSelect || !filterButton) {
console.error(
"Element #yearPicker or #btnFilterYear not found."
);
return;
}
// Set default value for input
yearSelect.value = this.filterYear;
yearSelect.addEventListener("change", () => {
this.updateYear(yearSelect.value);
});
// Handle button click
filterButton.addEventListener("click", () => {
this.updateYear(yearSelect.value);
});
console.log("init filter this year", this.filterYear);
// Load initial data
await this.updateData(this.filterYear);
} catch (error) {
console.error("Error initializing data:", error);
}
}
updateYear(value) {
let inputYear = parseInt(value, 10);
if (!isNaN(inputYear)) {
this.filterYear = inputYear;
this.updateData(this.filterYear);
} else {
console.error("Invalid year input");
}
}
async updateData(year) {
try {
this.totalTargetPAD = await this.getTargetPAD(year);
this.resultDataTotal = await this.getDataTotalPotensi(year);
this.dataVerification = await this.getDataVerfication(year);
this.dataNonVerification = await this.getDataNonVerfication(year);
this.dataBusiness = await this.getDataBusiness(year);
this.dataNonBusiness = await this.getDataNonBusiness(year);
this.dataTataRuang = await this.getDataTataRuang(year);
// total potensi
this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0);
@@ -54,7 +99,10 @@ class BigData {
this.bigTotalNonVerification = new Big(
this.dataNonVerification.total
);
this.percentageResultNonVerification = this.bigTotalNonVerification
this.percentageResultNonVerification =
this.bigTotalNonVerification <= 0 || this.bigTotalPotensi
? 0
: this.bigTotalNonVerification
.div(this.bigTotalPotensi)
.times(100)
.toFixed(2);
@@ -82,7 +130,8 @@ class BigData {
// non-business documents
this.bigTotalNonBusiness = new Big(this.dataNonBusiness.total);
this.percentageResultNonBusiness =
this.bigTotalNonBusiness <= 0
this.bigTotalNonBusiness <= 0 ||
this.bigTotalNonVerification <= 0
? 0
: this.bigTotalNonBusiness
.div(this.bigTotalNonVerification)
@@ -110,10 +159,10 @@ class BigData {
}
}
async getDataTotalPotensi() {
async getDataTotalPotensi(year) {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/all-task-documents`,
`${GlobalConfig.apiHost}/api/all-task-documents?year=${year}`,
{
credentials: "include",
headers: {
@@ -132,7 +181,6 @@ class BigData {
const data = await response.json();
return {
seriesData: data.data.series,
countData: data.data.count,
totalData: data.data.total,
};
@@ -142,7 +190,7 @@ class BigData {
}
}
async getTargetPAD() {
async getTargetPAD(year) {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/api-data-settings?search=target_pad`,
@@ -160,20 +208,24 @@ class BigData {
if (!response.ok) {
console.error("Network response was not ok", response);
return 0;
}
const data = await response.json();
return data.data[0].value;
const valueTargetPAD = data.data[0]?.value ?? 0;
const currentMonth = new Date().getMonth() + 1;
let result = (currentMonth / 12) * valueTargetPAD;
return result;
} catch (error) {
console.error("Error fetching chart data:", error);
return 0;
}
}
async getDataVerfication() {
async getDataVerfication(year) {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/verification-documents`,
`${GlobalConfig.apiHost}/api/verification-documents?year=${year}`,
{
credentials: "include",
headers: {
@@ -201,10 +253,10 @@ class BigData {
}
}
async getDataNonVerfication() {
async getDataNonVerfication(year) {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/non-verification-documents`,
`${GlobalConfig.apiHost}/api/non-verification-documents?year=${year}`,
{
credentials: "include",
headers: {
@@ -232,10 +284,10 @@ class BigData {
}
}
async getDataBusiness() {
async getDataBusiness(year) {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/business-documents`,
`${GlobalConfig.apiHost}/api/business-documents?year=${year}`,
{
credentials: "include",
headers: {
@@ -263,10 +315,10 @@ class BigData {
}
}
async getDataNonBusiness() {
async getDataNonBusiness(year) {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/non-business-documents`,
`${GlobalConfig.apiHost}/api/non-business-documents?year=${year}`,
{
credentials: "include",
headers: {
@@ -539,32 +591,55 @@ document.addEventListener("DOMContentLoaded", async function (e) {
await new BigData().init();
});
// function resizeDashboard() {
// //Target Width
// let targetElement = document.getElementById("dashboard-fixed-wrapper");
// let targetWidth = targetElement.offsetWidth;
// //console.log("TARGET ",targetWidth);
// //Real Object Width
// let dashboardElement = document.getElementById("dashboard-fixed-container");
// let dashboardWidth = 1110; //dashboardElement.offsetWidth;
// //console.log("CURRENT ",dashboardWidth);
// if (targetWidth > dashboardWidth) {
// targetWidth = dashboardWidth;
// }
// dashboardElement.style.transformOrigin = "left top";
// dashboardElement.style.transition = "transform 0.2s ease-in-out";
// dashboardElement.style.transform =
// "scale(" + (targetWidth / dashboardWidth).toFixed(2) + ")";
// //console.log("SCALE ", (targetWidth/dashboardWidth).toFixed(2));
// }
// window.addEventListener("load", function () {
// resizeDashboard();
// });
// window.addEventListener("resize", function () {
// resizeDashboard();
// });
function resizeDashboard() {
//Target Width
let targetElement = document.getElementById("dashboard-fixed-wrapper");
let targetWidth = targetElement.offsetWidth;
//console.log("TARGET ",targetWidth);
//Real Object Width
let dashboardElement = document.getElementById("dashboard-fixed-container");
let dashboardWidth = 1110; //dashboardElement.offsetWidth;
//console.log("CURRENT ",dashboardWidth);
if (targetWidth > dashboardWidth) {
targetWidth = dashboardWidth;
}
let targetWidth = targetElement.offsetWidth;
let dashboardWidth = 1110;
let scaleFactor = (targetWidth / dashboardWidth).toFixed(2);
// Prevent scaling beyond 1 (100%) to avoid overflow
scaleFactor = Math.min(scaleFactor, 1);
dashboardElement.style.transformOrigin = "left top";
dashboardElement.style.transition = "transform 0.2s ease-in-out";
dashboardElement.style.transform =
"scale(" + (targetWidth / dashboardWidth).toFixed(2) + ")";
//console.log("SCALE ", (targetWidth/dashboardWidth).toFixed(2));
dashboardElement.style.transform = `scale(${scaleFactor})`;
// Ensure horizontal scrolling is allowed if necessary
document.body.style.overflowX = "auto";
}
window.addEventListener("load", function () {
resizeDashboard();
});
window.addEventListener("resize", function () {
resizeDashboard();
});
window.addEventListener("load", resizeDashboard);
window.addEventListener("resize", resizeDashboard);
+57
View File
@@ -0,0 +1,57 @@
document.addEventListener("DOMContentLoaded", function (e) {
const toastNotification = document.getElementById("toastNotification");
const toast = new bootstrap.Toast(toastNotification);
document
.getElementById("btnCreateDataSettings")
.addEventListener("click", async function () {
let submitButton = this;
let spinner = document.getElementById("spinner");
let form = document.getElementById("formDataSettings");
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",
credentials: "include",
headers: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
"Content-Type": "application/json",
},
body: formData,
});
if (response.ok) {
let result = await response.json();
document.getElementById("toast-message").innerText =
result.message;
toast.show();
setTimeout(() => {
window.location.href = "/data-settings";
}, 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();
}
});
});
+130 -23
View File
@@ -4,12 +4,45 @@ import "gridjs/dist/gridjs.umd.js";
import GlobalConfig from "../global-config.js";
class DataSettings {
constructor() {
this.table = null; // Store Grid.js instance
}
init() {
this.getFetchApiData();
}
getFetchApiData() {
const table = new Grid({
let tableContainer = document.getElementById("table-data-settings");
if (this.table) {
// If table exists, update its data instead of recreating
this.table
.updateConfig({
server: {
url: `${GlobalConfig.apiHost}/api/api-data-settings`,
credentials: "include",
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
then: (data) =>
data.data.map((item) => [
item.id,
item.key,
item.value,
item.created_at,
item.id,
]),
total: (data) => data.meta.total,
},
})
.forceRender();
return;
}
this.table = new Grid({
columns: [
"ID",
"Key",
@@ -19,11 +52,14 @@ class DataSettings {
name: "Actions",
width: "120px",
formatter: function (cell) {
console.log("cell data", cell);
return gridjs.html(`
<div class="d-flex justify-items-end gap-10">
<a href="/data-settings/${cell}/edit" class="btn btn-yellow me-2">Update</a>
<button class="btn btn-red btn-delete btn-delete-data-settings" data-id="${cell}">Delete</button>
<div class="d-flex justify-content-center gap-2">
<a href="/data-settings/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
<i class='bx bx-edit'></i>
</a>
<button class="btn btn-sm btn-red d-inline-flex align-items-center justify-content-centerbtn-delete-data-settings" data-id="${cell}">
<i class='bx bxs-trash' ></i>
</button>
</div>
`);
},
@@ -62,44 +98,115 @@ class DataSettings {
]),
total: (data) => data.meta.total,
},
});
table.render(document.getElementById("table-data-settings"));
}).render(tableContainer);
document.addEventListener("click", this.handleDelete);
document.addEventListener("click", this.handleDelete.bind(this));
}
handleDelete(event) {
if (event.target.classList.contains("btn-delete-data-settings")) {
event.preventDefault();
const id = event.target.getAttribute("data-id");
let modalElement = document.getElementById("modalConfirmation");
let toastMessage = document.getElementById("toast-message");
if (confirm("Are you sure you want to delete this item?")) {
fetch(`/data-settings/${id}`, {
if (!modalElement) {
console.error("Modal element not found!");
return;
}
let modal = new bootstrap.Modal(modalElement);
let btnSaveConfirmation = document.getElementById(
"btnSaveConfirmation"
);
let toastElement = document.getElementById("toastNotification");
let toast = new bootstrap.Toast(toastElement);
// Remove previous event listeners to avoid multiple bindings
btnSaveConfirmation.replaceWith(
btnSaveConfirmation.cloneNode(true)
);
btnSaveConfirmation = document.getElementById(
"btnSaveConfirmation"
);
// Set the role ID on the confirm button inside the modal
btnSaveConfirmation.setAttribute("data-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",
},
})
.then((response) => {
if (response.ok) {
alert("Item deleted successfully!");
window.location.reload();
} else {
return response.json().then((error) => {
throw new Error(
error.message || "Failed to delete item."
}
);
});
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) => {
} catch (error) {
console.error("Error deleting item:", error);
alert("Something went wrong. Please try again.");
toastMessage.innerText = "An error occurred!";
toast.show();
}
});
}
}
refreshDataSettings() {
if (this.table) {
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();
}
}
}
document.addEventListener("DOMContentLoaded", function (e) {
+53
View File
@@ -0,0 +1,53 @@
document.addEventListener("DOMContentLoaded", function (e) {
let form = document.getElementById("formUpdateDataSettings");
let submitButton = document.getElementById("btnUpdateDataSettings");
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) {
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: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
},
body: formData,
});
if (response.ok) {
let result = await response.json();
toastMessage.innerText = result.message;
toast.show();
setTimeout(() => {
window.location.href = "/data-settings";
}, 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();
}
});
});
@@ -0,0 +1,66 @@
import { Grid } from "gridjs/dist/gridjs.umd.js";
import gridjs from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js";
import GlobalConfig from "../../global-config.js";
import GeneralTable from "../../table-generator.js";
const dataAdvertisementsColumns = [
"No",
"Nama Wajib Pajak",
"NPWPD",
"Jenis Reklame",
"Isi Reklame",
"Alamat Wajib Pajak",
"Lokasi Reklame",
"Desa",
"Kecamatan",
"Kontak",
{
name: "Actions",
widht: "120px",
formatter: function(cell, row) {
const id = row.cells[10].data;
const model = "data/advertisements";
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(
"reklame-data-table",
`${GlobalConfig.apiHost}/api/advertisements`,
`${GlobalConfig.apiHost}`,
dataAdvertisementsColumns
);
table.processData = function (data) {
return data.data.map((item) => {
return [
item.no,
item.business_name,
item.npwpd,
item.advertisement_type,
item.advertisement_content,
item.business_address,
item.advertisement_location,
item.village_name,
item.district_name,
item.contact,
item.id,
];
});
};
table.init();
});
@@ -0,0 +1,185 @@
import GlobalConfig from "../../global-config";
document.addEventListener("DOMContentLoaded", function () {
const saveButton = document.querySelector(".modal-footer .btn-primary");
const modalButton = document.querySelector(".btn-modal");
const form = document.querySelector("form#create-update-form");
var authLogo = document.querySelector(".auth-logo");
if (!saveButton || !form) return;
saveButton.addEventListener("click", function () {
// Disable tombol dan tampilkan spinner
modalButton.disabled = true;
modalButton.innerHTML = `
<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>
Loading...
`;
const isEdit = saveButton.classList.contains("btn-edit");
const formData = new FormData(form)
const toast = document.getElementById('toastEditUpdate');
const toastBody = toast.querySelector('.toast-body');
const toastHeader = toast.querySelector('.toast-header small');
const data = {};
// Mengonversi FormData ke dalam JSON
formData.forEach((value, key) => {
data[key] = value;
});
// Log semua data dalam FormData
for (let pair of formData.entries()) {
console.log(pair[0] + ": " + pair[1]);
}
const url = form.getAttribute("action");
console.log("Ini adalah url dari form action", url);
const method = isEdit ? "PUT" : "POST";
fetch(url, {
method: method,
body: JSON.stringify(data),
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(data => {
console.log("Response data:", data);
if (!data.errors) {
// Remove existing icon (if any) before adding the new one
if (authLogo) {
// Hapus ikon yang sudah ada jika ada
const existingIcon = authLogo.querySelector('.bx');
if (existingIcon) {
authLogo.removeChild(existingIcon);
}
// Buat ikon baru
const icon = document.createElement('i');
icon.classList.add('bx', 'bxs-check-square');
icon.style.fontSize = '25px';
icon.style.color = 'green'; // Pastikan 'green' dalam bentuk string
// Tambahkan ikon ke dalam auth-logo
authLogo.appendChild(icon);
}
// Set success message for the toast
toastBody.textContent = isEdit ? "Data updated successfully!" : "Data created successfully!";
toast.classList.add('show'); // Show the toast
setTimeout(() => {
toast.classList.remove('show'); // Hide the toast after 3 seconds
}, 3000);
setTimeout(() => {
window.location.href = '/data/advertisements';
}, 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: " + (responseData.message || "Something went wrong");
toast.classList.add('show'); // Show the toast
// Enable button and reset its text on error
modalButton.disabled = false;
modalButton.innerHTML = isEdit ? "Update" : "Create";
setTimeout(() => {
toast.classList.remove('show'); // Hide the toast after 3 seconds
}, 3000);
}
})
.catch(error => {
console.error("Error:", error);
if (authLogo) {
// Hapus ikon yang sudah ada jika ada
const existingIcon = authLogo.querySelector('.bx');
if (existingIcon) {
authLogo.removeChild(existingIcon);
}
// Buat ikon baru
const icon = document.createElement('i');
icon.classList.add('bx', 'bxs-error-alt');
icon.style.fontSize = '25px';
icon.style.color = 'red'; // Pastikan 'green' dalam bentuk string
// Tambahkan ikon ke dalam auth-logo
authLogo.appendChild(icon);
}
// Set error message for the toast
toastBody.textContent = "An error occurred while processing your request.";
toast.classList.add('show'); // Show the toast
// Enable button and reset its text on error
modalButton.disabled = false;
modalButton.innerHTML = isEdit ? "Update" : "Create";
setTimeout(() => {
toast.classList.remove('show'); // Hide the toast after 3 seconds
}, 3000);
});
});
// Fungsi fetchOptions untuk autocomplete server-side
window.fetchOptions = function (field) {
let inputValue = document.getElementById(field).value;
console.log("Query Value:", inputValue); // Debugging log
if (inputValue.length < 2) return;
let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih
let url = `${GlobalConfig.apiHost}/api/combobox/search-options?query=${encodeURIComponent(inputValue)}&field=${field}`;
// Jika field desa, tambahkan kecamatan sebagai filter
if (field === "village_name") {
url += `&district=${encodeURIComponent(districtValue)}`;
}
fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(data => {
let dataList = document.getElementById(field + "Options");
dataList.innerHTML = "";
data.forEach(item => {
let option = document.createElement("option");
option.value = item.name;
option.dataset.code = item.code;
dataList.appendChild(option);
});
})
.catch(error => console.error("Error fetching options:", error));
};
document.querySelector('.btn-back').addEventListener('click', function() {
window.history.back();
});
});
@@ -0,0 +1,114 @@
import { Dropzone } from "dropzone";
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: "http://localhost:8000/api/advertisements/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/advertisements";
}, 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);
});
// 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();
}
+55
View File
@@ -0,0 +1,55 @@
document.addEventListener("DOMContentLoaded", function (e) {
const toastNotification = document.getElementById("toastNotification");
const toast = new bootstrap.Toast(toastNotification);
document
.getElementById("btnCreateUsers")
.addEventListener("click", async function () {
let submitButton = this;
let spinner = document.getElementById("spinner");
let form = document.getElementById("formCreateUsers");
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: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-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 = "/master/users";
}, 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();
}
});
});
+53
View File
@@ -0,0 +1,53 @@
document.addEventListener("DOMContentLoaded", function (e) {
let form = document.getElementById("formUpdateUsers");
let submitButton = document.getElementById("btnUpdateUsers");
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) {
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: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
},
body: formData,
});
if (response.ok) {
let result = await response.json();
toastMessage.innerText = result.message;
toast.show();
setTimeout(() => {
window.location.href = "/master/users";
}, 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();
}
});
});
+19 -3
View File
@@ -17,6 +17,18 @@ class UsersTable {
"Firstname",
"Lastname",
"Position",
"Roles",
{
name: "Action",
formatter: (cell) =>
gridjs.html(`
<div class="d-flex justify-content-center">
<a href="/master/users/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
<i class='bx bx-edit'></i>
</a>
</div>
`),
},
],
pagination: {
limit: 15,
@@ -42,15 +54,19 @@ class UsersTable {
.getAttribute("content")}`,
"Content-Type": "application/json",
},
then: (data) =>
data.data.map((item) => [
then: (data) => {
console.log(data.data);
return data.data.map((item) => [
item.id,
item.name,
item.email,
item.firstname,
item.lastname,
item.position,
]),
item.roles,
item.id,
]);
},
total: (data) => data.meta.total,
},
}).render(document.getElementById("table-users"));
+55
View File
@@ -0,0 +1,55 @@
document.addEventListener("DOMContentLoaded", function (e) {
const toastNotification = document.getElementById("toastNotification");
const toast = new bootstrap.Toast(toastNotification);
document
.getElementById("btnCreateMenus")
.addEventListener("click", async function () {
let submitButton = this;
let spinner = document.getElementById("spinner");
let form = document.getElementById("formCreateMenus");
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: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-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);
}
} catch (error) {
console.error("Request failed:", error);
document.getElementById("toast-message").innerText =
error.message;
toast.show();
}
});
});
+221
View File
@@ -0,0 +1,221 @@
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";
class Menus {
constructor() {
this.table = null;
}
init() {
this.initTableMenus();
}
initTableMenus() {
let tableContainer = document.getElementById("table-menus");
if (this.table) {
// If table exists, update its data instead of recreating
this.table
.updateConfig({
server: {
url: `${GlobalConfig.apiHost}/api/api-menus`,
credentials: "include",
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
then: (data) =>
data.data.map((item) => [
item.id,
item.name,
item.url,
item.icon,
item.parent_id,
item.sort_order,
item.id,
]),
total: (data) => data.total,
},
})
.forceRender();
return;
}
this.table = new Grid({
columns: [
"ID",
"Name",
"Url",
"Icon",
"ParentID",
"Sort Order",
{
name: "Action",
formatter: (cell) =>
gridjs.html(`
<div class="d-flex justify-content-center align-items-center gap-2">
<a href="/menus/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
<i class='bx bx-edit'></i>
</a>
<button data-id="${cell}" class="btn btn-red btn-sm btn-delete-menu d-inline-flex align-items-center justify-content-center">
<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/api-menus`,
credentials: "include",
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
then: (data) =>
data.data.map((item) => [
item.id,
item.name,
item.url,
item.icon,
item.parent_id,
item.sort_order,
item.id,
]),
total: (data) => data.total,
},
}).render(tableContainer);
document.addEventListener("click", this.handleDelete.bind(this));
}
handleDelete(event) {
if (event.target.classList.contains("btn-delete-menu")) {
event.preventDefault();
const id = event.target.getAttribute("data-id");
let modalElement = document.getElementById("modalConfirmation");
let toastMessage = document.getElementById("toast-message");
if (!modalElement) {
console.error("Modal element not found!");
return;
}
let modal = new bootstrap.Modal(modalElement);
let btnSaveConfirmation = document.getElementById(
"btnSaveConfirmation"
);
let toastElement = document.getElementById("toastNotification");
let toast = new bootstrap.Toast(toastElement);
// Remove previous event listeners to avoid multiple bindings
btnSaveConfirmation.replaceWith(
btnSaveConfirmation.cloneNode(true)
);
btnSaveConfirmation = document.getElementById(
"btnSaveConfirmation"
);
// Set the role ID on the confirm button inside the modal
btnSaveConfirmation.setAttribute("data-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",
credentials: "include",
headers: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
"Content-Type": "application/json",
},
});
if (response.ok) {
let result = await response.json();
toastMessage.innerText =
result.message || "Deleted successfully!";
toast.show();
// Hide modal
modal.hide();
// Refresh Grid.js table
this.refreshTableMenus();
} else {
let error = await response.json();
console.error("Delete failed:", error);
toastMessage.innerText =
error.message || "Delete failed!";
toast.show();
}
} catch (error) {
console.error("Error deleting item:", error);
toastMessage.innerText = "An error occurred!";
toast.show();
}
});
}
}
refreshTableMenus() {
if (this.table) {
this.table
.updateConfig({
server: {
url: `${GlobalConfig.apiHost}/api/api-menus`,
credentials: "include",
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
then: (data) =>
data.data.map((item) => [
item.id,
item.name,
item.url,
item.icon,
item.parent_id,
item.sort_order,
item.id,
]),
total: (data) => data.total,
},
})
.forceRender();
} else {
this.initTableMenus(); // If no table exists, reinitialize it
}
}
}
document.addEventListener("DOMContentLoaded", function (e) {
new Menus().init();
});
+53
View File
@@ -0,0 +1,53 @@
document.addEventListener("DOMContentLoaded", function (e) {
let form = document.getElementById("formUpdateMenus");
let submitButton = document.getElementById("btnUpdateMenus");
let spinner = document.getElementById("spinner");
let toastMessage = document.getElementById("toast-message");
let toast = new bootstrap.Toast(
document.getElementById("toastNotification")
);
submitButton.addEventListener("click", async function () {
let submitButton = this;
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: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
},
body: formData,
});
if (response.ok) {
let result = await response.json();
toastMessage.innerText = result.message;
toast.show();
setTimeout(() => {
window.location.href = "/menus";
}, 2000);
} else {
let error = await response.json();
toastMessage.innerText = error.message;
toast.show();
console.error("Error:", error);
}
} catch (error) {
console.error("Request failed:", error);
toastMessage.innerText = error.message;
toast.show();
}
});
});
+2 -2
View File
@@ -25,8 +25,8 @@ class PbgTasks {
name: "Action",
formatter: function (cell) {
return gridjs.html(`
<div class="d-flex justify-items-end gap-10">
<a href="/pbg-task/${cell}" class="btn btn-yellow">Detail</a
<div class="d-flex justify-content-center align-items-center gap-2">
<a href="/pbg-task/${cell}" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">Detail</a
</div>
`);
},
+55
View File
@@ -0,0 +1,55 @@
document.addEventListener("DOMContentLoaded", function (e) {
const toastNotification = document.getElementById("toastNotification");
const toast = new bootstrap.Toast(toastNotification);
document
.getElementById("btnCreateRole")
.addEventListener("click", async function () {
let submitButton = this;
let spinner = document.getElementById("spinner");
let form = document.getElementById("formCreateRole");
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: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-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);
}
} catch (error) {
console.error("Request failed:", error);
document.getElementById("toast-message").innerText =
error.message;
toast.show();
}
});
});
+215
View File
@@ -0,0 +1,215 @@
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";
class Roles {
constructor() {
this.table = null; // Store Grid.js instance
}
init() {
this.initTableRoles();
}
initTableRoles() {
let tableContainer = document.getElementById("table-roles");
// If table instance already exists, update it instead of re-creating
if (this.table) {
this.table
.updateConfig({
server: {
url: `${GlobalConfig.apiHost}/api/api-roles`,
credentials: "include",
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
then: (data) =>
data.data.map((item) => [
item.id,
item.name,
item.description,
item.id,
]),
total: (data) => data.total,
},
})
.forceRender();
return;
}
// Create a new Grid.js instance only if it doesn't exist
this.table = new gridjs.Grid({
columns: [
"ID",
"Name",
"Description",
{
name: "Action",
formatter: (cell) =>
gridjs.html(`
<div class="d-flex justify-content-center gap-2">
<a href="/roles/${cell}/edit" class="btn btn-yellow btn-sm d-inline-flex align-items-center justify-content-center">
<i class='bx bx-edit'></i>
</a>
<a href="/roles/role-menu/${cell}" class="btn btn-primary btn-sm d-inline-flex align-items-center justify-content-center">
Role Menu
</a>
<button data-id="${cell}" class="btn btn-sm btn-red btn-delete-role 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/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,
},
}).render(tableContainer);
document.addEventListener("click", this.handleDelete.bind(this));
}
handleDelete(event) {
if (event.target.classList.contains("btn-delete-role")) {
event.preventDefault();
const id = event.target.getAttribute("data-id");
let modalElement = document.getElementById("modalConfirmation");
let toastMessage = document.getElementById("toast-message");
if (!modalElement) {
console.error("Modal element not found!");
return;
}
let modal = new bootstrap.Modal(modalElement);
let btnSaveConfirmation = document.getElementById(
"btnSaveConfirmation"
);
let toastElement = document.getElementById("toastNotification");
let toast = new bootstrap.Toast(toastElement);
// Remove previous event listeners to avoid multiple bindings
btnSaveConfirmation.replaceWith(
btnSaveConfirmation.cloneNode(true)
);
btnSaveConfirmation = document.getElementById(
"btnSaveConfirmation"
);
// Set the role ID on the confirm button inside the modal
btnSaveConfirmation.setAttribute("data-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",
credentials: "include",
headers: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
"Content-Type": "application/json",
},
});
if (response.ok) {
let result = await response.json();
toastMessage.innerText =
result.message || "Deleted successfully!";
toast.show();
// Hide modal
modal.hide();
// Refresh Grid.js table
this.refreshRolesTable();
} else {
let error = await response.json();
console.error("Delete failed:", error);
toastMessage.innerText =
error.message || "Delete failed!";
toast.show();
}
} catch (error) {
console.error("Error deleting item:", error);
toastMessage.innerText = "An error occurred!";
toast.show();
}
});
}
}
refreshRolesTable() {
if (this.table) {
this.table
.updateConfig({
server: {
url: `${GlobalConfig.apiHost}/api/api-roles`,
credentials: "include",
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
then: (data) =>
data.data.map((item) => [
item.id,
item.name,
item.description,
item.id,
]),
total: (data) => data.total,
},
})
.forceRender();
} else {
this.initTableRoles(); // If the table is null, reinitialize
}
}
}
document.addEventListener("DOMContentLoaded", function (e) {
new Roles().init();
});
+36
View File
@@ -0,0 +1,36 @@
class RoleMenus {
init() {
this.initCheckboxRoles();
}
initCheckboxRoles() {
const childPermissions =
document.querySelectorAll(".child-permissions");
childPermissions.forEach((child) => {
child.addEventListener("change", function () {
const parentId = this.dataset.parentId;
const parentShow = document.querySelector(
`input[name='permissions[${parentId}][allow_show]']`
);
if (parentShow) {
// If any child permission is checked, check parent "Show"
if (
document.querySelectorAll(
`.child-permission[data-parent-id="${parentId}"]:checked`
).length > 0
) {
parentShow.checked = true;
} else {
parentShow.checked = false;
}
}
});
});
}
}
document.addEventListener("DOMContentLoaded", function (event) {
new RoleMenus().init();
});
+53
View File
@@ -0,0 +1,53 @@
document.addEventListener("DOMContentLoaded", function (e) {
let form = document.getElementById("formUpdateRole");
let submitButton = document.getElementById("btnUpdateRole");
let spinner = document.getElementById("spinner");
let toastMessage = document.getElementById("toast-message");
let toast = new bootstrap.Toast(
document.getElementById("toastNotification")
);
submitButton.addEventListener("click", async function () {
let submitButton = this;
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: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
},
body: formData,
});
if (response.ok) {
let result = await response.json();
toastMessage.innerText = result.message;
toast.show();
setTimeout(() => {
window.location.href = "/roles";
}, 2000);
} else {
let error = await response.json();
toastMessage.innerText = error.message;
toast.show();
console.error("Error:", error);
}
} catch (error) {
console.error("Request failed:", error);
toastMessage.innerText = error.message;
toast.show();
}
});
});
+132
View File
@@ -0,0 +1,132 @@
import { Grid } from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js";
class GeneralTable {
constructor(tableId, apiUrl, baseUrl, columns, options = {}) {
this.tableId = tableId;
this.apiUrl = apiUrl;
this.baseUrl = baseUrl; // Tambahkan base URL
this.columns = columns;
this.options = options;
}
init() {
const table = new Grid({
columns: this.columns,
search: this.options.search || {
server: {
url: (prev, keyword) => `${prev}?search=${keyword}`,
},
},
pagination: this.options.pagination || {
limit: 15,
server: {
url: (prev, page) =>
`${prev}${prev.includes("?") ? "&" : "?"}page=${page + 1}`,
},
},
sort: this.options.sort || true,
server: {
url: this.apiUrl,
headers: this.options.headers || {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
then: (data) => this.processData(data),
total: (data) => data.meta.total,
},
});
table.render(document.getElementById(this.tableId));
this.handleActions();
}
// Memproses data dari API
processData(data) {
return data.data.map((item) => {
return this.columns.map((column) => {
return item[column] || '';
});
});
}
handleActions() {
document.addEventListener("click", (event) => {
if (event.target && event.target.classList.contains('btn-edit')) {
this.handleEdit(event);
}
else if (event.target && event.target.classList.contains('btn-delete')) {
this.handleDelete(event);
}
else if (event.target && event.target.classList.contains('btn-create')) {
this.handleCreate(event);
} else if (event.target && event.target.classList.contains('btn-bulk-create')) {
this.handleBulkCreate(event);
}
});
}
// Fungsi untuk menangani create
handleCreate(event) {
// Menggunakan model dan ID untuk membangun URL dinamis
const model = event.target.getAttribute('data-model'); // Mengambil model dari data-model
window.location.href = `${this.baseUrl}/${model}/create`;
}
handleBulkCreate(event) {
// Menggunakan model dan ID untuk membangun URL dinamis
const model = event.target.getAttribute('data-model');
window.location.href = `${this.baseUrl}/${model}/bulk-create`;
}
// Fungsi untuk menangani edit
handleEdit(event) {
const id = event.target.getAttribute('data-id');
const model = event.target.getAttribute('data-model'); // Mengambil model dari data-model
console.log('Editing record with ID:', id);
// Menggunakan model dan ID untuk membangun URL dinamis
window.location.href = `${this.baseUrl}/${model}/${id}/edit`;
}
// Fungsi untuk menangani delete
handleDelete(event) {
const id = event.target.getAttribute('data-id');
console.log(id);
if (confirm("Are you sure you want to delete this item?")) {
this.deleteRecord(id);
}
}
async deleteRecord(id) {
try {
console.log(id);
const response = await fetch(`${this.apiUrl}/${id}`, { // Menambahkan model dalam URL
method: 'DELETE',
headers: this.options.headers || {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
// headers: {
// 'Authorization': `Bearer ${document.querySelector('meta[name="api-token"]').getAttribute("content")}`,
// 'Content-Type': 'application/json',
// },
});
if (response.status === 204) { // Jika status code 204, berarti berhasil
alert('Data deleted successfully!');
location.reload();
} else {
const data = await response.json(); // Jika ada data di response body
alert('Failed to delete data: ' + (data.message || 'Unknown error.'));
}
} catch (error) {
console.error('Error deleting data:', error);
alert('Error deleting data.');
}
}
}
export default GeneralTable;
+11 -2
View File
@@ -10,6 +10,7 @@
width: 200px; /* Ukuran lingkaran */
height: 200px;
display: flex;
text-align: center;
align-items: center;
justify-content: center;
background-color: var(--circle-color); /* Warna lingkaran utama */
@@ -17,6 +18,7 @@
border: 6px solid white; /* Border putih */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Efek bayangan */
position: absolute;
// overflow: hidden;
.circle-content {
width: 180px; /* Ukuran lingkaran dalam */
@@ -39,6 +41,12 @@
font-weight: bold;
margin: 0 5px;
line-height: 1.5;
word-wrap: break-word; /* Break words if too long */
white-space: normal; /* Allow multi-line text */
text-align: center; /* Center text inside the circle */
overflow-wrap: break-word; /* Ensures breaking in modern browsers */
display: block; /* Ensures it respects container size */
max-width: 100%; /* Prevents exceeding the circle size */
}
.circle-content .document-total {
@@ -64,8 +72,8 @@
.small-circle-container {
position: absolute;
bottom: 0;
right: 0;
bottom: -10px;
right: -10px;
width: 50px; /* Ukuran lingkaran kecil */
height: 50px;
background-color: #2d4f90; /* Warna lingkaran kecil */
@@ -75,6 +83,7 @@
align-items: center;
justify-content: center;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Efek bayangan */
z-index: 10;
.small-circle-content {
width: 45px;
+78
View File
@@ -0,0 +1,78 @@
//
// bigdata.scss
//
.square {
height: 100px;
width: 100px;
position: absolute;
z-index: -1;
}
.dia-top-left-bottom-right:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(
to top right,
transparent calc(50% - 2px),
black,
transparent calc(50% + 2px)
);
}
.dia-top-right-bottom-left:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(
to top left,
transparent calc(50% - 2px),
black,
transparent calc(50% + 2px)
);
}
#dashboard-fixed-wrapper {
background-image: url("../../../public/images/bg-dashboard.jpg");
background-size: cover;
background-position: center;
}
#dashboard-fixed-wrapper::before {
content: "";
position: absolute;
pointer-events: none; /* Prevents the overlay from blocking interaction */
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(
255,
255,
255,
0.7
); /* Black overlay with 50% opacity */
}
#dashboard-fixed-wrapper {
max-width: 100vw; /* Ensures it doesn't exceed viewport */
}
#dashboard-fixed-container {
min-width: 1110px;
max-width: unset; /* Allow it to grow if needed */
}
@media (max-width: 768px) {
#dashboard-fixed-container {
transform: scale(0.8); /* Adjust the scale as needed */
}
}
+22 -9
View File
@@ -13,11 +13,11 @@
position: relative;
transition: all 0.3s ease-in-out;
min-height: calc(100vh - $topbar-height);
padding: calc($spacer * 1) calc($spacer * 0.5) $footer-height calc($spacer * 0.5);
padding: calc($spacer * 1) calc($spacer * 0.5) $footer-height
calc($spacer * 0.5);
margin-left: $sidebar-width;
}
// Animated Star
$shooting-time: 3000ms;
@@ -33,32 +33,45 @@ $shooting-time: 3000ms;
left: 50%;
top: 50%;
height: 2px;
background: linear-gradient(-45deg, rgba(95, 145, 255, 1), rgba(0, 0, 255, 0));
background: linear-gradient(
-45deg,
rgba(95, 145, 255, 1),
rgba(0, 0, 255, 0)
);
border-radius: 999px;
filter: drop-shadow(0 0 6px rgba(105, 155, 255, 1));
animation:
tail $shooting-time ease-in-out infinite,
animation: tail $shooting-time ease-in-out infinite,
shooting $shooting-time ease-in-out infinite;
&::before {
content: '';
content: "";
position: absolute;
top: calc(50% - 1px);
right: 0;
height: 2px;
background: linear-gradient(-45deg, rgba(0, 0, 255, 0), rgba(95, 145, 255, 1), rgba(0, 0, 255, 0));
background: linear-gradient(
-45deg,
rgba(0, 0, 255, 0),
rgba(95, 145, 255, 1),
rgba(0, 0, 255, 0)
);
transform: translateX(50%) rotateZ(45deg);
border-radius: 100%;
animation: shining $shooting-time ease-in-out infinite;
}
&::after {
content: '';
content: "";
position: absolute;
top: calc(50% - 1px);
right: 0;
height: 2px;
background: linear-gradient(-45deg, rgba(0, 0, 255, 0), rgba(95, 145, 255, 1), rgba(0, 0, 255, 0));
background: linear-gradient(
-45deg,
rgba(0, 0, 255, 0),
rgba(95, 145, 255, 1),
rgba(0, 0, 255, 0)
);
transform: translateX(50%) rotateZ(45deg);
border-radius: 100%;
animation: shining $shooting-time ease-in-out infinite;
+2
View File
@@ -59,3 +59,5 @@
// Pages
@import "pages/icon-demo";
@import "pages/authentication";
@import "dashboards/bigdata";
+3 -14
View File
@@ -13,15 +13,15 @@ class="authentication-bg"
<div class="card-body p-5">
<div class="text-center">
<div class="mx-auto mb-4 text-center auth-logo">
<a href="{{ route('home') }}" class="logo-dark">
<a href="{{ route('dashboard.home') }}" class="logo-dark">
<img src="/images/dputr-kab-bandung.png" height="auto" width="100%" alt="logo dark">
</a>
<a href="{{ route('home') }}" class="logo-light">
<a href="{{ route('dashboard.home') }}" class="logo-light">
<img src="/images/dputr-kab-bandung.png" height="auto" width="100%" alt="logo light">
</a>
</div>
<h4 class="fw-bold text-dark mb-2">Welcome Back!</h3>
<h4 class="fw-bold text-dark mb-2">Welcome Back!</h4>
<p class="text-muted">Sign in to your account to continue</p>
</div>
<form method="POST" action="{{ route('login') }}" class="mt-4">
@@ -39,25 +39,14 @@ class="authentication-bg"
<input type="email" class="form-control" id="email" name="email" value="user@demo.com" placeholder="Enter your email">
</div>
<div class="mb-3">
{{-- <div class="d-flex justify-content-between align-items-center">
<label for="password" class="form-label">Password</label>
<a href="{{ route ('password.request') }}" class="text-decoration-none small text-muted">Forgot password?</a>
</div> --}}
<input type="password" class="form-control" id="password" name="password" value="password" placeholder="Enter your password">
</div>
{{-- <div class="form-check mb-3">
<input type="checkbox" class="form-check-input" id="remember-me">
<label class="form-check-label" for="remember-me">Remember me</label>
</div> --}}
<div class="d-grid">
<button class="btn btn-dark btn-lg fw-medium" type="submit">Sign In</button>
</div>
</form>
</div>
</div>
{{-- <p class="text-center mt-4 text-white text-opacity-50">Don't have an account?
<a href="{{ route ('register') }}" class="text-decoration-none text-white fw-bold">Sign Up</a>
</p> --}}
</div>
</div>
</div>
@@ -0,0 +1,16 @@
@props(['buttonText' => 'Confirm', 'confirmationMessage' => 'Are you sure?'])
<div class="modal fade" id="modalConfirmation" tabindex="-1" aria-labelledby="modalConfirmationTitle">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body">
<p class="confirmation-message">{{$confirmationMessage}}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-bs-dismiss="modal" id="btnCloseModal">Close</button>
<button type="button" class="btn btn-primary" id="btnSaveConfirmation">{{$buttonText}}</button>
</div>
</div>
</div>
</div>
@@ -0,0 +1,14 @@
<div class="toast-container position-fixed end-0 top-0 p-3">
<div id="toastNotification" class="toast align-items-center" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<div class="auth-logo me-auto">
</div>
<small class="text-muted">{{now()->format("Y-m-d H:i:s")}}</small>
<button type="button" class="btn-close" data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
<div class="toast-body">
<p id="toast-message"></p>
</div>
</div>
</div>
+22 -47
View File
@@ -1,61 +1,36 @@
@extends('layouts.vertical', ['subtitle' => 'Dashboards'])
@section('css')
@vite(['resources/scss/dashboards/_bigdata.scss'])
@endsection
@section('content')
@include('layouts.partials/page-title', ['title' => 'Dashboards', 'subtitle' => 'Dashboard Pimpinan'])
<style>
.square{
height: 100px;
width: 100px;
position: absolute;
z-index:-1;
}
.dia-top-left-bottom-right:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(to top right, transparent calc(50% - 2px), black, transparent calc(50% + 2px));
}
.dia-top-right-bottom-left:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(to top left, transparent calc(50% - 2px), black, transparent calc(50% + 2px));
}
#dashboard-fixed-wrapper {
background-image:url('/images/bg-dashboard.jpg');background-size: cover;background-position: center;
}
#dashboard-fixed-wrapper::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.7); /* Black overlay with 50% opacity */
}
</style>
<div id="dashboard-fixed-wrapper" class="row">
<h2 style="margin-top:30px;margin-left:15px;color:#911701">
<span style="float:right;font-size:14px;margin-right:25px;color:black">Terakhir di update - {{$latest_created}}</span>
<div class="col-12">
<h2 class="mt-3 ms-2 text-danger">
<span class="float-end fs-6 me-3 text-black d-block d-sm-inline text-end">Terakhir di update - {{$latest_created}}</span>
ANALISA BIG DATA PROSES PBG <br>
MELALUI APLIKASI SIBEDAS PBG
</h2>
<div id="dashboard-fixed-container" style="width:1110px;height:770px;position:relative;margin:auto;">
</div>
<div class="row d-flex justify-content-end">
<div class="col-12 col-sm-6 col-md-3">
<div class="d-flex flex-sm-nowrap flex-wrap justify-content-end gap-2">
<select class="form-select w-auto" id="yearPicker" name="year" style="min-width: 100px;">
@for ($i = date('Y'); $i > date('Y') - 5; $i--)
<option value="{{ $i }}" {{ $i == date('Y') ? 'selected' : '' }}>{{ $i }}</option>
@endfor
</select>
<button class="btn btn-sm btn-primary" id="btnFilterYear">Filter</button>
</div>
</div>
</div>
<div id="dashboard-fixed-container" class="row" style="width:1110px;height:770px;position:relative;margin:auto;">
@component('components.circle', [
'document_title' => 'Kekurangan Potensi',
'document_color' => '#911701',
+7 -17
View File
@@ -4,26 +4,12 @@
@include('layouts.partials/page-title', ['title' => 'Data Settings', 'subtitle' => 'Setting Dashboard'])
<x-toast-notification />
<div class="row d-flex justify-content-center">
@if (session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="col-lg-6">
<div class="card">
<div class="card-body">
<form action="{{ route('data-settings.store') }}" method="POST">
<form id="formDataSettings" action="{{ route('data-settings.store') }}" method="POST">
@csrf
<div class="mb-3">
<label for="key" class="form-label">Key</label>
@@ -37,7 +23,10 @@
<label for="type" class="form-label">Type</label>
<input type="text" id="type" class="form-control" name="type">
</div>
<button type="submit" class="btn btn-success width-lg">Create</button>
<button class="btn btn-primary me-1" type="button" id="btnCreateDataSettings">
<span id="spinner" class="spinner-border spinner-border-sm me-1 d-none" role="status" aria-hidden="true"></span>
Create
</button>
</form>
</div>
</div>
@@ -47,4 +36,5 @@
@endsection
@section('scripts')
@vite(['resources/js/data-settings/create.js'])
@endsection
+7 -17
View File
@@ -4,26 +4,12 @@
@include('layouts.partials/page-title', ['title' => 'Data Settings', 'subtitle' => 'Setting Dashboard'])
<x-toast-notification />
<div class="row d-flex justify-content-center">
@if (session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="col-lg-6">
<div class="card">
<div class="card-body">
<form action="{{ route('data-settings.update', $data->id) }}" method="POST">
<form id="formUpdateDataSettings" action="{{ route('data-settings.update', $data->id) }}" method="POST">
@csrf
@method('PUT')
<div class="mb-3">
@@ -38,7 +24,10 @@
<label for="type" class="form-label">Type</label>
<input type="text" id="type" class="form-control" name="type" value="{{$data->type}}">
</div>
<button type="submit" class="btn btn-success width-lg">Update</button>
<button class="btn btn-primary me-1" type="button" id="btnUpdateDataSettings">
<span id="spinner" class="spinner-border spinner-border-sm me-1 d-none" role="status" aria-hidden="true"></span>
Update
</button>
</form>
</div>
</div>
@@ -48,4 +37,5 @@
@endsection
@section('scripts')
@vite(['resources/js/data-settings/update.js'])
@endsection
+10 -3
View File
@@ -8,14 +8,21 @@
@include('layouts.partials/page-title', ['title' => 'Data Settings', 'subtitle' => 'Setting Dashboard'])
<x-toast-notification />
<x-modal-confirmation buttonText="Delete" confirmationMessage="Are you sure you want to delete this?" />
<div class="row">
<div class="d-flex justify-content-end pb-3">
<a href="{{ route('data-settings.create')}}" class="btn btn-success width-lg">Create</a>
<div class="col-12">
<div class="card w-100">
<div class="card-body">
<div class="d-flex flex-wrap justify-content-end align-items-center mb-2">
<a href="{{ route('data-settings.create')}}" class="btn btn-success btn-sm d-block d-sm-inline w-auto">Create</a>
</div>
<div>
<div id="table-data-settings"></div>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,91 @@
@extends('layouts.vertical', ['subtitle' => 'File Uploads'])
@section('content')
@include('layouts.partials/page-title', ['title' => 'Form', 'subtitle' => 'File Uploads'])
<div class="row">
<div class="col-xl-12">
<div class="card">
<div class="card-header">
<h5 class="card-title">Upload Data Reklame</h5>
<p class="card-subtitle">
Please upload a file with the extension <strong>.xls or .xlsx</strong> with a maximum size of <strong>10 MB</strong>.
<br>
For <strong>.xls</strong> and <strong>.xlsx</strong> files, ensure that the data is contained within a <strong>single sheet</strong> with the following columns:
<strong>No, Nama Wajib Pajak, NPWPD, Jenis Reklame, Isi Reklame, Alamat Wajib Pajak, Lokasi Reklame, Desa,
Kecamatan, Panajang, Lebar, Sudut Pandang, Muka, Luas, Sudut, Kontak.</strong>
</p>
</div>
<div class="card-body">
<div class="mb-3">
<div class="dropzone">
<form action="" method="post" enctype="multipart/form-data">
<div class="fallback">
<input id="file-dropzone"type="file" name="file" multiple/>
</div>
</form>
<div class="dz-message needsclick">
<i class="h1 bx bx-cloud-upload"></i>
<h3>Drop files here or click to upload.</h3>
</div>
</div>
<ul class="list-unstyled mb-0" id="dropzone-preview">
<li class="mt-2" id="dropzone-preview-list">
<!-- This is used as the file preview template -->
<div class="border rounded">
<div class="d-flex align-items-center p-2">
<div class="flex-shrink-0 me-3">
<div class="avatar-sm bg-light rounded">
<img data-dz-thumbnail class="img-fluid rounded d-block" src="#"
alt="" />
</div>
</div>
<div class="flex-grow-1">
<div class="pt-1">
<h5 class="fs-14 mb-1" data-dz-name>&nbsp;
</h5>
<p class="fs-13 text-muted mb-0" data-dz-size></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
</div>
<div class="flex-shrink-0 ms-3">
<button data-dz-remove class="btn btn-sm btn-danger">Delete</button>
</div>
</div>
</div>
</li>
</ul>
<!-- end dropzon-preview -->
</div>
<div class="d-flex justify-content-end">
<button id="submit-upload" class="btn btn-primary">Upload Files</button>
</div>
</div> <!-- end card body -->
</div> <!-- end card -->
</div> <!-- end col -->
</div> <!-- end row -->
<div class="toast-container position-fixed end-0 top-0 p-3">
<div id="toastUploadAdvertisement" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<div class="auth-logo me-auto">
</div>
<small class="text-muted"></small>
<button type="button" class="btn-close" data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
<div class="toast-body">
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/data/advertisements/form-upload.js'])
@endsection
@@ -0,0 +1,120 @@
@extends('layouts.vertical', ['subtitle' => $subtitle]) <!-- Menggunakan subtitle dari controller -->
@section('content')
@include('layouts.partials/page-title', ['title' => $title, 'subtitle' => $subtitle]) <!-- Menggunakan title dan subtitle dari controller -->
<div class="row d-flex justify-content-center">
@if (session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="col-lg-12 col-md-12">
<div class="card">
<div class="card-header">
<button class="btn btn-danger float-end btn-back">
<i class='bx bx-arrow-back'></i>
Back
</button>
</div>
<div class="card-body">
<form id="create-update-form" action="{{ isset($modelInstance) && $modelInstance->id ? $apiUrl . '/' . $modelInstance->id : $apiUrl }}" method="POST">
@csrf
@if(isset($modelInstance))
@method('PUT')
@endif
<div class="row">
@foreach($fields as $field => $label)
<div class="col-md-6 form-group mb-3">
<label for="{{ $field }}">{{ $label }}</label>
@php
$fieldType = $fieldTypes[$field] ?? 'text'; // Default text jika tidak ditemukan tipe
@endphp
@if($fieldType == 'textarea')
<textarea id="{{ $field }}" name="{{ $field }}" class="form-control">{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}</textarea>
@elseif($fieldType == 'select' && isset($dropdownOptions[$field]))
<select id="{{ $field }}" name="{{ $field }}" class="form-control">
@foreach($dropdownOptions[$field] as $code => $name)
<option value="{{ $code }}" {{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') == $code ? 'selected' : '' }}>{{ $name }}</option>
@endforeach
</select>
@elseif($fieldType == 'combobox' && isset($dropdownOptions[$field]))
<input class="form-control" list="{{ $field }}Options" id="{{ $field }}" name="{{ $field }}"
value="{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}" placeholder="Type to search..." oninput="fetchOptions('{{ $field }}')">
<datalist id="{{ $field }}Options"></datalist>
@else
<input type="{{ $fieldType }}" id="{{ $field }}" name="{{ $field }}" class="form-control" value="{{ old($field, isset($modelInstance) ? $modelInstance->{$field} : '') }}">
@endif
</div>
@endforeach
</div>
<div class="d-flex justify-content-end">
<button type="button" class="btn {{ isset($modelInstance) ? 'btn-warning' : 'btn-success' }} width-lg btn-modal" data-bs-toggle="modal" data-bs-target="#confirmationModalCenter">
{{ isset($modelInstance) ? 'Update' : 'Create' }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="confirmationModalCenter" tabindex="-1"
aria-labelledby="confirmationModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmationModalCenterTitle">
{{ isset($modelInstance) ? 'Update Confirmation' : 'Create Confirmation' }}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<p>{{ isset($modelInstance) ? 'Are you sure you want to save the data changes?' : 'Are you sure you want to create new data based on the form contents?' }}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary {{ isset($modelInstance) ? 'btn-edit' : 'btn-create' }}" data-bs-dismiss="modal">Save changes</button>
</div>
</div>
</div>
</div>
<div class="toast-container position-fixed end-0 top-0 p-3">
<div id="toastEditUpdate" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<div class="auth-logo me-auto">
</div>
<small class="text-muted"></small>
<button type="button" class="btn-close" data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
<div class="toast-body">
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/data/advertisements/form-create-update.js'])
@endsection
@@ -0,0 +1,39 @@
@extends('layouts.vertical', ['subtitle' => 'Reklame'])
@section('css')
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
@endsection
@section('content')
@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'Reklame'])
<div class="card">
<div class="card-header">
<h5 class="card-title">Daftar Reklame</h5>
</div>
<div class="card-body">
<div class="row">
<div class="d-flex justify-content-end gap-10 pb-3">
<button class="btn btn-success me-2 width-lg btn-create" data-model="data/advertisements">
<i class='bx bxs-file-plus'></i>
Create</button>
<button class="btn btn-primary width-lg btn-bulk-create" data-model="data/advertisements">
<i class='bx bx-upload' ></i>
Bulk Create
</button>
</div>
<div>
<div id="reklame-data-table"></div>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/data/advertisements/data-advertisements.js'])
@endsection
@@ -1,114 +1,49 @@
<div class="app-sidebar">
<!-- Sidebar Logo -->
<div class="logo-box">
<a href="{{ route('home') }}" class="logo-dark">
<a href="{{ route('dashboard.home') }}" class="logo-dark">
<img src="/images/dputr-kab-bandung.png" class="logo-sm" alt="logo sm">
<img src="/images/dputr-kab-bandung.png" class="logo-lg" alt="logo dark">
</a>
<a href="{{ route('home') }}" class="logo-light">
<a href="{{ route('dashboard.home') }}" class="logo-light">
<img src="/images/dputr-kab-bandung.png" class="logo-sm" alt="logo sm">
<img src="/images/dputr-kab-bandung.png" class="logo-lg" alt="logo light">
</a>
</div>
<div class="scrollbar" data-simplebar>
<ul class="navbar-nav" id="navbar-nav">
<li class="menu-title">Menu</li>
@foreach ($menus as $menu)
<li class="nav-item">
<a class="nav-link menu-arrow" href="#sidebarDashboard" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarDashboard">
<!-- parent menu -->
@if ($menu->parent_id == null)
<a class="nav-link menu-arrow" href="#sidebar-{{$menu->id}}" data-bs-toggle="collapse" role="button"
aria-expanded="true" aria-controls="sidebar-{{$menu->id}}">
<span class="nav-icon">
<iconify-icon icon="mingcute:home-3-line"></iconify-icon>
<iconify-icon icon="{{$menu->icon}}"></iconify-icon>
</span>
<span class="nav-text"> Dashboards</span>
<span class="nav-text">{{$menu->name}}</span>
</a>
<div class="collapse" id="sidebarDashboard">
@endif
<!-- children menu foreach -->
@if ($menu->children->count() > 0)
<div class="collapse" id="sidebar-{{$menu->id}}">
<ul class="nav sub-navbar-nav">
@foreach ( $menu->children as $child)
<li class="sub-nav-item">
<a class="sub-nav-link" href="{{ route ('home' ) }}">Dashboard Pimpinan</a>
</li>
<li class="sub-nav-item">
<a class="sub-nav-link" href="{{ route ('dashboards.pbg' ) }}">Dashboard PBG</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-arrow" href="#sidebarDataMaster" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarDataMaster">
<span class="nav-icon">
<iconify-icon icon="mingcute:cylinder-line"></iconify-icon>
</span>
<span class="nav-text">Master</span>
</a>
<div class="collapse" id="sidebarDataMaster">
<ul class="nav sub-navbar-nav">
<li class="sub-nav-item">
<a class="sub-nav-link" href="{{ route ('users.index' ) }}">Users</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-arrow" href="#sidebarSettings" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarSettings">
<span class="nav-icon">
<iconify-icon icon="mingcute:settings-6-line"></iconify-icon>
</span>
<span class="nav-text">Settings</span>
</a>
<div class="collapse" id="sidebarSettings">
<ul class="nav sub-navbar-nav">
<li class="sub-nav-item d-none">
<a class="sub-nav-link" href="{{ route ('general.index' ) }}">General</a>
</li>
<li class="sub-nav-item">
<a class="sub-nav-link" href="{{ route ('settings.syncronize' ) }}">Syncronize</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-arrow" href="#dataSettings" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="dataSettings">
<span class="nav-icon">
<iconify-icon icon="mingcute:settings-1-line"></iconify-icon>
</span>
<span class="nav-text">Data Settings</span>
</a>
<div class="collapse" id="dataSettings">
<ul class="nav sub-navbar-nav">
<li class="sub-nav-item">
<a class="sub-nav-link" href="{{ route ('data-settings.index' ) }}">Setting Dashboard</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-arrow" href="#data" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="data">
<span class="nav-icon">
<iconify-icon icon="mingcute:task-line"></iconify-icon>
</span>
<span class="nav-text">Data</span>
</a>
<div class="collapse" id="data">
<ul class="nav sub-navbar-nav">
<li class="sub-nav-item">
<a class="sub-nav-link" href="{{ route ('pbg-task.index' ) }}">PBG</a>
<a class="sub-nav-link" href="{{ $child->url ? (Route::has($child->url) ? route($child->url) : $child->url) : '#' }}">
{{ $child->name }}
</a>
</li>
@endforeach
</ul>
</div>
@endif
</li>
@endforeach
</ul>
</div>
</div>
@@ -154,7 +154,7 @@
</a>
<div class="dropdown-menu dropdown-menu-end">
<!-- item-->
<h6 class="dropdown-header">Welcome!</h6>
<h6 class="dropdown-header">{{ Auth::user()->email }}</h6>
<!-- <a class="dropdown-item" href="#">
<iconify-icon icon="solar:user-outline"
@@ -172,7 +172,7 @@
class="align-middle me-2 fs-18"></iconify-icon><span
class="align-middle">Help</span>
</a>
<a class="dropdown-item" href="auth-{{ route ('home') }}">
<a class="dropdown-item" href="auth-{{ route ('dashboard.home') }}">
<iconify-icon icon="solar:lock-keyhole-outline"
class="align-middle me-2 fs-18"></iconify-icon><span class="align-middle">Lock
screen</span>
+17 -4
View File
@@ -4,11 +4,12 @@
@include('layouts.partials/page-title', ['title' => 'Users', 'subtitle' => 'Create'])
<x-toast-notification />
<div class="row d-flex justify-content-center">
<div class="col-lg-6">
<div class="card">
<div class="card-body">
<form action="{{route('users.store')}}" method="POST">
<form id="formCreateUsers" action="{{route('users.store')}}" method="POST">
@csrf
<div class="mb-3">
<label class="form-label" for="name">Name</label>
@@ -26,7 +27,7 @@
placeholder="Enter your password" required>
</div>
<div class="mb-3">
<label class="form-label" for="password_confirmation">Password</label>
<label class="form-label" for="password_confirmation">Password Confirmation</label>
<input type="password" id="password_confirmation" class="form-control" name="password_confirmation"
placeholder="Enter your password confirmation" required>
</div>
@@ -45,8 +46,19 @@
<input type="text" id="position" class="form-control" name="position"
placeholder="Enter your position" required>
</div>
<!-- username, firstname, lastname, position -->
<button type="submit" class="btn btn-success width-lg">Create</button>
<div class="mb-3">
<label class="form-label" for="role">Role</label>
<select name="role_id" id="role" class="form-control">
<option value="">Select Role</option>
@foreach ($roles as $role)
<option value="{{$role->id}}">{{$role->name}}</option>
@endforeach
</select>
</div>
<button class="btn btn-primary me-1" type="button" id="btnCreateUsers">
<span id="spinner" class="spinner-border spinner-border-sm me-1 d-none" role="status" aria-hidden="true"></span>
Create
</button>
</form>
</div>
</div>
@@ -56,4 +68,5 @@
@endsection
@section('scripts')
@vite(['resources/js/master/users/create.js'])
@endsection
+24 -13
View File
@@ -4,44 +4,54 @@
@include('layouts.partials/page-title', ['title' => 'Users', 'subtitle' => 'Create'])
<x-toast-notification />
<div class="row d-flex justify-content-center">
<div class="col-lg-6">
<div class="card">
<div class="card-body">
<form action="{{ route('master.users.update')}}">
<form id="formUpdateUsers" action="{{ route('users.update', $user->id)}}" method="post">
@csrf
@method("put")
<div class="mb-3">
<label class="form-label" for="name">Name</label>
<input type="name" id="name" name="name"
class="form-control" placeholder="Enter your name" required>
class="form-control" placeholder="Enter your name" value="{{$user->name}}" required>
</div>
<div class="mb-3">
<label class="form-label" for="email">Email</label>
<input type="email" id="email" name="email"
class="form-control" placeholder="Enter your email" required>
</div>
<div class="mb-3">
<label class="form-label" for="password">Password</label>
<input type="text" id="password" class="form-control" name="password"
placeholder="Enter your password" required>
class="form-control" placeholder="Enter your email" value="{{$user->email}}" required>
</div>
<div class="mb-3">
<label class="form-label" for="firstname">Firstname</label>
<input type="text" id="firstname" class="form-control" name="firstname"
placeholder="Enter your firstname" required>
placeholder="Enter your firstname" value="{{$user->firstname}}" required>
</div>
<div class="mb-3">
<label class="form-label" for="lastname">Lastname</label>
<input type="text" id="lastname" class="form-control" name="lastname"
placeholder="Enter your lastname" required>
placeholder="Enter your lastname" value="{{$user->lastname}}" required>
</div>
<div class="mb-3">
<label class="form-label" for="position">Position</label>
<input type="text" id="position" class="form-control" name="position"
placeholder="Enter your position" required>
placeholder="Enter your position" value="{{$user->position}}" required>
</div>
<!-- username, firstname, lastname, position -->
<button type="submit" class="btn btn-outline-success width-lg">Update</button>
<div class="mb-3">
<label class="form-label" for="role">Role</label>
<select name="role_id" id="role" class="form-control">
<option value="">Select Role</option>
@foreach($roles as $role)
<option value="{{ $role->id }}" {{ $user->roles->contains($role->id) ? 'selected' : '' }}>
{{ $role->name }}
</option>
@endforeach
</select>
</div>
<button class="btn btn-primary me-1" type="button" id="btnUpdateUsers">
<span id="spinner" class="spinner-border spinner-border-sm me-1 d-none" role="status" aria-hidden="true"></span>
Update
</button>
</form>
</div>
</div>
@@ -51,4 +61,5 @@
@endsection
@section('scripts')
@vite(['resources/js/master/users/update.js'])
@endsection
+9 -4
View File
@@ -9,14 +9,19 @@
@include('layouts.partials/page-title', ['title' => 'Master', 'subtitle' => 'Users'])
<div class="row">
<div class="d-flex justify-content-end pb-3">
<a href="{{ route('users.create')}}" class="btn btn-success width-lg">Create</a>
<div class="col-12">
<div class="card w-100">
<div class="card-body">
<div class="d-flex flex-wrap justify-content-end align-items-center mb-2">
<a href="{{ route('users.create') }}" class="btn btn-success btn-sm d-block d-sm-inline w-auto">
Create
</a>
</div>
{{$users}}
<div>
<div id="table-users"></div>
</div>
</div>
</div>
</div>
@endsection
+61
View File
@@ -0,0 +1,61 @@
@extends('layouts.vertical', ['subtitle' => 'Menu'])
@section('css')
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
@endsection
@section('content')
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Menu'])
<x-toast-notification />
<div class="row d-flex justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form id="formCreateMenus" action="{{route("menus.store")}}" method="post">
@csrf
<div class="mb-3">
<label class="form-label" for="name">Name</label>
<input type="text" id="name" name="name"
class="form-control" placeholder="Enter menu name" required>
</div>
<div class="mb-3">
<label class="form-label" for="url">URL</label>
<input type="text" id="url" name="url"
class="form-control" placeholder="Enter menu url" required>
</div>
<div class="mb-3">
<label class="form-label" for="icon">Icon</label>
<input type="text" id="icon" name="icon"
class="form-control" placeholder="Enter menu icon" required>
</div>
<div class="mb-3">
<label class="form-label" for="parent_id">Parent Menu</label>
<select name="parent_id" class="form-control">
<option value="">Select parent menu</option>
@foreach($parent_menus as $menu)
<option value="{{ $menu->id }}">{{ $menu->name }}</option>
@endforeach
</select>
</div>
<div class="mb-3">
<label class="form-label" for="sort_order">Sort Order</label>
<input type="number" id="sort_order" name="sort_order"
class="form-control" placeholder="Enter sort order" required>
</div>
<button class="btn btn-primary me-1" type="button" id="btnCreateMenus">
<span id="spinner" class="spinner-border spinner-border-sm me-1 d-none" role="status" aria-hidden="true"></span>
Create
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/menus/create.js'])
@endsection
+62
View File
@@ -0,0 +1,62 @@
@extends('layouts.vertical', ['subtitle' => 'Menu'])
@section('css')
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
@endsection
@section('content')
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Menu'])
<x-toast-notification/>
<div class="row d-flex justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form id="formUpdateMenus" action="{{route("menus.update", $menu->id)}}" method="post">
@csrf
@method("put")
<div class="mb-3">
<label class="form-label" for="name">Name</label>
<input type="text" id="name" name="name"
class="form-control" placeholder="Enter menu name" value="{{$menu->name}}" required>
</div>
<div class="mb-3">
<label class="form-label" for="url">URL</label>
<input type="text" id="url" name="url"
class="form-control" placeholder="Enter menu url" value="{{$menu->url}}" required>
</div>
<div class="mb-3">
<label class="form-label" for="icon">Icon</label>
<input type="text" id="icon" name="icon"
class="form-control" placeholder="Enter menu icon" value="{{$menu->icon}}" required>
</div>
<div class="mb-3">
<label class="form-label" for="parent_id">Parent Menu</label>
<select name="parent_id" class="form-control">
<option value="">Select parent menu (Leave blank for parent)</option>
@foreach($parent_menus as $parent)
<option value="{{$parent->id}}"{{ $menu->parent_id == $parent->id ? 'selected' : '' }}>{{ $parent->name }}</option>
@endforeach
</select>
</div>
<div class="mb-3">
<label class="form-label" for="sort_order">Sort Order</label>
<input type="number" id="sort_order" name="sort_order"
class="form-control" placeholder="Enter sort order" value="{{$menu->sort_order}}" required>
</div>
<button class="btn btn-primary me-1" type="button" id="btnUpdateMenus">
<span id="spinner" class="spinner-border spinner-border-sm me-1 d-none" role="status" aria-hidden="true"></span>
Update
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/menus/update.js'])
@endsection
+33
View File
@@ -0,0 +1,33 @@
@extends('layouts.vertical', ['subtitle' => 'Menu'])
@section('css')
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
@endsection
@section('content')
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Menu'])
<x-toast-notification />
<x-modal-confirmation buttonText="Delete" confirmationMessage="Are you sure you want to delete this?" />
<div class="row">
<div class="col-12">
<div class="card w-100">
<div class="card-body">
<div class="d-flex flex-wrap justify-content-end align-items-center mb-2">
<a href="{{ route('menus.create')}}" class="btn btn-success btn-sm d-block d-sm-inline w-auto">Create</a>
</div>
<div>
<div id="table-menus"></div>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/menus/index.js'])
@endsection
+3 -3
View File
@@ -17,11 +17,11 @@ class="authentication-bg"
<div class="p-4">
<div class="mx-auto mb-4 text-center">
<div class="mx-auto text-center auth-logo">
<!-- <a href="{{ route('home') }}" class="logo-dark">
<!-- <a href="{{ route('dashboard.home') }}" class="logo-dark">
<img src="/images/simbg-dputr.png" height="200" width="100%" alt="dputr logo">
</a>
<a href="{{ route('home') }}" class="logo-light">
<a href="{{ route('dashboard.home') }}" class="logo-light">
<img src="/images/simbg-dputr.png" height="200" width="100%" alt="dputr light">
</a> -->
</div>
@@ -32,7 +32,7 @@ class="authentication-bg"
<p class="text-muted mt-1 mb-4">The page you're trying to reach seems to have gone <br /> missing in the digital wilderness.</p>
<div class="text-center">
<a href="{{ route('home') }}" class="btn btn-danger">Back to Home</a>
<a href="{{ route('dashboard.home') }}" class="btn btn-danger">Back to Home</a>
</div>
</div>
</div>
+7 -3
View File
@@ -9,13 +9,17 @@
@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'PBG'])
<div class="row">
<div class="d-flex justify-content-end pb-3">
<a href="{{ route('pbg-task.create')}}" class="btn btn-success width-lg">Create</a>
<div class="col-12">
<div class="card w-100">
<div class="card-body">
<div class="d-flex flex-wrap justify-content-end">
<a href="{{ route('pbg-task.create')}}" class="btn btn-success btn-sm d-block d-sm-inline w-auto">Create</a>
</div>
<div>
<div id="table-pbg-tasks"></div>
</div>
</div>
</div>
</div>
@endsection
+35 -34
View File
@@ -8,35 +8,9 @@
@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'PBG'])
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<ul class="nav nav-tabs nav-justified">
<li class="nav-item">
<a href="#pbgTask" data-bs-toggle="tab" aria-expanded="true" class="nav-link active">
<span class="d-none d-sm-block">PBG Task</span>
</a>
</li>
<li class="nav-item">
<a href="#pbgTaskRetributions" data-bs-toggle="tab" aria-expanded="false"
class="nav-link">
<span class="d-none d-sm-block">PBG Task Retributions</span>
</a>
</li>
<li class="nav-item">
<a href="#pbgTaskIntegration" data-bs-toggle="tab" aria-expanded="false" class="nav-link">
<span class="d-none d-sm-block">PBG Task Index Integrations</span>
</a>
</li>
<li class="nav-item">
<a href="#pbgTaskPrasarana" data-bs-toggle="tab" aria-expanded="false" class="nav-link">
<span class="d-none d-sm-block">PBG Task Prasarana</span>
</a>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane active" id="pbgTask">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
@@ -63,15 +37,15 @@
<dt>Document Number</dt>
<dd>{{$data->document_number}}</dd>
</div>
<div class="mb-3">
<dt>Address</dt>
<dd>{{$data->address}}</dd>
<div>
<dt>Status Name</dt>
<dd>{{$data->status_name}}</dd>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<dt>Status Name</dt>
<dd>{{$data->status_name}}</dd>
<dt>Address</dt>
<dd>{{$data->address}}</dd>
</div>
<div class="mb-3">
<dt>SLF Status Name</dt>
@@ -89,14 +63,40 @@
<dt>Due Date</dt>
<dd>{{$data->due_date}}</dd>
</div>
<div class="mb-3">
<div>
<dt>Task Created At</dt>
<dd>{{$data->task_created_at}}</dd>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="pbgTaskRetributions">
</div>
</div>
<div class="col-12">
<div class="card">
<div class="card-header">
<ul class="nav nav-tabs nav-justified">
<li class="nav-item">
<a href="#pbgTaskRetributions" data-bs-toggle="tab" aria-expanded="false"
class="nav-link active">
<span class="d-none d-sm-block">PBG Task Retributions</span>
</a>
</li>
<li class="nav-item">
<a href="#pbgTaskIntegration" data-bs-toggle="tab" aria-expanded="false" class="nav-link">
<span class="d-none d-sm-block">PBG Task Index Integrations</span>
</a>
</li>
<li class="nav-item">
<a href="#pbgTaskPrasarana" data-bs-toggle="tab" aria-expanded="false" class="nav-link">
<span class="d-none d-sm-block">PBG Task Prasarana</span>
</a>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane active" id="pbgTaskRetributions">
@if ($data->pbg_task_retributions)
<div class="row">
<div class="col-md-6">
@@ -250,6 +250,7 @@
</div>
</div>
</div>
</div>
@endsection
+38
View File
@@ -0,0 +1,38 @@
@extends('layouts.vertical', ['subtitle' => 'Role'])
@section('content')
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Role'])
<x-toast-notification />
<div class="row d-flex justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form action="{{route("roles.store")}}" method="post" id="formCreateRole" data-redirect="{{route("roles.index")}}">
@csrf
<div class="mb-3">
<label class="form-label" for="name">Name</label>
<input type="text" id="name" name="name"
class="form-control" placeholder="Enter role name" required>
</div>
<div class="mb-3">
<label class="form-label" for="description">Description</label>
<input type="text" id="description" name="description"
class="form-control" placeholder="Enter description">
</div>
<button class="btn btn-primary me-1" type="button" id="btnCreateRole">
<span id="spinner" class="spinner-border spinner-border-sm me-1 d-none" role="status" aria-hidden="true"></span>
Create
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/roles/create.js'])
@endsection
+38
View File
@@ -0,0 +1,38 @@
@extends('layouts.vertical', ['subtitle' => 'Role'])
@section('content')
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Role'])
<x-toast-notification/>
<div class="row d-flex justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form id="formUpdateRole" action="{{route("roles.update", $role->id)}}" method="post" >
@csrf
@method("put")
<div class="mb-3">
<label class="form-label" for="name">Name</label>
<input type="text" id="name" name="name"
class="form-control" placeholder="Enter role name" value="{{$role->name}}" required>
</div>
<div class="mb-3">
<label class="form-label" for="description">Description</label>
<input type="text" id="description" name="description"
class="form-control" placeholder="Enter description" value="{{$role->description}}">
</div>
<button class="btn btn-primary me-1" type="button" id="btnUpdateRole">
<span id="spinner" class="spinner-border spinner-border-sm me-1 d-none" role="status" aria-hidden="true"></span>
Update
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
@vite(['resources/js/roles/update.js'])
@endsection

Some files were not shown because too many files have changed in this diff Show More