- {/* Meta & Thumbnail Card */}
-
+ {/* ================= RIGHT ================= */}
+
+
+ {/* Creator */}
+
+
Creator
+
+ {detailData?.createdByName || "-"}
+
+
+
{/* Thumbnail */}
- {/* Tag */}
+ {/* Tags */}
Tag
- {detailData?.tags
- ?.split(",")
- .map((tag: string, i: number) => (
- 0 ? (
+ tags.map((tag: string, i: number) => (
+
{tag}
-
- ))}
+
+ ))
+ ) : (
+ —
+ )}
- {/* Notes */}
+ {/* Suggestion Box */}
-
Notes
-
- -
+
+
+ Suggestion Box (0)
+
+
+
+
Description:
+
+ {detailData?.isPublish ? (
+
+ Approved
+
+ ) : (
+
+ Pending
+
+ )}
+
+
Comment:
+
+ {detailData?.customCreatorName || "-"}
+
+
+
setOpenHistory(true)}
+ >
+ View Approver History
+
-
-
-
-
- Description :
-
- {detailData?.isPublish === true ? (
-
- Approved
-
- ) : (
-
- Pending
-
- )}
-
Comment
-
View Approver History
- {/* ================= ACTION BUTTON ================= */}
+ {/* ACTION */}
{isApproverOrAdmin(levelId) && !detailData?.isPublish && (
<>
@@ -829,7 +859,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
setApprovalStatus(4);
doApproval();
}}
- className="w-full bg-orange-500 hover:bg-orange-600 text-white py-3 rounded-xl"
+ className="w-full bg-orange-500 hover:bg-orange-600 text-white"
>
Revision
@@ -839,17 +869,16 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
setApprovalStatus(5);
doApproval();
}}
- className="w-full bg-red-600 hover:bg-red-700 text-white py-3 rounded-xl"
+ className="w-full bg-red-600 hover:bg-red-700 text-white"
>
Reject
>
)}
- {/* 🔥 Jika levelId 3 → hanya tampilkan Cancel */}
{isContributorRole(levelId) && (
-
+
);
}
+ if (!isDetail) {
+ return (
+
+ );
+ }
}
diff --git a/components/landing-page/retracting-sidedar.tsx b/components/landing-page/retracting-sidedar.tsx
index e14bb31..67b4994 100644
--- a/components/landing-page/retracting-sidedar.tsx
+++ b/components/landing-page/retracting-sidedar.tsx
@@ -64,7 +64,65 @@ const getSidebarByRole = (roleId: string | null) => {
];
}
- if (roleId === "2" || roleId === "3") {
+ if (roleId === "2") {
+ return [
+ {
+ title: "Dashboard",
+ items: [
+ {
+ title: "Dashboard",
+ icon: () => (
+
+ ),
+ link: "/admin/dashboard",
+ },
+ ],
+ },
+ {
+ items: [
+ {
+ title: "Content Website",
+ icon: () =>
,
+ link: "/admin/content-website",
+ },
+ ],
+ },
+ {
+ title: "News & Article",
+ items: [
+ {
+ title: "News & Article",
+ icon: () => (
+
+ ),
+ children: [
+ {
+ title: "Text",
+ icon: () =>
,
+ link: "/admin/news-article/text",
+ },
+ {
+ title: "Image",
+ icon: () =>
,
+ link: "/admin/news-article/image",
+ },
+ {
+ title: "Video",
+ icon: () =>
,
+ link: "/admin/news-article/video",
+ },
+ {
+ title: "Audio",
+ icon: () =>
,
+ link: "/admin/news-article/audio",
+ },
+ ],
+ },
+ ],
+ },
+ ];
+ }
+ if (roleId === "3") {
return [
{
title: "Dashboard",
diff --git a/components/main/news-article-list.tsx b/components/main/news-article-list.tsx
index 0a4cd61..157cc2a 100644
--- a/components/main/news-article-list.tsx
+++ b/components/main/news-article-list.tsx
@@ -22,7 +22,10 @@ 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";
+import {
+ ARTICLE_KIND_LABEL,
+ articleListPath,
+} from "@/constants/article-content-types";
type Props = {
kind: ArticleContentKind;
@@ -36,6 +39,7 @@ export default function NewsArticleList({ kind, typeId }: Props) {
const [search, setSearch] = useState("");
const [debouncedSearch, setDebouncedSearch] = useState("");
const [levelId, setLevelId] = useState
();
+ const [selectedTag, setSelectedTag] = useState("all");
useEffect(() => {
setLevelId(Cookies.get("urie"));
@@ -96,6 +100,7 @@ export default function NewsArticleList({ kind, typeId }: Props) {
showCancelButton: true,
});
if (!ok.isConfirmed) return;
+
loading();
try {
const res = await deleteArticle(String(id));
@@ -108,12 +113,56 @@ export default function NewsArticleList({ kind, typeId }: Props) {
return;
}
await fetchData();
- await Swal.fire({ icon: "success", title: "Deleted", timer: 1200, showConfirmButton: false });
+ 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);
@@ -122,12 +171,13 @@ export default function NewsArticleList({ kind, typeId }: Props) {
- News & Articles — {label}
+ News & Articles
- Create and manage {label.toLowerCase()} articles. Organize with tags only.
+ Create and manage {label.toLowerCase()} articles.
+
{isContributorRole(levelId) && (
@@ -138,6 +188,33 @@ export default function NewsArticleList({ kind, typeId }: Props) {
)}
+
+ setSelectedTag("all")}
+ className={`px-4 py-1.5 rounded-full text-sm text-black font-bold border ${
+ selectedTag === "all"
+ ? "bg-blue-600 text-white"
+ : "bg-white text-slate-600"
+ }`}
+ >
+ All ({articles.length})
+
+ {topTags.map((tag) => (
+ setSelectedTag(tag)}
+ className={`px-4 py-1.5 rounded-full text-sm text-black font-bold border ${
+ selectedTag === tag
+ ? "bg-blue-600 text-white"
+ : "bg-white text-slate-600"
+ }`}
+ >
+ {tag} ({tagCounts[tag]})
+
+ ))}
+
+
+ {/* SEARCH */}
@@ -153,79 +230,93 @@ export default function NewsArticleList({ kind, typeId }: Props) {
+ {/* TABLE */}
Article
- Tags
+ Category
+ Author
Status
Date
Actions
+
- {articles.length > 0 ? (
- articles.map((article) => (
-
-
- {article.title}
-
-
-
- {article.tags || "—"}
-
-
-
- {(() => {
- const status = getStatus(article);
- return (
-
- {status}
-
- );
- })()}
-
- {formatDate(article.createdAt)}
-
-
-
-
-
-
-
-
-
-
-
- {isContributorRole(levelId) && (
- handleDelete(article.id)}
+ {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) && (
+ handleDelete(article.id)}
+ >
+
+
+ )}
+
+
+ );
+ })
) : (
-
- No articles yet. Create one to get started.
+
+ No articles found.
)}
+ {/* PAGINATION */}
Page {page} of {totalPage}
@@ -235,13 +326,15 @@ export default function NewsArticleList({ kind, typeId }: Props) {
variant="outline"
size="sm"
disabled={page === 1}
- onClick={() => setPage((p) => Math.max(1, p - 1))}
+ onClick={() => setPage((p) => p - 1)}
>
Previous
+
{page}
+