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/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 index 65b672a..6490c86 100644 --- a/app/Http/Controllers/Data/UmkmController.php +++ b/app/Http/Controllers/Data/UmkmController.php @@ -37,9 +37,9 @@ class UmkmController extends Controller $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' => DB::table('business_scale')->orderBy('business_scale')->pluck('business_scale', 'id'), - 'permit_status' => DB::table('permit_status')->orderBy('permit_status')->pluck('permit_status', 'id'), - 'business_form' => DB::table('business_form')->orderBy('business_form')->pluck('business_form', 'id') + '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(); @@ -60,7 +60,7 @@ class UmkmController extends Controller $modelInstance = Umkm::find($id); // Pastikan model ditemukan if (!$modelInstance) { - return redirect()->route('umkm.index')->with('error', 'umkm not found'); + return redirect()->route('umkm.index')->with('error', 'Umkm not found'); } // Mengambil dan memetakan village_name dan district_name 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/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/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/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/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/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/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/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/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()) +
+ +
+ @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.blade.php b/resources/views/data/umkm/form.blade.php index 645798d..8b950eb 100644 --- a/resources/views/data/umkm/form.blade.php +++ b/resources/views/data/umkm/form.blade.php @@ -50,7 +50,8 @@ +
+
+
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 ec38c6c..bd6f7e8 100644 --- a/routes/api.php +++ b/routes/api.php @@ -9,6 +9,7 @@ use App\Http\Controllers\Api\UsersController; use App\Http\Controllers\Settings\SyncronizeController; use App\Http\Controllers\Api\AdvertisementController; use App\Http\Controllers\Api\UmkmController; +use App\Http\Controllers\Api\TourismController; use Illuminate\Support\Facades\Route; Route::post('/login', [UsersController::class, 'login'])->name('api.user.login'); @@ -52,6 +53,10 @@ Route::group(['middleware' => 'auth:sanctum'], function (){ 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']); }); diff --git a/routes/web.php b/routes/web.php index dec8837..c8f56ea 100755 --- a/routes/web.php +++ b/routes/web.php @@ -8,6 +8,8 @@ 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'; @@ -57,5 +59,17 @@ Route::group(['middleware' => 'auth'], function(){ // 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'); + }); + + // Report + Route::group(['prefix' => '/report'], function(){ + // Resource route, kecuali create karena dibuat terpisah + Route::resource('/tourisms', ReportTourismController::class); }); }); \ No newline at end of file