+
+
+ Subscribe us to get
+ the latest news!
+
- {/* Bottom Row */}
-
-
- © 2020 - © Copyright humasRI Team All Rights Reserved .
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ Email address:
+
- // fill-rule="evenodd"
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ SIGN UP
+
+
+
+
+
+
+
+
+
+
+
+
+ © 2025 Warga Bicara - All Rights Reserved.
+
);
}
diff --git a/components/landing-page/header.tsx b/components/landing-page/header.tsx
index 92b2b1a..b2e49d4 100644
--- a/components/landing-page/header.tsx
+++ b/components/landing-page/header.tsx
@@ -1,18 +1,19 @@
"use client";
-import { useEffect, useState } from "react";
-import Image from "next/image";
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;
- slug: string;
createdAt: string;
+ slug: string;
createdByName: string;
+ publishedAt: string;
customCreatorName: string;
thumbnailUrl: string;
categories: { title: string }[];
@@ -24,74 +25,207 @@ export default function Header() {
useEffect(() => {
const fetchArticles = async () => {
- try {
- const req = {
- limit: "5", // tampilkan 5 artikel seperti data dummy sebelumnya
- page: 1,
- search: "",
- categorySlug: "",
- sort: "desc",
- isPublish: true,
- sortBy: "created_at",
- };
+ const req = {
+ limit: "10",
+ page: 1,
+ search: "",
+ categorySlug: "",
+ sort: "desc",
+ isPublish: true,
+ sortBy: "created_at",
+ };
- const res = await getListArticle(req);
- setArticles(res?.data?.data || []);
- } catch (err) {
- console.error("Error fetching articles:", err);
- }
+ 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 (
-
-
- {articles.map((article) => {
- const imageUrl =
- article.thumbnailUrl ||
- article.files?.[0]?.fileUrl ||
- "/placeholder.jpg"; // fallback jika gambar tidak ada
+
+ {/* FLASH STRIP */}
+
+
+
Flash
+ ⚡
+
+
LOAD MORE ➜
+
- const category =
- article.categoryName ||
- article.categories?.[0]?.title ||
- "SUARA WARGA";
-
- // Format tanggal dari createdAt
- const date = new Date(article.createdAt).toLocaleDateString("id-ID", {
- day: "numeric",
- month: "long",
- year: "numeric",
- });
-
- return (
-
-
+
+
+ {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}
-
- {article.title}
-
-
{date}
+
+ {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
index 66b9a57..7d72ef4 100644
--- a/components/landing-page/health.tsx
+++ b/components/landing-page/health.tsx
@@ -1,8 +1,9 @@
"use client";
+
import { useEffect, useState } from "react";
import Image from "next/image";
-import { getListArticle } from "@/service/article";
import Link from "next/link";
+import { getListArticle } from "@/service/article";
type Article = {
id: number;
@@ -10,248 +11,175 @@ type Article = {
description: string;
categoryName: string;
createdAt: string;
+ publishedAt: string;
slug: string;
createdByName: string;
- categories: { title: string }[];
customCreatorName?: string;
thumbnailUrl?: string;
- files?: { fileUrl: string; file_alt: string }[];
+ categories?: { title: string }[];
};
-export default function Health() {
+export default function NewsTerkini() {
const [articles, setArticles] = useState
([]);
- const [isLoading, setIsLoading] = useState(true);
+ const [popular, setPopular] = useState([]);
+ const [loading, setLoading] = useState(true);
useEffect(() => {
- fetchArticles();
+ loadData();
}, []);
- async function fetchArticles() {
- setIsLoading(true);
+ async function loadData() {
+ setLoading(true);
+
try {
const res = await getListArticle({
- limit: "12",
+ limit: "20",
page: 1,
search: "",
- categorySlug: "", // ubah sesuai slug kategori kamu
isPublish: true,
- sortBy: "created_at",
sort: "desc",
+ sortBy: "created_at",
});
- setArticles(res?.data?.data || []);
- } catch (error) {
- console.error("Error fetching Health articles:", error);
- } finally {
- setIsLoading(false);
+
+ const data = res?.data?.data || [];
+ setArticles(data.slice(0, 5));
+ setPopular(data.slice(0, 5));
+ } catch (err) {
+ console.log(err);
}
+
+ setLoading(false);
}
- // Format tanggal Indonesia
- const formatDate = (dateString: string) => {
- const date = new Date(dateString);
- return date.toLocaleDateString("id-ID", {
- day: "2-digit",
+ const formatDate = (d: string) =>
+ new Date(d).toLocaleDateString("id-ID", {
+ day: "numeric",
month: "long",
year: "numeric",
});
- };
- // Mapping artikel ke posisi layout
- 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);
-
- if (isLoading)
+ if (loading)
return (
-
- Memuat berita kesehatan...
+
+ Memuat berita terbaru...
);
return (
-
-
- KESEHATAN
-
-
+
+
+
BERITA TERKINI
+
- {articles.length === 0 ? (
-
- Belum ada berita di kategori kesehatan.
-
- ) : (
-
- {/* === LEFT COLUMN === */}
- {leftMain && (
-
-
-
+
+ {articles.map((item) => (
+
+
+
+ {/* CATEGORY */}
+
+ {item.categoryName || "Kategori"}
+
+
+ {/* JUDUL */}
+
+ {item.title}
+
+
+ {/* DESKRIPSI */}
+
+ {item.description}
+
+
+ {/* AUTHOR + DATE */}
+
+ By {item.customCreatorName || item.createdByName} —{" "}
+ {formatDate(item.publishedAt)}
+
+
+
-
- {leftMain.categories?.[0]?.title}
-
-
- {leftMain.title}
-
-
- by {leftMain.customCreatorName || leftMain.createdByName} ·{" "}
- {formatDate(leftMain.createdAt)}
-
-
- {leftMain.description}
-
-
-
- {leftList.map((item) => (
-
-
-
-
-
-
-
- {item.title}
-
-
- {formatDate(item.createdAt)}
-
-
-
-
- ))}
-
- )}
-
- {/* === CENTER COLUMN === */}
- {centerMain && (
-
-
-
-
-
- {centerMain.categories?.[0]?.title}
-
-
-
- {centerMain.title}
-
-
- by {centerMain.customCreatorName || centerMain.createdByName}{" "}
- · {formatDate(centerMain.createdAt)}
-
-
- {centerMain.description}
-
-
-
- {centerList.map((item) => (
-
-
-
-
-
-
-
- {item.title}
-
-
- {formatDate(item.createdAt)}
-
-
-
-
- ))}
-
-
- )}
-
- {/* === RIGHT COLUMN === */}
- {rightMain && (
-
-
-
-
-
- {rightMain.categories?.[0]?.title}
-
-
-
- {rightMain.title}
-
-
- by {rightMain.customCreatorName || rightMain.createdByName} ·{" "}
- {formatDate(rightMain.createdAt)}
-
-
- {rightMain.description}
-
-
-
- {rightList.map((item) => (
-
-
-
-
-
-
-
- {item.title}
-
-
- {formatDate(item.createdAt)}
-
-
-
-
- ))}
-
-
- )}
+
+ ))}
- )}
-
-
+ {/* 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
index 799228a..b01a2d1 100644
--- a/components/landing-page/latest-news.tsx
+++ b/components/landing-page/latest-news.tsx
@@ -1,6 +1,7 @@
"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";
@@ -10,8 +11,9 @@ type Article = {
title: string;
description: string;
categoryName: string;
- createdAt: string;
slug: string;
+ createdAt: string;
+ publishedAt: string;
createdByName: string;
customCreatorName: string;
thumbnailUrl: string;
@@ -31,7 +33,6 @@ export default function News() {
endDate: null,
});
- // Fetch data setiap kali page berubah
useEffect(() => {
initState();
}, [page, showData, startDateValue, selectedCategories]);
@@ -56,126 +57,70 @@ export default function News() {
}
}
- const handlePrev = () => {
- if (page > 1) setPage((prev) => prev - 1);
- };
-
- const handleNext = () => {
- if (page < totalPage) setPage((prev) => prev + 1);
- };
-
return (
-
- {/* Berita Terbaru */}
-
-
+
+ {/* TITLE */}
+
-
- {articles.length > 0 ? (
- articles.map((item) => (
-
-
-
-
-
- {item.categoryName ||
- item.categories?.[0]?.title ||
- "Umum"}
-
-
+ {/* GRID 4 KOLOM */}
+
+ {articles.slice(0, 4).map((item) => (
+
+
+ {/* GAMBAR */}
+
+
-
- {item.title}
-
-
-
-
-
-
- {new Date(item.createdAt).toLocaleDateString("id-ID", {
- day: "2-digit",
- month: "long",
- year: "numeric",
- })}
-
-
+ {/* BADGE CATEGORY DI DALAM GAMBAR */}
+
+
+ {item.categoryName || "Kategori"}
+
+
- ))
- ) : (
-
- Tidak ada artikel tersedia.
-
- )}
-
- {/* Pagination */}
-
-
- ‹ PREV
-
+ {/* JUDUL */}
+
+ {item.title}
+
- = totalPage}
- className={`border px-3 py-1 text-xs rounded-sm ${
- page >= totalPage
- ? "opacity-50 cursor-not-allowed"
- : "hover:bg-gray-100"
- }`}
- >
- NEXT ›
-
-
+ {/* AUTHOR + DATE */}
+
+
+ By {item.customCreatorName || item.createdByName || "Admin"}
+
+ -
+
+ {new Date(item.publishedAt).toLocaleDateString("id-ID", {
+ day: "numeric",
+ month: "long",
+ year: "numeric",
+ })}
+
+
+
+
+ ))}
- {/* Twitter Section */}
-
-
- Twitter @ArahNegeri
-
- {/* Embed atau konten lain */}
+
+
-
- {/* Banner bawah */}
-
-
-
);
}
diff --git a/components/landing-page/navbar.tsx b/components/landing-page/navbar.tsx
index 6a4d4f7..189d72e 100644
--- a/components/landing-page/navbar.tsx
+++ b/components/landing-page/navbar.tsx
@@ -1,144 +1,170 @@
"use client";
-import { Lock, Menu, Search } from "lucide-react";
+
+import { Search } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
-import { Button } from "../ui/button";
+import { usePathname } from "next/navigation";
export default function Navbar() {
+ const pathname = usePathname();
+ const isActive = (href: any) => {
+ return pathname === href || pathname.startsWith(href + "/");
+ };
+
return (
- <>
-
-
-
-
-
+
+
+ {/* Left: Logo */}
+
+
+
+
+
+ {/* Social Icons */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Kiri: Hamburger */}
-
-
-
+ {/* Middle Menu */}
+
+
+
+ Beranda
+
- {/* Tengah: Menu Utama */}
-
-
- BERANDA
-
-
- BERITA WARGA
-
-
- PEMBANGUNAN
-
-
- KESEHATAN
-
+
+ Berita Warga
+
+
+
+ Pembangunan
+
+
+
+ Kesehatan
+
- {/* Kanan: Search Icon */}
-
-
-
-
- {" "}
-
- Login
-
+
+
document.documentElement.classList.toggle("dark")}
+ className="w-10 h-5 rounded-full bg-gray-300 dark:bg-gray-700 relative transition-all"
+ >
+
+
+
+ {/* BURGER BUTTON (mobile menu) */}
+
+
+
+
+
+
+
+
+
+
+ LOGIN
+
- >
+
);
}
diff --git a/components/landing-page/opinion-news.tsx b/components/landing-page/opinion-news.tsx
new file mode 100644
index 0000000..90edd40
--- /dev/null
+++ b/components/landing-page/opinion-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 OpinionNews() {
+ 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/youtube-selection.tsx b/components/landing-page/youtube-selection.tsx
new file mode 100644
index 0000000..2243f66
--- /dev/null
+++ b/components/landing-page/youtube-selection.tsx
@@ -0,0 +1,151 @@
+import { Eye, Heart, MessageCircle } from "lucide-react";
+import Image from "next/image";
+
+interface VideoItem {
+ id: number;
+ title: string;
+ thumbnail: string;
+ duration: string;
+ publishedAt: string;
+ views: string;
+ likes: string;
+ comments: string;
+}
+
+const sampleVideos: VideoItem[] = [
+ {
+ id: 1,
+ title: "Cuplikan Kegiatan Presiden di IKN",
+ thumbnail: "/yt/thumb1.jpg",
+ duration: "12:30",
+ publishedAt: "2 jam yang lalu",
+ views: "12K",
+ likes: "230",
+ comments: "45",
+ },
+ {
+ id: 2,
+ title: "Pembangunan MRT Fase Berikutnya Resmi Dimulai",
+ thumbnail: "/yt/thumb2.jpg",
+ duration: "08:12",
+ publishedAt: "5 jam yang lalu",
+ views: "9.4K",
+ likes: "180",
+ comments: "30",
+ },
+ {
+ id: 3,
+ title: "Wilayah Indonesia Siap Hadapi Cuaca Ekstrem",
+ thumbnail: "/yt/thumb3.jpg",
+ duration: "05:50",
+ publishedAt: "1 hari lalu",
+ views: "21K",
+ likes: "540",
+ comments: "121",
+ },
+ {
+ id: 4,
+ title: "Peningkatan Ekonomi Regional Terus Dijaga",
+ thumbnail: "/yt/thumb4.jpg",
+ duration: "10:44",
+ publishedAt: "2 hari lalu",
+ views: "18K",
+ likes: "420",
+ comments: "88",
+ },
+ {
+ id: 5,
+ title: "Laporan Khusus Perkembangan Industri Kreatif",
+ thumbnail: "/yt/thumb5.jpg",
+ duration: "14:02",
+ publishedAt: "3 hari lalu",
+ views: "30K",
+ likes: "830",
+ comments: "200",
+ },
+ {
+ id: 6,
+ title: "Paparan Menteri Perhubungan Soal Transportasi",
+ thumbnail: "/yt/thumb6.jpg",
+ duration: "07:21",
+ publishedAt: "4 hari lalu",
+ views: "9K",
+ likes: "114",
+ comments: "26",
+ },
+];
+
+export default function YouTubeSection() {
+ return (
+
+ {/* Header Channel */}
+
+
+
+
YouTube • Channel Resmi
+
+ Lebih dari 3.5 juta pengikut • 12k video
+
+
+
+
+ Subscribe
+
+
+
+ {/* Grid Video */}
+
+ {sampleVideos.map((v) => (
+
+
+
+
+
+ {v.duration}
+
+
+
+
+ {v.title}
+
+
+
{v.publishedAt}
+
+
+
+ {v.views}
+
+
+ {v.likes}
+
+
+ {v.comments}
+
+
+
+ ))}
+
+
+ {/* Pagination */}
+
+
+ Lihat Selanjutnya →
+
+
+
+ );
+}
diff --git a/public/wargabicara-logo.png b/public/wargabicara-logo.png
new file mode 100644
index 0000000..e213020
Binary files /dev/null and b/public/wargabicara-logo.png differ
diff --git a/service/article.ts b/service/article.ts
index 4f338cd..fec69b4 100644
--- a/service/article.ts
+++ b/service/article.ts
@@ -30,7 +30,7 @@ export async function getListArticle(props: PaginationRequest) {
}&categoryId=${category || ""}&sortBy=${sortBy || "created_at"}&sort=${
sort || "desc"
}&category=${categorySlug || ""}&isBanner=${isBanner || ""}`,
- null
+ null,
);
}
@@ -59,7 +59,7 @@ export async function getArticlePagination(props: PaginationRequest) {
sortBy || "created_at"
}&sort=${sort || "asc"}&category=${categorySlug || ""}&isBanner=${
isBanner || ""
- }`
+ }`,
);
}
@@ -75,7 +75,7 @@ export async function getTopArticles(props: PaginationRequest) {
}&title=${search}&startDate=${startDate || ""}&endDate=${
endDate || ""
}&category=${category || ""}&sortBy=view_count&sort=desc`,
- headers
+ headers,
);
}
@@ -106,6 +106,13 @@ export async function getArticleById(id: any) {
return await httpGet(`/articles/${id}`, headers);
}
+export async function getArticleFiles() {
+ const headers = {
+ "content-type": "application/json",
+ };
+ return await httpGet(`/article-files`, headers);
+}
+
export async function getArticleBySlug(slug: any) {
const headers = {
"content-type": "application/json",
@@ -125,7 +132,7 @@ export async function getArticleByCategory() {
}
export async function getCategoryPagination(data: any) {
return await httpGet(
- `/article-categories?limit=${data?.limit}&page=${data?.page}&title=${data?.search}`
+ `/article-categories?limit=${data?.limit}&page=${data?.page}&title=${data?.search}`,
);
}
@@ -152,7 +159,7 @@ export async function deleteArticleFiles(id: number) {
export async function getUserLevelDataStat(startDate: string, endDate: string) {
return await httpGet(
- `/articles/statistic/user-levels?startDate=${startDate}&endDate=${endDate}`
+ `/articles/statistic/user-levels?startDate=${startDate}&endDate=${endDate}`,
);
}
export async function getStatisticMonthly(year: string) {
diff --git a/tsconfig.json b/tsconfig.json
index d8b9323..e7ff3a2 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "ES2017",
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -11,7 +15,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
- "jsx": "preserve",
+ "jsx": "react-jsx",
"incremental": true,
"plugins": [
{
@@ -19,9 +23,19 @@
}
],
"paths": {
- "@/*": ["./*"]
+ "@/*": [
+ "./*"
+ ]
}
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
- "exclude": ["node_modules"]
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
}