"use client"; import { useState, useEffect } from "react"; import Image from "next/image"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { ThumbsUp, ThumbsDown, Search, Filter, Calendar, Tag } from "lucide-react"; import Link from "next/link"; import { useParams, useRouter, useSearchParams } from "next/navigation"; import { listArticles } from "@/service/landing/landing"; import { getArticleCategories } from "@/service/categories/article-categories"; import { toggleBookmark, getBookmarkSummaryForUser } from "@/service/content"; import { getCookiesDecrypt } from "@/lib/utils"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, } from "@/components/ui/pagination"; // Format tanggal function formatTanggal(dateString: string) { if (!dateString) return ""; return ( new Date(dateString) .toLocaleString("id-ID", { day: "2-digit", month: "short", year: "numeric", hour: "2-digit", minute: "2-digit", hour12: false, timeZone: "Asia/Jakarta", }) .replace(/\./g, ":") + " WIB" ); } // Function to get link based on typeId function getLink(item: any) { switch (item?.typeId) { case 1: return `/content/image/detail/${item?.id}`; case 2: return `/content/video/detail/${item?.id}`; case 3: return `/content/text/detail/${item?.id}`; case 4: return `/content/audio/detail/${item?.id}`; default: return "#"; } } export default function ArticleListPage() { const [articles, setArticles] = useState([]); const [categories, setCategories] = useState([]); const [bookmarkedIds, setBookmarkedIds] = useState>(new Set()); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(""); const [selectedCategory, setSelectedCategory] = useState("all"); const [selectedType, setSelectedType] = useState("2"); const [startDate, setStartDate] = useState(""); const [endDate, setEndDate] = useState(""); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [totalData, setTotalData] = useState(0); const params = useParams(); const slug = params?.slug as string; const router = useRouter(); const searchParams = useSearchParams(); const MySwal = withReactContent(Swal); const itemsPerPage = 6; // Load categories on component mount useEffect(() => { loadCategories(); }, []); // Load articles when filters change useEffect(() => { loadArticles(); }, [currentPage, selectedCategory, selectedType, searchTerm, startDate, endDate]); // Sync bookmarks useEffect(() => { syncBookmarks(); }, []); async function loadCategories() { try { const response = await getArticleCategories(); if (response?.data?.data) { setCategories(response.data.data); } } catch (error) { console.error("Error loading categories:", error); } } async function loadArticles() { try { setLoading(true); const categoryId = selectedCategory === "all" ? undefined : selectedCategory; const typeId = selectedType === "all" ? undefined : parseInt(selectedType); const response = await listArticles( currentPage, itemsPerPage, typeId, searchTerm || undefined, categoryId, "createdAt", slug ); if (response?.data?.data) { const articlesData = response.data.data; setArticles(articlesData); setTotalPages(response.data.meta.totalPage || 1); setTotalData(response.data.meta.count || 0); } } catch (error) { console.error("Error loading articles:", error); } finally { setLoading(false); } } async function syncBookmarks() { const roleId = Number(getCookiesDecrypt("urie")); if (roleId && !isNaN(roleId)) { try { const savedLocal = localStorage.getItem("bookmarkedIds"); let localSet = new Set(); if (savedLocal) { localSet = new Set(JSON.parse(savedLocal)); setBookmarkedIds(localSet); } const res = await getBookmarkSummaryForUser(); const bookmarks = res?.data?.data?.recentBookmarks || res?.data?.data?.bookmarks || res?.data?.data || []; const ids = new Set( (Array.isArray(bookmarks) ? bookmarks : []) .map((b: any) => Number(b.articleId ?? b.id ?? b.article?.id)) .filter((x) => !isNaN(x)) ); const merged = new Set([...localSet, ...ids]); setBookmarkedIds(merged); localStorage.setItem( "bookmarkedIds", JSON.stringify(Array.from(merged)) ); } catch (error) { console.error("Error syncing bookmarks:", error); } } } const handleSave = async (id: number) => { const roleId = Number(getCookiesDecrypt("urie")); if (!roleId || isNaN(roleId)) { MySwal.fire({ icon: "warning", title: "Login diperlukan", text: "Silakan login terlebih dahulu untuk menyimpan artikel.", confirmButtonText: "Login Sekarang", confirmButtonColor: "#d33", }); return; } try { const res = await toggleBookmark(id); if (res?.error) { MySwal.fire({ icon: "error", title: "Gagal", text: "Gagal menyimpan artikel.", confirmButtonColor: "#d33", }); } else { const updated = new Set(bookmarkedIds); updated.add(Number(id)); setBookmarkedIds(updated); localStorage.setItem( "bookmarkedIds", JSON.stringify(Array.from(updated)) ); MySwal.fire({ icon: "success", title: "Berhasil", text: "Artikel berhasil disimpan ke bookmark.", timer: 1500, showConfirmButton: false, }); } } catch (err) { console.error("Error saving bookmark:", err); MySwal.fire({ icon: "error", title: "Kesalahan", text: "Terjadi kesalahan saat menyimpan artikel.", }); } }; const handleSearch = (e: React.FormEvent) => { e.preventDefault(); setCurrentPage(1); loadArticles(); }; const handleFilterChange = () => { setCurrentPage(1); loadArticles(); }; const handlePageChange = (page: number) => { setCurrentPage(page); }; const getTypeLabel = (typeId: number) => { switch (typeId) { case 1: return "📸 Image"; case 2: return "🎬 Video"; case 3: return "📝 Text"; case 4: return "🎵 Audio"; default: return "📄 Content"; } }; return (
{/* Filter Sidebar */}

Filter Artikel

{/* Search */}
setSearchTerm(e.target.value)} className="flex-1" />
{/* Category Filter */}
{/* Type Filter */}
{/* Date Filter */}
{ setStartDate(e.target.value); handleFilterChange(); }} /> { setEndDate(e.target.value); handleFilterChange(); }} />
{/* Clear Filters */}
{/* Main Content */}

Daftar Artikel

Menampilkan {totalData} artikel {searchTerm && ` untuk "${searchTerm}"`} {selectedCategory !== "all" && ` dalam kategori "${categories.find(c => c.id === parseInt(selectedCategory))?.title || selectedCategory}"`}

{/* Articles Grid */} {loading ? (
{[...Array(6)].map((_, i) => (
))}
) : articles.length > 0 ? (
{articles.map((article) => (
{article.title
{article.clientName} {article.categoryName || "Tanpa Kategori"}

{formatTanggal(article.createdAt)}

{article.title}

{/*

{article.description || article.content || ""}

*/}
))}
) : (

Tidak ada artikel ditemukan

Coba ubah filter atau kata kunci pencarian

)} {/* Pagination */} {totalPages > 1 && (
handlePageChange(currentPage - 1)} className={currentPage === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"} /> {Array.from({ length: Math.min(5, totalPages) }, (_, i) => { const pageNumber = Math.max(1, Math.min(totalPages - 4, currentPage - 2)) + i; if (pageNumber > totalPages) return null; return ( handlePageChange(pageNumber)} isActive={currentPage === pageNumber} className="cursor-pointer" > {pageNumber} ); })} handlePageChange(currentPage + 1)} className={currentPage === totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"} />
)}
); }