"use client"; import { useEffect, useState, useCallback } from "react"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Search, Plus, Eye, Pencil, Trash2 } from "lucide-react"; import Link from "next/link"; import { getArticlePagination, deleteArticle } from "@/service/article"; import { formatDate } from "@/utils/global"; import { close, loading } from "@/config/swal"; import Cookies from "js-cookie"; import { isContributorRole } from "@/constants/user-roles"; import Swal from "sweetalert2"; import type { ArticleContentKind } from "@/constants/article-content-types"; import { ARTICLE_KIND_LABEL, articleListPath, } from "@/constants/article-content-types"; type Props = { kind: ArticleContentKind; typeId: number; }; export default function NewsArticleList({ kind, typeId }: Props) { const [articles, setArticles] = useState([]); const [page, setPage] = useState(1); const [totalPage, setTotalPage] = useState(1); const [search, setSearch] = useState(""); const [debouncedSearch, setDebouncedSearch] = useState(""); const [levelId, setLevelId] = useState(); const [selectedTag, setSelectedTag] = useState("all"); useEffect(() => { setLevelId(Cookies.get("urie")); }, []); useEffect(() => { const t = setTimeout(() => setDebouncedSearch(search), 350); return () => clearTimeout(t); }, [search]); const fetchData = useCallback(async () => { loading(); try { const req = { limit: "10", page, title: debouncedSearch, source: "", categoryId: null, search: "", sort: "desc", sortBy: "created_at", typeId, }; const res = await getArticlePagination(req as any); const payload = (res as any)?.data; const data = payload?.data ?? []; setArticles(Array.isArray(data) ? data : []); setTotalPage(payload?.meta?.totalPage ?? 1); } finally { close(); } }, [page, debouncedSearch, typeId]); useEffect(() => { fetchData(); }, [fetchData]); const getStatus = (article: any) => { if (article.isDraft) return "Draft"; if (article.publishStatus?.toLowerCase() === "cancel") return "Pending"; if (article.isPublish) return "Published"; return "Pending"; }; const statusClass = (status: string) => { const v = status.toLowerCase(); if (v === "published") return "bg-green-100 text-green-700"; if (v === "pending") return "bg-yellow-100 text-yellow-700"; if (v === "draft") return "bg-gray-200 text-gray-600"; return "bg-gray-200 text-gray-600"; }; async function handleDelete(id: number) { const ok = await Swal.fire({ icon: "warning", title: "Delete this article?", showCancelButton: true, }); if (!ok.isConfirmed) return; loading(); try { const res = await deleteArticle(String(id)); if ((res as any)?.error) { await Swal.fire({ icon: "error", title: "Delete failed", text: String((res as any)?.message ?? ""), }); return; } await fetchData(); await Swal.fire({ icon: "success", title: "Deleted", timer: 1200, showConfirmButton: false, }); } finally { close(); } } const parseTags = (tags?: string) => { if (!tags) return []; return tags .split(",") .map((t) => t.replace("#", "").trim()) .filter(Boolean); }; const tagCounts: Record = {}; articles.forEach((article) => { parseTags(article.tags).forEach((tag) => { tagCounts[tag] = (tagCounts[tag] || 0) + 1; }); }); const tagEntries = Object.entries(tagCounts); const allOne = tagEntries.every(([, count]) => count === 1); let topTags: string[]; if (allOne) { topTags = tagEntries .sort(() => Math.random() - 0.5) .slice(0, 5) .map(([tag]) => tag); } else { topTags = tagEntries .sort((a, b) => b[1] - a[1]) .slice(0, 5) .map(([tag]) => tag); } const filteredArticles = selectedTag === "all" ? articles : articles.filter((a) => parseTags(a.tags).includes(selectedTag)); const label = ARTICLE_KIND_LABEL[kind]; const basePath = articleListPath(kind); return (

News & Articles

Create and manage {label.toLowerCase()} articles.

{isContributorRole(levelId) && ( )}
{topTags.map((tag) => ( ))}
{/* SEARCH */}
{ setSearch(e.target.value); setPage(1); }} />
{/* TABLE */} Article Category Author Status Date Actions {filteredArticles.length > 0 ? ( filteredArticles.map((article) => { const status = getStatus(article); return ( {article.title} {article.categoryName ? ( {article.categoryName} ) : ( "—" )} {article.createdByName || "—"} {status} {formatDate(article.createdAt)} {isContributorRole(levelId) && ( )} ); }) ) : ( No articles found. )}
{/* PAGINATION */}

Page {page} of {totalPage}

); }