update flow approve and kontributor
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
0430d15fd2
commit
96e8538e6a
|
|
@ -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<string | undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
const ulne = Cookies.get("ulne");
|
||||
setLevelId(ulne);
|
||||
}, []);
|
||||
|
||||
if (!mounted) {
|
||||
|
|
@ -28,7 +33,7 @@ export default function ContentWebsitePage() {
|
|||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<div className="p-6">
|
||||
<ContentWebsite />
|
||||
{levelId === "2" ? <ApproverContentWebsite /> : <ContentWebsite />}
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -161,6 +161,13 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
|||
const [startDateValue, setStartDateValue] = useState<Date | undefined>();
|
||||
const [startTimeValue, setStartTimeValue] = useState<string>("");
|
||||
|
||||
const [levelId, setLevelId] = useState<string | undefined>();
|
||||
|
||||
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<typeof createArticleSchema>) => {
|
||||
|
|
@ -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 }) {
|
|||
<Mail size={20} />
|
||||
<p className="text-sm ">Suggestion Box (0)</p>
|
||||
</div>
|
||||
<div className="border p-3 border-black rounded-lg space-y-2 ">
|
||||
<h2 className="text-sm text-black font-semibold">
|
||||
Description :
|
||||
</h2>
|
||||
{detailData?.isPublish === true ? (
|
||||
<span className="inline-block bg-green-100 text-green-700 text-xs font-semibold px-3 py-1 rounded-full">
|
||||
Approved
|
||||
</span>
|
||||
) : (
|
||||
<span className="inline-block bg-yellow-100 text-yellow-700 text-xs font-semibold px-3 py-1 rounded-full">
|
||||
Pending
|
||||
</span>
|
||||
)}
|
||||
<p className="text-sm text-black font-semibold">Comment</p>
|
||||
<h2 className="text-blue-600 text-xs">View Approver History</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Action Button */}
|
||||
<div className="flex justify-end">
|
||||
<Link href="/admin/news-article/image">
|
||||
<Button
|
||||
variant={"outline"}
|
||||
className="px-6 py-2 rounded-lg transition"
|
||||
>
|
||||
Kembali
|
||||
</Button>
|
||||
</Link>
|
||||
{/* ================= ACTION BUTTON ================= */}
|
||||
<div className="space-y-3">
|
||||
{levelId === "2" && !detailData?.isPublish && (
|
||||
<>
|
||||
<Button
|
||||
onClick={doPublish}
|
||||
className="w-full bg-blue-600 hover:bg-blue-700 text-white py-3 rounded-xl"
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => {
|
||||
setApprovalStatus(4);
|
||||
doApproval();
|
||||
}}
|
||||
className="w-full bg-orange-500 hover:bg-orange-600 text-white py-3 rounded-xl"
|
||||
>
|
||||
Revision
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => {
|
||||
setApprovalStatus(5);
|
||||
doApproval();
|
||||
}}
|
||||
className="w-full bg-red-600 hover:bg-red-700 text-white py-3 rounded-xl"
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* 🔥 Jika levelId 3 → hanya tampilkan Cancel */}
|
||||
{levelId === "3" && (
|
||||
<Link href="/admin/news-article/image">
|
||||
<Button variant="outline" className="w-full py-3 rounded-xl">
|
||||
Cancel
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
</p>
|
||||
)}
|
||||
<Controller
|
||||
{/* <Controller
|
||||
control={control}
|
||||
name="userLevelType"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
|
|
@ -438,7 +439,7 @@ export default function FormMasterUser() {
|
|||
<p className="text-red-400 text-sm">
|
||||
{errors.userLevelType?.message}
|
||||
</p>
|
||||
)}
|
||||
)} */}
|
||||
<Controller
|
||||
control={control}
|
||||
name="userRoleType"
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ interface SidebarSection {
|
|||
children?: SidebarItem[];
|
||||
}
|
||||
|
||||
const getSidebarByRole = (roleId: string | null) => {
|
||||
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: () => (
|
||||
<Icon icon="material-symbols:dashboard" className="text-lg" />
|
||||
),
|
||||
link: "/admin/dashboard",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{
|
||||
title: "Content Website",
|
||||
icon: () => <Icon icon="ri:article-line" className="text-lg" />,
|
||||
link: "/admin/content-website",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "News & Article",
|
||||
items: [
|
||||
{
|
||||
title: "News & Article",
|
||||
icon: () => (
|
||||
<Icon icon="grommet-icons:article" className="text-lg" />
|
||||
),
|
||||
children: [
|
||||
{
|
||||
title: "Text",
|
||||
icon: () => <Icon icon="mdi:file-document-outline" />,
|
||||
link: "/admin/news-article/text",
|
||||
},
|
||||
{
|
||||
title: "Image",
|
||||
icon: () => <Icon icon="mdi:image-outline" />,
|
||||
link: "/admin/news-article/image",
|
||||
},
|
||||
{
|
||||
title: "Video",
|
||||
icon: () => <Icon icon="mdi:video-outline" />,
|
||||
link: "/admin/news-article/video",
|
||||
},
|
||||
{
|
||||
title: "Audio",
|
||||
icon: () => <Icon icon="mdi:music-note-outline" />,
|
||||
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<string>("Guest");
|
||||
const [roleId, setRoleId] = useState<string | null>(null);
|
||||
const [LevelId, setLevelId] = useState<string | null>(null);
|
||||
const [openMenus, setOpenMenus] = useState<string[]>([]);
|
||||
|
||||
// ===============================
|
||||
|
|
@ -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 (
|
||||
<div className="flex flex-col h-full">
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<div className="space-y-6">
|
||||
{/* HEADER */}
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-800">Content Website</h1>
|
||||
<p className="text-slate-500">
|
||||
Update homepage content, products, services, and partners
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* TABS */}
|
||||
<div className="bg-white rounded-2xl shadow border p-2 flex flex-wrap gap-2">
|
||||
{tabs.map((tab, i) => (
|
||||
<button
|
||||
key={i}
|
||||
className={`px-4 py-2 rounded-xl text-sm font-medium transition ${
|
||||
i === 0
|
||||
? "bg-blue-600 text-white"
|
||||
: "hover:bg-slate-100 text-slate-600"
|
||||
}`}
|
||||
>
|
||||
{tab}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* SEARCH & FILTER */}
|
||||
<div className="flex gap-4">
|
||||
<Input placeholder="Search Hero Section by title, author, or content..." />
|
||||
<Button variant="outline" className="flex items-center gap-2">
|
||||
<Filter size={16} /> Filters
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* TABLE */}
|
||||
<div className="bg-white rounded-2xl shadow border overflow-hidden">
|
||||
<table className="w-full text-sm">
|
||||
<thead className="bg-slate-50 text-slate-600">
|
||||
<tr>
|
||||
<th className="text-left px-6 py-4">Main Title</th>
|
||||
<th className="text-left px-6 py-4">Subtitle</th>
|
||||
<th className="text-left px-6 py-4">Author</th>
|
||||
<th className="text-left px-6 py-4">Status</th>
|
||||
<th className="text-left px-6 py-4">Date</th>
|
||||
<th className="text-left px-6 py-4">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{data.map((item, i) => (
|
||||
<tr key={i} className="border-t hover:bg-slate-50 transition">
|
||||
<td className="px-6 py-4 font-medium text-slate-800">
|
||||
{item.title}
|
||||
</td>
|
||||
|
||||
<td className="px-6 py-4">{item.subtitle}</td>
|
||||
|
||||
<td className="px-6 py-4 text-slate-600">{item.author}</td>
|
||||
|
||||
<td className="px-6 py-4">
|
||||
<span
|
||||
className={`text-xs font-medium px-3 py-1 rounded-full ${
|
||||
item.status === "Published"
|
||||
? "bg-green-100 text-green-600"
|
||||
: "bg-yellow-100 text-yellow-600"
|
||||
}`}
|
||||
>
|
||||
{item.status}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td className="px-6 py-4 text-slate-600">{item.date}</td>
|
||||
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex gap-3 text-slate-500">
|
||||
<Eye
|
||||
size={18}
|
||||
className="cursor-pointer hover:text-blue-600"
|
||||
/>
|
||||
<Pencil
|
||||
size={18}
|
||||
className="cursor-pointer hover:text-green-600"
|
||||
/>
|
||||
<Trash2
|
||||
size={18}
|
||||
className="cursor-pointer hover:text-red-600"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{/* FOOTER */}
|
||||
<div className="flex justify-between items-center px-6 py-4 border-t bg-slate-50">
|
||||
<p className="text-sm text-slate-500">Showing 1 to 2 of 2 items</p>
|
||||
|
||||
<div className="flex gap-2">
|
||||
<button className="px-4 py-2 border rounded-lg text-sm">
|
||||
Previous
|
||||
</button>
|
||||
<button className="px-4 py-2 bg-blue-600 text-white rounded-lg text-sm">
|
||||
1
|
||||
</button>
|
||||
<button className="px-4 py-2 border rounded-lg text-sm">2</button>
|
||||
<button className="px-4 py-2 border rounded-lg text-sm">3</button>
|
||||
<button className="px-4 py-2 border rounded-lg text-sm">
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -52,10 +52,10 @@ interface PostCount {
|
|||
}
|
||||
|
||||
export default function DashboardContainer() {
|
||||
const [roleName, setRoleName] = useState<string | undefined>();
|
||||
const [levelName, setLevelName] = useState<string | undefined>();
|
||||
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 (
|
||||
<div className="space-y-8">
|
||||
{/* HEADER */}
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-800">
|
||||
Approver Dashboard
|
||||
</h1>
|
||||
<p className="text-slate-500">
|
||||
Review and manage content submissions
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* ================= STAT CARDS ================= */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{stats.map((card, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="bg-white rounded-2xl shadow border p-6 flex justify-between items-start"
|
||||
>
|
||||
<div>
|
||||
<p className="text-sm text-slate-500">{card.title}</p>
|
||||
<h2 className="text-3xl font-bold text-slate-800 mt-2">
|
||||
{card.value}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="text-right">
|
||||
<p className="text-sm text-green-600 font-medium">
|
||||
{card.growth}
|
||||
</p>
|
||||
<div className={`w-10 h-10 rounded-xl mt-3 ${card.color}`} />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* ================= CONTENT SECTION ================= */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* LEFT - Pending Review */}
|
||||
<div className="lg:col-span-2 bg-white rounded-2xl shadow border p-6 space-y-6">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-lg font-semibold">
|
||||
Pending Review{" "}
|
||||
<span className="ml-2 text-xs bg-amber-100 text-amber-600 px-3 py-1 rounded-full">
|
||||
{pendingList.length} Items
|
||||
</span>
|
||||
</h2>
|
||||
<button className="text-blue-600 text-sm font-medium">
|
||||
View All
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{pendingList.map((item, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="border border-amber-300 bg-amber-50 rounded-xl p-4 space-y-4"
|
||||
>
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
<h4 className="font-semibold text-slate-800">
|
||||
{item.title}
|
||||
</h4>
|
||||
<p className="text-sm text-slate-500 mt-1">
|
||||
{item.author} • {item.category} • {item.time}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<span className="text-xs bg-amber-200 text-amber-700 px-3 py-1 rounded-full">
|
||||
{item.status}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4">
|
||||
<button className="flex-1 bg-green-600 hover:bg-green-700 text-white py-2 rounded-lg text-sm font-medium">
|
||||
Approve
|
||||
</button>
|
||||
|
||||
<button className="flex-1 bg-red-600 hover:bg-red-700 text-white py-2 rounded-lg text-sm font-medium">
|
||||
Reject
|
||||
</button>
|
||||
|
||||
<button className="px-4 py-2 bg-gray-200 rounded-lg text-sm">
|
||||
Review
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* RIGHT - Recent Activity */}
|
||||
<div className="bg-white rounded-2xl shadow border p-6 space-y-6">
|
||||
<h2 className="text-lg font-semibold">Recent Activity</h2>
|
||||
|
||||
<div className="space-y-4">
|
||||
{activities.map((item, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="border rounded-xl p-4 flex justify-between items-center"
|
||||
>
|
||||
<div>
|
||||
<p
|
||||
className={`text-sm font-medium ${
|
||||
item.status === "Approved"
|
||||
? "text-green-600"
|
||||
: "text-red-600"
|
||||
}`}
|
||||
>
|
||||
{item.status}
|
||||
</p>
|
||||
<p className="text-sm text-slate-700">{item.title}</p>
|
||||
<p className="text-xs text-slate-500">{item.time}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<button className="w-full bg-[#966314] hover:bg-[#7a4f0f] text-white py-3 rounded-xl text-sm font-medium">
|
||||
View All Activity
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>{roleName === "Admin" ? <AdminDashboard /> : <ContributorDashboard />}</>
|
||||
<>
|
||||
{levelName === "1" && <AdminDashboard />}
|
||||
{levelName === "3" && <ContributorDashboard />}
|
||||
{levelName === "2" && <ApproverDashboard />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<any[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [totalPage, setTotalPage] = useState(1);
|
||||
const [search, setSearch] = useState("");
|
||||
const [levelId, setLevelId] = useState<string | undefined>();
|
||||
|
||||
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
|
||||
</p>
|
||||
</div>
|
||||
<Link href={"/admin/news-article/image/create"}>
|
||||
<Button className="bg-blue-600 hover:bg-blue-700 rounded-lg">
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
Create New Article
|
||||
</Button>
|
||||
</Link>
|
||||
{levelId === "3" && (
|
||||
<Link href={"/admin/news-article/image/create"}>
|
||||
<Button className="bg-blue-600 hover:bg-blue-700 rounded-lg">
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
Create New Article
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* ================= SEARCH ================= */}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue