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')
+
+
+
+
+
+
+
+
+ - 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')
+
+
+
+
 }})
+
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')
+
+
+
+@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(){