-
+
-
+
{articleDetail?.customCreatorName ||
articleDetail?.createdByName}
-
-
- {new Date(
- articleDetail?.publishedAt ?? articleDetail?.createdAt
- ).toLocaleDateString("id-ID", {
+ {new Date(
+ articleDetail?.publishedAt ?? articleDetail?.createdAt,
+ )
+ .toLocaleString("id-ID", {
day: "numeric",
month: "long",
year: "numeric",
- })}
-
+ hour: "2-digit",
+ minute: "2-digit",
+ hour12: false,
+ timeZone: "Asia/Jakarta",
+ })
+ .replace("pukul ", "")}{" "}
+ WIB
in
{articleDetail?.categories?.[0]?.title}
@@ -363,7 +368,7 @@ export default function DetailContent() {
- Komentar *
+ Komentar *
@@ -573,7 +578,7 @@ export default function DetailContent() {
htmlFor="nama"
className="block text-sm font-medium mb-1"
>
- Nama
*
+ Nama
*
- Email
*
+ Email
*
KIRIM KOMENTAR
@@ -634,7 +639,7 @@ export default function DetailContent() {
Kirim
@@ -675,7 +680,7 @@ export default function DetailContent() {
day: "2-digit",
month: "long",
year: "numeric",
- }
+ },
)}
💬 0
diff --git a/components/landing-page/development.tsx b/components/landing-page/development.tsx
new file mode 100644
index 0000000..6d6f912
--- /dev/null
+++ b/components/landing-page/development.tsx
@@ -0,0 +1,136 @@
+"use client";
+import { useEffect, useState } from "react";
+import Image from "next/image";
+import { getListArticle } from "@/service/article";
+import Link from "next/link";
+
+type Article = {
+ id: number;
+ title: string;
+ description: string;
+ categoryName: string;
+ slug: string;
+ createdAt: string;
+ publishedAt: string;
+ createdByName: string;
+ customCreatorName: string;
+ thumbnailUrl: string;
+ categories: { title: string }[];
+ files: { fileUrl: string; file_alt: string }[];
+};
+
+export default function Development() {
+ const [articles, setArticles] = useState
([]);
+ const [page, setPage] = useState(1);
+ const [totalPage, setTotalPage] = useState(1);
+
+ useEffect(() => {
+ initState();
+ }, [page]);
+
+ async function initState() {
+ const req = {
+ limit: "10",
+ page,
+ search: "",
+ categorySlug: "",
+ sort: "desc",
+ isPublish: true,
+ sortBy: "created_at",
+ };
+
+ try {
+ const res = await getListArticle(req);
+ setArticles(res?.data?.data || []);
+ setTotalPage(res?.data?.meta?.totalPage || 1);
+ } catch (err) {
+ console.error("Error fetching articles:", err);
+ }
+ }
+
+ // Format tanggal ke gaya lokal
+ const formatDate = (dateString: string) => {
+ const date = new Date(dateString);
+ return date.toLocaleDateString("id-ID", {
+ day: "2-digit",
+ month: "long",
+ year: "numeric",
+ });
+ };
+
+ // Mapping struktur seperti dummy sebelumnya
+ const leftMain = articles[0];
+ const leftList = articles.slice(1, 4);
+ const centerMain = articles[4];
+ const centerList = articles.slice(5, 8);
+ const rightMain = articles[8];
+ const rightList = articles.slice(9, 12);
+
+ return (
+
+
+
+
+
+
+
+ {articles.slice(0, 6).map((item) => (
+
+
+
+
+
+
+
+
+ BERITA OPINI
+
+
+
+
+ {item.title}
+
+
+
+ By{" "}
+
+ {item.customCreatorName}
+
+
+
+
+ {new Date(item.publishedAt).toLocaleDateString("id-ID", {
+ day: "numeric",
+ month: "long",
+ year: "numeric",
+ })}
+
+
+
+ ))}
+
+
+
+
+
+
+ );
+}
diff --git a/components/landing-page/footer.tsx b/components/landing-page/footer.tsx
index 0a1093e..d4e7895 100644
--- a/components/landing-page/footer.tsx
+++ b/components/landing-page/footer.tsx
@@ -1,108 +1,66 @@
+// components/Footer.tsx
import Image from "next/image";
-import Link from "next/link";
+import { Facebook, Twitter, Instagram, Youtube } from "lucide-react";
export default function Footer() {
return (
-
-
+
+
{/* Logo */}
-
+
- {/* Menu Links */}
-
- {[
- "About Us",
- "Cart",
- "Checkout",
- "Contact",
- "Homepage – Fast News",
- "Login/Register",
- "My account",
- "Sample Page",
- "Shop",
- ].map((item, idx) => (
-
- {item}
-
- ))}
+ {/* Subscribe Box */}
+
-
- {/* Social Icons */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Copyright */}
-
- © 2025 KebaikanIndonesia - All Rights Reserved.
-
+
+
+
+
+
+
+
+
+
+
+
+ © 2025 Mikul News - All Rights Reserved.
+
);
}
diff --git a/components/landing-page/header.tsx b/components/landing-page/header.tsx
new file mode 100644
index 0000000..f4ee40b
--- /dev/null
+++ b/components/landing-page/header.tsx
@@ -0,0 +1,232 @@
+"use client";
+
+import { getListArticle } from "@/service/article";
+import Image from "next/image";
+import Link from "next/link";
+import { useEffect, useState } from "react";
+
+type Article = {
+ id: number;
+ title: string;
+ description: string;
+ categoryName: string;
+ createdAt: string;
+ slug: string;
+ createdByName: string;
+ publishedAt: string;
+ customCreatorName: string;
+ thumbnailUrl: string;
+ categories: { title: string }[];
+ files: { fileUrl: string; file_alt: string }[];
+};
+
+export default function Header() {
+ const [articles, setArticles] = useState
([]);
+
+ useEffect(() => {
+ const fetchArticles = async () => {
+ const req = {
+ limit: "10",
+ page: 1,
+ search: "",
+ categorySlug: "",
+ sort: "desc",
+ isPublish: true,
+ sortBy: "created_at",
+ };
+
+ const res = await getListArticle(req);
+ setArticles(res?.data?.data || []);
+ };
+
+ fetchArticles();
+ }, []);
+
+ const flashArticles = articles.slice(0, 8);
+ const mainArticle = articles[8] || articles[0];
+ const recentPosts = articles.slice(1, 5);
+
+ return (
+
+ {/* FLASH STRIP */}
+
+
+
Flash
+ ⚡
+
+
LOAD MORE ➜
+
+
+
+
+ {flashArticles.map((item) => (
+
+
+
+
+
+ {/* dark overlay with text */}
+
+
{item.title}
+
+
+ {item.categoryName ||
+ item.categories?.[0]?.title ||
+ "Berita"}
+
+ ●
+
+
+
+ {/* play icon */}
+
+
+ ))}
+
+
+
+ {/* Main Layout */}
+
+ {/* LEFT SIDE – MAIN ARTICLE */}
+ {mainArticle ? (
+
+
+
+
+ {/* White Card Overlay */}
+
+
+ {mainArticle.categoryName ||
+ mainArticle.categories?.[0]?.title ||
+ "Berita"}
+
+
+
+ {mainArticle.title}
+
+
+
+
+ By{" "}
+ {mainArticle.customCreatorName ||
+ mainArticle.createdByName ||
+ "Admin"}
+
+ •
+
+ {new Date(mainArticle.publishedAt).toLocaleDateString(
+ "id-ID",
+ {
+ day: "2-digit",
+ month: "long",
+ year: "numeric",
+ },
+ )}
+
+
+
+
+
+ ) : (
+
Loading...
+ )}
+
+ {/* RIGHT SIDE – RECENT POSTS */}
+
+
Recent Posts
+
+
+ {recentPosts.map((item) => (
+
+
+
+
+
+
+
+ {item.title}
+
+
+ {new Date(item.publishedAt).toLocaleDateString("id-ID", {
+ day: "2-digit",
+ month: "long",
+ year: "numeric",
+ })}
+
+
+
+ ))}
+
+
+
+
+ {/* LOAD MORE */}
+
+
+ {/* KOLOM PPS BOTTOM BANNER */}
+
+
+
+
+ );
+}
diff --git a/components/landing-page/health.tsx b/components/landing-page/health.tsx
new file mode 100644
index 0000000..a3176d9
--- /dev/null
+++ b/components/landing-page/health.tsx
@@ -0,0 +1,186 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import Image from "next/image";
+import Link from "next/link";
+import { getListArticle } from "@/service/article";
+
+type Article = {
+ id: number;
+ title: string;
+ description: string;
+ categoryName: string;
+ createdAt: string;
+ publishedAt: string;
+ slug: string;
+ createdByName: string;
+ customCreatorName?: string;
+ thumbnailUrl?: string;
+ categories?: { title: string }[];
+};
+
+export default function NewsTerkini() {
+ const [articles, setArticles] = useState([]);
+ const [popular, setPopular] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ loadData();
+ }, []);
+
+ async function loadData() {
+ setLoading(true);
+
+ try {
+ const res = await getListArticle({
+ limit: "20",
+ page: 1,
+ search: "",
+ isPublish: true,
+ sort: "desc",
+ sortBy: "created_at",
+ });
+
+ const data = res?.data?.data || [];
+ setArticles(data.slice(0, 5));
+ setPopular(data.slice(0, 5));
+ } catch (err) {
+ console.log(err);
+ }
+
+ setLoading(false);
+ }
+
+ const formatDate = (d: string) =>
+ new Date(d).toLocaleDateString("id-ID", {
+ day: "numeric",
+ month: "long",
+ year: "numeric",
+ });
+
+ if (loading)
+ return (
+
+ Memuat berita terbaru...
+
+ );
+
+ return (
+
+
+
BERITA TERKINI
+
+
+
+ {articles.map((item) => (
+
+
+
+ {/* CATEGORY */}
+
+ {item.categoryName || "Kategori"}
+
+
+ {/* JUDUL */}
+
+ {item.title}
+
+
+ {/* DESKRIPSI */}
+
+ {item.description}
+
+
+ {/* AUTHOR + DATE */}
+
+ By {item.customCreatorName || item.createdByName} —{" "}
+ {formatDate(item.publishedAt)}
+
+
+
+
+
+
+
+ ))}
+
+
+ {/* LOAD MORE */}
+
+ LOAD MORE ↓
+
+
+
+
+
TERBANYAK DIBAGIKAN
+
+
+
+ {popular.map((item, index) => (
+
+ {/* NOMOR */}
+
+ {(index + 1).toString().padStart(2, "0")}
+
+
+
+
+ {item.categories?.[0]?.title || "Kategori"}
+
+
+ {item.title}
+
+
+ {formatDate(item.createdAt)}
+
+
+
+ {/* THUMBNAIL KECIL */}
+
+
+
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/components/landing-page/latest-news.tsx b/components/landing-page/latest-news.tsx
new file mode 100644
index 0000000..9f8c836
--- /dev/null
+++ b/components/landing-page/latest-news.tsx
@@ -0,0 +1,126 @@
+"use client";
+
+import { getListArticle } from "@/service/article";
+import { ChevronDown } from "lucide-react";
+import Image from "next/image";
+import Link from "next/link";
+import { useEffect, useState } from "react";
+
+type Article = {
+ id: number;
+ title: string;
+ description: string;
+ categoryName: string;
+ slug: string;
+ createdAt: string;
+ publishedAt: string;
+ createdByName: string;
+ customCreatorName: string;
+ thumbnailUrl: string;
+ categories: { title: string }[];
+ files: { fileUrl: string; file_alt: string }[];
+};
+
+export default function News() {
+ const [page, setPage] = useState(1);
+ const [totalPage, setTotalPage] = useState(1);
+ const [articles, setArticles] = useState([]);
+ const [showData, setShowData] = useState("6");
+ const [search] = useState("");
+ const [selectedCategories] = useState("");
+ const [startDateValue] = useState({
+ startDate: null,
+ endDate: null,
+ });
+
+ useEffect(() => {
+ initState();
+ }, [page, showData, startDateValue, selectedCategories]);
+
+ async function initState() {
+ const req = {
+ limit: showData,
+ page,
+ search,
+ categorySlug: Array.from(selectedCategories).join(","),
+ sort: "desc",
+ isPublish: true,
+ sortBy: "created_at",
+ };
+
+ try {
+ const res = await getListArticle(req);
+ setArticles(res?.data?.data || []);
+ setTotalPage(res?.data?.meta?.totalPage || 1);
+ } catch (err) {
+ console.error("Error fetching articles:", err);
+ }
+ }
+
+ return (
+
+
+ {/* TITLE */}
+
+
+ {/* GRID 4 KOLOM */}
+
+ {articles.slice(0, 4).map((item) => (
+
+
+ {/* GAMBAR */}
+
+
+
+ {/* BADGE CATEGORY DI DALAM GAMBAR */}
+
+
+ {item.categoryName || "Kategori"}
+
+
+
+
+ {/* JUDUL */}
+
+ {item.title}
+
+
+ {/* AUTHOR + DATE */}
+
+
+ By {item.customCreatorName || item.createdByName || "Admin"}
+
+ -
+
+ {new Date(item.publishedAt).toLocaleDateString("id-ID", {
+ day: "numeric",
+ month: "long",
+ year: "numeric",
+ })}
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+ );
+}
diff --git a/components/landing-page/navbar.tsx b/components/landing-page/navbar.tsx
index 01661d2..d65415e 100644
--- a/components/landing-page/navbar.tsx
+++ b/components/landing-page/navbar.tsx
@@ -1,120 +1,190 @@
"use client";
-import { Menu, Search } from "lucide-react";
-import { Button } from "@/components/ui/button";
-import { cn } from "@/lib/utils";
-import Link from "next/link";
+import { Search } from "lucide-react";
import Image from "next/image";
-
-const navItems = [
- { label: "BERANDA", href: "/", active: true },
- { label: "BERITA TERKINI", href: "/category/latest-news" },
- { label: "BERITA POPULER", href: "/category/popular-news" },
- { label: "DAMAI INDONESIAKU", href: "/category/peace-indonesia" },
- { label: "JAGA NEGERI", href: "/category/guard-the-country" },
- { label: "BERITA OPINI", href: "/category/opinion-news" },
-];
+import Link from "next/link";
+import { usePathname } from "next/navigation";
export default function Navbar() {
- return (
-