182 lines
5.3 KiB
TypeScript
182 lines
5.3 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
const dummy = [
|
||
|
|
{ name: "Chrome", value: 42 },
|
||
|
|
{ name: "Firefox", value: 23 },
|
||
|
|
{ name: "Edge", value: 15 },
|
||
|
|
{ name: "Safari", value: 37 },
|
||
|
|
{ name: "Opera", value: 8 },
|
||
|
|
{ name: "Brave", value: 29 },
|
||
|
|
];
|
||
|
|
|
||
|
|
import {
|
||
|
|
convertDateFormatNoTime,
|
||
|
|
convertDateFormatNoTimeV2,
|
||
|
|
} from "@/utils/global";
|
||
|
|
import {
|
||
|
|
Calendar,
|
||
|
|
Popover,
|
||
|
|
PopoverContent,
|
||
|
|
PopoverTrigger,
|
||
|
|
} from "@heroui/react";
|
||
|
|
import { parseDate } from "@internationalized/date";
|
||
|
|
import { Fragment, useEffect, useState } from "react";
|
||
|
|
import ReactApexChart from "react-apexcharts";
|
||
|
|
|
||
|
|
export default function PieChartLoginBrowser() {
|
||
|
|
const [series, setSeries] = useState<number[]>([]);
|
||
|
|
const [labels, setLabels] = useState<string[]>([]);
|
||
|
|
const [data, setData] = useState<any>([]);
|
||
|
|
const [total, setTotal] = useState(0);
|
||
|
|
const [selectedLabel, setSelectedLabel] = useState<string>("");
|
||
|
|
|
||
|
|
const [topContentDate, setTopContentDate] = useState({
|
||
|
|
startDate: parseDate(
|
||
|
|
convertDateFormatNoTimeV2(
|
||
|
|
new Date(new Date().setDate(new Date().getDate() - 7))
|
||
|
|
)
|
||
|
|
),
|
||
|
|
endDate: parseDate(convertDateFormatNoTimeV2(new Date())),
|
||
|
|
});
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
fetchData();
|
||
|
|
}, [topContentDate.startDate, topContentDate.endDate]);
|
||
|
|
|
||
|
|
const fetchData = async () => {
|
||
|
|
const data = dummy;
|
||
|
|
setData(data);
|
||
|
|
const label = data.map((a) => a.name);
|
||
|
|
const seriesNow = data.map((a) => a.value);
|
||
|
|
const totalNow = seriesNow.reduce((a, c) => a + c, 0);
|
||
|
|
setTotal(totalNow);
|
||
|
|
setLabels(label);
|
||
|
|
setSeries(seriesNow);
|
||
|
|
};
|
||
|
|
|
||
|
|
const getPersentage = (value: number) => {
|
||
|
|
const count = ((value / total) * 100).toFixed(1);
|
||
|
|
return `${count}%`;
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="flex flex-row w-full mt-5 gap-4">
|
||
|
|
<div className="w-1/2 border-1 rounded-lg p-4">
|
||
|
|
<p className="font-bold">Browser Statistics</p>
|
||
|
|
<ReactApexChart
|
||
|
|
options={{
|
||
|
|
chart: {
|
||
|
|
width: 600,
|
||
|
|
type: "pie" as const,
|
||
|
|
events: {
|
||
|
|
dataPointSelection: function (
|
||
|
|
event: any,
|
||
|
|
chartContext: any,
|
||
|
|
config: any
|
||
|
|
) {
|
||
|
|
const selectedIndex = config.dataPointIndex;
|
||
|
|
const selected = labels[selectedIndex];
|
||
|
|
setSelectedLabel(selected);
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
labels: labels,
|
||
|
|
responsive: [
|
||
|
|
{
|
||
|
|
breakpoint: 480,
|
||
|
|
options: {
|
||
|
|
chart: {
|
||
|
|
width: 200,
|
||
|
|
},
|
||
|
|
legend: {
|
||
|
|
position: "bottom",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
],
|
||
|
|
}}
|
||
|
|
series={series}
|
||
|
|
type="pie"
|
||
|
|
width={600}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div className="w-1/2 flex flex-col border-1 rounded-lg p-4">
|
||
|
|
<div className="flex flex-row gap-1 justify-center">
|
||
|
|
<p> Browser Statistics from</p>
|
||
|
|
<Popover
|
||
|
|
placement="bottom"
|
||
|
|
classNames={{ content: ["!bg-transparent", "p-0"] }}
|
||
|
|
>
|
||
|
|
<PopoverTrigger>
|
||
|
|
<a className="cursor-pointer underline">
|
||
|
|
{convertDateFormatNoTime(topContentDate.startDate)}
|
||
|
|
</a>
|
||
|
|
</PopoverTrigger>
|
||
|
|
<PopoverContent className="bg-transparent">
|
||
|
|
<Calendar
|
||
|
|
value={topContentDate.startDate}
|
||
|
|
onChange={(e) =>
|
||
|
|
setTopContentDate({
|
||
|
|
startDate: e,
|
||
|
|
endDate: topContentDate.endDate,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
maxValue={topContentDate.endDate}
|
||
|
|
/>
|
||
|
|
</PopoverContent>
|
||
|
|
</Popover>
|
||
|
|
<p>to</p>
|
||
|
|
<Popover
|
||
|
|
placement="bottom"
|
||
|
|
classNames={{ content: ["!bg-transparent", "p-0"] }}
|
||
|
|
>
|
||
|
|
<PopoverTrigger>
|
||
|
|
<a className="cursor-pointer underline">
|
||
|
|
{convertDateFormatNoTime(topContentDate.endDate)}
|
||
|
|
</a>
|
||
|
|
</PopoverTrigger>
|
||
|
|
<PopoverContent className="bg-transparent">
|
||
|
|
<Calendar
|
||
|
|
value={topContentDate.endDate}
|
||
|
|
onChange={(e) =>
|
||
|
|
setTopContentDate({
|
||
|
|
startDate: topContentDate.startDate,
|
||
|
|
endDate: e,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
minValue={topContentDate.startDate}
|
||
|
|
/>
|
||
|
|
</PopoverContent>
|
||
|
|
</Popover>
|
||
|
|
</div>
|
||
|
|
<div className="flex flex-col mt-5 overflow-auto gap-3 p-4">
|
||
|
|
<div className="grid grid-cols-3 p-4">
|
||
|
|
<p>Browser</p>
|
||
|
|
<p>Visitors</p>
|
||
|
|
<p>Persentage</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{data &&
|
||
|
|
data?.map((list: any, index: number) => (
|
||
|
|
<div
|
||
|
|
key={list.name}
|
||
|
|
className={`grid grid-cols-3 p-4 ${
|
||
|
|
selectedLabel === list.name
|
||
|
|
? "bg-slate-600 text-white"
|
||
|
|
: index % 2 == 0
|
||
|
|
? "bg-gray-200"
|
||
|
|
: "bg-white"
|
||
|
|
}`}
|
||
|
|
>
|
||
|
|
<p className="font-semibold">{list.name}</p>
|
||
|
|
<p>{list.value}</p>
|
||
|
|
<p>{getPersentage(list.value)}</p>
|
||
|
|
</div>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|