diff --git a/app/Http/Controllers/Api/AdvertisementController.php b/app/Http/Controllers/Api/AdvertisementController.php index 554213e..0a51f50 100644 --- a/app/Http/Controllers/Api/AdvertisementController.php +++ b/app/Http/Controllers/Api/AdvertisementController.php @@ -53,7 +53,7 @@ class AdvertisementController extends Controller $advertisement->village_name = $village ? $village->village_name : null; $district = DB::table('districts')->where('district_code', $advertisement->district_code)->first(); - $advertisement->district_name = $district ? $district->district_name : null; + $advertisement->district_name = $district ? $district->district_name : null; return $advertisement; }); @@ -75,10 +75,10 @@ class AdvertisementController extends Controller { $data = $request->validated(); - // Cari village_code berdasarkan village_name - $village_code = DB::table('villages')->where('village_name', $data['village_name'])->value('village_code'); // Cari district_code berdasarkan district_name $district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code'); + // Cari village_code berdasarkan village_name + $village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code'); // Tambahkan village_code dan district_code ke data $data['village_code'] = $village_code; @@ -142,10 +142,10 @@ class AdvertisementController extends Controller { $data = $request->validated(); - // Cari village_code berdasarkan village_name - $village_code = DB::table('villages')->where('village_name', $data['village_name'])->value('village_code'); // Cari district_code berdasarkan district_name $district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code'); + // Cari village_code berdasarkan village_name + $village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code'); // Tambahkan village_code dan district_code ke data $data['village_code'] = $village_code; @@ -196,4 +196,17 @@ class AdvertisementController extends Controller return response()->json($results); } + + public function downloadExcelAdvertisement() + { + $filePath = storage_path('app/public/templateFile/template_reklame.xlsx'); + + // Cek apakah file ada + if (!file_exists($filePath)) { + return response()-> json(['message' => 'File tidak ditemukan!'], Response::HTTP_NOT_FOUND); + } + + // Return file to download + return response()->download($filePath); + } } diff --git a/app/Http/Controllers/Api/TourismController.php b/app/Http/Controllers/Api/TourismController.php new file mode 100644 index 0000000..b47542d --- /dev/null +++ b/app/Http/Controllers/Api/TourismController.php @@ -0,0 +1,117 @@ +input('per_page', 15); + $search = $request->input('search', ''); + + $query = Tourism::query(); + $tourisms = $query->paginate($perPage); + + $tourisms->getCollection()->transform(function ($tourisms) { + $village = DB::table('villages')->where('village_code', $tourisms->village_code)->first(); + $tourisms->village_name = $village ? $village->village_name : null; + + $district = DB::table('districts')->where('district_code', $tourisms->district_code)->first(); + $tourisms->district_name = $district ? $district->district_name : null; + + $business_type = DB::table('business_type')->where('id', $tourisms->business_type_id)->first(); + $tourisms->business_type = $business_type ? $business_type->business_type : null; + return $tourisms; + }); + + return response()->json([ + 'data' => TourismResource::collection($tourisms), + 'meta' => [ + 'total' => $tourisms->total(), + 'per_page' => $tourisms->perPage(), + 'current_page' => $tourisms->currentPage(), + 'last_page' => $tourisms->lastPage(), + ] + ]); + } + + /** + * Store a newly created resource in storage. + */ + public function store(TourismRequest $request): Tourism + { + return Tourism::create($request->validated()); + } + + /** + * Import advertisements from Excel or CSV + */ + public function importFromFile(Request $request) + { + //Validasi file + $validator = Validator::make($request->all(), [ + 'file' => 'required|mimes:xlsx, xls|max:10240' + ]); + + if ($validator->fails()) { + return response()->json([ + 'message' => 'File validation failed.', + 'errors' => $validator->errors() + ], 400); + } + + try { + $file = $request->file('file'); + Excel::import(new TourismImport, $file); + return response()->json([ + 'message' => 'File uploaded and imported successfully!' + ], 200); + } catch (\Exception $e) { + return response()->json([ + 'message' => 'Error during file import.', + 'error' => $e->getMessage() + ], 500); + } + } + + /** + * Display the specified resource. + */ + public function show(Tourism $tourism): Tourism + { + return $tourism; + } + + /** + * Update the specified resource in storage. + */ + public function update(TourismRequest $request, Tourism $tourism): Tourism + { + $tourism->update($request->validated()); + + return $tourism; + } + + public function destroy(Tourism $tourism): Response + { + $tourism->delete(); + + return response()->noContent(); + } +} diff --git a/app/Http/Controllers/Api/UmkmController.php b/app/Http/Controllers/Api/UmkmController.php new file mode 100644 index 0000000..dc81709 --- /dev/null +++ b/app/Http/Controllers/Api/UmkmController.php @@ -0,0 +1,189 @@ +input('per_page', 15); + $search = $request->input('search', ''); + + $query = Umkm::query(); + + $umkm = $query->paginate($perPage); + + $umkm->getCollection()->transform(function ($umkm) { + $village = DB::table('villages')->where('village_code', $umkm->village_code)->first(); + $umkm->village_name = $village ? $village->village_name : null; + + $district = DB::table('districts')->where('district_code', $umkm->district_code)->first(); + $umkm->district_name = $district ? $district->district_name : null; + + $business_scale = DB::table('business_scale')->where('id', $umkm->business_scale_id)->first(); + $umkm->business_scale = $business_scale ? $business_scale->business_scale : null; + + $permit_status = DB::table('permit_status')->where('id', $umkm->permit_status_id)->first(); + $umkm->permit_status = $permit_status ? $permit_status->permit_status : null; + + $business_form = DB::table('business_form')->where('id', $umkm->business_form_id)->first(); + $umkm->business_form = $business_form ? $business_form->business_form : null; + return $umkm; + }); + + return response()->json([ + 'data' => UmkmResource::collection($umkm), + 'meta' => [ + 'total' => $umkm->total(), + 'per_page' => $umkm->perPage(), + 'current_page' => $umkm->currentPage(), + 'last_page' => $umkm->lastPage(), + ] + ]); + } + + /** + * Store a newly created resource in storage. + */ + public function store(UmkmRequest $request): Umkm + { + info($request); + $data = $request->validated(); + + // Cari kode berdasarkan nama + $district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code'); + $village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code'); + $business_scale_id = DB::table('business_scale')->where('id', $data['business_scale'])->value('id'); + $permit_status_id = DB::table('permit_status')->where('id', $data['permit_status'])->value('id'); + $business_form_id = DB::table('business_form')->where('id', $data['business_form'])->value('id'); + + info($business_scale_id); + + // Update data dengan kode yang ditemukan + $data['village_code'] = $village_code; + $data['district_code'] = $district_code; + $data['land_area'] = (double) $request['land_area']; + $data['business_scale_id'] = (int) $business_scale_id; + $data['permit_status_id'] = (int) $permit_status_id; + $data['business_form_id'] = (int) $business_form_id; + + info($data); + + // Simpan ke database + return Umkm::create($data); + } + + /** + * Import advertisements from Excel or CSV. + */ + public function importFromFile(Request $request) + { + // Validasi file + $validator = Validator::make($request->all(), [ + 'file' => 'required|mimes:xlsx, xls|max:10240', + ]); + + if ($validator->fails()) { + return response()->json([ + 'message' => 'File validation failed.', + 'errors' => $validator->errors() + ], 400); + } + + try { + // Ambil file dari request + $file = $request->file('file'); + + // Menggunakan Laravel Excel untuk mengimpor file + Excel::import(new UmkmImport, $file); + + // Jika sukses, kembalikan response sukses + return response()->json([ + 'message' => 'File uploaded and imported successfully!' + ], 200); + } catch (\Exception $e) { + return response()->json([ + 'message' => 'Error during file import.', + 'error' => $e->getMessage() + ], 500); + } + } + + /** + * Display the specified resource. + */ + public function show(Umkm $umkm): Umkm + { + return $umkm; + } + + /** + * Update the specified resource in storage. + */ + public function update(UmkmRequest $request, Umkm $umkm): Umkm + { + info($request); + $data = $request->validated(); + + + // Cari district_code berdasarkan district_name + $district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code'); + // Cari village_code berdasarkan village_name + $village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code'); + $business_scale_id = DB::table('business_scale')->where('id', $data['business_scale_id'])->value('id'); + $permit_status_id = DB::table('permit_status')->where('id', $data['permit_status_id'])->value('id'); + $business_form_id = DB::table('business_form')->where('id', $data['business_form_id'])->value('id'); + + + // Tambahkan village_code dan district_code ke data + $data['village_code'] = $village_code; + $data['district_code'] = $district_code; + $data['land_area'] = (double) $request['land_area']; + $data['business_scale_id'] = (int) $business_scale_id; + $data['permit_status_id'] = (int) $permit_status_id; + $data['business_form_id'] = (int) $business_form_id; + + // Log data setelah transformasi + info($data); + + $umkm->update($data); + + return $umkm; + } + + public function destroy(Umkm $umkm): Response + { + $umkm->delete(); + + return response()->noContent(); + } + + public function downloadExcelUmkm() + { + $filePath = storage_path('app/public/templateFile/template_umkm.xlsx'); + + // Cek apakah file ada + if (!file_exists($filePath)) { + return response()-> json(['message' => 'File tidak ditemukan!'], Response::HTTP_NOT_FOUND); + } + + // Return file to download + return response()->download($filePath); + } +} diff --git a/app/Http/Controllers/Data/TourismController.php b/app/Http/Controllers/Data/TourismController.php new file mode 100644 index 0000000..c3cf489 --- /dev/null +++ b/app/Http/Controllers/Data/TourismController.php @@ -0,0 +1,118 @@ + DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'), + 'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'), + 'business_type_id' => DB::table('business_type')->orderBy('business_type')->pluck('business_type', 'id'), + ]; + + $fields = $this->getFields(); + $fieldTypes = $this->getFieldTypes(); + + $apiUrl = url('/api/tourisms'); + + return view('data.tourisms.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions')); + } + + /** + * show the form for editing the specified resource. + */ + public function edit($id) + { + $title = 'Pariwisata'; + $subtitle = 'Create Data'; + + $modelInstance = Tourism::find($id); + // Pastikan model ditemukan + if (!$modelInstance) { + return redirect()->route('tourisms.index') ->with('error', 'Pariwisata tidak ditemukan'); + } + + // Mengambil dan memetakan village_name dan district_name + $village = DB::table('villages')->where('village_code', $modelInstance->village_code)->first(); + $modelInstance->village_name = $village ? $village->village_name : null; + + $district = DB::table('districts')->where('district_code', $modelInstance->district_code)->first(); + $modelInstance->district_name = $district ? $district->district_name : null; + + $business_type = DB::table('business_type')->where('id', $modelInstance->business_type_id)->first(); + $modelInstance->business_scale_id = $business_type ? $business_type->id : null; + + $dropdownOptions = [ + 'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'), + 'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'), + 'business_type_id' => DB::table('business_type')->orderBy('business_type')->pluck('business_type', 'id'), + ]; + + $fields = $this->getFields(); + $fieldTypes = $this->getFieldTypes(); + + $apiUrl = url('/api/tourisms'); + + return view('data.tourisms.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions')); + } + + private function getFields() + { + return [ + "business_name" => "Nama Usaha", + "project_name" => "Nama Project", + "business_address" => "Alamat Usaha", + "district_name" => "Kecamatan", + "village_name" => "Desa", + "land_area" => "Luas Tanah", + "investment_amount" => "Jumlah Investasi", + "number_of_employee" => "TKI", + "business_type_id" => "Jenis Usaha", + ]; + } + + private function getFieldTypes() + { + return [ + "business_name" => "text", + "project_name" => "text", + "business_address" => "textarea", + "district_name" => "combobox", + "village_name" => "combobox", + "land_area" => "text", + "investment_amount" => "text", + "number_of_employee" => "text", + "business_type_id" => "select", + ]; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Data/UmkmController.php b/app/Http/Controllers/Data/UmkmController.php new file mode 100644 index 0000000..6490c86 --- /dev/null +++ b/app/Http/Controllers/Data/UmkmController.php @@ -0,0 +1,149 @@ + DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'), + 'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'), + 'business_scale_id' => DB::table('business_scale')->orderBy('business_scale')->pluck('business_scale', 'id'), + 'permit_status_id' => DB::table('permit_status')->orderBy('permit_status')->pluck('permit_status', 'id'), + 'business_form_id' => DB::table('business_form')->orderBy('business_form')->pluck('business_form', 'id') + ]; + + $fields = $this->getFields(); + $fieldTypes = $this->getFieldTypes(); + + $apiUrl = url('/api/umkm'); + + return view('data.umkm.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions')); + } + + /** + * Show the form for editing the specified resource. + */ + public function edit($id) + { + $title = 'UMKM'; + $subtitle = 'Update Data'; + $modelInstance = Umkm::find($id); + // Pastikan model ditemukan + if (!$modelInstance) { + return redirect()->route('umkm.index')->with('error', 'Umkm not found'); + } + + // Mengambil dan memetakan village_name dan district_name + $village = DB::table('villages')->where('village_code', $modelInstance->village_code)->first(); + $modelInstance->village_name = $village ? $village->village_name : null; + + $district = DB::table('districts')->where('district_code', $modelInstance->district_code)->first(); + $modelInstance->district_name = $district ? $district->district_name : null; + + $business_scale = DB::table('business_scale')->where('id', $modelInstance->business_scale_id)->first(); + $modelInstance->business_scale_id = $business_scale ? $business_scale->id : null; + + $permit_status = DB::table('permit_status')->where('id', $modelInstance->permit_status_id)->first(); + $modelInstance->permit_status_id = $permit_status ? $permit_status->id : null; + + $business_form = DB::table('business_form')->where('id', $modelInstance->business_form_id)->first(); + $modelInstance->business_form_id = $business_form ? $business_form->id : null; + + // dd($modelInstance['business_form_id']); + // Mengambil data untuk dropdown + $dropdownOptions = [ + 'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'), + 'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'), + 'business_scale_id' => DB::table('business_scale')->orderBy('business_scale')->pluck('business_scale', 'id'), + 'permit_status_id' => DB::table('permit_status')->orderBy('permit_status')->pluck('permit_status', 'id'), + 'business_form_id' => DB::table('business_form')->orderBy('business_form')->pluck('business_form', 'id') + ]; + + info("AdvertisementController@edit diakses dengan Model Instance: $modelInstance"); + $fields = $this->getFields(); + $fieldTypes = $this->getFieldTypes(); + + $apiUrl = url('/api/umkm'); + + // dd($modelInstance->business_form_id, $dropdownOptions['business_form']); + return view('data.umkm.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions')); + } + + private function getFields() + { + return [ + "business_name" => "Nama Usaha", + "business_address" => "Alamat Usaha", + "business_desc" => "Deskripsi Usaha", + "business_contact" => "Kontak Usaha", + "business_id_number" => "NIB", + "business_scale_id" => "Skala Usaha", + "owner_id" => "NIK", + "owner_name" => "Nama Pemilik", + "owner_address" => "Alamat Pemilik", + "owner_contact" => "Kontak Pemilik", + "business_type" => "Jenis Usaha", + "district_name" => "Kecamatan", + "village_name" => "Desa", + "number_of_employee" => "Jumlah Karyawan", + "land_area" => "Luas Tanah", + "permit_status_id" => "Ijin Status", + "business_form_id" => "Bisnis Form", + "revenue" => "Omset" + ]; + } + + private function getFieldTypes() + { + return [ + "business_name" => "text", + "business_address" => "text", + "business_desc" => "textarea", + "business_contact" => "text", + "business_id_number" => "text", + "business_scale_id" => "select", + "owner_id" => "text", + "owner_name" => "text", + "owner_address" => "text", + "owner_contact" => "text", + "business_type" => "text", + "district_name" => "combobox", + "village_name" => "combobox", + "number_of_employee" => "text", + "land_area" => "text", + "permit_status_id" => "select", + "business_form_id" => "select", + "revenue" => "text" + ]; + } +} diff --git a/app/Http/Controllers/Report/ReportTourismController.php b/app/Http/Controllers/Report/ReportTourismController.php new file mode 100644 index 0000000..da279c1 --- /dev/null +++ b/app/Http/Controllers/Report/ReportTourismController.php @@ -0,0 +1,21 @@ +|string> + */ + public function rules(): array + { + return [ + 'jenis_proyek' => 'string', + 'nib' => 'string', + 'business_name' => 'required|string', + 'status_penanaman_modal' => 'string', + 'business_form' => 'string', + 'uraian_resiko_proyek' => 'string', + 'project_name' => 'required|string', + 'business_address' => 'required|string', + 'district_code' => 'required|string', + 'village_code' => 'required|string', + 'land_area' => 'required|string', + 'investment_amount' => 'required|string', + 'number_of_employee' => 'required|string', + 'business_type_id' => 'required|string', + ]; + } +} diff --git a/app/Http/Requests/UmkmRequest.php b/app/Http/Requests/UmkmRequest.php new file mode 100644 index 0000000..b8ba842 --- /dev/null +++ b/app/Http/Requests/UmkmRequest.php @@ -0,0 +1,106 @@ +|string> + */ + public function rules(): array + { + return [ + 'business_name' => 'required|string', + 'business_address' => 'required|string', + 'business_desc' => 'required|string', + 'business_contact' => 'required|string', + 'business_id_number' => 'string', + 'business_scale_id' => 'required', + 'owner_id' => 'required|string', + 'owner_name' => 'required|string', + 'owner_address' => 'required|string', + 'owner_contact' => 'required|string', + 'business_type' => 'required|string', + 'business_form_id' => 'required|string', + 'revenue' => 'required|numeric|between:0,999999999999999999.99', + 'village_name' => 'required|string', + 'district_name' => 'required', + 'number_of_employee' => 'required', + 'permit_status_id' => 'required', + 'land_area' => 'required|integer|between:0,99999999999', + ]; + } + + /** + * Get the validation messages for the request. + * + * @return array + */ + public function messages(): array + { + return [ + 'business_name.required' => 'Nama usaha wajib diisi.', + 'business_name.string' => 'Nama usaha harus berupa teks.', + + 'business_address.required' => 'Alamat usaha wajib diisi.', + 'business_address.string' => 'Alamat usaha harus berupa teks.', + + 'business_desc.required' => 'Deskripsi usaha wajib diisi.', + 'business_desc.string' => 'Deskripsi usaha harus berupa teks.', + + 'business_contact.required' => 'Kontak usaha wajib diisi.', + 'business_contact.string' => 'Kontak usaha harus berupa teks.', + + 'business_id_number.string' => 'Nomor ID usaha harus berupa teks.', + + 'business_scale.required' => 'Skala usaha wajib diisi.', + + 'owner_id.required' => 'ID pemilik wajib diisi.', + 'owner_id.string' => 'ID pemilik harus berupa teks.', + + 'owner_name.required' => 'Nama pemilik wajib diisi.', + 'owner_name.string' => 'Nama pemilik harus berupa teks.', + + 'owner_address.required' => 'Alamat pemilik wajib diisi.', + 'owner_address.string' => 'Alamat pemilik harus berupa teks.', + + 'owner_contact.required' => 'Kontak pemilik wajib diisi.', + 'owner_contact.string' => 'Kontak pemilik harus berupa teks.', + + 'business_type.required' => 'Jenis usaha wajib diisi.', + 'business_type.string' => 'Jenis usaha harus berupa teks.', + + 'business_form.required' => 'Bentuk usaha wajib diisi.', + 'business_form.string' => 'Bentuk usaha harus berupa teks.', + + 'revenue.required' => 'Omset wajib diisi.', + 'revenue.numeric' => 'Omset harus berupa angka yang valid.', + 'revenue.between' => 'Omset harus berada di antara 0 dan 9.999.999.999,99.', + + 'village_name.required' => 'Nama desa wajib diisi.', + 'village_name.string' => 'Nama desa harus berupa teks.', + + 'district_name.required' => 'Nama distrik wajib diisi.', + + 'number_of_employee.required' => 'Jumlah karyawan wajib diisi.', + + 'permit_status.required' => 'Status izin wajib diisi.', + + 'land_area.required' => 'Luas lahan wajib diisi.', + 'land_area.integer' => 'Luas lahan harus berupa angka bulat.', + 'land_area.between' => 'Luas lahan harus berada di antara 0 dan 99.999.999.999.', + ]; + } +} diff --git a/app/Http/Resources/TourismResource.php b/app/Http/Resources/TourismResource.php new file mode 100644 index 0000000..d11dedb --- /dev/null +++ b/app/Http/Resources/TourismResource.php @@ -0,0 +1,19 @@ + + */ + public function toArray(Request $request): array + { + return parent::toArray($request); + } +} diff --git a/app/Http/Resources/UmkmResource.php b/app/Http/Resources/UmkmResource.php new file mode 100644 index 0000000..fe395d0 --- /dev/null +++ b/app/Http/Resources/UmkmResource.php @@ -0,0 +1,19 @@ + + */ + public function toArray(Request $request): array + { + return parent::toArray($request); + } +} diff --git a/app/Imports/AdvertisementImport.php b/app/Imports/AdvertisementImport.php index 1c27243..119f884 100644 --- a/app/Imports/AdvertisementImport.php +++ b/app/Imports/AdvertisementImport.php @@ -47,7 +47,7 @@ class AdvertisementImport implements ToCollection $districtCode = $districts[$districtName] ?? null; $listTrueVillage = DB::table('villages') - ->where('district_code', $districtCode) // Perbaikan pada where() + ->where('district_code', $districtCode) ->get() ->mapWithKeys(function ($item) { return [strtolower(trim($item->village_name)) => [ diff --git a/app/Imports/TourismImport.php b/app/Imports/TourismImport.php new file mode 100644 index 0000000..6c00e3d --- /dev/null +++ b/app/Imports/TourismImport.php @@ -0,0 +1,96 @@ +isEmpty()) + { + return; + } + + // Ambil data districts dengan normalisasi nama + $districts = DB::table('districts') + ->get() + ->mapWithKeys(function ($item) { + return [strtolower(trim($item->district_name)) => $item->district_code]; + }) + ->toArray(); + // Cari header secara otomatis + $header = $rows->first(); + $headerIndex = collect($header)->search(fn($value) => !empty($value)); + + // Pastikan header ditemukan + if ($headerIndex === false) { + return; + } + + info($rows); + + foreach ($rows->skip(1) as $row) { + // Normalisasi nama kecamatan dan desa + $districtName = strtolower(trim(str_replace('Kecamatan', '', $row[13]))); + $villageName = strtolower(trim($row[14])); + + // Cari distric_code dari table districts + $districtCode = $districts[$districtName] ?? null; + + $listTrueVillage = DB::table('villages') + ->where('district_code', $districtCode) + ->get() + ->mapWithKeys(function ($item) { + return [strtolower(trim($item->village_name)) => [ + 'village_code' => $item->village_code, + 'district_code' => $item->district_code + ]]; + }) + ->toArray(); + + // ambill village code yang village_name sama dengan $villageName + $villageCode = $listTrueVillage[$villageName]['village_code'] ?? '000000'; + + $dataToInsert[] = [ + 'project_id' => $row[1], + 'jenis_proyek' => $row[2], + 'nib' => $row[3], + 'business_name' => $row[4], + 'terbit_oss' => DateTime::createFromFormat('d/m/Y', $row[5])->format('Y-m-d'), + 'status_penanaman_modal' => $row[6], + 'business_form' => $row[7], + 'uraian_resiko_proyek' => $row[8], + 'project_name' => $row[9], + 'business_type_id' => $row[10], + 'business_scale_id' => (int) $row[11], + 'business_address' => $row[12], + 'district_code' => $districtCode, + 'village_code' => $villageCode, + 'land_area' => $row[15], + 'investment_amount' => (string) $row[16], + 'number_of_employee' => (string) $row[17], + ]; + } + + if(!empty($dataToInsert)) { + Tourism::insert($dataToInsert); + } else { + return; + } + } +} \ No newline at end of file diff --git a/app/Imports/UmkmImport.php b/app/Imports/UmkmImport.php new file mode 100644 index 0000000..7b48df0 --- /dev/null +++ b/app/Imports/UmkmImport.php @@ -0,0 +1,98 @@ +isEmpty()) + { + return; + } + + // Ambil data districts dengan normalisasi nama + $districts = DB::table('districts') + ->get() + ->mapWithKeys(function ($item) { + return [strtolower(trim($item->district_name)) => $item->district_code]; + }) + ->toArray(); + // Cari header secara otomatis + $header = $rows->first(); + $headerIndex = collect($header)->search(fn($value) => !empty($value)); + + // Pastikan header ditemukan + if ($headerIndex === false) { + return; + } + + info($rows); + + foreach ($rows->skip(1) as $row) { + // Normalisasi nama kecamatan dan desa + $districtName = strtolower(trim(str_replace('Kecamatan', '', $row[14]))); + $villageName = strtolower(trim($row[13])); + + // Cari distric_code dari table districts + $districtCode = $districts[$districtName] ?? null; + + $listTrueVillage = DB::table('villages') + ->where('district_code', $districtCode) + ->get() + ->mapWithKeys(function ($item) { + return [strtolower(trim($item->village_name)) => [ + 'village_code' => $item->village_code, + 'district_code' => $item->district_code + ]]; + }) + ->toArray(); + + // ambil village code yang village_name sama dengan $villageName + $villageCode = $listTrueVillage[$villageName]['village_code'] ?? '0000'; + + $dataToInsert[] = [ + 'business_name' => $row[0], + 'business_address' => $row[1], + 'business_desc' => $row[2], + 'business_contact' => $row[3], + 'business_id_number' => $row[4], + 'business_scale_id' => $row[5], + 'owner_id' => $row[6], + 'owner_name' => $row[7], + 'owner_address' => $row[8], + 'owner_contact' => $row[9], + 'business_type' => $row[10], + 'business_form_id' => $row[11], + 'revenue' => $row[12], + 'village_code' => $villageCode, + 'district_code' => $districtCode, + 'number_of_employee' => $row[15], + 'land_area' => $row[16], + 'permit_status_id' => $row[17], + ]; + } + + info($dataToInsert); + if (!empty($dataToInsert)) { + Umkm::insert($dataToInsert); + } else { + return; + } + } +} \ No newline at end of file diff --git a/app/Models/BusinessTypeCount.php b/app/Models/BusinessTypeCount.php new file mode 100644 index 0000000..25cf41a --- /dev/null +++ b/app/Models/BusinessTypeCount.php @@ -0,0 +1,14 @@ + + */ + protected $fillable = ['project_id', 'jenis_proyek', 'nib', 'business_name', 'terbit_oss', 'status_penanaman_modal', 'business_form', 'uraian_resiko_proyek', 'project_name', 'business_scale_id', 'business_address', 'district_code', 'village_code', 'land_area', 'investment_amount', 'number_of_employee', 'business_type_id']; + + +} diff --git a/app/Models/Umkm.php b/app/Models/Umkm.php new file mode 100644 index 0000000..f719943 --- /dev/null +++ b/app/Models/Umkm.php @@ -0,0 +1,48 @@ + + */ + protected $fillable = ['business_name', 'business_address', 'business_desc', 'business_contact', 'business_id_number', 'business_scale_id', 'owner_id', 'owner_name', 'owner_address', 'owner_contact', 'business_type', 'business_form_id', 'revenue', 'village_code', 'district_code', 'number_of_employee', 'land_area', 'permit_status_id']; + + +} diff --git a/database/migrations/2025_02_12_083512_create_table_umkm.php b/database/migrations/2025_02_12_083512_create_table_umkm.php new file mode 100644 index 0000000..f13ccd8 --- /dev/null +++ b/database/migrations/2025_02_12_083512_create_table_umkm.php @@ -0,0 +1,46 @@ +id(); + $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); + $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')); + $table->string('business_name'); + $table->string('business_address'); + $table->string('business_desc'); + $table->string('business_contact'); + $table->string('business_id_number')->nullable(); + $table->integer('business_scale_id'); + $table->string('owner_id'); + $table->string('owner_name'); + $table->string('owner_address'); + $table->string('owner_contact'); + $table->string('business_type'); + $table->string('business_form'); + $table->decimal('revenue'); + $table->string('village_code'); + $table->integer('distric_code'); + $table->integer('number_of_employee'); + $table->float('land_area')->nullable(); + $table->integer('permit_status_id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('umkm'); + } +}; diff --git a/database/migrations/2025_02_12_091119_create_business_scale_table.php b/database/migrations/2025_02_12_091119_create_business_scale_table.php new file mode 100644 index 0000000..4d57e52 --- /dev/null +++ b/database/migrations/2025_02_12_091119_create_business_scale_table.php @@ -0,0 +1,29 @@ +id(); + $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); + $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')); + $table->string('business_scale'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('business_scale'); + } +}; diff --git a/database/migrations/2025_02_12_091312_create_permit_status_table.php b/database/migrations/2025_02_12_091312_create_permit_status_table.php new file mode 100644 index 0000000..4d81daf --- /dev/null +++ b/database/migrations/2025_02_12_091312_create_permit_status_table.php @@ -0,0 +1,29 @@ +id(); + $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); + $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')); + $table->string('permit_status'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('permit_status'); + } +}; diff --git a/database/migrations/2025_02_12_100256_update_business_form_column_in_umkm_table.php b/database/migrations/2025_02_12_100256_update_business_form_column_in_umkm_table.php new file mode 100644 index 0000000..b577091 --- /dev/null +++ b/database/migrations/2025_02_12_100256_update_business_form_column_in_umkm_table.php @@ -0,0 +1,30 @@ +dropColumn('business_form'); + $table->integer('business_form_id')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('umkm', function (Blueprint $table) { + $table->dropColumn('business_form_id'); + $table->string('business_form')->nullable(); + }); + } +}; diff --git a/database/migrations/2025_02_12_100644_create_business_form_table.php b/database/migrations/2025_02_12_100644_create_business_form_table.php new file mode 100644 index 0000000..9865bff --- /dev/null +++ b/database/migrations/2025_02_12_100644_create_business_form_table.php @@ -0,0 +1,29 @@ +id(); + $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); + $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')); + $table->string('business_form'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('business_form'); + } +}; diff --git a/database/migrations/2025_02_12_103210_update_distric_code_column_in_umkm_table.php b/database/migrations/2025_02_12_103210_update_distric_code_column_in_umkm_table.php new file mode 100644 index 0000000..053586e --- /dev/null +++ b/database/migrations/2025_02_12_103210_update_distric_code_column_in_umkm_table.php @@ -0,0 +1,28 @@ +renameColumn('distric_code', 'district_code'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('umkm', function (Blueprint $table) { + $table->renameColumn('district_code', 'distric_code'); + }); + } +}; diff --git a/database/migrations/2025_02_13_072400_rename_umkms_table_to_umkm.php b/database/migrations/2025_02_13_072400_rename_umkms_table_to_umkm.php new file mode 100644 index 0000000..6b09ed1 --- /dev/null +++ b/database/migrations/2025_02_13_072400_rename_umkms_table_to_umkm.php @@ -0,0 +1,28 @@ +decimal('revenue', 20, 2)->change(); + + // Mengubah kolom 'land_area' menjadi decimal(20, 2) + $table->integer('land_area')->nullable()->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('umkm', function (Blueprint $table) { + // Mengembalikan kolom 'revenue' ke decimal default (jika ada) + $table->decimal('revenue')->change(); + + // Mengembalikan kolom 'land_area' ke tipe sebelumnya (float atau lainnya) + $table->float('land_area')->nullable()->change(); + }); + } +}; diff --git a/database/migrations/2025_02_17_072649_create_tourism_table.php b/database/migrations/2025_02_17_072649_create_tourism_table.php new file mode 100644 index 0000000..3809f2c --- /dev/null +++ b/database/migrations/2025_02_17_072649_create_tourism_table.php @@ -0,0 +1,36 @@ +id(); + $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); + $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')); + $table->string('business_name'); + $table->string('project_name'); + $table->string('business_address'); + $table->string('village_code'); + $table->string('land_area'); + $table->string('investment_amount'); + $table->string('number_of_employee'); + $table->string('business_type_id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('tourism'); + } +}; diff --git a/database/migrations/2025_02_17_075547_create_business_type_table.php b/database/migrations/2025_02_17_075547_create_business_type_table.php new file mode 100644 index 0000000..cd7c88e --- /dev/null +++ b/database/migrations/2025_02_17_075547_create_business_type_table.php @@ -0,0 +1,29 @@ +id(); + $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); + $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')); + $table->string('business_type'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('business_type'); + } +}; diff --git a/database/migrations/2025_02_17_082731_add_district_code_to_tourism_table.php b/database/migrations/2025_02_17_082731_add_district_code_to_tourism_table.php new file mode 100644 index 0000000..a500795 --- /dev/null +++ b/database/migrations/2025_02_17_082731_add_district_code_to_tourism_table.php @@ -0,0 +1,28 @@ +string('district_code')->after('business_address'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('tourism', function (Blueprint $table) { + $table->dropColumn('district_code'); + }); + } +}; diff --git a/database/migrations/2025_02_17_092740_rename_tourism_to_tourisms.php b/database/migrations/2025_02_17_092740_rename_tourism_to_tourisms.php new file mode 100644 index 0000000..cc1411e --- /dev/null +++ b/database/migrations/2025_02_17_092740_rename_tourism_to_tourisms.php @@ -0,0 +1,24 @@ +integer('project_id')->nullable()->after('id'); + $table->string('jenis_proyek')->nullable()->after('project_id'); + $table->string('nib')->nullable()->after('jenis_proyek'); + $table->integer('business_scale_id')->nullable()->after('project_name'); + $table->date('terbit_oss')->nullable()->after('business_name'); + $table->string('status_penanaman_modal')->nullable()->after('terbit_oss'); + $table->string('business_form')->nullable()->after('status_penanaman_modal'); + $table->string('uraian_resiko_proyek')->nullable()->after('business_form'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('tourisms', function (Blueprint $table) { + $table->dropColumn(['project_id', 'jenis_proyek', 'nib', 'business_scale_id', 'terbit_oss', + 'status_penanaman_modal', 'business_form', 'uraian_resiko_proyek']); + }); + } +}; diff --git a/database/migrations/2025_02_17_131349_change_project_id_to_string_in_tourisms.php b/database/migrations/2025_02_17_131349_change_project_id_to_string_in_tourisms.php new file mode 100644 index 0000000..7ebee79 --- /dev/null +++ b/database/migrations/2025_02_17_131349_change_project_id_to_string_in_tourisms.php @@ -0,0 +1,32 @@ +string('project_id')->change(); + $table->integer('district_code')->change(); + $table->integer('business_type_id')->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('tourisms', function (Blueprint $table) { + $table->integer('project_id')->change(); + $table->string('district_code')->change(); + $table->string('business_type_id')->change(); + }); + } +}; diff --git a/database/seeders/BusinessFormSeeder.php b/database/seeders/BusinessFormSeeder.php new file mode 100644 index 0000000..6447f14 --- /dev/null +++ b/database/seeders/BusinessFormSeeder.php @@ -0,0 +1,26 @@ +insert([ + ['business_form' => 'Perseorangan'], + ['business_form' => 'Persekutuan'], + ['business_form' => 'Koperasi'], + ['business_form' => 'CV'], + ['business_form' => 'PT'], + ['business_form' => 'PTTB'], + ['business_form' => 'Perseroan'], + ]); + } +} diff --git a/database/seeders/BusinessScaleSeeder.php b/database/seeders/BusinessScaleSeeder.php new file mode 100644 index 0000000..1c31b0f --- /dev/null +++ b/database/seeders/BusinessScaleSeeder.php @@ -0,0 +1,22 @@ +insert([ + ['business_scale' => 'Micro'], + ['business_scale' => 'Kecil'], + ['business_scale' => 'Menengah'], + ]); + } +} diff --git a/database/seeders/BusinessTypeSeeder.php b/database/seeders/BusinessTypeSeeder.php new file mode 100644 index 0000000..f9df40f --- /dev/null +++ b/database/seeders/BusinessTypeSeeder.php @@ -0,0 +1,28 @@ +insert([ + ['business_type' => 'Villas'], + ['business_type' => 'Hotels'], + ['business_type' => 'Restaurants / Food Stores'], + ['business_type' => 'Cafes'], + ['business_type' => 'Adventure / Outdoor Activities'], + ['business_type' => 'Event Organizers'], + ['business_type' => 'Travel & Tours'], + ['business_type' => 'Miscellaneous'], + ['business_type' => 'Others'], + ]); + } +} diff --git a/database/seeders/PermitStatusSeeder.php b/database/seeders/PermitStatusSeeder.php new file mode 100644 index 0000000..90f4c20 --- /dev/null +++ b/database/seeders/PermitStatusSeeder.php @@ -0,0 +1,22 @@ +insert([ + ['permit_status' => 'Not Registered'], + ['permit_status' => 'Registered'], + ['permit_status' => 'Application Process'], + ]); + } +} diff --git a/database/view_query/business_type_counts.sql b/database/view_query/business_type_counts.sql new file mode 100644 index 0000000..847c6f6 --- /dev/null +++ b/database/view_query/business_type_counts.sql @@ -0,0 +1,5 @@ +CREATE VIEW business_type_counts AS +SELECT b.business_type, COUNT(t.id) AS count +FROM tourisms t +JOIN business_type b ON t.business_type_id = b.id +GROUP BY b.business_type; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 5c72d9d..2ee8071 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,6 @@ "": { "dependencies": { "apexcharts": "^3.44.2", - "big.js": "^6.2.2", "bootstrap": "^5.3.3", "countup.js": "^2.3.2", "dropzone": "^5.9.0", @@ -19,6 +18,7 @@ "node-waves": "^0.7.6", "quill": "^1.3.7", "simplebar": "^5.3.9", + "sweetalert2": "^11.16.0", "wnumb": "^1.2.0" }, "devDependencies": { @@ -478,19 +478,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/big.js": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz", - "integrity": "sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==", - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bigjs" - } - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2521,6 +2508,16 @@ "node": ">= 0.8.0" } }, + "node_modules/sweetalert2": { + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.16.0.tgz", + "integrity": "sha512-4CGgNMpQHcwV+Gov0j4u3lDc/5lyl04NBsa1vW0Se9cqsrQoUimD6/Z5UyZiRP4kMbwQGyb7wsp0x3ytybti6w==", + "license": "MIT", + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/limonte" + } + }, "node_modules/tailwindcss": { "version": "3.4.15", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz", diff --git a/package.json b/package.json index 1d9c568..eece330 100755 --- a/package.json +++ b/package.json @@ -1,35 +1,35 @@ { - "private": true, - "type": "module", - "scripts": { - "build": "vite build", - "dev": "vite" - }, - "devDependencies": { - "autoprefixer": "^10.4.20", - "axios": "^1.7.4", - "concurrently": "^9.0.1", - "laravel-vite-plugin": "^1.0", - "postcss": "^8.4.47", - "sass": "^1.81.1", - "tailwindcss": "^3.4.13", - "vite": "^5.0" - }, - "dependencies": { - "apexcharts": "^3.44.2", - "big.js": "^6.2.2", - "bootstrap": "^5.3.3", - "countup.js": "^2.3.2", - "dropzone": "^5.9.0", - "flatpickr": "^4.6.13", - "gmaps": "^0.4.25", - "gridjs": "^5.1.0", - "iconify-icon": "^2.1.0", - "jsvectormap": "^1.5.1", - "moment": "^2.29.4", - "node-waves": "^0.7.6", - "quill": "^1.3.7", - "simplebar": "^5.3.9", - "wnumb": "^1.2.0" - } + "private": true, + "type": "module", + "scripts": { + "build": "vite build", + "dev": "vite" + }, + "devDependencies": { + "autoprefixer": "^10.4.20", + "axios": "^1.7.4", + "concurrently": "^9.0.1", + "laravel-vite-plugin": "^1.0", + "postcss": "^8.4.47", + "sass": "^1.81.1", + "tailwindcss": "^3.4.13", + "vite": "^5.0" + }, + "dependencies": { + "apexcharts": "^3.44.2", + "bootstrap": "^5.3.3", + "countup.js": "^2.3.2", + "dropzone": "^5.9.0", + "flatpickr": "^4.6.13", + "gmaps": "^0.4.25", + "gridjs": "^5.1.0", + "iconify-icon": "^2.1.0", + "jsvectormap": "^1.5.1", + "moment": "^2.29.4", + "node-waves": "^0.7.6", + "quill": "^1.3.7", + "simplebar": "^5.3.9", + "sweetalert2": "^11.16.0", + "wnumb": "^1.2.0" + } } diff --git a/resources/js/data/advertisements/form-upload.js b/resources/js/data/advertisements/form-upload.js index b9c3521..ba6ec67 100644 --- a/resources/js/data/advertisements/form-upload.js +++ b/resources/js/data/advertisements/form-upload.js @@ -1,4 +1,5 @@ import { Dropzone } from "dropzone"; +import GlobalConfig from "../../global-config.js"; Dropzone.autoDiscover = false; @@ -14,7 +15,7 @@ console.log(dropzonePreviewNode); ((previewTemplate = dropzonePreviewNode.parentNode.innerHTML), dropzonePreviewNode.parentNode.removeChild(dropzonePreviewNode), (dropzone = new Dropzone(".dropzone", { - url: "http://localhost:8000/api/advertisements/import", + url: `${GlobalConfig.apiHost}/api/advertisements/import`, // url: "https://httpbin.org/post", method: "post", acceptedFiles: ".xls,.xlsx", // Use acceptedFiles for better validation @@ -85,6 +86,40 @@ dropzone.on("complete", function(file) { dropzone.removeFile(file); }); +// Add event listener to donwload file template +document.getElementById('downloadtempadvertisement').addEventListener('click', function() { + var url = `${GlobalConfig.apiHost}/api/download-template-advertisement`; + fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}` + }, + }) + .then(response => { + if (response.ok) { + return response.blob(); + } else { + return response.json(); + } + }) + .then((blob) => { + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.style.display = 'none'; + a.href = url; + a.download = 'template_reklame.xlsx'; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + }) + .catch((error) => { + console.error("Gagal mendownload file:", error); + showToast('bxs-error-alt', 'red', "Template file is not already exist."); + }) +}) + // Function to show toast function showToast(iconClass, iconColor, message) { const toastElement = document.getElementById('toastUploadAdvertisement'); diff --git a/resources/js/data/tourisms/data-tourisms.js b/resources/js/data/tourisms/data-tourisms.js new file mode 100644 index 0000000..c9ed40f --- /dev/null +++ b/resources/js/data/tourisms/data-tourisms.js @@ -0,0 +1,79 @@ +import { Grid } from "gridjs/dist/gridjs.umd.js"; +import gridjs from "gridjs/dist/gridjs.umd.js"; +import "gridjs/dist/gridjs.umd.js"; +import GlobalConfig from "../../global-config.js"; +import GeneralTable from "../../table-generator.js"; + + +const dataTourismsColumns = [ + "Proyek ID", + "Jenis Proyek", + "NIB", + "Nama Perusahaan", + "Terbit OSS", + "Status Penanaman Modal", + "Bentuk Bisnis", + "Uraian Resiko Proyek", + "Nama Proyek", + "Alamat Usaha", + "Kecamatan", + "Desa", + "Luas Tanah", + "Jumlah Investasi", + "TKI", + "Tipe Usaha", + { + name: "Actions", + widht: "120px", + formatter: function(cell, row) { + const id = row.cells[16].data; + const model = "data/tourisms"; + return gridjs.html(` +
+ + +
+ `); + } + } +]; + +document.addEventListener("DOMContentLoaded", () => { + const table = new GeneralTable( + "tourisms-data-table", + `${GlobalConfig.apiHost}/api/tourisms`, + `${GlobalConfig.apiHost}`, + dataTourismsColumns + ); + + table.processData = function (data) { + return data.data.map((item) => { + return [ + item.project_id, + item.jenis_project, + item.nib, + item.business_name, + item.terbit_oss, + item.status_penanaman_modal, + item.business_form, + item.uraian_resiko_project, + item.project_name, + item.business_address, + item.district_name, + item.village_name, + item.land_area, + item.investment_amount, + item.number_of_employee, + item.business_type, + item.id, + ]; + }); + }; + + table.init(); +}) \ No newline at end of file diff --git a/resources/js/data/tourisms/form-upload.js b/resources/js/data/tourisms/form-upload.js new file mode 100644 index 0000000..4bb1383 --- /dev/null +++ b/resources/js/data/tourisms/form-upload.js @@ -0,0 +1,149 @@ +import { Dropzone } from "dropzone"; +import GlobalConfig from "../../global-config.js"; + +Dropzone.autoDiscover = false; + +var previewTemplate, + dropzone, + dropzonePreviewNode = document.querySelector("#dropzone-preview-list"); +console.log(previewTemplate); +console.log(dropzone); +console.log(dropzonePreviewNode); + +(dropzonePreviewNode.id = ""), + dropzonePreviewNode && + ((previewTemplate = dropzonePreviewNode.parentNode.innerHTML), + dropzonePreviewNode.parentNode.removeChild(dropzonePreviewNode), + (dropzone = new Dropzone(".dropzone", { + url: `${GlobalConfig.apiHost}/api/tourisms/import`, + // url: "https://httpbin.org/post", + method: "post", + acceptedFiles: ".xls,.xlsx", // Use acceptedFiles for better validation + previewTemplate: previewTemplate, + previewsContainer: "#dropzone-preview", + autoProcessQueue: false, // Disable auto post + headers: { + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}` + }, + init: function() { + // Listen for the success event + this.on("success", function(file, response) { + console.log("File successfully uploaded:", file); + console.log("API Response:", response); + + // Show success toast + showToast('bxs-check-square', 'green', response.message); + document.getElementById("submit-upload").innerHTML = "Upload Files"; + // Tunggu sebentar lalu reload halaman + setTimeout(() => { + window.location.href = "/data/tourisms"; + }, 2000); + }); + // Listen for the error event + this.on("error", function(file, errorMessage) { + console.error("Error uploading file:", file); + console.error("Error message:", errorMessage); + // Handle the error response + + // Show error toast + showToast('bxs-error-alt', 'red', errorMessage.message); + document.getElementById("submit-upload").innerHTML = "Upload Files"; + }); + } + }))); + +// Add event listener to control the submission manually +document.querySelector("#submit-upload").addEventListener("click", function() { + console.log("Ini adalah value dropzone", dropzone.files[0]); + const formData = new FormData() + console.log("Dropzonefiles",dropzone.files); + + this.innerHTML = 'Loading...'; + + // Pastikan ada file dalam queue sebelum memprosesnya + if (dropzone.files.length > 0) { + formData.append('file', dropzone.files[0]) + console.log("ini adalah form data on submit", ...formData); + dropzone.processQueue(); // Ini akan manual memicu upload + } else { + // Show error toast when no file is selected + showToast('bxs-error-alt', 'red', "Please add a file first."); + document.getElementById("submit-upload").innerHTML = "Upload Files"; + } +}); + +// Optional: Listen for the 'addedfile' event to log or control file add behavior +dropzone.on("addedfile", function (file) { + console.log("File ditambahkan:", file); + console.log("Nama File:", file.name); + console.log("Tipe File:", file.type); + console.log("Ukuran File:", (file.size / 1024).toFixed(2) + " KB"); +}); + +dropzone.on("complete", function(file) { + dropzone.removeFile(file); +}); + +// Add event listener to download file template +document.getElementById('downloadtemptourisms').addEventListener('click', function() { + var url = `${GlobalConfig.apiHost}/api/download-template-umkm`; + fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}` + }, + }) + .then(response => { + if (response.ok) { + return response.blob(); // Jika respons OK, konversi menjadi blob + } else { + return response.json(); // Jika respons gagal, konversi menjadi JSON untuk menangani pesan error + } + }) + .then((blob) => { + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.style.display = 'none'; + a.href = url; + a.download = 'template_tourisms.xlsx'; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + }) + .catch((error) => { + console.error("Gagal mendownload file:", error); + showToast('bxs-error-alt', 'red', "Template file is not already exist."); + }) +}) + +// Function to show toast +function showToast(iconClass, iconColor, message) { + const toastElement = document.getElementById('toastUploadUmkm'); + const toastBody = toastElement.querySelector('.toast-body'); + const toastHeader = toastElement.querySelector('.toast-header'); + + // Remove existing icon (if any) before adding the new one + const existingIcon = toastHeader.querySelector('.bx'); + if (existingIcon) { + toastHeader.querySelector('.auth-logo').removeChild(existingIcon); // Remove the existing icon + } + + // Add the new icon to the toast header + const icon = document.createElement('i'); + icon.classList.add('bx', iconClass); + icon.style.fontSize = '25px'; + icon.style.color = iconColor; + toastHeader.querySelector('.auth-logo').appendChild(icon); + + // Set the toast message + toastBody.textContent = message; + + // Show the toast + const toast = new bootstrap.Toast(toastElement); // Inisialisasi Bootstrap Toast + toast.show(); +} + diff --git a/resources/js/data/umkm/data-umkm.js b/resources/js/data/umkm/data-umkm.js new file mode 100644 index 0000000..47bf872 --- /dev/null +++ b/resources/js/data/umkm/data-umkm.js @@ -0,0 +1,81 @@ +import gridjs from "gridjs/dist/gridjs.umd.js"; +import "gridjs/dist/gridjs.umd.js"; +import GlobalConfig from "../../global-config.js"; +import GeneralTable from "../../table-generator.js"; + +const dataUMKMColumns = [ + "Nama Usaha", + "Alamat Usaha", + "Deskripsi Usaha", + "Kontak Usaha", + "NIB", + "Skala Usaha", + "NIK", + "Nama Pemilik", + "Alamat Pemilik", + "Kontak Pemilik", + "Jenis Usaha", + "Bentuk Usaha", + "Revenue", + "Desa", + "Kecamatan", + "Jumlah Karyawan", + "Luas Tanah", + "Ijin Status", + { + name: "Actions", + widht: "120px", + formatter: function(cell, row) { + const id = row.cells[18].data; + const model = "data/umkm"; + return gridjs.html(` +
+ + +
+ `); + } + } +]; + +document.addEventListener("DOMContentLoaded", () => { + const table = new GeneralTable( + "umkm-data-table", + `${GlobalConfig.apiHost}/api/umkm`, + `${GlobalConfig.apiHost}`, + dataUMKMColumns + ); + + table.processData = function (data) { + return data.data.map((item) => { + return [ + item.business_name, + item.business_address, + item.business_desc, + item.business_contact, + item.business_id_number, + item.business_scale, + item.owner_id, + item.owner_name, + item.owner_address, + item.owner_contact, + item.business_type, + item.business_form, + item.revenue, + item.village_name, + item.district_name, + item.number_of_employee, + item.land_area, + item.permit_status, + item.id, + ]; + }); + }; + + table.init(); +}); \ No newline at end of file diff --git a/resources/js/data/umkm/form-create-update.js b/resources/js/data/umkm/form-create-update.js new file mode 100644 index 0000000..1e93639 --- /dev/null +++ b/resources/js/data/umkm/form-create-update.js @@ -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 = ` + + Loading... + `; + const isEdit = saveButton.classList.contains("btn-edit"); + const formData = new FormData(form) + const toast = document.getElementById('toastEditUpdate'); + const toastBody = toast.querySelector('.toast-body'); + const toastHeader = toast.querySelector('.toast-header small'); + + const data = {}; + + // Mengonversi FormData ke dalam JSON + formData.forEach((value, key) => { + data[key] = value; + }); + + // Log semua data dalam FormData + for (let pair of formData.entries()) { + console.log(pair[0] + ": " + pair[1]); + } + const url = form.getAttribute("action"); + console.log("Ini adalah url dari form action", url); + + const method = isEdit ? "PUT" : "POST"; + + fetch(url, { + method: method, + body: JSON.stringify(data), + headers: { + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}`, + "Content-Type": "application/json", + } + }) + .then(response => response.json()) + .then(data => { + console.log("Response data:", data); + if (!data.errors) { + // Remove existing icon (if any) before adding the new one + if (authLogo) { + // Hapus ikon yang sudah ada jika ada + const existingIcon = authLogo.querySelector('.bx'); + if (existingIcon) { + authLogo.removeChild(existingIcon); + } + + // Buat ikon baru + const icon = document.createElement('i'); + icon.classList.add('bx', 'bxs-check-square'); + icon.style.fontSize = '25px'; + icon.style.color = 'green'; // Pastikan 'green' dalam bentuk string + + // Tambahkan ikon ke dalam auth-logo + authLogo.appendChild(icon); + } + + // Set success message for the toast + toastBody.textContent = isEdit ? "Data updated successfully!" : "Data created successfully!"; + toast.classList.add('show'); // Show the toast + setTimeout(() => { + toast.classList.remove('show'); // Hide the toast after 3 seconds + }, 3000); + + setTimeout(() => { + window.location.href = '/data/umkm'; + }, 3000); + } else { + if (authLogo) { + // Hapus ikon yang sudah ada jika ada + const existingIcon = authLogo.querySelector('.bx'); + if (existingIcon) { + authLogo.removeChild(existingIcon); + } + + // Buat ikon baru + const icon = document.createElement('i'); + icon.classList.add('bx', 'bxs-error-alt'); + icon.style.fontSize = '25px'; + icon.style.color = 'red'; // Pastikan 'green' dalam bentuk string + + // Tambahkan ikon ke dalam auth-logo + authLogo.appendChild(icon); + } + // Set error message for the toast + toastBody.textContent = "Error: " + (data.message || "Something went wrong"); + toast.classList.add('show'); // Show the toast + + // Enable button and reset its text on error + modalButton.disabled = false; + modalButton.innerHTML = isEdit ? "Update" : "Create"; + + setTimeout(() => { + toast.classList.remove('show'); // Hide the toast after 3 seconds + }, 3000); + } + }) + .catch(error => { + console.error("Error:", error); + if (authLogo) { + // Hapus ikon yang sudah ada jika ada + const existingIcon = authLogo.querySelector('.bx'); + if (existingIcon) { + authLogo.removeChild(existingIcon); + } + + // Buat ikon baru + const icon = document.createElement('i'); + icon.classList.add('bx', 'bxs-error-alt'); + icon.style.fontSize = '25px'; + icon.style.color = 'red'; // Pastikan 'green' dalam bentuk string + + // Tambahkan ikon ke dalam auth-logo + authLogo.appendChild(icon); + } + // Set error message for the toast + toastBody.textContent = "An error occurred while processing your request."; + toast.classList.add('show'); // Show the toast + + // Enable button and reset its text on error + modalButton.disabled = false; + modalButton.innerHTML = isEdit ? "Update" : "Create"; + + setTimeout(() => { + toast.classList.remove('show'); // Hide the toast after 3 seconds + }, 3000); + }); + }); + + // Fungsi fetchOptions untuk autocomplete server-side + window.fetchOptions = function (field) { + let inputValue = document.getElementById(field).value; + console.log("Query Value:", inputValue); // Debugging log + if (inputValue.length < 2) return; + let districtValue = document.getElementById("district_name").value; // Ambil kecamatan terpilih + + let url = `${GlobalConfig.apiHost}/api/combobox/search-options?query=${encodeURIComponent(inputValue)}&field=${field}`; + + // Jika field desa, tambahkan kecamatan sebagai filter + if (field === "village_name") { + url += `&district=${encodeURIComponent(districtValue)}`; + } + + fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}`, + "Content-Type": "application/json", + } + }) + .then(response => response.json()) + .then(data => { + let dataList = document.getElementById(field + "Options"); + dataList.innerHTML = ""; + + data.forEach(item => { + let option = document.createElement("option"); + option.value = item.name; + option.dataset.code = item.code; + dataList.appendChild(option); + }); + }) + .catch(error => console.error("Error fetching options:", error)); + }; + + document.querySelector('.btn-back').addEventListener('click', function() { + window.history.back(); + }); +}); \ No newline at end of file diff --git a/resources/js/data/umkm/form-upload.js b/resources/js/data/umkm/form-upload.js new file mode 100644 index 0000000..e1828e9 --- /dev/null +++ b/resources/js/data/umkm/form-upload.js @@ -0,0 +1,149 @@ +import { Dropzone } from "dropzone"; +import GlobalConfig from "../../global-config.js"; + +Dropzone.autoDiscover = false; + +var previewTemplate, + dropzone, + dropzonePreviewNode = document.querySelector("#dropzone-preview-list"); +console.log(previewTemplate); +console.log(dropzone); +console.log(dropzonePreviewNode); + +(dropzonePreviewNode.id = ""), + dropzonePreviewNode && + ((previewTemplate = dropzonePreviewNode.parentNode.innerHTML), + dropzonePreviewNode.parentNode.removeChild(dropzonePreviewNode), + (dropzone = new Dropzone(".dropzone", { + url: `${GlobalConfig.apiHost}/api/umkm/import`, + // url: "https://httpbin.org/post", + method: "post", + acceptedFiles: ".xls,.xlsx", // Use acceptedFiles for better validation + previewTemplate: previewTemplate, + previewsContainer: "#dropzone-preview", + autoProcessQueue: false, // Disable auto post + headers: { + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}` + }, + init: function() { + // Listen for the success event + this.on("success", function(file, response) { + console.log("File successfully uploaded:", file); + console.log("API Response:", response); + + // Show success toast + showToast('bxs-check-square', 'green', response.message); + document.getElementById("submit-upload").innerHTML = "Upload Files"; + // Tunggu sebentar lalu reload halaman + setTimeout(() => { + window.location.href = "/data/umkm"; + }, 2000); + }); + // Listen for the error event + this.on("error", function(file, errorMessage) { + console.error("Error uploading file:", file); + console.error("Error message:", errorMessage); + // Handle the error response + + // Show error toast + showToast('bxs-error-alt', 'red', errorMessage.message); + document.getElementById("submit-upload").innerHTML = "Upload Files"; + }); + } + }))); + +// Add event listener to control the submission manually +document.querySelector("#submit-upload").addEventListener("click", function() { + console.log("Ini adalah value dropzone", dropzone.files[0]); + const formData = new FormData() + console.log("Dropzonefiles",dropzone.files); + + this.innerHTML = 'Loading...'; + + // Pastikan ada file dalam queue sebelum memprosesnya + if (dropzone.files.length > 0) { + formData.append('file', dropzone.files[0]) + console.log("ini adalah form data on submit", ...formData); + dropzone.processQueue(); // Ini akan manual memicu upload + } else { + // Show error toast when no file is selected + showToast('bxs-error-alt', 'red', "Please add a file first."); + document.getElementById("submit-upload").innerHTML = "Upload Files"; + } +}); + +// Optional: Listen for the 'addedfile' event to log or control file add behavior +dropzone.on("addedfile", function (file) { + console.log("File ditambahkan:", file); + console.log("Nama File:", file.name); + console.log("Tipe File:", file.type); + console.log("Ukuran File:", (file.size / 1024).toFixed(2) + " KB"); +}); + +dropzone.on("complete", function(file) { + dropzone.removeFile(file); +}); + +// Add event listener to download file template +document.getElementById('downloadtempumkm').addEventListener('click', function() { + var url = `${GlobalConfig.apiHost}/api/download-template-umkm`; + fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${document + .querySelector('meta[name="api-token"]') + .getAttribute("content")}` + }, + }) + .then(response => { + if (response.ok) { + return response.blob(); // Jika respons OK, konversi menjadi blob + } else { + return response.json(); // Jika respons gagal, konversi menjadi JSON untuk menangani pesan error + } + }) + .then((blob) => { + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.style.display = 'none'; + a.href = url; + a.download = 'template_umkm.xlsx'; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + }) + .catch((error) => { + console.error("Gagal mendownload file:", error); + showToast('bxs-error-alt', 'red', "Template file is not already exist."); + }) +}) + +// Function to show toast +function showToast(iconClass, iconColor, message) { + const toastElement = document.getElementById('toastUploadUmkm'); + const toastBody = toastElement.querySelector('.toast-body'); + const toastHeader = toastElement.querySelector('.toast-header'); + + // Remove existing icon (if any) before adding the new one + const existingIcon = toastHeader.querySelector('.bx'); + if (existingIcon) { + toastHeader.querySelector('.auth-logo').removeChild(existingIcon); // Remove the existing icon + } + + // Add the new icon to the toast header + const icon = document.createElement('i'); + icon.classList.add('bx', iconClass); + icon.style.fontSize = '25px'; + icon.style.color = iconColor; + toastHeader.querySelector('.auth-logo').appendChild(icon); + + // Set the toast message + toastBody.textContent = message; + + // Show the toast + const toast = new bootstrap.Toast(toastElement); // Inisialisasi Bootstrap Toast + toast.show(); +} + diff --git a/resources/js/report/tourisms/index.js b/resources/js/report/tourisms/index.js new file mode 100644 index 0000000..e34ba4e --- /dev/null +++ b/resources/js/report/tourisms/index.js @@ -0,0 +1,16 @@ +import gridjs from "gridjs/dist/gridjs.umd.js"; +import "gridjs/dist/gridjs.umd.js"; + +// Mengambil data dari input dengan id="business_type_counts" +const businessTypeCountsElement = document.getElementById("business_type_counts"); +console.log(businessTypeCountsElement); +const businessTypeCounts = JSON.parse(businessTypeCountsElement.value); // Cek apakah data sudah terbawa dengan benar + +// Membuat Grid.js instance +new gridjs.Grid({ + columns: ["Jenis Bisnis Pariwisata", "Jumlah Total"], // Nama kolom + data: businessTypeCounts.map(item => [item.business_type, item.count]), // Mengubah data untuk Grid.js + search: true, // Menambahkan fitur pencarian + pagination: true, // Menambahkan fitur pagination + sort: true, // Menambahkan fitur sorting +}).render(document.getElementById("tourisms-report-data-table")); diff --git a/resources/js/table-generator.js b/resources/js/table-generator.js index 00febe4..45da245 100644 --- a/resources/js/table-generator.js +++ b/resources/js/table-generator.js @@ -1,5 +1,6 @@ import { Grid } from "gridjs/dist/gridjs.umd.js"; import "gridjs/dist/gridjs.umd.js"; +import Swal from "sweetalert2"; class GeneralTable { constructor(tableId, apiUrl, baseUrl, columns, options = {}) { @@ -94,9 +95,29 @@ class GeneralTable { handleDelete(event) { const id = event.target.getAttribute('data-id'); console.log(id); - if (confirm("Are you sure you want to delete this item?")) { - this.deleteRecord(id); - } + // if (confirm("Are you sure you want to delete this item?")) { + // this.deleteRecord(id); + // } + Swal.fire({ + title: "Are you sure?", + text: "You won't be able to revert this!", + icon: "warning", + showCancelButton: true, + confirmButtonColor: "#d33", + cancelButtonColor: "#3085d6", + confirmButtonText: "Yes, delete it!" + }).then((result) => { + if (result.isConfirmed) { + this.deleteRecord(id); + Swal.fire({ + title: "Deleted!", + text: "Your record has been deleted.", + icon: "success", + showConfirmButton: false, // Menghilangkan tombol OK + timer: 2000 // Menutup otomatis dalam 2 detik (opsional) + }); + } + }); } async deleteRecord(id) { @@ -110,23 +131,30 @@ class GeneralTable { .getAttribute("content")}`, "Content-Type": "application/json", }, - // headers: { - // 'Authorization': `Bearer ${document.querySelector('meta[name="api-token"]').getAttribute("content")}`, - // 'Content-Type': 'application/json', - // }, }); - if (response.status === 204) { // Jika status code 204, berarti berhasil - alert('Data deleted successfully!'); + if (response.status === 204) { location.reload(); } else { - const data = await response.json(); // Jika ada data di response body - alert('Failed to delete data: ' + (data.message || 'Unknown error.')); + const data = await response.json(); + showErrorAlert(`Failed to delete record: ${data.message || "Unknown error"}`); } } catch (error) { console.error('Error deleting data:', error); - alert('Error deleting data.'); + showErrorAlert("Error deleting data. Please try again."); } } } +// Fungsi untuk menampilkan alert +function showErrorAlert(message) { + const alertContainer = document.getElementById("alert-container"); + + alertContainer.innerHTML = ` + + `; +} + export default GeneralTable; \ No newline at end of file diff --git a/resources/views/data/advertisements/form-upload.blade.php b/resources/views/data/advertisements/form-upload.blade.php index 1056274..ba03aa9 100644 --- a/resources/views/data/advertisements/form-upload.blade.php +++ b/resources/views/data/advertisements/form-upload.blade.php @@ -8,14 +8,10 @@
-
Upload Data Reklame
-

- Please upload a file with the extension .xls or .xlsx with a maximum size of 10 MB. -
- For .xls and .xlsx files, ensure that the data is contained within a single sheet with the following columns: - No, Nama Wajib Pajak, NPWPD, Jenis Reklame, Isi Reklame, Alamat Wajib Pajak, Lokasi Reklame, Desa, - Kecamatan, Panajang, Lebar, Sudut Pandang, Muka, Luas, Sudut, Kontak. -

+
+
Upload Data Reklame
+ +
@@ -31,6 +27,10 @@

Drop files here or click to upload.

+

+ Please upload a file with the extension .xls or .xlsx with a maximum size of 10 MB. +
+

@@ -82,7 +82,7 @@
-
+ @endsection diff --git a/resources/views/data/tourisms/form-upload.blade.php b/resources/views/data/tourisms/form-upload.blade.php new file mode 100644 index 0000000..9f77c02 --- /dev/null +++ b/resources/views/data/tourisms/form-upload.blade.php @@ -0,0 +1,91 @@ +@extends('layouts.vertical', ['subtitle' => 'File Upload']) + +@section('content') + +@include('layouts.partials/page-title', ['title' => 'Form', 'subtitle' => 'File Uploads']) + +
+
+
+
+
+
Upload Data Pariwisata
+ +
+
+ +
+ +
+ +
+
+
+ +
+
+
+ +

Drop files here or click to upload.

+

+ Please upload a file with the extension .xls or .xlsx with a maximum size of 10 MB. +
+

+
+
+ +
    +
  • + +
    +
    +
    +
    + +
    +
    +
    +
    +
      +
    +

    + +
    +
    +
    + +
    +
    +
    +
  • +
+ +
+
+ +
+
+
+
+
+ +
+ +
+ +@endsection + +@section('scripts') +@vite(['resources/js/data/tourisms/form-upload.js']) +@endsection \ No newline at end of file diff --git a/resources/views/data/tourisms/form.blade.php b/resources/views/data/tourisms/form.blade.php new file mode 100644 index 0000000..8b950eb --- /dev/null +++ b/resources/views/data/tourisms/form.blade.php @@ -0,0 +1,127 @@ +@extends('layouts.vertical', ['subtitle' => $subtitle]) + +@section('content') + +@include('layouts.partials/page-title', ['title' => $title, 'subtitle' => $subtitle]) + +
+ @if (session('error')) +
+ {{ session('error') }} +
+ @endif + + @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + +
+
+
+ +
+
+
+ @csrf + @if(isset($modelInstance)) + @method('PUT') + @endif + +
+ @foreach($fields as $field => $label) +
+ + @php + $fieldType = $fieldTypes[$field] ?? 'text'; // Default text jika tidak ditemukan tipe + @endphp + + @if($fieldType == 'textarea') + + @elseif($fieldType == 'select' && isset($dropdownOptions[$field])) + + @elseif($fieldType == 'combobox' && isset($dropdownOptions[$field])) + + + @else + + @endif +
+ @endforeach +
+ +
+ +
+
+
+
+
+
+ + + + + +
+ +
+ +@endsection + +@section('scripts') +@vite(['resources/js/data/umkm/form-create-update.js']) +@endsection \ No newline at end of file diff --git a/resources/views/data/tourisms/index.blade.php b/resources/views/data/tourisms/index.blade.php new file mode 100644 index 0000000..d663489 --- /dev/null +++ b/resources/views/data/tourisms/index.blade.php @@ -0,0 +1,38 @@ +@extends('layouts.vertical', ['subtitle' => 'Pariwisata']) + +@section('css') +@vite(['node_modules/gridjs/dist/theme/mermaid.min.css']) +@endsection + +@section('content') +@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'Pariwisata']) + +
+
+
Daftar Pariwisata
+
+
+
+
+ + +
+
+
+
+
+
+
+ +{{--
--}} + +@endsection + +@section('scripts') +@vite(['resources/js/data/tourisms/data-tourisms.js']) +@endsection \ No newline at end of file diff --git a/resources/views/data/umkm/form-upload.blade.php b/resources/views/data/umkm/form-upload.blade.php new file mode 100644 index 0000000..fadfae0 --- /dev/null +++ b/resources/views/data/umkm/form-upload.blade.php @@ -0,0 +1,91 @@ +@extends('layouts.vertical', ['subtitle' => 'File Upload']) + +@section('content') + +@include('layouts.partials/page-title', ['title' => 'Form', 'subtitle' => 'File Uploads']) + +
+
+
+
+
+
Upload Data Umkm
+ +
+
+ +
+ +
+ +
+
+
+ +
+
+
+ +

Drop files here or click to upload.

+

+ Please upload a file with the extension .xls or .xlsx with a maximum size of 10 MB. +
+

+
+
+ +
    +
  • + +
    +
    +
    +
    + +
    +
    +
    +
    +
      +
    +

    + +
    +
    +
    + +
    +
    +
    +
  • +
+ +
+
+ +
+
+
+
+
+ +
+ +
+ +@endsection + +@section('scripts') +@vite(['resources/js/data/umkm/form-upload.js']) +@endsection \ No newline at end of file diff --git a/resources/views/data/umkm/form.blade.php b/resources/views/data/umkm/form.blade.php new file mode 100644 index 0000000..8b950eb --- /dev/null +++ b/resources/views/data/umkm/form.blade.php @@ -0,0 +1,127 @@ +@extends('layouts.vertical', ['subtitle' => $subtitle]) + +@section('content') + +@include('layouts.partials/page-title', ['title' => $title, 'subtitle' => $subtitle]) + +
+ @if (session('error')) +
+ {{ session('error') }} +
+ @endif + + @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + +
+
+
+ +
+
+
+ @csrf + @if(isset($modelInstance)) + @method('PUT') + @endif + +
+ @foreach($fields as $field => $label) +
+ + @php + $fieldType = $fieldTypes[$field] ?? 'text'; // Default text jika tidak ditemukan tipe + @endphp + + @if($fieldType == 'textarea') + + @elseif($fieldType == 'select' && isset($dropdownOptions[$field])) + + @elseif($fieldType == 'combobox' && isset($dropdownOptions[$field])) + + + @else + + @endif +
+ @endforeach +
+ +
+ +
+
+
+
+
+
+ + + + + +
+ +
+ +@endsection + +@section('scripts') +@vite(['resources/js/data/umkm/form-create-update.js']) +@endsection \ No newline at end of file diff --git a/resources/views/data/umkm/index.blade.php b/resources/views/data/umkm/index.blade.php new file mode 100644 index 0000000..6f8977d --- /dev/null +++ b/resources/views/data/umkm/index.blade.php @@ -0,0 +1,38 @@ +@extends('layouts.vertical', ['subtitle' => 'UMKM']) + +@section('css') +@vite(['node_modules/gridjs/dist/theme/mermaid.min.css']) +@endsection + +@section('content') +@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'UMKM']) + +
+
+
Daftar UMKM
+
+
+
+
+ + +
+
+
+
+
+
+
+ +
+ +@endsection + +@section('scripts') +@vite(['resources/js/data/umkm/data-umkm.js']) +@endsection \ No newline at end of file diff --git a/resources/views/report/tourisms/index.blade.php b/resources/views/report/tourisms/index.blade.php new file mode 100644 index 0000000..5e65d98 --- /dev/null +++ b/resources/views/report/tourisms/index.blade.php @@ -0,0 +1,28 @@ +@extends('layouts.vertical', ['subtitle' => 'Report Pariwisata']) + +@section('css') +@vite(['node_modules/gridjs/dist/theme/mermaid.min.css']) +@endsection + +@section('content') +@include('layouts.partials/page-title', ['title' => 'Report', 'subtitle' => 'Report Pariwisata']) + + +
+
+
Laporan Pariwisata
+
+
+
+
+
+
+
+
+
+ +@endsection + +@section('scripts') +@vite(['resources/js/report/tourisms/index.js']) +@endsection \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index fbdc03a..5af44ee 100644 --- a/routes/api.php +++ b/routes/api.php @@ -14,6 +14,8 @@ use App\Http\Controllers\Api\ScrapingController; use App\Http\Controllers\Api\UsersController; use App\Http\Controllers\Settings\SyncronizeController; use App\Http\Controllers\Api\AdvertisementController; +use App\Http\Controllers\Api\UmkmController; +use App\Http\Controllers\Api\TourismController; use Illuminate\Support\Facades\Route; Route::post('/login', [UsersController::class, 'login'])->name('api.user.login'); @@ -53,7 +55,18 @@ Route::group(['middleware' => 'auth:sanctum'], function (){ Route::apiResource('advertisements', AdvertisementController::class); Route::get('/combobox/search-options', [AdvertisementController::class, 'searchOptionsInAdvertisements']); Route::post('/advertisements/import', [AdvertisementController::class, 'importFromFile']); + Route::get('/download-template-advertisement', [AdvertisementController::class, 'downloadExcelAdvertisement']); + // umkm + Route::apiResource('umkm', UmkmController::class); + Route::post('/umkm/import', [UmkmController::class, 'importFromFile']); + Route::get('/download-template-umkm', [UmkmController::class, 'downloadExcelUmkm']); + + //tourism + Route::apiResource('tourisms', TourismController::class); + Route::post('/tourisms/import', [TourismController::class, 'importFromFile']); + + // data-settings Route::apiResource('/api-data-settings', DataSettingController::class); diff --git a/routes/web.php b/routes/web.php index 51104ea..10f6eed 100755 --- a/routes/web.php +++ b/routes/web.php @@ -11,6 +11,9 @@ use App\Http\Controllers\RolesController; use App\Http\Controllers\Settings\SettingsController; use App\Http\Controllers\Settings\SyncronizeController; use App\Http\Controllers\Data\AdvertisementController; +use App\Http\Controllers\Data\UmkmController; +use App\Http\Controllers\Data\TourismController; +use App\Http\Controllers\Report\ReportTourismController; use Illuminate\Support\Facades\Route; require __DIR__ . '/auth.php'; @@ -63,6 +66,25 @@ Route::group(['middleware' => 'auth'], function(){ // Rute khusus untuk create dan bulk-create Route::get('/advertisements/create', [AdvertisementController::class, 'create'])->name('advertisements.create'); Route::get('/advertisements/bulk-create', [AdvertisementController::class, 'bulkCreate'])->name('advertisements.bulk-create'); + + // Resource route, kecuali create karena dibuat terpisah + Route::resource('/umkm', UmkmController::class)->except(['create', 'show']); + + // Rute khusus untuk create dan bulk-create + Route::get('/umkm/create', [UmkmController::class, 'create'])->name('umkm.create'); + Route::get('/umkm/bulk-create', [UmkmController::class, 'bulkCreate'])->name('umkm.bulk-create'); + + // Resource route, kecuali create karena dibuat terpisah + Route::resource('/tourisms', TourismController::class)->except(['create', 'show']); + // Rute khusus untuk create dan bulk-create + Route::get('/tourisms/create', [TourismController::class, 'create'])->name('tourisms.create'); + Route::get('/tourisms/bulk-create', [TourismController::class, 'bulkCreate'])->name('tourisms.bulk-create'); Route::resource('/business-industries',BusinessOrIndustriesController::class); }); + + // Report + Route::group(['prefix' => '/report'], function(){ + // Resource route, kecuali create karena dibuat terpisah + Route::resource('/tourisms', ReportTourismController::class); + }); }); \ No newline at end of file