226 lines
5.5 KiB
TypeScript
226 lines
5.5 KiB
TypeScript
"use client";
|
|
import React, { Component, useEffect, useState } from "react";
|
|
import ReactApexChart from "react-apexcharts";
|
|
import dummyData from "../../../../const/dummy.json";
|
|
import {
|
|
getStatisticMonthly,
|
|
getStatisticVisitorsMonthly,
|
|
} from "@/services/article";
|
|
|
|
type WeekData = {
|
|
week: number;
|
|
days: number[];
|
|
total: number;
|
|
};
|
|
|
|
type RemainingDays = {
|
|
days: number[];
|
|
total: number;
|
|
};
|
|
|
|
function processMonthlyData(count: number[]): {
|
|
weeks: WeekData[];
|
|
remaining_days: RemainingDays;
|
|
} {
|
|
const weeks: WeekData[] = [];
|
|
let weekIndex = 1;
|
|
|
|
for (let i = 0; i < count.length; i += 7) {
|
|
const weekData = count.slice(i, i + 7);
|
|
weeks.push({
|
|
week: weekIndex,
|
|
days: weekData,
|
|
total: weekData.reduce((sum, day) => sum + day, 0),
|
|
});
|
|
weekIndex++;
|
|
}
|
|
|
|
const remainingDays: RemainingDays = {
|
|
days: count.length % 7 === 0 ? [] : count.slice(-count.length % 7),
|
|
total: count.slice(-count.length % 7).reduce((sum, day) => sum + day, 0),
|
|
};
|
|
|
|
return {
|
|
weeks,
|
|
remaining_days: remainingDays,
|
|
};
|
|
}
|
|
|
|
function getRangeAcrossMonths(
|
|
data: any[],
|
|
startYear: number,
|
|
startMonth: number,
|
|
startDay: number,
|
|
endYear: number,
|
|
endMonth: number,
|
|
endDay: number
|
|
) {
|
|
const visitors: number[] = [];
|
|
const labels: string[] = [];
|
|
|
|
const sortedData = [...data].sort(
|
|
(a, b) => a.year - b.year || a.month - b.month
|
|
);
|
|
|
|
for (const item of sortedData) {
|
|
const { year, month, data: v } = item;
|
|
|
|
if (year < startYear || (year === startYear && month < startMonth))
|
|
continue;
|
|
|
|
if (year > endYear || (year === endYear && month > endMonth)) continue;
|
|
|
|
let startIndex = 0;
|
|
let endIndex = v.length - 1;
|
|
|
|
if (year === startYear && month === startMonth) {
|
|
startIndex = startDay - 1;
|
|
}
|
|
|
|
if (year === endYear && month === endMonth) {
|
|
endIndex = endDay - 1;
|
|
}
|
|
|
|
for (let i = startIndex; i <= endIndex; i++) {
|
|
if (v[i] == null) continue;
|
|
|
|
visitors.push(v[i]);
|
|
labels.push(
|
|
`${String(i + 1).padStart(2, "0")}-${String(month).padStart(
|
|
2,
|
|
"0"
|
|
)}-${year}`
|
|
);
|
|
}
|
|
}
|
|
|
|
return { visitors, labels };
|
|
}
|
|
|
|
const ApexChartColumnVisitors = (props: {
|
|
type: string;
|
|
date: string;
|
|
range: { start: any; end: any };
|
|
total: (data: number) => void;
|
|
}) => {
|
|
const { date, type, range, total } = props;
|
|
const [categories, setCategories] = useState<string[]>([]);
|
|
const [series, setSeries] = useState<{ name: string; data: number[] }[]>([]);
|
|
const [seriesVisitors, setSeriesVisitors] = useState<number[]>([]);
|
|
|
|
const [years, setYear] = useState("");
|
|
const [datas, setDatas] = useState<any>([]);
|
|
|
|
useEffect(() => {
|
|
initFetch();
|
|
}, [date, type, range]);
|
|
|
|
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 = [];
|
|
|
|
if (
|
|
(type === "monthly" && splitDate[1] === years) ||
|
|
(type === "daily" && splitDateDaily === years && !isAccrossYear)
|
|
) {
|
|
data = datas;
|
|
} else {
|
|
if (isAccrossYear && type === "daily") {
|
|
const resStart = await getStatisticVisitorsMonthly(splitDateDaily);
|
|
const resEnd = await getStatisticVisitorsMonthly(splitDateDailyEnd);
|
|
data = [...resStart?.data?.data, ...resEnd?.data?.data];
|
|
setDatas(data);
|
|
} else {
|
|
const res = await getStatisticVisitorsMonthly(
|
|
type === "monthly" ? splitDate[1] : splitDateDaily
|
|
);
|
|
|
|
data = res?.data?.data;
|
|
setDatas(data);
|
|
}
|
|
}
|
|
const getDatas = data?.find(
|
|
(a: any) =>
|
|
a.month == Number(splitDate[0]) && a.year === Number(splitDate[1])
|
|
);
|
|
if (getDatas) {
|
|
if (type == "monthly") {
|
|
setSeriesVisitors(getDatas.data);
|
|
total(getDatas.data.reduce((a: number, b: number) => a + b, 0));
|
|
}
|
|
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
|
|
);
|
|
|
|
setSeriesVisitors(mappedData.visitors);
|
|
total(mappedData.visitors.reduce((a: number, b: number) => a + b, 0));
|
|
|
|
setCategories(mappedData.labels);
|
|
}
|
|
// if (type === "weekly") {
|
|
// const category = [];
|
|
// for (let i = 1; i <= temp1.weeks.length; i++) {
|
|
// category.push(`Week ${i}`);
|
|
// }
|
|
// setCategories(category);
|
|
// }
|
|
} else {
|
|
setSeriesVisitors([]);
|
|
}
|
|
|
|
setYear(type === "monthly" ? splitDate[1] : splitDateDaily);
|
|
};
|
|
|
|
useEffect(() => {
|
|
const temp = [
|
|
{
|
|
name: "Visitors",
|
|
data: seriesVisitors || [],
|
|
},
|
|
];
|
|
|
|
setSeries(temp);
|
|
}, [seriesVisitors]);
|
|
|
|
return (
|
|
<div className="h-full">
|
|
<div id="chart" className="h-full">
|
|
<ReactApexChart
|
|
options={{
|
|
chart: {
|
|
height: "100%",
|
|
type: "area",
|
|
},
|
|
stroke: {
|
|
curve: "smooth",
|
|
},
|
|
dataLabels: {
|
|
enabled: false,
|
|
},
|
|
xaxis: {
|
|
categories: type == "daily" ? categories : [],
|
|
},
|
|
}}
|
|
series={series}
|
|
type="area"
|
|
height="100%"
|
|
/>
|
|
</div>
|
|
<div id="html-dist"></div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ApexChartColumnVisitors;
|