From c6c25d5fe725f8035d831ff64397e7bbf9846459 Mon Sep 17 00:00:00 2001 From: habibie11 Date: Wed, 4 Mar 2026 21:54:41 +0700 Subject: [PATCH] add artikel opensid ke frontend --- .../Controllers/Web/ArtikelController.php | 77 +++++++++++ app/Services/ArtikelService.php | 26 +++- resources/views/web/artikel/index.blade.php | 89 +++++++++++++ resources/views/web/artikel/show.blade.php | 74 +++++++++++ resources/views/web/index.blade.php | 12 +- .../web/partials/artikel_terbaru.blade.php | 124 ++++++++++++++++++ routes/web.php | 4 + tests/Feature/ArtikelWebTest.php | 98 ++++++++++++++ 8 files changed, 495 insertions(+), 9 deletions(-) create mode 100644 app/Http/Controllers/Web/ArtikelController.php create mode 100644 resources/views/web/artikel/index.blade.php create mode 100644 resources/views/web/artikel/show.blade.php create mode 100644 resources/views/web/partials/artikel_terbaru.blade.php create mode 100644 tests/Feature/ArtikelWebTest.php diff --git a/app/Http/Controllers/Web/ArtikelController.php b/app/Http/Controllers/Web/ArtikelController.php new file mode 100644 index 00000000..7f1785f1 --- /dev/null +++ b/app/Http/Controllers/Web/ArtikelController.php @@ -0,0 +1,77 @@ +artikelService = $artikelService; + } + + /** + * Tampilkan daftar artikel OpenSID. + * + * @param Request $request + * @return \Illuminate\View\View + */ + public function index(Request $request) + { + $search = $request->get('search', ''); + $categoryId = $request->get('kategori', ''); + + $filters = []; + if (!empty($search)) { + $filters['filter[search]'] = $search; + } + if (!empty($categoryId)) { + $filters['filter[id_kategori]'] = $categoryId; + } + + // Ambil data melalui service + // Format Pagination API json format + $filters['page[number]'] = $request->get('page', 1); + $filters['page[size]'] = 6; + $filters['sort'] = '-tgl_upload'; // Terurut berdasarkan tanggal terbaru + + // Caching ditangani oleh ArtikelService + $articles = $this->artikelService->artikel($filters); + + // Filter out disabled articles just in case API returns them + $articles = $articles->filter(function ($item) { + return isset($item->enabled) && $item->enabled == 1; + }); + + return view('web.artikel.index', [ + 'title' => 'Artikel Berita', + 'articles' => $articles, + 'search' => $search, + 'categoryId' => $categoryId + ]); + } + + /** + * Tampilkan detail artikel OpenSID. + * + * @param int $id + * @return \Illuminate\View\View + */ + public function show($id) + { + $article = $this->artikelService->artikelById($id); + + if (!$article || !isset($article->enabled) || $article->enabled == 0) { + abort(404, 'Artikel tidak ditemukan atau tidak aktif'); + } + + return view('web.artikel.show', [ + 'object' => $article + ]); + } +} diff --git a/app/Services/ArtikelService.php b/app/Services/ArtikelService.php index 5b899677..618ea0c0 100644 --- a/app/Services/ArtikelService.php +++ b/app/Services/ArtikelService.php @@ -14,12 +14,26 @@ public function artikel(array $filters = []) // Ambil dari cache dulu return Cache::remember($cacheKey, $this->cacheTtl, function () use ($filters) { - $data = $this->apiRequest('/api/v1/artikel', $filters); - if (! $data) { + $data = $this->apiRequest('/api/v1/artikel/list', $filters); + if (!$data) { return collect([]); } - - return collect($data)->map(fn ($item) => (object) $item['attributes']); + return collect($data)->map(function ($item) { + // Return 'attributes' but with 'id' populated + $attributes = $item['attributes'] ?? []; + $attributes['id'] = $item['id'] ?? null; + + // Fetch detail to enrich with gambar and isi if missing + if (isset($attributes['id']) && (!isset($attributes['gambar']) || !isset($attributes['isi']))) { + $detail = $this->artikelById($attributes['id']); + if ($detail) { + $attributes['gambar'] = $detail->gambar ?? null; + $attributes['isi'] = $detail->isi ?? null; + } + } + + return (object) $attributes; + }); }); } @@ -32,8 +46,8 @@ public function artikelById(int $id) 'id' => $id, ]); - if (is_array($data) && isset($data['data'])) { - return (object) $data['data']; + if (is_array($data) && count($data) > 0) { + return (object) $data; } return null; diff --git a/resources/views/web/artikel/index.blade.php b/resources/views/web/artikel/index.blade.php new file mode 100644 index 00000000..7593e8bc --- /dev/null +++ b/resources/views/web/artikel/index.blade.php @@ -0,0 +1,89 @@ +@extends('layouts.web') + +@section('content') +
+ +
+
+
+

{{ $title }}

+ +
+
+
+ + + +
+
+
+ +
+ +
+ +
+
+
+ + +
+
+ @forelse ($articles as $article) +
+
+ @if (isset($article->gambar) && !empty($article->gambar)) + {{ $article->judul ?? '' }} + @else + + Placeholder + Thumbnail + + @endif +
+
{{ $article->judul ?? '' }}
+
+ {{ $article->kategori_nama ?? 'Kategori' }} +
+
+ {!! Str::words(strip_tags($article->isi ?? ''), 20, '...') !!} +
+
+ + + {{ isset($article->tgl_upload) ? \Carbon\Carbon::parse($article->tgl_upload)->translatedFormat('d F Y') : '' }} + +
+
+
+
+ @empty +
+
+ Belum ada artikel yang dipublikasikan. +
+
+ @endforelse +
+ + +
+ +
+@endsection \ No newline at end of file diff --git a/resources/views/web/artikel/show.blade.php b/resources/views/web/artikel/show.blade.php new file mode 100644 index 00000000..cccd82a4 --- /dev/null +++ b/resources/views/web/artikel/show.blade.php @@ -0,0 +1,74 @@ +@extends('layouts.web') + +@section('content') +
+ +
+
+
+ +
+
+
+ + + +
+
+
+
+
+

{{ $object->judul ?? '' }}

+
+ {{ $object->kategori_nama ?? 'Kategori' }} + {{ isset($object->tgl_upload) ? \Carbon\Carbon::parse($object->tgl_upload)->translatedFormat('d F Y') : '' }} +
+
+ + @if (isset($object->gambar) && !empty($object->gambar)) + {{ $object->judul ?? '' }} + @endif + +
+
+ {!! $object->isi ?? '' !!} +
+
+ + +
+
+
+
+ +
+@endsection + +@push('styles') + +@endpush \ No newline at end of file diff --git a/resources/views/web/index.blade.php b/resources/views/web/index.blade.php index 5a807326..2c887c43 100644 --- a/resources/views/web/index.blade.php +++ b/resources/views/web/index.blade.php @@ -32,6 +32,12 @@ + +
+ @include('web.partials.artikel_terbaru') +
+ +
@include('web.partials.team') @@ -41,7 +47,7 @@ @push('scripts') -@endpush +@endpush \ No newline at end of file diff --git a/resources/views/web/partials/artikel_terbaru.blade.php b/resources/views/web/partials/artikel_terbaru.blade.php new file mode 100644 index 00000000..685ec992 --- /dev/null +++ b/resources/views/web/partials/artikel_terbaru.blade.php @@ -0,0 +1,124 @@ +
+
+
+
+

Artikel Terbaru

+

Berita dan informasi terbaru seputar {{ config('app.sebutanKab') }}

+
+
+ +
+
+
+
+ + @for ($i = 0; $i < 6; $i++) +
+
+
+
+
+ +
+
+ +
+

+ + + +

+
+
+
+ @endfor +
+
+
+
+ +@push('scripts') + +@endpush \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 013484a9..5e5fb95c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -399,8 +399,12 @@ Route::get('/geo-spasial', [PresisiController::class, 'geoSpasial'])->name('presisi.geo-spasial'); }); +use App\Http\Controllers\Web\ArtikelController; + Route::middleware(['website.enable', 'log.visitor'])->group(function () { Route::get('/', [PageController::class, 'getIndex'])->name('web.index'); + Route::get('artikel-opensid', [ArtikelController::class, 'index'])->name('web.artikel.index'); + Route::get('artikel-opensid/{id}', [ArtikelController::class, 'show'])->name('web.artikel.show'); Route::get('a/{aSlug}', [PageController::class, 'getArticle'])->name('article'); Route::get('p/{pSlug}', [PageController::class, 'getPage'])->name('page'); Route::get('c/{cSlug}', [PageController::class, 'getCategory'])->name('category'); diff --git a/tests/Feature/ArtikelWebTest.php b/tests/Feature/ArtikelWebTest.php new file mode 100644 index 00000000..4eb7e255 --- /dev/null +++ b/tests/Feature/ArtikelWebTest.php @@ -0,0 +1,98 @@ +withoutMiddleware([\App\Http\Middleware\WebsiteEnable::class]); + + // Mock the ArtikelService + $mockService = Mockery::mock(ArtikelService::class); + $mockService->shouldReceive('artikel')->andReturn(collect([ + (object) [ + 'id' => 1, + 'judul' => 'Test Artikel OpenSID', + 'isi' => 'Konten artikel test', + 'id_kategori' => 1, + 'kategori_nama' => 'Berita Desa', + 'tgl_upload' => '2023-10-01 10:00:00', + 'enabled' => 1, + ] + ])); + + $this->app->instance(ArtikelService::class, $mockService); + + $response = $this->get(route('web.artikel.index')); + $response->dump(); + $response->assertStatus(200); + $response->assertViewIs('web.artikel.index'); + $response->assertSee('Artikel Berita'); + $response->assertSee('Test Artikel OpenSID'); + $response->assertSee('Berita Desa'); + } + + /** @test */ + public function it_can_access_public_artikel_show() + { + $this->withoutMiddleware([\App\Http\Middleware\WebsiteEnable::class]); + + // Mock the ArtikelService + $mockService = Mockery::mock(ArtikelService::class); + $mockService->shouldReceive('artikelById')->with(1)->andReturn((object) [ + 'id' => 1, + 'judul' => 'Detail Test Artikel', + 'isi' => 'Konten detail artikel test', + 'id_kategori' => 1, + 'kategori_nama' => 'Berita Desa', + 'tgl_upload' => '2023-10-01 10:00:00', + 'enabled' => 1, + ]); + + $this->app->instance(ArtikelService::class, $mockService); + + $response = $this->get(route('web.artikel.show', ['id' => 1])); + $response->assertStatus(200); + $response->assertViewIs('web.artikel.show'); + $response->assertSee('Detail Test Artikel'); + $response->assertSee('Konten detail artikel test'); + } + + /** @test */ + public function it_aborts_404_for_disabled_or_missing_artikel() + { + $this->withoutMiddleware([\App\Http\Middleware\WebsiteEnable::class]); + + // Mock the ArtikelService + $mockService = Mockery::mock(ArtikelService::class); + $mockService->shouldReceive('artikelById')->with(99)->andReturn(null); + + $mockService->shouldReceive('artikelById')->with(2)->andReturn((object) [ + 'id' => 2, + 'judul' => 'Hidden Artikel', + 'enabled' => 0, + ]); + + $this->app->instance(ArtikelService::class, $mockService); + + // Test non-existent article + $response404 = $this->get(route('web.artikel.show', ['id' => 99])); + $response404->assertStatus(404); + + // Test disabled article + $responseDisabled = $this->get(route('web.artikel.show', ['id' => 2])); + $responseDisabled->assertStatus(404); + } +}