From 2618ac06d054dfc91741c55ef0d2335152f12125 Mon Sep 17 00:00:00 2001 From: arifal Date: Mon, 5 May 2025 18:36:56 +0700 Subject: [PATCH] partial update create page quick search --- .../Controllers/QuickSearchController.php | 69 +++++ resources/js/quick-search/detail.js | 0 resources/js/quick-search/index.js | 21 ++ resources/js/quick-search/result.js | 87 ++++++ resources/scss/pages/quick-search/index.scss | 78 ++++++ resources/scss/pages/quick-search/result.scss | 90 ++++++ resources/views/quick-search/detail.blade.php | 258 ++++++++++++++++++ resources/views/quick-search/index.blade.php | 30 ++ resources/views/quick-search/result.blade.php | 24 ++ routes/web.php | 6 + 10 files changed, 663 insertions(+) create mode 100644 app/Http/Controllers/QuickSearchController.php create mode 100644 resources/js/quick-search/detail.js create mode 100644 resources/js/quick-search/index.js create mode 100644 resources/js/quick-search/result.js create mode 100644 resources/scss/pages/quick-search/index.scss create mode 100644 resources/scss/pages/quick-search/result.scss create mode 100644 resources/views/quick-search/detail.blade.php create mode 100644 resources/views/quick-search/index.blade.php create mode 100644 resources/views/quick-search/result.blade.php diff --git a/app/Http/Controllers/QuickSearchController.php b/app/Http/Controllers/QuickSearchController.php new file mode 100644 index 0000000..acebfdc --- /dev/null +++ b/app/Http/Controllers/QuickSearchController.php @@ -0,0 +1,69 @@ +get("keyword"); + + return view('quick-search.result', compact('keyword')); + } + + public function quick_search_datatable(Request $request) + { + try { + $query = PbgTask::orderBy('id', 'desc'); + + if ($request->filled('search')) { + $search = $request->get('search'); + $query->where(function ($q) use ($search) { + $q->where('name', 'LIKE', "%$search%") + ->orWhere('registration_number', 'LIKE', "%$search%") + ->orWhere('address', 'LIKE', "%$search%") + ->orWhere('document_number', 'LIKE', "%$search%"); + }); + } + + return response()->json($query->paginate()); + } catch (\Throwable $e) { + \Log::error("Error fetching datatable data: " . $e->getMessage()); + return response()->json([ + 'message' => 'Terjadi kesalahan saat mengambil data.', + 'error' => $e->getMessage(), + ], 500); + } + } + + public function show($id) + { + try { + $data = PbgTask::with([ + 'pbg_task_retributions', + 'pbg_task_index_integrations', + 'pbg_task_retributions.pbg_task_prasarana' + ])->findOrFail($id); + + $statusOptions = PbgTaskStatus::getStatuses(); + $applicationTypes = PbgTaskApplicationTypes::labels(); + + return view("quick-search.detail", compact("data", 'statusOptions', 'applicationTypes')); + } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) { + \Log::warning("PbgTask with ID {$id} not found."); + return redirect()->route('quick-search.index')->with('error', 'Data tidak ditemukan.'); + } catch (\Throwable $e) { + \Log::error("Error in QuickSearchController@show: " . $e->getMessage()); + return response()->view('pages.404', [], 500); // Optional: create `resources/views/errors/500.blade.php` + } + } +} diff --git a/resources/js/quick-search/detail.js b/resources/js/quick-search/detail.js new file mode 100644 index 0000000..e69de29 diff --git a/resources/js/quick-search/index.js b/resources/js/quick-search/index.js new file mode 100644 index 0000000..83eccd0 --- /dev/null +++ b/resources/js/quick-search/index.js @@ -0,0 +1,21 @@ +document.addEventListener("DOMContentLoaded", function () { + const searchBtn = document.getElementById("searchBtn"); + const searchInput = document.getElementById("searchInput"); + + searchBtn.addEventListener("click", function () { + const keyword = searchInput.value.trim(); + if (keyword !== "") { + // Redirect to the route with query parameter + window.location.href = `/search-result?keyword=${encodeURIComponent( + keyword + )}`; + } + }); + + // Optional: trigger search on Enter key + searchInput.addEventListener("keydown", function (e) { + if (e.key === "Enter") { + searchBtn.click(); + } + }); +}); diff --git a/resources/js/quick-search/result.js b/resources/js/quick-search/result.js new file mode 100644 index 0000000..7b824e7 --- /dev/null +++ b/resources/js/quick-search/result.js @@ -0,0 +1,87 @@ +import { Grid, html } from "gridjs"; + +class QuickSearchResult { + constructor() { + this.table = null; + const baseInput = document.getElementById("base_url_datatable"); + this.datatableUrl = baseInput ? baseInput.value : ""; + } + + init() { + this.initDatatable(); + } + + initDatatable() { + const tableContainer = document.getElementById( + "datatable-quick-search-result" + ); + + const config = { + columns: [ + "ID", + { name: "Name" }, + { name: "Condition" }, + "Registration Number", + "Document Number", + { name: "Address" }, + "Status", + "Function Type", + "Consultation Type", + { name: "Due Date" }, + { + name: "Action", + formatter: (cell) => { + return html(` + + + + `); + }, + }, + ], + search: false, + pagination: { + limit: 15, + server: { + url: (prev, page) => + `${prev}${prev.includes("?") ? "&" : "?"}page=${ + page + 1 + }`, + }, + }, + sort: true, + server: { + url: this.datatableUrl, + then: (data) => + data.data.map((item) => [ + item.id, + item.name, + item.condition, + item.registration_number, + item.document_number, + item.address, + item.status_name, + item.function_type, + item.consultation_type, + item.due_date, + item, + ]), + total: (data) => data.total, + }, + }; + + if (this.table) { + this.table = this.table.updateConfig(config).forceRender(); + } else { + tableContainer.innerHTML = ""; + this.table = new Grid(config).render(tableContainer); + } + } +} + +document.addEventListener("DOMContentLoaded", function () { + const app = new QuickSearchResult(); + app.init(); +}); diff --git a/resources/scss/pages/quick-search/index.scss b/resources/scss/pages/quick-search/index.scss new file mode 100644 index 0000000..dbf96dc --- /dev/null +++ b/resources/scss/pages/quick-search/index.scss @@ -0,0 +1,78 @@ +.gsp-body { + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; // ensures full vertical centering + background: #f0f2f5; +} + +.gsp-icon { + width: 180px; // slightly smaller for better mobile view + height: auto; + margin-bottom: 15px; +} + +.gsp-title { + font-size: 36px; + font-weight: 700; + color: #333; +} + +.gsp-input { + width: 100%; + height: 44px; + font-size: 16px; + padding: 0 20px; + border-radius: 24px; + border: 1px solid #dfe1e5; + background-color: #fff; + box-shadow: none; + transition: box-shadow 0.2s ease-in-out, border-color 0.2s; + + &:focus { + border-color: transparent; + box-shadow: 0 1px 6px rgba(32, 33, 36, 0.28); + outline: none; + } +} + +.gsp-btn { + height: 44px; + padding: 0 24px; + font-size: 16px; + border: none; + border-radius: 24px; + background-color: #1a73e8; + color: white; + cursor: pointer; + transition: background-color 0.2s ease-in-out; + + &:hover { + background-color: #1558d6; + } +} + +@media (max-width: 576px) { + .gsp-input-wrapper { + flex-direction: column; + align-items: stretch; + } + + .gsp-btn { + width: 100%; + padding: 0 20px; + } + + .gsp-input { + padding: 0 20px; + font-size: 16px; + } + + .gsp-title { + font-size: 28px; + } + + .gsp-icon { + width: 140px; + } +} diff --git a/resources/scss/pages/quick-search/result.scss b/resources/scss/pages/quick-search/result.scss new file mode 100644 index 0000000..7578421 --- /dev/null +++ b/resources/scss/pages/quick-search/result.scss @@ -0,0 +1,90 @@ +.qs-wrapper { + padding: 30px 15px; + max-width: 1200px; + margin: 0 auto; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + color: #2c3e50; +} + +.qs-header { + margin-bottom: 30px; + text-align: center; + + h2 { + font-size: 24px; + font-weight: 600; + color: #1a237e; + + em { + font-style: normal; + color: #0d47a1; + } + } + + p { + font-size: 16px; + color: #555; + } +} + +.qs-table-wrapper { + background-color: #fff; + border-radius: 10px; + padding: 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + overflow-x: auto; // allow horizontal scroll on small screens +} + +/* Grid.js overrides */ +.qs-table-wrapper .gridjs { + font-size: 14px; + color: #333; +} + +.qs-table-wrapper .gridjs-table { + width: 100%; + border-collapse: collapse; +} + +.qs-table-wrapper .gridjs-th, +.qs-table-wrapper .gridjs-td { + padding: 12px 16px; + border: 1px solid #e0e0e0; + text-align: left; + vertical-align: middle; +} + +.qs-table-wrapper .gridjs-th { + background-color: #f5f5f5; + font-weight: 600; + color: #1b1b1b; +} + +.qs-table-wrapper .gridjs-tr:hover { + background-color: #f9f9f9; +} + +.qs-table-wrapper .gridjs-pagination { + margin-top: 16px; + justify-content: center; +} + +@media (max-width: 768px) { + .qs-header h2 { + font-size: 20px; + } + + .qs-wrapper { + padding: 20px 10px; + } + + .qs-table-wrapper { + padding: 15px; + } + + .qs-table-wrapper .gridjs-th, + .qs-table-wrapper .gridjs-td { + padding: 10px 12px; + font-size: 13px; + } +} diff --git a/resources/views/quick-search/detail.blade.php b/resources/views/quick-search/detail.blade.php new file mode 100644 index 0000000..66f08ed --- /dev/null +++ b/resources/views/quick-search/detail.blade.php @@ -0,0 +1,258 @@ +@extends('layouts.base', ['subtitle' => 'Quick Search']) + +@section('css') +@endsection + +@section('content') +
+
+
+
+
Detail Informasi Permohonan PBG
+
+
+
+
+
+
Nama Pemohon
+
{{ $data->name }}
+ +
Nama Pemilik
+
{{ $data->owner_name }}
+ +
Jenis Permohonan
+
{{ $applicationTypes[$data->application_type] ?? '-' }}
+ +
Kondisi
+
{{ $data->condition }}
+ +
Nomor Registrasi
+
{{ $data->registration_number }}
+ +
Nomor Dokumen
+
{{ $data->document_number }}
+ +
Status
+
{{ $statusOptions[$data->status] ?? '-' }}
+
+
+ +
+
+
Alamat
+
{{ $data->address }}
+ +
Status SLF
+
{{ $data->slf_status_name }}
+ +
Fungsi Bangunan
+
{{ $data->function_type }}
+ +
Jenis Konsultasi
+
{{ $data->consultation_type }}
+ +
Jatuh Tempo
+
{{ \Carbon\Carbon::parse($data->due_date)->format('d M Y') }}
+ +
Tanggal Dibuat
+
{{ \Carbon\Carbon::parse($data->task_created_at)->format('d M Y H:i') }}
+
+
+ +
+
+
+
+
+
+ +
+
+
+ @if ($data->pbg_task_retributions) +
+
+
+
Luas Bangunan
+
{{$data->pbg_task_retributions->luas_bangunan}}
+
+
+
Indeks Lokalitas
+
{{$data->pbg_task_retributions->indeks_lokalitas}}
+
+
+
Wilayah SHST
+
{{$data->pbg_task_retributions->wilayah_shst}}
+
+
+
Kegiatan Name
+
{{$data->pbg_task_retributions->kegiatan_name}}
+
+
+
Nilai SHST
+
{{$data->pbg_task_retributions->nilai_shst}}
+
+
+
Indeks Integrasi
+
{{$data->pbg_task_retributions->indeks_terintegrasi}}
+
+
+
Indeks Bg Terbangun
+
{{$data->pbg_task_retributions->indeks_bg_terbangun}}
+
+
+
+
+
Nilai Retribusi Bangunan
+
{{$data->pbg_task_retributions->nilai_retribusi_bangunan}}
+
+
+
Nilai Prasarana
+
{{$data->pbg_task_retributions->nilai_prasarana}}
+
+
+
PBG Dokumen
+
{{$data->pbg_task_retributions->pbg_document}}
+
+
+
Underpayment
+
{{$data->pbg_task_retributions->underpayment}}
+
+
+
SKRD Amount
+
{{$data->pbg_task_retributions->skrd_amount}}
+
+
+
+ @else +
+
+ Data Not Available +
+
+ @endif +
+
+ @if ($data->pbg_task_index_integrations) +
+
+
+
Indeks Fungsi Bangunan
+
{{$data->pbg_task_index_integrations->indeks_fungsi_bangunan}}
+
+
+
Indeks Parameter Kompleksitas
+
{{$data->pbg_task_index_integrations->indeks_parameter_kompleksitas}}
+
+
+
Indeks Parameter Permanensi
+
{{$data->pbg_task_index_integrations->indeks_parameter_permanensi}}
+
+
+
Indeks Paramter Ketinggian
+
{{$data->pbg_task_index_integrations->indeks_parameter_ketinggian}}
+
+
+
Faktor Kepemilikan
+
{{$data->pbg_task_index_integrations->faktor_kepemilikan}}
+
+
+
Indeks Terintegrasi
+
{{$data->pbg_task_index_integrations->indeks_terintegrasi}}
+
+
+
Total
+
{{$data->pbg_task_index_integrations->total}}
+
+
+
+ @else +
+
+ Data Not Available +
+
+ @endif +
+
+
+ @if ($data->pbg_task_retributions && $data->pbg_task_retributions->pbg_task_prasarana) + @foreach ($data->pbg_task_retributions->pbg_task_prasarana as $prasarana) +
+
+
Prasarana Type
+
{{$prasarana->prasarana_type}}
+
+
+
Building Type
+
{{$prasarana->building_type}}
+
+
+
Total
+
{{$prasarana->total}}
+
+
+
Quantity
+
{{$prasarana->quantity}}
+
+
+
Unit
+
{{$prasarana->unit}}
+
+
+
Index Prasarana
+
{{$prasarana->index_prasarana}}
+
+
+
Created At
+
{{$prasarana->created_at}}
+
+
+ @endforeach + @else +
+
+ Data Not Available +
+
+ @endif +
+
+
+ +
+
+
+
+
+
+
+ +@endsection + +@section('scripts') +@endsection \ No newline at end of file diff --git a/resources/views/quick-search/index.blade.php b/resources/views/quick-search/index.blade.php new file mode 100644 index 0000000..fbcec76 --- /dev/null +++ b/resources/views/quick-search/index.blade.php @@ -0,0 +1,30 @@ +@extends('layouts.base', ['subtitle' => 'Quick Search']) + +@section('css') +@vite(['resources/scss/pages/quick-search/index.scss']) +@endsection + +@section('body-attribuet') +class="gsp-body" +@endsection + +@section('content') +
+
+
+ PBG Icon +

SIBEDAS PBG

+
+
+
+ +
+ +
+
+
+@endsection + +@section('scripts') +@vite(['resources/js/quick-search/index.js']) +@endsection \ No newline at end of file diff --git a/resources/views/quick-search/result.blade.php b/resources/views/quick-search/result.blade.php new file mode 100644 index 0000000..de6b61e --- /dev/null +++ b/resources/views/quick-search/result.blade.php @@ -0,0 +1,24 @@ +@extends('layouts.base', ['subtitle' => 'Quick Search']) + +@section('css') +@vite(['resources/scss/pages/quick-search/result.scss']) +@vite(['node_modules/gridjs/dist/theme/mermaid.min.css']) +@endsection + +@section('content') + + +
+
+

Hasil Pencarian: {{ $keyword }}

+

Berikut adalah data hasil pencarian berdasarkan kata kunci yang Anda masukkan.

+
+
+
+
+
+@endsection + +@section('scripts') +@vite(['resources/js/quick-search/result.js']) +@endsection \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index ca33c37..82521e1 100755 --- a/routes/web.php +++ b/routes/web.php @@ -15,6 +15,7 @@ use App\Http\Controllers\Master\UsersController; use App\Http\Controllers\MenusController; use App\Http\Controllers\PaymentRecapsController; use App\Http\Controllers\PbgTaskAttachmentsController; +use App\Http\Controllers\QuickSearchController; use App\Http\Controllers\ReportPaymentRecapsController; use App\Http\Controllers\ReportPbgPTSPController; use App\Http\Controllers\RequestAssignment\PbgTaskController; @@ -34,6 +35,11 @@ use Illuminate\Support\Facades\Route; require __DIR__ . '/auth.php'; +Route::get('/search', [QuickSearchController::class, 'index'])->name('search'); +Route::get('/search-result', [QuickSearchController::class, 'search_result'])->name('search-result'); +Route::get('/quick-search-datatable', [QuickSearchController::class, 'quick_search_datatable'])->name('quick-search-datatable'); +Route::get('/quick-search/{id}', [QuickSearchController::class, 'show'])->name('quick-search.detail'); + // auth Route::group(['middleware' => 'auth'], function(){