web-humas-fe/components/main/dashboard/chart/multiline-chart.tsx

259 lines
6.3 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import ReactApexChart from "react-apexcharts";
import dummy from "../../../../const/dummy.json";
import { getStatisticUsersMonthly } from "@/services/article";
function getRangeAcrossMonths(
data: any[],
startYear: number,
startMonth: number,
startDay: number,
endYear: number,
endMonth: number,
endDay: number
) {
const labels: string[] = [];
const users: { name: string; data: number[] }[] = [];
const sortedData = [...data].sort(
(a, b) => a.year - b.year || a.month - b.month
);
for (const monthData of sortedData) {
const { year, month, user_levels: u } = monthData;
if (year < startYear || (year === startYear && month < startMonth))
continue;
if (year > endYear || (year === endYear && month > endMonth)) continue;
let startIndex = 0;
let endIndex = u[0].data.length - 1;
if (year === startYear && month === startMonth) {
startIndex = startDay - 1;
}
if (year === endYear && month === endMonth) {
endIndex = endDay - 1;
}
for (let j = 0; j < u.length; j++) {
const now = u[j].data;
const temp: number[] = [];
for (let i = startIndex; i <= endIndex; i++) {
if (now[i] == null) continue;
temp.push(now[i]);
if (j === 0) {
labels.push(
`${String(i + 1).padStart(2, "0")}-${String(month).padStart(
2,
"0"
)}-${year}`
);
}
}
const existing = users.find((item) => item.name === u[j].name);
if (existing) {
existing.data.push(...temp);
} else {
users.push({ name: u[j].name, data: temp });
}
}
}
return { users, labels };
}
const ApexMultiLineChart = (props: {
type: string;
date: string;
range: { start: any; end: any };
}) => {
const { date, type, range } = props;
const [datas, setDatas] = useState<any>([]);
const [years, setYear] = useState("");
const [series, setSeries] = useState<any>([]);
const [categories, setCategories] = useState<string[]>([]);
useEffect(() => {
initFetch();
}, [date, type, range.start, range.end]);
const initFetch = async () => {
const splitDate = date.split(" ");
const splitDateDaily = String(range.start.year);
const splitDateDailyEnd = String(range.end.year);
const isAccrossYear = splitDateDaily !== splitDateDailyEnd;
let data: any = [];
if (
(type === "monthly" && splitDate[1] === years) ||
(type === "daily" && splitDateDaily === years && !isAccrossYear)
) {
data = datas;
} else {
if (isAccrossYear && type === "daily") {
const resStart = await getStatisticUsersMonthly(splitDateDaily);
const resEnd = await getStatisticUsersMonthly(splitDateDailyEnd);
data = [...resStart?.data?.data, ...resEnd?.data?.data];
setDatas(data);
} else {
const res = await getStatisticUsersMonthly(
type === "monthly" ? splitDate[1] : splitDateDaily
);
data = res?.data?.data;
setDatas(data);
}
}
if (type === "daily") {
const mappedData = getRangeAcrossMonths(
data,
range.start.year,
range.start.month,
range.start.day,
range.end.year,
range.end.month,
range.end.day
);
setSeries(mappedData.users);
setCategories(mappedData.labels);
}
if (type === "monthly") {
const getDatas = data?.find(
(a: any) =>
a.month == Number(splitDate[0]) && a.year === Number(splitDate[1])
);
if (getDatas) {
setSeries(getDatas.user_levels);
} else {
setSeries([]);
}
}
setYear(type === "monthly" ? splitDate[1] : splitDateDaily);
};
return (
<div>
<div id="chart">
<ReactApexChart
series={series}
options={{
chart: {
height: 600,
type: "line",
dropShadow: {
enabled: true,
color: "#000",
top: 18,
left: 7,
blur: 10,
opacity: 0.5,
},
zoom: {
enabled: true,
},
toolbar: {
show: false,
},
},
colors: [
"#1f77b4",
"#2ca02c",
"#9467bd",
"#8c564b",
"#e377c2",
"#7f7f7f",
"#bcbd22",
"#17becf",
"#aec7e8",
"#98df8a",
"#c5b0d5",
"#c49c94",
"#9edae5",
"#393b79",
"#637939",
"#8c6d31",
"#843c39",
"#7b4173",
"#3182bd",
"#6baed6",
"#9ecae1",
"#31a354",
"#74c476",
"#a1d99b",
"#756bb1",
"#9e9ac8",
"#bcbddc",
"#636363",
"#969696",
"#bdbdbd",
"#17becf",
"#8da0cb",
"#66c2a5",
"#a6d854",
"#ffd92f",
"#b3b3b3",
"#80b1d3",
"#fdb462",
],
dataLabels: {
enabled: true,
},
stroke: {
curve: "smooth",
},
title: {
text: "Users",
align: "left",
},
grid: {
borderColor: "#e7e7e7",
row: {
colors: ["#f3f3f3", "transparent"],
opacity: 0.5,
},
},
markers: {
size: 0.5,
},
xaxis: {
categories: type == "daily" ? categories : [],
title: {
text: "Days",
},
},
yaxis: {
title: {
text: "Articles",
},
},
legend: {
position: "right",
horizontalAlign: "right",
floating: false,
offsetY: -25,
offsetX: -5,
},
}}
type="line"
height={600}
/>
</div>
<div id="html-dist"></div>
</div>
);
};
export default ApexMultiLineChart;