From 861aff3c780c6643cd1fd45a068680dc70a620c1 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Wed, 24 Dec 2025 14:50:26 +0700 Subject: [PATCH] feat: Implement news listing page with search, filter, and pagination, and update news table schema. --- app/Http/Controllers/Home/NewsController.php | 70 +++++ .../2025_12_12_082036_create_news_table.php | 2 +- .../js/pages/home/components/Headline.jsx | 43 +++ resources/js/pages/home/components/Navbar.jsx | 10 +- .../js/pages/home/news/components/Author.jsx | 33 +++ .../home/news/components/MainContent.jsx | 272 ++++++++++++++++++ .../pages/home/news/components/MostViewed.jsx | 114 ++++++++ .../js/pages/home/news/components/Search.jsx | 31 ++ resources/js/pages/home/news/pages/Index.jsx | 32 +++ routes/web.php | 2 + 10 files changed, 606 insertions(+), 3 deletions(-) create mode 100644 app/Http/Controllers/Home/NewsController.php create mode 100644 resources/js/pages/home/components/Headline.jsx create mode 100644 resources/js/pages/home/news/components/Author.jsx create mode 100644 resources/js/pages/home/news/components/MainContent.jsx create mode 100644 resources/js/pages/home/news/components/MostViewed.jsx create mode 100644 resources/js/pages/home/news/components/Search.jsx create mode 100644 resources/js/pages/home/news/pages/Index.jsx diff --git a/app/Http/Controllers/Home/NewsController.php b/app/Http/Controllers/Home/NewsController.php new file mode 100644 index 0000000..48d16f9 --- /dev/null +++ b/app/Http/Controllers/Home/NewsController.php @@ -0,0 +1,70 @@ +get('search'); + $category = $request->get('category'); + + $news = News::with(['author', 'categories']) + ->published() + ->when($search, function ($query, $search) { + $query->where(function ($q) use ($search) { + $q->where('title', 'like', "%{$search}%") + ->orWhere('content', 'like', "%{$search}%") + ->orWhere('excerpt', 'like', "%{$search}%"); + }); + }) + ->when($category, function ($query, $category) { + if ($category !== 'all') { + $query->whereHas('categories', function ($q) use ($category) { + $q->where('categories.id', $category); + }); + } + }) + ->orderBy('published_at', 'desc') + ->paginate(12) + ->withQueryString() + ->through(function ($news) { + $news->thumbnail = $news->getFirstMediaUrl('news'); + $news->formatted_published_at = Carbon::parse($news->published_at) + ->locale('id') + ->translatedFormat('l, d F Y'); + + return $news; + }); + + $mostViewedNews = News::with(['author', 'categories']) + ->published() + ->orderBy('views', 'desc') + ->take(4) + ->get() + ->map(function ($news) { + $news->thumbnail = $news->getFirstMediaUrl('news'); + $news->formatted_published_at = Carbon::parse($news->published_at) + ->locale('id') + ->translatedFormat('l, d F Y'); + + return $news; + }); + + return Inertia::render('home/news/pages/Index', [ + 'pageTitle' => 'Berita', + 'pageDescription' => 'Dapatkan informasi terbaru, artikel, dan update berita terkini tentang Purwakarta.', + 'categories' => Category::active()->get(), + 'news' => $news, + 'mostViewedNews' => $mostViewedNews, + 'filters' => request()->only(['search', 'category']), + ]); + } +} diff --git a/database/migrations/2025_12_12_082036_create_news_table.php b/database/migrations/2025_12_12_082036_create_news_table.php index dd97848..d558310 100644 --- a/database/migrations/2025_12_12_082036_create_news_table.php +++ b/database/migrations/2025_12_12_082036_create_news_table.php @@ -21,7 +21,7 @@ public function up(): void $table->text('content'); $table->text('excerpt'); $table->string('link', 50)->nullable(); - $table->unsignedInteger('view')->default(0); + $table->unsignedInteger('views')->default(0); $table->enum('status', [NewsStatus::values()])->comment(NewsStatus::comment()); $table->timestamp('published_at')->nullable(); $table->timestamp('created_at')->useCurrent(); diff --git a/resources/js/pages/home/components/Headline.jsx b/resources/js/pages/home/components/Headline.jsx new file mode 100644 index 0000000..0c671d0 --- /dev/null +++ b/resources/js/pages/home/components/Headline.jsx @@ -0,0 +1,43 @@ +import Container from '@mui/material/Container'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; + +export default function Headline({ pageTitle, pageDescription }) { + return ( + + + + + {pageTitle} + + + {pageDescription} + + + + ); +} diff --git a/resources/js/pages/home/components/Navbar.jsx b/resources/js/pages/home/components/Navbar.jsx index 9c52ce7..184f37e 100644 --- a/resources/js/pages/home/components/Navbar.jsx +++ b/resources/js/pages/home/components/Navbar.jsx @@ -13,6 +13,7 @@ import MenuIcon from '@mui/icons-material/Menu'; import CloseRoundedIcon from '@mui/icons-material/CloseRounded'; import ColorModeIconDropdown from '../../theme/ColorModeIconDropdown'; import Logo from './Logo'; +import { router } from '@inertiajs/react'; const StyledToolbar = styled(Toolbar)(({ theme }) => ({ display: 'flex', @@ -53,8 +54,13 @@ export default function Navbar() { -