diff --git a/app/Http/Controllers/FrontEnd/PageController.php b/app/Http/Controllers/FrontEnd/PageController.php index b665d330a2..1293e312ed 100644 --- a/app/Http/Controllers/FrontEnd/PageController.php +++ b/app/Http/Controllers/FrontEnd/PageController.php @@ -42,6 +42,7 @@ use App\Models\Event; use App\Models\Kategori; use App\Models\Survei; +use App\Models\TipePotensi; use App\Services\DesaService; use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; @@ -140,12 +141,23 @@ public function filterFeeds(Request $request): JsonResponse return response()->json(compact('html')); } - public function PotensiByKategory(string $slug): View + public function PotensiIndex(): View { $page_title = 'Potensi'; - $page_description = 'Potensi-Potensi'; + $page_description = 'Potensi-Potensi Kecamatan'; + $kategori_potensi = TipePotensi::all(); + + return view('pages.potensi.index', compact(['page_title', 'page_description', 'kategori_potensi'])); + } + + public function PotensiByKategory(string $slug): View + { + $kategori = TipePotensi::where('slug', $slug)->first(); + $page_title = 'Potensi' . ($kategori ? ' - ' . $kategori->nama_kategori : ''); + $page_description = 'Potensi-Potensi Kecamatan' . ($kategori ? ' Kategori ' . $kategori->nama_kategori : ''); + $kategori_potensi = TipePotensi::all(); - return view('pages.potensi.index', compact(['page_title', 'page_description', 'slug'])); + return view('pages.potensi.index', compact(['page_title', 'page_description', 'slug', 'kategori', 'kategori_potensi'])); } public function PotensiShow(string $kategori, string $id): View diff --git a/app/Http/Controllers/Setting/NavMenuController.php b/app/Http/Controllers/Setting/NavMenuController.php index 5855dbbe5b..98eaca5c10 100644 --- a/app/Http/Controllers/Setting/NavMenuController.php +++ b/app/Http/Controllers/Setting/NavMenuController.php @@ -33,14 +33,14 @@ use App\Http\Controllers\Controller; use App\Models\Artikel; +use App\Models\JenisDokumen; use App\Models\Kategori; use App\Models\NavMenu; -use App\Models\JenisDokumen; +use App\Models\TipePotensi; use Illuminate\Http\Request; class NavMenuController extends Controller { - public function index() { $page_title = 'Pengaturan Menu'; @@ -65,12 +65,17 @@ public function index() ), 'Kategori' => Kategori::cursor()->pluck('nama', 'link')->toArray(), 'Dokumen' => JenisDokumen::cursor()->pluck('nama', 'link')->toArray(), + 'Potensi' => array_merge( + ['/potensi' => 'Semua Potensi'], + TipePotensi::cursor()->mapWithKeys(function ($item) { + return ['/potensi/' . $item->slug => $item->nama_kategori]; + })->toArray() + ), ]; return view('setting.nav_menu.index', compact('page_title', 'page_description', 'nav_menus', 'sourceItem')); } - public function store(Request $request) { NavMenu::whereNotNull('id')->delete(); @@ -90,11 +95,12 @@ private function loopTree(array $elements, $parentId = null) { $sequence = 1; foreach ($elements as $element) { + $type = strtolower($element['type'] ?? ''); $input = [ 'name' => $element['text'], 'url' => $element['href'], 'target' => $element['target'], - 'type' => $element['type'], + 'type' => in_array($type, ['link', 'halaman', 'kategori', 'modul', 'dokumen']) ? $type : 'modul', 'is_show' => isset($element['is_show']) ? $element['is_show'] : 1, 'order' => $sequence, 'parent_id' => $parentId, diff --git a/catatan_rilis.md b/catatan_rilis.md index 95607af530..73ff564175 100644 --- a/catatan_rilis.md +++ b/catatan_rilis.md @@ -23,6 +23,7 @@ Terimakasih [isi disini] yang telah berkontribusi langsung mengembangkan aplikas 12. [#1737](https://github.com/OpenSID/OpenDK/issues/1737) fungsi kirim pesan error 500. 13. [#1761](https://github.com/OpenSID/OpenDK/issues/1761)Perbaikan validasi valid_file menolak PDF sah karena string generik "function". 14. [#1764](https://github.com/OpenSID/OpenDK/issues/1764) Gagal Menampilkan data foto/video dari link pada web dan admin. +15. [#1767](https://github.com/OpenSID/OpenDK/issues/1767)Perbaikan menu potensi pada halaman publik tidak berfungsi. #### TEKNIS diff --git a/database/migrations/2026_09_30_080000_fix_potensi_nav_menu.php b/database/migrations/2026_09_30_080000_fix_potensi_nav_menu.php new file mode 100644 index 0000000000..271da7b608 --- /dev/null +++ b/database/migrations/2026_09_30_080000_fix_potensi_nav_menu.php @@ -0,0 +1,40 @@ +where('url', '#') + ->update([ + 'url' => '/potensi', + 'target' => '_self', + 'type' => 'modul', + ]); + + try { + app(CacheService::class)->removeCachePrefix(config('theme-api.website.cache_prefix', 'website:api')); + } catch (\Throwable $e) { + // Abaikan jika cache service belum siap + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // Tidak perlu direverse karena perbaikan data + } +}; diff --git a/database/seeders/DasNavigationTableSeeder.php b/database/seeders/DasNavigationTableSeeder.php index faffe95350..e31e22e5d4 100644 --- a/database/seeders/DasNavigationTableSeeder.php +++ b/database/seeders/DasNavigationTableSeeder.php @@ -77,8 +77,8 @@ public function run() [ 'name' => 'Potensi', 'slug' => Str::slug('Potensi'), - 'type' => MenuTipe::EKSTERNAL, - 'url' => '#', + 'type' => MenuTipe::POTENSI, + 'url' => 'potensi', 'order' => 4, 'status' => 1, ], diff --git a/resources/views/setting/nav_menu/field.blade.php b/resources/views/setting/nav_menu/field.blade.php index 11d434cbee..d2d4c086d1 100644 --- a/resources/views/setting/nav_menu/field.blade.php +++ b/resources/views/setting/nav_menu/field.blade.php @@ -24,6 +24,9 @@ + @@ -63,6 +66,7 @@ case 'Kategori': case 'Halaman': case 'Dokumen': + case 'Potensi': let select = document.querySelector('select[name=sourcelist]'); select.style.display = 'block'; // Tampilkan select sourcelist diff --git a/resources/views/setting/nav_menu/index.blade.php b/resources/views/setting/nav_menu/index.blade.php index e5e081ce31..7cdd994eaf 100644 --- a/resources/views/setting/nav_menu/index.blade.php +++ b/resources/views/setting/nav_menu/index.blade.php @@ -157,6 +157,7 @@ let sourceKategori = $('#sourceKategori'); let sourceModul = $('#sourceModul'); let sourceDokumen = $('#sourceDokumen'); + let sourcePotensi = $('#sourcePotensi'); let source = ''; if (sourceLink.is(':checked')) source = sourceLink.val(); @@ -164,6 +165,7 @@ else if (sourceKategori.is(':checked')) source = sourceKategori.val(); else if (sourceModul.is(':checked')) source = sourceModul.val(); else if (sourceDokumen.is(':checked')) source = sourceDokumen.val(); + else if (sourcePotensi.is(':checked')) source = 'modul'; editor.add(source); }); diff --git a/resources/views/setting/navigation/form.blade.php b/resources/views/setting/navigation/form.blade.php index ee4e4548e6..e7e93a43fc 100644 --- a/resources/views/setting/navigation/form.blade.php +++ b/resources/views/setting/navigation/form.blade.php @@ -27,18 +27,19 @@ @endforeach diff --git a/routes/web.php b/routes/web.php index 1f0e59d33d..fcde690df4 100644 --- a/routes/web.php +++ b/routes/web.php @@ -233,7 +233,7 @@ }); Route::group(['prefix' => 'potensi'], function () { - Route::permanentRedirect('/', '/'); + Route::get('/', 'PageController@PotensiIndex')->name('potensi.index'); Route::get('{slug}', 'PageController@PotensiByKategory')->name('potensi.kategori'); Route::get('{kategori}/{id}', 'PageController@PotensiShow')->name('potensi.kategori.show'); }); diff --git a/tests/Feature/Frontend/PotensiPublicTest.php b/tests/Feature/Frontend/PotensiPublicTest.php new file mode 100644 index 0000000000..9139b9c73f --- /dev/null +++ b/tests/Feature/Frontend/PotensiPublicTest.php @@ -0,0 +1,73 @@ +tipePotensi = TipePotensi::firstOrCreate( + ['slug' => 'pariwisata'], + ['nama_kategori' => 'Pariwisata'] + ); + + $this->potensi = Potensi::firstOrCreate( + ['nama_potensi' => 'Air Terjun Indah'], + [ + 'kategori_id' => $this->tipePotensi->id, + 'deskripsi' => 'Deskripsi wisata alam air terjun indah', + 'lokasi' => 'Kecamatan Contoh', + 'file_gambar' => 'storage/potensi_kecamatan/sample.jpg', + ] + ); +}); + +it('displays all potensi page at /potensi successfully', function () { + $response = $this->get('/potensi'); + + $response->assertOk(); + $response->assertViewIs('pages.potensi.index'); + $response->assertViewHas('page_title', 'Potensi'); + $response->assertViewHas('kategori_potensi'); +}); + +it('displays potensi by category page at /potensi/{slug} successfully', function () { + $response = $this->get('/potensi/' . $this->tipePotensi->slug); + + $response->assertOk(); + $response->assertViewIs('pages.potensi.index'); + $response->assertViewHas('slug', $this->tipePotensi->slug); + $response->assertViewHas('kategori_potensi'); +}); + +it('displays potensi detail page at /potensi/{kategori}/{id} successfully', function () { + $response = $this->get('/potensi/' . $this->tipePotensi->slug . '/' . $this->potensi->id); + + $response->assertOk(); + $response->assertViewIs('pages.potensi.show'); + $response->assertViewHas('id', (string) $this->potensi->id); +}); + +it('ensures nav_menus table contains /potensi for Potensi menu', function () { + $nav = NavMenu::where('name', 'Potensi')->first(); + + expect($nav)->not->toBeNull(); + expect($nav->url)->toBe('/potensi'); +}); + +it('returns /potensi in the website api navmenus data', function () { + $response = $this->getJson('/api/frontend/v1/website'); + + $response->assertOk(); + $data = $response->json('data'); + + $navmenusItem = collect($data)->firstWhere('id', 'navmenus'); + expect($navmenusItem)->not->toBeNull(); + + $menus = $navmenusItem['attributes'][0] ?? []; + $potensiMenu = collect($menus)->firstWhere('name', 'Potensi'); + + expect($potensiMenu)->not->toBeNull(); + expect($potensiMenu['url'])->toBe('/potensi'); +}); diff --git a/themes/opendk/default/resources/views/pages/potensi/index.blade.php b/themes/opendk/default/resources/views/pages/potensi/index.blade.php index 27cdc7c582..b1d8b89671 100644 --- a/themes/opendk/default/resources/views/pages/potensi/index.blade.php +++ b/themes/opendk/default/resources/views/pages/potensi/index.blade.php @@ -4,10 +4,18 @@