271 lines
9.8 KiB
TypeScript
271 lines
9.8 KiB
TypeScript
"use client";
|
|
import {
|
|
DashboardCommentIcon,
|
|
DashboardConnectIcon,
|
|
DashboardShareIcon,
|
|
DashboardSpeecIcon,
|
|
DashboardTopLeftPointIcon,
|
|
DashboardUserIcon,
|
|
} from "@/components/icons/dashboard-icon";
|
|
import { Submenu1Icon } from "@/components/icons/sidebar-icon";
|
|
import {
|
|
Button,
|
|
Checkbox,
|
|
CheckboxGroup,
|
|
Pagination,
|
|
Select,
|
|
SelectItem,
|
|
SelectSection,
|
|
} from "@nextui-org/react";
|
|
import ApexChartColumn from "./chart/column-chart";
|
|
import ApexChartDonut from "./chart/donut-chart";
|
|
import ApexChartLineArea from "./chart/line-area-chart";
|
|
import Cookies from "js-cookie";
|
|
import Link from "next/link";
|
|
import { useEffect, useState } from "react";
|
|
import { getListArticle } from "@/service/article";
|
|
import { Article } from "@/types/globals";
|
|
import { convertDateFormat, textEllipsis } from "@/utils/global";
|
|
import Datepicker from "react-tailwindcss-datepicker";
|
|
|
|
type ArticleData = Article & {
|
|
no: number;
|
|
createdAt: string;
|
|
};
|
|
|
|
export default function DashboardContainer() {
|
|
const username = Cookies.get("username");
|
|
const fullname = Cookies.get("ufne");
|
|
const [page, setPage] = useState(1);
|
|
const [totalPage, setTotalPage] = useState(1);
|
|
const [article, setArticle] = useState<ArticleData[]>([]);
|
|
const [analyticsView, setAnalyticView] = useState<string[]>([
|
|
"visit",
|
|
"view",
|
|
"share",
|
|
]);
|
|
const [startDateValue, setStartDateValue] = useState({
|
|
startDate: new Date(),
|
|
endDate: new Date(),
|
|
});
|
|
|
|
const [typeDate, setTypeDate] = useState("monthly");
|
|
|
|
useEffect(() => {
|
|
initState();
|
|
}, [page]);
|
|
|
|
async function initState() {
|
|
const req = {
|
|
limit: "4",
|
|
page: page,
|
|
search: "",
|
|
};
|
|
const res = await getListArticle(req);
|
|
setArticle(res.data?.data);
|
|
setTotalPage(res?.data?.meta?.totalPage);
|
|
}
|
|
|
|
const getMonthYear = (date: Date | string) => {
|
|
const newDate = new Date(date);
|
|
|
|
const months = [
|
|
"january",
|
|
"february",
|
|
"march",
|
|
"april",
|
|
"may",
|
|
"june",
|
|
"july",
|
|
"august",
|
|
"september",
|
|
"october",
|
|
"november",
|
|
"december",
|
|
];
|
|
const year = newDate.getFullYear();
|
|
|
|
const month = months[newDate.getMonth()];
|
|
return month + " " + year;
|
|
};
|
|
|
|
return (
|
|
<div className="px-2 lg:p-8 flex justify-center">
|
|
<div className="w-full flex flex-col gap-6">
|
|
<div className="w-full flex flex-col lg:flex-row gap-6 justify-center">
|
|
<div className="px-4 lg:px-8 py-4 justify-between w-full lg:w-[37%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col rounded-lg">
|
|
<div className="flex justify-between w-full items-center">
|
|
<div className="flex flex-col gap-2">
|
|
<p className="font-bold text-xl ">{fullname}</p>
|
|
<p>{username}</p>
|
|
</div>
|
|
<DashboardUserIcon size={78} />
|
|
</div>
|
|
<div className="flex flex-row gap-5">
|
|
<p className="text-lg font-semibold">
|
|
4 Post <span className="text-sm font-normal">Hari ini</span>
|
|
</p>
|
|
<p className="text-lg font-semibold">
|
|
12 Post <span className="text-sm font-normal">Minggu ini</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="lg:w-[20%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
|
<div className="h-1/2 flex items-center justify-center">
|
|
<DashboardSpeecIcon />
|
|
</div>
|
|
<div className="">Total post</div>
|
|
<div className="font-semibold text-lg">121</div>
|
|
</div>
|
|
<div className="w-full lg:w-[15%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
|
<div className="h-1/2 flex items-center justify-center">
|
|
<DashboardConnectIcon />
|
|
</div>
|
|
<div className="">Total views</div>
|
|
<div className="font-semibold text-lg">154</div>
|
|
</div>
|
|
<div className="w-full lg:w-[15%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
|
<div className="h-1/2 flex items-center justify-center">
|
|
<DashboardShareIcon />
|
|
</div>
|
|
<div className="">Total share</div>
|
|
<div className="font-semibold text-lg">154</div>
|
|
</div>
|
|
<div className="w-full lg:w-[15%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
|
<div className="h-1/2 flex items-center justify-center">
|
|
<DashboardCommentIcon size={50} />
|
|
</div>
|
|
<div className="">Total comment</div>
|
|
<div className="font-semibold text-lg">530</div>
|
|
</div>
|
|
</div>
|
|
<div className="w-full flex flex-col lg:flex-row gap-6 justify-center ">
|
|
<div className="border-1 shadow-sm w-screen rounded-lg lg:w-[55%] p-6 flex flex-col">
|
|
<div className="flex justify-between mb-3">
|
|
<div className="font-semibold flex flex-col">
|
|
Analytics
|
|
<div className="font-normal text-xs text-gray-600 flex flex-row gap-2">
|
|
<CheckboxGroup
|
|
label=""
|
|
value={analyticsView}
|
|
orientation="vertical"
|
|
onValueChange={setAnalyticView}
|
|
className="lg:hidden"
|
|
>
|
|
<Checkbox size="sm" value="visit">
|
|
Visit
|
|
</Checkbox>
|
|
<Checkbox size="sm" value="view" color="success">
|
|
View
|
|
</Checkbox>
|
|
<Checkbox size="sm" value="share" color="warning">
|
|
Share
|
|
</Checkbox>
|
|
</CheckboxGroup>
|
|
<CheckboxGroup
|
|
label=""
|
|
value={analyticsView}
|
|
orientation="horizontal"
|
|
onValueChange={setAnalyticView}
|
|
className="hidden lg:block"
|
|
>
|
|
<Checkbox size="sm" value="visit">
|
|
Visit
|
|
</Checkbox>
|
|
<Checkbox size="sm" value="view" color="success">
|
|
View
|
|
</Checkbox>
|
|
<Checkbox size="sm" value="share" color="warning">
|
|
Share
|
|
</Checkbox>
|
|
</CheckboxGroup>
|
|
</div>
|
|
</div>
|
|
<div className="flex flex-col lg:flex-row gap-2">
|
|
<Button
|
|
color="primary"
|
|
variant={typeDate === "monthly" ? "solid" : "bordered"}
|
|
onClick={() => setTypeDate("monthly")}
|
|
className="w-[140px] text-xs lg:text-sm h-[30px] lg:h-[40px] rounded-sm lg:rounded-lg"
|
|
>
|
|
Bulanan
|
|
</Button>
|
|
<Button
|
|
color="primary"
|
|
onClick={() => setTypeDate("weekly")}
|
|
variant={typeDate === "weekly" ? "solid" : "bordered"}
|
|
className="w-[140px] text-xs lg:text-sm h-[30px] lg:h-[40px] rounded-sm lg:rounded-lg"
|
|
>
|
|
Mingguan
|
|
</Button>
|
|
<div className="w-[140px]">
|
|
<Datepicker
|
|
value={startDateValue}
|
|
displayFormat="DD/MM/YYYY"
|
|
asSingle={true}
|
|
useRange={false}
|
|
onChange={(e: any) => setStartDateValue(e)}
|
|
inputClassName="z-50 w-full text-xs lg:text-sm bg-transparent border-1 border-gray-200 px-2 py-[6px] rounded-sm lg:rounded-lg h-[30px] lg:h-[40px] text-gray-600 dark:text-gray-300"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex flex-row w-full h-full">
|
|
<div className="w-full h-[30vh] lg:h-full text-black">
|
|
<ApexChartColumn
|
|
type={typeDate}
|
|
date={getMonthYear(startDateValue.startDate)}
|
|
view={analyticsView}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex flex-col w-full lg:w-[45%] gap-6 shadow-md bg-white dark:bg-[#18181b] rounded-lg p-8">
|
|
<div className="flex justify-between">
|
|
<p>Recent Article</p>
|
|
<Link href="/admin/article/create">
|
|
<Button color="primary" variant="bordered">
|
|
Buat Article
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
{article?.map((list: any) => (
|
|
<div
|
|
key={list?.id}
|
|
className="flex flex-row gap-2 items-center border-b-2 py-2"
|
|
>
|
|
<img
|
|
src={list?.thumbnailUrl || `/no-image.jpg`}
|
|
className="h-[70px] w-[70px] object-cover rounded-lg"
|
|
/>
|
|
<div className="flex flex-col gap-2">
|
|
<p>{textEllipsis(list?.title, 58)}</p>
|
|
<p className="text-xs">
|
|
{convertDateFormat(list?.createdAt)}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
<div className="my-2 w-full flex justify-center">
|
|
<Pagination
|
|
isCompact
|
|
showControls
|
|
showShadow
|
|
color="primary"
|
|
classNames={{
|
|
base: "bg-transparent",
|
|
wrapper: "bg-transparent",
|
|
}}
|
|
page={page}
|
|
total={totalPage}
|
|
onChange={(page) => setPage(page)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|