From 96e8538e6a458071ee88d2038b795e3768a5fee5 Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Fri, 27 Feb 2026 16:52:08 +0800 Subject: [PATCH] update flow approve and kontributor --- app/(admin)/admin/content-website/page.tsx | 9 +- components/form/article/edit-article-form.tsx | 80 +++++-- components/form/form-master-user.tsx | 9 +- .../landing-page/retracting-sidedar.tsx | 75 ++++++- components/main/content-website-approver.tsx | 149 +++++++++++++ .../main/dashboard/dashboard-container.tsx | 202 +++++++++++++++++- components/main/news-image.tsx | 46 ++-- service/article.ts | 14 +- 8 files changed, 528 insertions(+), 56 deletions(-) create mode 100644 components/main/content-website-approver.tsx diff --git a/app/(admin)/admin/content-website/page.tsx b/app/(admin)/admin/content-website/page.tsx index eb5f4ce..adc8d97 100644 --- a/app/(admin)/admin/content-website/page.tsx +++ b/app/(admin)/admin/content-website/page.tsx @@ -1,15 +1,20 @@ "use client"; +import Cookies from "js-cookie"; import ContentWebsite from "@/components/main/content-website"; -import DashboardContainer from "@/components/main/dashboard/dashboard-container"; + import { motion } from "framer-motion"; import { useEffect, useState } from "react"; +import ApproverContentWebsite from "@/components/main/content-website-approver"; export default function ContentWebsitePage() { const [mounted, setMounted] = useState(false); + const [levelId, setLevelId] = useState(); useEffect(() => { setMounted(true); + const ulne = Cookies.get("ulne"); + setLevelId(ulne); }, []); if (!mounted) { @@ -28,7 +33,7 @@ export default function ContentWebsitePage() { transition={{ duration: 0.3 }} >
- + {levelId === "2" ? : }
); diff --git a/components/form/article/edit-article-form.tsx b/components/form/article/edit-article-form.tsx index f4f5844..b22d3b6 100644 --- a/components/form/article/edit-article-form.tsx +++ b/components/form/article/edit-article-form.tsx @@ -161,6 +161,13 @@ export default function EditArticleForm(props: { isDetail: boolean }) { const [startDateValue, setStartDateValue] = useState(); const [startTimeValue, setStartTimeValue] = useState(""); + const [levelId, setLevelId] = useState(); + + useEffect(() => { + const ulne = Cookies.get("ulne"); + setLevelId(ulne); + }, []); + const { getRootProps, getInputProps } = useDropzone({ onDrop: (acceptedFiles) => { setFiles((prevFiles) => [ @@ -333,7 +340,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { return; } - successSubmit("/admin/article"); + successSubmit("/admin/news-article/image"); }; const publishScheduled = async () => { @@ -391,7 +398,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { return; } - successSubmit("/admin/article"); + successSubmit("/admin/news-article/image"); }; const save = async (values: z.infer) => { @@ -521,7 +528,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { return; } - successSubmit("/admin/article"); + successSubmit("/admin/news-article/image"); } }); }; @@ -793,18 +800,65 @@ export default function EditArticleForm(props: { isDetail: boolean }) {

Suggestion Box (0)

+
+

+ Description : +

+ {detailData?.isPublish === true ? ( + + Approved + + ) : ( + + Pending + + )} +

Comment

+

View Approver History

+
- {/* Action Button */} -
- - - + {/* ================= ACTION BUTTON ================= */} +
+ {levelId === "2" && !detailData?.isPublish && ( + <> + + + + + + + )} + + {/* 🔥 Jika levelId 3 → hanya tampilkan Cancel */} + {levelId === "3" && ( + + + + )}
diff --git a/components/form/form-master-user.tsx b/components/form/form-master-user.tsx index d9a12a6..9523027 100644 --- a/components/form/form-master-user.tsx +++ b/components/form/form-master-user.tsx @@ -49,7 +49,7 @@ const masterUserSchema = z.object({ genderType: z.string().min(1, { message: "Required" }), phoneNumber: z.string().min(1, { message: "Required" }), address: z.string().min(1, { message: "Required" }), - userLevelType: userSchema, + // userLevelType: userSchema, userRoleType: userSchema, }); @@ -98,7 +98,7 @@ export default function FormMasterUser() { identityNumber: data.identityNumber, identityType: "nrp", phoneNumber: data.phoneNumber, - userLevelId: data.userLevelType.id, + userLevelId: 3, userRoleId: data.userRoleType.id, username: data.username, }; @@ -206,6 +206,7 @@ export default function FormMasterUser() { close(); if (res?.data?.data) { setupParent(res?.data?.data, "role"); + console.log("role", res?.data?.data); } }; @@ -408,7 +409,7 @@ export default function FormMasterUser() { {errors.phoneNumber?.message}

)} - ( @@ -438,7 +439,7 @@ export default function FormMasterUser() {

{errors.userLevelType?.message}

- )} + )} */} { - if (roleId === "1") { +const getSidebarByLevel = (levelId: string | null) => { + if (levelId === "1") { return [ { title: "Dashboard", @@ -64,7 +64,7 @@ const getSidebarByRole = (roleId: string | null) => { ]; } - if (roleId === "2" || roleId === "3") { + if (levelId === "3") { return [ { title: "Dashboard", @@ -141,7 +141,66 @@ const getSidebarByRole = (roleId: string | null) => { ]; } - // fallback kalau role tidak dikenal + if (levelId === "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", + }, + ], + }, + ], + }, + ]; + } + + // fallback kalau Level tidak dikenal return []; }; @@ -260,7 +319,7 @@ const SidebarContent = ({ const { theme, toggleTheme } = useTheme(); const [username, setUsername] = useState("Guest"); - const [roleId, setRoleId] = useState(null); + const [LevelId, setLevelId] = useState(null); const [openMenus, setOpenMenus] = useState([]); // =============================== @@ -275,10 +334,10 @@ const SidebarContent = ({ }; const cookieUsername = getCookie("username"); - const cookieRoleId = getCookie("urie"); + const cookieLevelId = getCookie("ulne"); if (cookieUsername) setUsername(cookieUsername); - if (cookieRoleId) setRoleId(cookieRoleId); + if (cookieLevelId) setLevelId(cookieLevelId); }, []); // =============================== @@ -298,7 +357,7 @@ const SidebarContent = ({ ); }; - const sidebarSections = getSidebarByRole(roleId); + const sidebarSections = getSidebarByLevel(LevelId); return (
diff --git a/components/main/content-website-approver.tsx b/components/main/content-website-approver.tsx new file mode 100644 index 0000000..bf874cc --- /dev/null +++ b/components/main/content-website-approver.tsx @@ -0,0 +1,149 @@ +"use client"; + +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Eye, Pencil, Trash2, Filter } from "lucide-react"; + +export default function ApproverContentWebsite() { + const tabs = [ + "Hero Section", + "About Us", + "Our Products", + "Our Services", + "Technology Partners", + "Pop Up", + ]; + + const data = [ + { + title: "Beyond Expectations to Build Reputation.", + subtitle: "-", + author: "John Kontributor", + status: "Published", + date: "2024-01-15", + }, + { + title: "Manajemen Reputasi untuk Institusi", + subtitle: "-", + author: "Sarah Kontributor", + status: "Pending", + date: "2024-01-14", + }, + ]; + + return ( +
+ {/* HEADER */} +
+

Content Website

+

+ Update homepage content, products, services, and partners +

+
+ + {/* TABS */} +
+ {tabs.map((tab, i) => ( + + ))} +
+ + {/* SEARCH & FILTER */} +
+ + +
+ + {/* TABLE */} +
+ + + + + + + + + + + + + + {data.map((item, i) => ( + + + + + + + + + + + + + + ))} + +
Main TitleSubtitleAuthorStatusDateActions
+ {item.title} + {item.subtitle}{item.author} + + {item.status} + + {item.date} +
+ + + +
+
+ + {/* FOOTER */} +
+

Showing 1 to 2 of 2 items

+ +
+ + + + + +
+
+
+
+ ); +} diff --git a/components/main/dashboard/dashboard-container.tsx b/components/main/dashboard/dashboard-container.tsx index 4f0330f..4ab91ff 100644 --- a/components/main/dashboard/dashboard-container.tsx +++ b/components/main/dashboard/dashboard-container.tsx @@ -52,10 +52,10 @@ interface PostCount { } export default function DashboardContainer() { - const [roleName, setRoleName] = useState(); + const [levelName, setLevelName] = useState(); useEffect(() => { - const role = Cookies.get("roleName"); - setRoleName(role); + const levelId = Cookies.get("ulne"); + setLevelName(levelId); }, []); const username = Cookies.get("username"); @@ -135,7 +135,7 @@ export default function DashboardContainer() { return month + " " + year; }; - if (!roleName) return null; + if (!levelName) return null; const AdminDashboard = () => { const tasks = [ { @@ -494,7 +494,199 @@ export default function DashboardContainer() { ); }; + const ApproverDashboard = () => { + const stats = [ + { + title: "Pending Review", + value: 12, + growth: "+3", + color: "bg-yellow-500", + }, + { + title: "Approved Today", + value: 8, + growth: "+5", + color: "bg-green-600", + }, + { + title: "Total Published", + value: 156, + growth: "+12%", + color: "bg-blue-600", + }, + { + title: "Rejected", + value: 5, + growth: "-1", + color: "bg-red-600", + }, + ]; + + const pendingList = [ + { + title: "MediaHUB Content Aggregator", + author: "John Kontributor", + category: "Product", + time: "2 hours ago", + status: "Pending", + }, + { + title: "Artifintel Services Update", + author: "John Kontributor", + category: "Service", + time: "2 hours ago", + status: "Pending", + }, + ]; + + const activities = [ + { + status: "Approved", + title: "Technology Summit Event", + time: "10 mins ago", + }, + { + status: "Rejected", + title: "Product Update Draft", + time: "25 mins ago", + }, + { + status: "Approved", + title: "Partner Logo Update", + time: "1 hour ago", + }, + ]; + + return ( +
+ {/* HEADER */} +
+

+ Approver Dashboard +

+

+ Review and manage content submissions +

+
+ + {/* ================= STAT CARDS ================= */} +
+ {stats.map((card, i) => ( +
+
+

{card.title}

+

+ {card.value} +

+
+ +
+

+ {card.growth} +

+
+
+
+ ))} +
+ + {/* ================= CONTENT SECTION ================= */} +
+ {/* LEFT - Pending Review */} +
+
+

+ Pending Review{" "} + + {pendingList.length} Items + +

+ +
+ + {pendingList.map((item, i) => ( +
+
+
+

+ {item.title} +

+

+ {item.author} • {item.category} • {item.time} +

+
+ + + {item.status} + +
+ +
+ + + + + +
+
+ ))} +
+ + {/* RIGHT - Recent Activity */} +
+

Recent Activity

+ +
+ {activities.map((item, i) => ( +
+
+

+ {item.status} +

+

{item.title}

+

{item.time}

+
+
+ ))} +
+ + +
+
+
+ ); + }; + return ( - <>{roleName === "Admin" ? : } + <> + {levelName === "1" && } + {levelName === "3" && } + {levelName === "2" && } + ); } diff --git a/components/main/news-image.tsx b/components/main/news-image.tsx index deb8782..826ecb9 100644 --- a/components/main/news-image.tsx +++ b/components/main/news-image.tsx @@ -18,12 +18,19 @@ import Link from "next/link"; import { getArticlePagination } from "@/service/article"; import { formatDate } from "@/utils/global"; import { close, loading } from "@/config/swal"; +import Cookies from "js-cookie"; export default function NewsImage() { const [articles, setArticles] = useState([]); const [page, setPage] = useState(1); const [totalPage, setTotalPage] = useState(1); const [search, setSearch] = useState(""); + const [levelId, setLevelId] = useState(); + + useEffect(() => { + const ulne = Cookies.get("ulne"); + setLevelId(ulne); + }, []); useEffect(() => { fetchData(); @@ -52,18 +59,21 @@ export default function NewsImage() { } const statusVariant = (status: string) => { - switch (status?.toLowerCase()) { - case "publish": - return "bg-green-100 text-green-700"; - case "pending": - return "bg-yellow-100 text-yellow-700"; - case "draft": - return "bg-gray-200 text-gray-600"; - case "reject": - return "bg-red-100 text-red-600"; - default: - return "bg-gray-200 text-gray-600"; + const value = status?.toLowerCase(); + + if (value === "published") { + return "bg-green-100 text-green-700"; } + + if (value === "pending") { + return "bg-yellow-100 text-yellow-700"; + } + + if (value === "cancel") { + return "bg-red-100 text-red-700"; + } + + return "bg-gray-200 text-gray-600"; }; return ( @@ -78,12 +88,14 @@ export default function NewsImage() { Create and manage news articles and blog posts

- - - + {levelId === "3" && ( + + + + )}
{/* ================= SEARCH ================= */} diff --git a/service/article.ts b/service/article.ts index 2d55bb2..b0ae2dc 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, ); } @@ -50,7 +50,7 @@ export async function getArticlePagination(props: PaginationRequest) { source, } = props; - return await httpGetInterceptor( + return await httpGet( `/articles?limit=${limit}&page=${page}&title=${search}&startDate=${ startDate || "" }&endDate=${endDate || ""}&categoryId=${category || ""}&source=${ @@ -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, ); } @@ -121,11 +121,11 @@ export async function deleteArticle(id: string) { } export async function getArticleByCategory() { - return await httpGetInterceptor(`/article-categories?limit=1000`); + return await httpGet(`/article-categories?limit=1000`); } 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}`, ); } @@ -159,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) {