This commit is contained in:
Anang Yusman 2025-07-03 16:09:16 +08:00
parent b449cab9dd
commit 78c097e7a3
10 changed files with 799 additions and 142 deletions

View File

@ -0,0 +1,34 @@
import Author from "@/components/landing-page/author";
import HeaderCitizen from "@/components/landing-page/citizen-news/header-citizen";
import Footer from "@/components/landing-page/footer";
import Header from "@/components/landing-page/header";
import Latest from "@/components/landing-page/latest";
import LatestandPopular from "@/components/landing-page/latest-and-popular";
import Navbar from "@/components/landing-page/navbar";
import News from "@/components/landing-page/news";
import Image from "next/image";
export default function Development() {
return (
<div className="relative min-h-screen font-[family-name:var(--font-geist-sans)]">
<div className="fixed top-0 left-0 w-full h-auto z-0">
<Image
src="/rumput.jpg"
alt="Background"
width={1450}
height={600}
className="w-full h-auto object-cover"
priority
/>
</div>
<div className="relative z-10 bg-[#F2F4F3] max-w-7xl mx-auto">
<Navbar />
<div className="flex-1">
<HeaderCitizen />
</div>
<Footer />
</div>
</div>
);
}

View File

@ -0,0 +1,30 @@
import HeaderDevelopment from "@/components/landing-page/development/header-development";
import Footer from "@/components/landing-page/footer";
import Navbar from "@/components/landing-page/navbar";
import Image from "next/image";
export default function Development() {
return (
<div className="relative min-h-screen font-[family-name:var(--font-geist-sans)]">
<div className="fixed top-0 left-0 w-full h-auto z-0">
<Image
src="/rumput.jpg"
alt="Background"
width={1450}
height={600}
className="w-full h-auto object-cover"
priority
/>
</div>
<div className="relative z-10 bg-[#F2F4F3] max-w-7xl mx-auto">
<Navbar />
<div className="flex-1">
<HeaderDevelopment />
</div>
<Footer />
</div>
</div>
);
}

View File

@ -0,0 +1,34 @@
import Author from "@/components/landing-page/author";
import Footer from "@/components/landing-page/footer";
import Header from "@/components/landing-page/header";
import HeaderHealth from "@/components/landing-page/health/header-health";
import Latest from "@/components/landing-page/latest";
import LatestandPopular from "@/components/landing-page/latest-and-popular";
import Navbar from "@/components/landing-page/navbar";
import News from "@/components/landing-page/news";
import Image from "next/image";
export default function Development() {
return (
<div className="relative min-h-screen font-[family-name:var(--font-geist-sans)]">
<div className="fixed top-0 left-0 w-full h-auto z-0">
<Image
src="/rumput.jpg"
alt="Background"
width={1450}
height={600}
className="w-full h-auto object-cover"
priority
/>
</div>
<div className="relative z-10 bg-[#F2F4F3] max-w-7xl mx-auto">
<Navbar />
<div className="flex-1">
<HeaderHealth />
</div>
<Footer />
</div>
</div>
);
}

View File

@ -3,8 +3,9 @@ import Image from "next/image";
import Author from "../landing-page/author"; import Author from "../landing-page/author";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { getListArticle } from "@/service/article"; import { getArticleById, getListArticle } from "@/service/article";
import { close } from "@/config/swal"; import { close, loading } from "@/config/swal";
import { useParams } from "next/navigation";
type TabKey = "trending" | "comments" | "latest"; type TabKey = "trending" | "comments" | "latest";
@ -25,17 +26,35 @@ type Article = {
}[]; }[];
}; };
interface CategoryType {
id: number;
label: string;
value: number;
}
export default function DetailContent() { export default function DetailContent() {
const params = useParams();
const id = params?.id;
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [totalPage, setTotalPage] = useState(1); const [totalPage, setTotalPage] = useState(1);
const [articles, setArticles] = useState<Article[]>([]); const [articles, setArticles] = useState<Article[]>([]);
const [articleDetail, setArticleDetail] = useState<any>(null);
const [showData, setShowData] = useState("5"); const [showData, setShowData] = useState("5");
const [search, setSearch] = useState(""); const [search, setSearch] = useState("-");
const [selectedCategories, setSelectedCategories] = useState<any>(""); const [listCategory, setListCategory] = useState<CategoryType[]>([]);
const [selectedCategories, setSelectedCategories] = useState<any>("-");
const [startDateValue, setStartDateValue] = useState({ const [startDateValue, setStartDateValue] = useState({
startDate: null, startDate: null,
endDate: null, endDate: null,
}); });
const [detailfiles, setDetailFiles] = useState<any>([]);
const [mainImage, setMainImage] = useState(0);
const [thumbnail, setThumbnail] = useState("-");
const [diseId, setDiseId] = useState(0);
const [thumbnailImg, setThumbnailImg] = useState<File[]>([]);
const [selectedMainImage, setSelectedMainImage] = useState<number | null>(
null
);
const [tabArticles, setTabArticles] = useState<Article[]>([]); const [tabArticles, setTabArticles] = useState<Article[]>([]);
@ -55,8 +74,8 @@ export default function DetailContent() {
const req = { const req = {
limit: "5", limit: "5",
page: 1, page: 1,
search: "", search: "-",
categorySlug: "", categorySlug: "-",
sort: "desc", sort: "desc",
sortBy: "created_at", sortBy: "created_at",
}; };
@ -145,11 +164,28 @@ export default function DetailContent() {
// close(); // close();
} }
} }
useEffect(() => {
initStateData();
}, [listCategory]);
async function initStateData() {
loading();
const res = await getArticleById(id);
const data = res.data?.data;
setThumbnail(data?.thumbnailUrl);
setDiseId(data?.aiArticleId);
setDetailFiles(data?.files);
setArticleDetail(data); // <-- Add this
close();
}
return ( return (
<> <>
<div className="flex items-center bg-[#F2F4F3] w-full overflow-hidden mb-4 py-6 px-8"> <div className="flex items-center bg-[#F2F4F3] w-full overflow-hidden mb-4 py-6 px-8">
<Image <Image
src="/mikul.png" src={"/mikul.png"}
alt="Background" alt="Background"
width={272} width={272}
height={90} height={90}
@ -159,39 +195,67 @@ export default function DetailContent() {
</div> </div>
<div className="bg-white grid grid-cols-1 md:grid-cols-3 gap-6 px-8 py-8"> <div className="bg-white grid grid-cols-1 md:grid-cols-3 gap-6 px-8 py-8">
<div className="md:col-span-2"> <div className="md:col-span-2">
<p className="text-sm text-gray-500 mb-2">Home &gt; Internasional</p> <p className="text-sm text-gray-500 mb-2">Home {">"}Detail</p>
<h1 className="text-3xl md:text-4xl font-bold text-[#1a1a1a] leading-tight mb-4"> <h1 className="text-3xl md:text-4xl font-bold text-[#1a1a1a] leading-tight mb-4">
Bom Bunuh Diri Guncang Gereja di Damaskus, 20 Orang Tewas dan {articleDetail?.title}
Puluhan Terluka
</h1> </h1>
<div className="flex items-center space-x-2 text-sm text-gray-500 mb-4"> <div className="flex items-center space-x-2 text-sm text-gray-500 mb-4">
<Image <div className="text-[#31942E]">
src="/author.png" <svg
alt="author" xmlns="http://www.w3.org/2000/svg"
width={30} width="24"
height={30} height="24"
className="rounded-full" viewBox="0 0 24 24"
/> >
<span className="text-[#3ba6ed] font-medium"> <g
christine natalia fill="none"
// fill-rule="evenodd"
>
<path d="m12.594 23.258l-.012.002l-.071.035l-.02.004l-.014-.004l-.071-.036q-.016-.004-.024.006l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.016-.018m.264-.113l-.014.002l-.184.093l-.01.01l-.003.011l.018.43l.005.012l.008.008l.201.092q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.003-.011l.018-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10s10-4.477 10-10S17.523 2 12 2M8.5 9.5a3.5 3.5 0 1 1 7 0a3.5 3.5 0 0 1-7 0m9.758 7.484A7.99 7.99 0 0 1 12 20a7.99 7.99 0 0 1-6.258-3.016C7.363 15.821 9.575 15 12 15s4.637.821 6.258 1.984"
/>
</g>
</svg>
</div>
<span className="text-[#31942E] font-medium">
{articleDetail?.createdByName}
</span> </span>
<span></span> <span></span>
<span>23 Juni 2025</span> <span>
<span>
{new Date(articleDetail?.createdAt).toLocaleDateString(
"id-ID",
{
day: "numeric",
month: "long",
year: "numeric",
}
)}
</span>
</span>
<span></span> <span></span>
<span>Internasional</span> <span>{articleDetail?.categories?.[0]?.title}</span>
</div> </div>
<div className="w-full h-auto mb-6"> <div className="w-full h-auto mb-6">
<Image {articleDetail?.files?.[0]?.file_url ? (
src="/bom.png" <Image
alt="Berita" src={articleDetail.files[0].file_url}
width={800} alt="Berita"
height={400} width={800}
className="rounded-lg w-full object-cover" height={400}
/> className="rounded-lg w-full object-cover"
/>
) : (
<div className="w-full h-[400px] bg-gray-100 flex items-center justify-center rounded-lg">
<p className="text-gray-400 text-sm">Gambar tidak tersedia</p>
</div>
)}
<p className="text-sm text-gray-500 mt-2 text-end"> <p className="text-sm text-gray-500 mt-2 text-end">
Bom Bunuh Diri Guncang Gereja di Damaskus, 20 Orang Tewas dan {articleDetail?.slug}
Puluhan Terluka
</p> </p>
</div> </div>
<div className="flex relative"> <div className="flex relative">
@ -262,87 +326,32 @@ export default function DetailContent() {
</div> </div>
<div className="flex-1 overflow-y-auto"> <div className="flex-1 overflow-y-auto">
<p className="text-gray-700 leading-relaxed text-justify"> <p className="text-gray-700 leading-relaxed text-justify">
Sebuah aksi bom bunuh diri terjadi di Gereja Saint Elias, <span className="text-black font-bold text-md">
kawasan Dwelaa, Damaskus, Suriah, pada Minggu (22/6), menewaskan Mikulnews.com -
sedikitnya 20 orang dan melukai 52 lainnya. Insiden tragis ini </span>
terjadi saat gereja tengah dipenuhi jemaat, termasuk anak-anak
dan lansia, yang sedang mengikuti ibadah mingguan. Kementerian {articleDetail?.description}
Dalam Negeri Suriah mengonfirmasi bahwa pelaku serangan
merupakan anggota kelompok teroris ISIS. Dalam keterangan resmi,
pihak kementerian menyebut pelaku memasuki gereja dengan membawa
senjata api, melepaskan tembakan, dan kemudian meledakkan diri
dengan sabuk peledak yang dibawanya. Pasca ledakan, aparat
keamanan langsung mengamankan lokasi dan menutup akses ke area
sekitar untuk mencegah kemungkinan serangan susulan. Pihak
berwenang juga mengerahkan tim penyelamat dan tenaga medis untuk
mengevakuasi korban dan memberikan perawatan darurat kepada yang
terluka. Kementerian Kesehatan, melalui kantor berita SANA,
menginformasikan bahwa sebagian besar korban luka mengalami
cedera serius akibat serpihan ledakan. Sejumlah korban masih
dalam kondisi kritis dan dirawat di beberapa rumah sakit rujukan
di Damaskus. Seorang saksi mata bernama Lawrence Maamari
menuturkan bahwa pelaku masuk ke dalam gereja dengan senapan di
tangan. Jemaat yang panik sempat mencoba menghadang pelaku
sebelum akhirnya terjadi ledakan. Saksi lainnya, Ziad (40),
pemilik toko di dekat lokasi, mengatakan mendengar suara
tembakan disusul ledakan besar. Kami melihat kobaran api di
dalam gereja dan bangku-bangku terlempar ke arah pintu masuk,
ujarnya. Suasana mencekam sempat terjadi selama beberapa jam.
Beberapa warga kehilangan anggota keluarga dan berupaya
mencarinya di antara puing-puing bangunan serta rumah sakit
terdekat. Insiden ini menuai kecaman internasional. Utusan
Khusus PBB untuk Suriah, Geir Pedersen, menyebut aksi tersebut
sebagai kejahatan keji dan mendesak adanya penyelidikan
menyeluruh. Sementara itu, Kementerian Luar Negeri Prancis
menyatakan bahwa serangan ini merupakan bentuk terorisme brutal,
serta kembali menyuarakan pentingnya transisi damai di Suriah
agar seluruh warga dapat hidup dalam keamanan tanpa
diskriminasi. Pemerintah Suriah menilai serangan ini sebagai
langkah terdesak dari kelompok radikal untuk mengganggu
stabilitas nasional dan menciptakan ketegangan sektarian.
Menteri Dalam Negeri, Anas Khattab, menyampaikan belasungkawa
kepada keluarga korban dan menyatakan bahwa penyelidikan sudah
dimulai oleh tim khusus kementeriannya. Dalam keterangannya,
Khattab menegaskan bahwa aksi teror serupa tidak akan
menghentikan tekad pemerintah dalam menciptakan perdamaian. Ia
juga mengungkapkan bahwa kelompok ISIS kini menargetkan
komunitas-komunitas tertentu, termasuk umat Kristen dan Syiah,
dengan pola serangan yang lebih terorganisir. Beberapa minggu
sebelumnya, aparat keamanan berhasil menggagalkan sejumlah
rencana serangan dan menangkap sel-sel ISIS di wilayah Damaskus.
Operasi kontra-terorisme di Aleppo bahkan menewaskan tiga
anggota kelompok tersebut dan satu petugas keamanan. Insiden bom
bunuh diri di Damaskus menjadi pengingat bahwa ancaman
ekstremisme belum sepenuhnya sirna di Suriah. Pemerintah pun
terus berupaya meningkatkan keamanan dan memperkuat kerja sama
dengan pihak internasional dalam memberantas terorisme.
</p> </p>
<Author /> <Author />
<div className=" flex flex-row gap-2 items-center"> <div className="flex flex-row gap-2 items-center">
<span className="font-semibold text-sm text-gray-700"> <span className="font-semibold text-sm text-gray-700">
Tags: Tags:
</span> </span>
<div className="flex flex-wrap gap-2 mt-1"> <div className="flex flex-wrap gap-2 mt-1">
{[ {articleDetail?.tags ? (
"Bom bunuh diri Suriah", <span className="bg-gray-100 text-gray-700 text-sm px-2 py-1 rounded">
"Bom Damaskus", {articleDetail.tags}
"Gereja Saint Elias",
"Serangan ISIS",
].map((tag, index) => (
<span
key={index}
className="bg-gray-100 text-gray-700 text-sm px-2 py-1 rounded"
>
{tag}
</span> </span>
))} ) : (
<span className="text-sm text-gray-500">Tidak ada tag</span>
)}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div className="relative mb-2 h-[120px] overflow-hidden flex items-center border my-8"> <div className="relative mb-2 h-[120px] overflow-hidden flex items-center border my-8">
<Image <Image
src="/image-kolom.png" src={"/image-kolom.png"}
alt="Berita Utama" alt="Berita Utama"
fill fill
className="object-contain" className="object-contain"
@ -351,7 +360,7 @@ export default function DetailContent() {
<div className="mt-10"> <div className="mt-10">
<div className="flex items-center space-x-4 p-4 border rounded-lg mb-6"> <div className="flex items-center space-x-4 p-4 border rounded-lg mb-6">
<Image <Image
src="/author.png" src={"/author.png"}
alt="Author" alt="Author"
width={60} width={60}
height={60} height={60}
@ -457,7 +466,7 @@ export default function DetailContent() {
<div className="sticky top-0 space-y-6"> <div className="sticky top-0 space-y-6">
<div className="bg-white shadow p-4 rounded-lg"> <div className="bg-white shadow p-4 rounded-lg">
<Image <Image
src="/kolom.png" src={"/kolom.png"}
alt="Iklan" alt="Iklan"
width={345} width={345}
height={345} height={345}
@ -537,7 +546,7 @@ export default function DetailContent() {
<div className="space-y-4"> <div className="space-y-4">
<div className="relative"> <div className="relative">
<Image <Image
src="/gaza.png" src={"/gaza.png"}
alt="Recommended Article" alt="Recommended Article"
width={400} width={400}
height={200} height={200}
@ -557,7 +566,7 @@ export default function DetailContent() {
<div className="space-y-3"> <div className="space-y-3">
<div className="flex space-x-3"> <div className="flex space-x-3">
<Image <Image
src="/perang.png" src={"/perang.png"}
alt="OPM Serang Gereja" alt="OPM Serang Gereja"
width={80} width={80}
height={60} height={60}
@ -576,7 +585,7 @@ export default function DetailContent() {
<div className="flex space-x-3"> <div className="flex space-x-3">
<Image <Image
src="/jateng.png" src={"/jateng.png"}
alt="Denda Merokok" alt="Denda Merokok"
width={80} width={80}
height={60} height={60}
@ -595,7 +604,7 @@ export default function DetailContent() {
<div className="flex space-x-3"> <div className="flex space-x-3">
<Image <Image
src="/investasi.jpg" src={"/investasi.jpg"}
alt="Pengguna Internet" alt="Pengguna Internet"
width={80} width={80}
height={60} height={60}

View File

@ -0,0 +1,178 @@
"use client";
import { getListArticle } from "@/service/article";
import { useEffect, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { usePathname } from "next/navigation";
type Article = {
id: number;
title: string;
description: string;
categoryName: string;
createdAt: string;
createdByName: string;
thumbnailUrl: string;
categories: {
title: string;
}[];
files: {
file_url: string;
file_alt: string;
}[];
};
const slugToLabel = (slug: string) => {
const mapping: Record<string, string> = {
development: "Pembangunan",
health: "Kesehatan",
"citizen-news": "Berita Warga",
};
return mapping[slug] || slug.charAt(0).toUpperCase() + slug.slice(1);
};
export default function HeaderCitizen() {
const [page, setPage] = useState(1);
const [totalPage, setTotalPage] = useState(1);
const [articles, setArticles] = useState<Article[]>([]);
const [showData, setShowData] = useState("5");
const [search, setSearch] = useState("");
const [selectedCategories, setSelectedCategories] = useState<any>("");
const [startDateValue, setStartDateValue] = useState({
startDate: null,
endDate: null,
});
const pathname = usePathname(); // e.g., "/category/development"
const pathSegments = pathname.split("/").filter(Boolean); // ["category", "development"]
const categorySlug = pathSegments[1]; // "development"
const categoryLabel = slugToLabel(categorySlug);
useEffect(() => {
initState();
}, [page, showData, startDateValue, selectedCategories]);
async function initState() {
// loading();
const req = {
limit: showData,
page,
search,
categorySlug: Array.from(selectedCategories).join(","),
sort: "desc",
sortBy: "created_at",
};
try {
const res = await getListArticle(req);
setArticles(res?.data?.data || []);
setTotalPage(res?.data?.meta?.totalPage || 1);
} finally {
// close();
}
}
return (
<section className="max-w-7xl mx-auto bg-white">
<div className="flex flex-col items-start bg-[#F2F4F3] w-full overflow-hidden py-6 px-8 gap-3">
<Image
src="/mikul.png"
alt="Background"
width={272}
height={90}
className="w-full md:w-[272px] h-[90px] object-cover border"
priority
/>
<p className="text-gray-400 text-sm">
<Link href="/" className="hover:underline">
Home
</Link>{" "}
{">"} <span className="text-black">{categoryLabel}</span>
</p>
<p className="text-3xl font-bold ">Berita Warga</p>
</div>
<div className="pb-5">
<div className="grid grid-cols-1 md:grid-cols-3 gap-2 m-8">
{/* Gambar besar di kiri */}
{articles.length > 0 && (
<div className="md:col-span-2 relative">
<Link href={`/detail/${articles[0]?.id}`}>
<Image
src={
articles[0]?.files?.[0]?.file_url ||
articles[0]?.files?.[0]?.file_url ||
"/default-image.jpg"
}
alt={articles[0].title}
width={800}
height={500}
className="w-full h-full max-h-[460px] object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/50 to-transparent p-6 flex flex-col justify-end">
<span className="text-xs bg-yellow-400 text-black px-2 py-0.5 inline-block mb-2 uppercase w-[130px]">
{articles[0].categories?.[0]?.title || "TANPA KATEGORI"}
</span>
<h2 className="text-sm md:text-xl lg:text-2xl font-bold text-white leading-snug mb-2 w-full md:w-9/12">
{articles[0].title}
</h2>
<p className="text-white text-xs">
{articles[0].createdByName} -{" "}
{new Date(articles[0].createdAt).toLocaleDateString(
"id-ID",
{
day: "numeric",
month: "long",
year: "numeric",
}
)}
</p>
</div>
</Link>
</div>
)}
{/* Dua gambar kecil di kanan */}
<div className="grid grid-rows-2 gap-2">
{articles.slice(1, 3).map((article, index) => (
<div key={index} className="relative">
<Link href={`/detail/${article?.id}`}>
<Image
src={
article.thumbnailUrl ||
article?.files?.[0]?.file_url ||
"/default-image.jpg"
}
alt={article.title}
width={400}
height={240}
className="w-full h-56 object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/40 to-transparent p-4 flex flex-col justify-end">
<span className="text-xs bg-yellow-400 text-black px-2 py-0.5 inline-block uppercase w-[130px]">
{article.categoryName || "TANPA KATEGORI"}
</span>
<h3 className="text-sm font-semibold text-white leading-snug mb-1">
{article.title}
</h3>
</div>
</Link>
</div>
))}
</div>
</div>
<div className="relative mt-10 mb-2 h-[188px] overflow-hidden flex items-center mx-8 border my-8">
<Image
src="/image-kolom.png"
alt="Berita Utama"
fill
className="object-contain"
/>
</div>
</div>
</section>
);
}

View File

@ -0,0 +1,176 @@
"use client";
import { getListArticle } from "@/service/article";
import { useEffect, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { usePathname } from "next/navigation";
type Article = {
id: number;
title: string;
description: string;
categoryName: string;
createdAt: string;
createdByName: string;
thumbnailUrl: string;
categories: {
title: string;
}[];
files: {
file_url: string;
file_alt: string;
}[];
};
const slugToLabel = (slug: string) => {
const mapping: Record<string, string> = {
development: "Pembangunan",
health: "Kesehatan",
"citizen-news": "Berita Warga",
};
return mapping[slug] || slug.charAt(0).toUpperCase() + slug.slice(1);
};
export default function HeaderDevelopment() {
const [page, setPage] = useState(1);
const [totalPage, setTotalPage] = useState(1);
const [articles, setArticles] = useState<Article[]>([]);
const [showData, setShowData] = useState("5");
const [search, setSearch] = useState("");
const [selectedCategories, setSelectedCategories] = useState<any>("");
const [startDateValue, setStartDateValue] = useState({
startDate: null,
endDate: null,
});
const pathname = usePathname(); // e.g., "/category/development"
const pathSegments = pathname.split("/").filter(Boolean); // ["category", "development"]
const categorySlug = pathSegments[1]; // "development"
const categoryLabel = slugToLabel(categorySlug);
useEffect(() => {
initState();
}, [page, showData, startDateValue, selectedCategories]);
async function initState() {
// loading();
const req = {
limit: showData,
page,
search,
categorySlug: Array.from(selectedCategories).join(","),
sort: "desc",
sortBy: "created_at",
};
try {
const res = await getListArticle(req);
setArticles(res?.data?.data || []);
setTotalPage(res?.data?.meta?.totalPage || 1);
} finally {
// close();
}
}
return (
<section className="max-w-7xl mx-auto bg-white">
<div className="flex flex-col jus items-start bg-[#F2F4F3] w-full overflow-hidden py-6 px-8 gap-3">
<Image
src="/mikul.png"
alt="Background"
width={272}
height={90}
className="w-full md:w-[272px] h-[90px] object-cover border"
priority
/>
<p className="text-gray-400 text-sm">
<Link href="/" className="hover:underline">
Home
</Link>{" "}
{">"}{" "}
<Link href="/category" className="hover:underline">
Category
</Link>{" "}
{">"} <span className="text-black">{categoryLabel}</span>
</p>
<p className="text-3xl font-bold ">Pembangunan</p>
</div>
<div className="pb-5">
<div className="grid grid-cols-1 md:grid-cols-3 gap-2 m-8">
{/* Gambar besar di kiri */}
{articles.length > 0 && (
<div className="md:col-span-2 relative">
<Link href={`/detail/${articles[0]?.id}`}>
<Image
src={
articles[0]?.files?.[0]?.file_url ||
articles[0]?.files?.[0]?.file_url ||
"/default-image.jpg"
}
alt={articles[0].title}
width={800}
height={500}
className="w-full h-full max-h-[460px] object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/50 to-transparent p-6 flex flex-col justify-end">
<span className="text-xs bg-yellow-400 text-black px-2 py-0.5 inline-block mb-2 uppercase w-[130px]">
{articles[0].categories?.[0]?.title || "TANPA KATEGORI"}
</span>
<h2 className="text-sm md:text-xl lg:text-2xl font-bold text-white leading-snug mb-2 w-full md:w-9/12">
{articles[0].title}
</h2>
<p className="text-white text-xs">
{articles[0].createdByName} -{" "}
{new Date(articles[0].createdAt).toLocaleDateString(
"id-ID",
{
day: "numeric",
month: "long",
year: "numeric",
}
)}
</p>
</div>
</Link>
</div>
)}
{/* Dua gambar kecil di kanan */}
<div className="grid grid-rows-2 gap-2">
{articles.slice(1, 3).map((article, index) => (
<div key={index} className="relative">
<Link href={`/detail/${article?.id}`}>
<Image
src={
article.thumbnailUrl ||
article?.files?.[0]?.file_url ||
"/default-image.jpg"
}
alt={article.title}
width={400}
height={240}
className="w-full h-56 object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/40 to-transparent p-4 flex flex-col justify-end">
<span className="text-xs bg-yellow-400 text-black px-2 py-0.5 inline-block uppercase w-[130px]">
{article.categoryName || "TANPA KATEGORI"}
</span>
<h3 className="text-sm font-semibold text-white leading-snug mb-1">
{article.title}
</h3>
</div>
</Link>
</div>
))}
</div>
</div>
<div>
</div>>
</div>
</section>
);
}

View File

@ -72,13 +72,13 @@ export default function HeroNewsSection() {
</div> </div>
<div className="pb-5"> <div className="pb-5">
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-0.5 m-8 "> <div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-2 m-8 ">
{articles.length > 0 && ( {articles.length > 0 && (
<div className="md:col-span-2 lg:col-span-3 relative"> <div className="md:col-span-2 lg:col-span-3 relative">
<Link href={`/detail/${articles[0]?.id}`}> <Link href={`/detail/${articles[0]?.id}`}>
<Image <Image
src={ src={
articles[0].thumbnailUrl || articles[0]?.files?.[0]?.file_url ||
articles[0]?.files?.[0]?.file_url || articles[0]?.files?.[0]?.file_url ||
"/default-image.jpg" "/default-image.jpg"
} }
@ -113,7 +113,7 @@ export default function HeroNewsSection() {
<div className="md:col-span-1 lg:col-span-2 grid grid-cols-1 sm:grid-cols-2 gap-2"> <div className="md:col-span-1 lg:col-span-2 grid grid-cols-1 sm:grid-cols-2 gap-2">
{articles.slice(1, 5).map((article, index) => ( {articles.slice(1, 5).map((article, index) => (
<div key={index} className="relative"> <div key={index} className="relative">
<Link href={`/detail/${articles[0]?.id}`}> <Link href={`/detail/${article?.id}`}>
<Image <Image
src={ src={
article.thumbnailUrl || article.thumbnailUrl ||

View File

@ -0,0 +1,178 @@
"use client";
import { getListArticle } from "@/service/article";
import { useEffect, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { usePathname } from "next/navigation";
type Article = {
id: number;
title: string;
description: string;
categoryName: string;
createdAt: string;
createdByName: string;
thumbnailUrl: string;
categories: {
title: string;
}[];
files: {
file_url: string;
file_alt: string;
}[];
};
const slugToLabel = (slug: string) => {
const mapping: Record<string, string> = {
development: "Pembangunan",
health: "Kesehatan",
"citizen-news": "Berita Warga",
};
return mapping[slug] || slug.charAt(0).toUpperCase() + slug.slice(1);
};
export default function HeaderHealth() {
const [page, setPage] = useState(1);
const [totalPage, setTotalPage] = useState(1);
const [articles, setArticles] = useState<Article[]>([]);
const [showData, setShowData] = useState("5");
const [search, setSearch] = useState("");
const [selectedCategories, setSelectedCategories] = useState<any>("");
const [startDateValue, setStartDateValue] = useState({
startDate: null,
endDate: null,
});
const pathname = usePathname(); // e.g., "/category/development"
const pathSegments = pathname.split("/").filter(Boolean); // ["category", "development"]
const categorySlug = pathSegments[1]; // "development"
const categoryLabel = slugToLabel(categorySlug);
useEffect(() => {
initState();
}, [page, showData, startDateValue, selectedCategories]);
async function initState() {
// loading();
const req = {
limit: showData,
page,
search,
categorySlug: Array.from(selectedCategories).join(","),
sort: "desc",
sortBy: "created_at",
};
try {
const res = await getListArticle(req);
setArticles(res?.data?.data || []);
setTotalPage(res?.data?.meta?.totalPage || 1);
} finally {
// close();
}
}
return (
<section className="max-w-7xl mx-auto bg-white">
<div className="flex flex-col items-start bg-[#F2F4F3] w-full overflow-hidden py-6 px-8 gap-3">
<Image
src="/mikul.png"
alt="Background"
width={272}
height={90}
className="w-full md:w-[272px] h-[90px] object-cover border"
priority
/>
<p className="text-gray-400 text-sm">
<Link href="/" className="hover:underline">
Home
</Link>{" "}
{">"} <span className="text-black">{categoryLabel}</span>
</p>
<p className="text-3xl font-bold ">Kesehatan</p>
</div>
<div className="pb-5">
<div className="grid grid-cols-1 md:grid-cols-3 gap-2 m-8">
{/* Gambar besar di kiri */}
{articles.length > 0 && (
<div className="md:col-span-2 relative">
<Link href={`/detail/${articles[0]?.id}`}>
<Image
src={
articles[0]?.files?.[0]?.file_url ||
articles[0]?.files?.[0]?.file_url ||
"/default-image.jpg"
}
alt={articles[0].title}
width={800}
height={500}
className="w-full h-full max-h-[460px] object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/50 to-transparent p-6 flex flex-col justify-end">
<span className="text-xs bg-yellow-400 text-black px-2 py-0.5 inline-block mb-2 uppercase w-[130px]">
{articles[0].categories?.[0]?.title || "TANPA KATEGORI"}
</span>
<h2 className="text-sm md:text-xl lg:text-2xl font-bold text-white leading-snug mb-2 w-full md:w-9/12">
{articles[0].title}
</h2>
<p className="text-white text-xs">
{articles[0].createdByName} -{" "}
{new Date(articles[0].createdAt).toLocaleDateString(
"id-ID",
{
day: "numeric",
month: "long",
year: "numeric",
}
)}
</p>
</div>
</Link>
</div>
)}
{/* Dua gambar kecil di kanan */}
<div className="grid grid-rows-2 gap-2">
{articles.slice(1, 3).map((article, index) => (
<div key={index} className="relative">
<Link href={`/detail/${article?.id}`}>
<Image
src={
article.thumbnailUrl ||
article?.files?.[0]?.file_url ||
"/default-image.jpg"
}
alt={article.title}
width={400}
height={240}
className="w-full h-56 object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/40 to-transparent p-4 flex flex-col justify-end">
<span className="text-xs bg-yellow-400 text-black px-2 py-0.5 inline-block uppercase w-[130px]">
{article.categoryName || "TANPA KATEGORI"}
</span>
<h3 className="text-sm font-semibold text-white leading-snug mb-1">
{article.title}
</h3>
</div>
</Link>
</div>
))}
</div>
</div>
<div className="relative mt-10 mb-2 h-[188px] overflow-hidden flex items-center mx-8 border my-8">
<Image
src="/image-kolom.png"
alt="Berita Utama"
fill
className="object-contain"
/>
</div>
</div>
</section>
);
}

View File

@ -2,26 +2,43 @@
import { useState } from "react"; import { useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { Menu, Lock, Search } from "lucide-react"; import { Menu, Lock, Search } from "lucide-react";
import { usePathname } from "next/navigation";
const Navbar = () => { const Navbar = () => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const toggleMenu = () => setIsOpen(!isOpen); const toggleMenu = () => setIsOpen(!isOpen);
const pathname = usePathname();
const navLinks = [
{ href: "/", label: "BERANDA" },
{ href: "/category/development", label: "PEMBANGUNAN" },
{ href: "/category/health", label: "KESEHATAN" },
{ href: "/category/citizen-news", label: "BERITA WARGA" },
];
const isActive = (href: string) => {
if (href === "/") {
return pathname === "/";
}
return pathname.startsWith(href);
};
return ( return (
<nav className="w-full bg-white shadow-md"> <nav className="w-full bg-white shadow-md">
<div className="max-w-7xl mx-auto py-2 px-0 md:px-4 flex flex-col md:flex-row justify-end items-start md:justify-between md:items-center gap-4 bg-[#308A2E]"> <div className="max-w-7xl mx-auto py-2 px-0 md:px-4 flex flex-col md:flex-row justify-end items-start md:justify-between md:items-center gap-4 bg-[#308A2E]">
<div className="flex items-center gap-4 w-full md:w-auto mx-3 md:mx-5"> <div className="flex items-center gap-4 w-full md:w-auto mx-3 md:mx-5">
<div className="flex gap-3 text-xs mx-3 text-white"> <div className="flex gap-3 text-xs mx-3 text-white">
<Link href="/terpopuler" className="hover:text-yellow-400"> <Link href="/about" className="hover:text-yellow-400 ">
About About
</Link> </Link>
<Link href="/nusantara" className="hover:text-yellow-400"> <Link href="/advertise" className="hover:text-yellow-400">
Advertise Advertise
</Link> </Link>
<Link href="/catatan" className="hover:text-yellow-400"> <Link href="/privacy" className="hover:text-yellow-400">
Privacy & Policy Privacy & Policy
</Link> </Link>
<Link href="/inovasi" className="hover:text-yellow-400"> <Link href="/contact" className="hover:text-yellow-400">
Contact Contact
</Link> </Link>
</div> </div>
@ -29,7 +46,12 @@ const Navbar = () => {
<div className="flex items-center gap-5 text-sm whitespace-nowrap text-white mx-5"> <div className="flex items-center gap-5 text-sm whitespace-nowrap text-white mx-5">
<div className="hidden md:block min-w-fit whitespace-nowrap text-white text-xs"> <div className="hidden md:block min-w-fit whitespace-nowrap text-white text-xs">
Kamis, Maret 27, 2025 {new Date().toLocaleDateString("id-ID", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
})}
</div> </div>
<div className="flex gap-3 text-white text-lg"> <div className="flex gap-3 text-white text-lg">
<Link href="#" aria-label="Facebook"> <Link href="#" aria-label="Facebook">
@ -165,42 +187,38 @@ const Navbar = () => {
{/* Navigation Links (Desktop Only) */} {/* Navigation Links (Desktop Only) */}
<div className="hidden md:flex items-center md:gap-x-32 font-semibold text-sm"> <div className="hidden md:flex items-center md:gap-x-32 font-semibold text-sm">
<Link href="/" className="text-yellow-400 pl-4"> {navLinks.map((link, idx) => (
BERANDA <Link
</Link> key={idx}
<Link href="/terpopuler" className="hover:text-yellow-400"> href={link.href}
PEMBANGUNAN className={`pl-4 pr-4 ${
</Link> isActive(link.href)
<Link href="/nusantara" className="hover:text-yellow-400"> ? "text-yellow-400"
KESEHATAN : "hover:text-yellow-400 text-white"
</Link> }`}
<Link href="/catatan" className="hover:text-yellow-400 pr-4"> >
BERITA WARGA {link.label}
</Link> </Link>
))}
<Search className="w-5 h-5 hover:text-yellow-400 cursor-pointer ml-4" /> <Search className="w-5 h-5 hover:text-yellow-400 cursor-pointer ml-4" />
</div> </div>
</div> </div>
{isOpen && ( {isOpen && (
<div className="md:hidden px-4 pb-4 flex flex-col gap-2 font-semibold text-sm bg-[#31942E]"> <div className="md:hidden px-4 pb-4 flex flex-col gap-2 font-semibold text-sm bg-[#31942E]">
<Link href="/" className="text-yellow-400"> {navLinks.map((link, idx) => (
BERANDA <Link
</Link> key={idx}
<Link href="/terpopuler" className="hover:text-yellow-400"> href={link.href}
TERPOPULER className={`${
</Link> isActive(link.href)
<Link href="/nusantara" className="hover:text-yellow-400"> ? "text-yellow-400"
NUSANTARA : "hover:text-yellow-400 text-white"
</Link> }`}
<Link href="/catatan" className="hover:text-yellow-400"> >
CATATAN NEGERI {link.label}
</Link> </Link>
<Link href="/inovasi" className="hover:text-yellow-400"> ))}
INOVASI
</Link>
<Link href="/jaga" className="hover:text-yellow-400">
JAGA INDONESIA
</Link>
</div> </div>
)} )}
</div> </div>