mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
working on statistics page.
This commit is contained in:
@@ -2,11 +2,6 @@
|
||||
|
||||
import * as React from "react"
|
||||
import * as RechartsPrimitive from "recharts"
|
||||
import {
|
||||
NameType,
|
||||
Payload,
|
||||
ValueType,
|
||||
} from "recharts/types/component/DefaultTooltipContent"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ export const SidebarMenuCustom = (props: SidebarMenuCustomProps) => {
|
||||
icon: ShieldHalf,
|
||||
},
|
||||
{
|
||||
title: "Statistic",
|
||||
url: "kpi",
|
||||
title: "Statistics",
|
||||
url: "statistics",
|
||||
icon: ChartArea,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
// "use client"
|
||||
//
|
||||
// import {CartesianGrid, Line, LineChart, Tooltip, XAxis, YAxis} from "recharts"
|
||||
// import {ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent,} from "@/components/ui/chart"
|
||||
// import {humanReadableDate} from "@/utils/date-formatting";
|
||||
//
|
||||
//
|
||||
// export type lineChartProps = {
|
||||
// data: any
|
||||
// }
|
||||
//
|
||||
// export function EvolutionLineChart(props: lineChartProps) {
|
||||
//
|
||||
// const {data} = props
|
||||
//
|
||||
// // Process data to calculate cumulative count
|
||||
// const cumulativeData = data.reduce((acc, backup) => {
|
||||
// const date = backup.createdAt.toISOString().split("T")[0]; // Format as YYYY-MM-DD
|
||||
//
|
||||
// // Increment count for the current date or initialize it
|
||||
// if (acc.length && acc[acc.length - 1].date === date) {
|
||||
// acc[acc.length - 1].count += 1;
|
||||
// } else {
|
||||
// const lastCount = acc.length ? acc[acc.length - 1].count : 0;
|
||||
// acc.push({date, count: lastCount + 1});
|
||||
// }
|
||||
//
|
||||
// return acc;
|
||||
// }, [] as { date: string; count: number }[]);
|
||||
//
|
||||
//
|
||||
// const chartConfig = {
|
||||
// date: {
|
||||
// label: "Date",
|
||||
// color: "#2563eb",
|
||||
// },
|
||||
// count: {
|
||||
// label: "Number of backups",
|
||||
// color: "#60a5fa",
|
||||
// },
|
||||
// } satisfies ChartConfig
|
||||
//
|
||||
//
|
||||
// return (
|
||||
// <ChartContainer config={chartConfig}>
|
||||
// <LineChart
|
||||
// accessibilityLayer
|
||||
// data={data}
|
||||
// margin={{
|
||||
// left: 12,
|
||||
// right: 12,
|
||||
// }}
|
||||
// >
|
||||
// <CartesianGrid vertical={false}/>
|
||||
// <XAxis
|
||||
// dataKey="date"
|
||||
// tickLine={false}
|
||||
// axisLine={false}
|
||||
// tickMargin={8}
|
||||
// tickFormatter={(value) => humanReadableDate(Date(value)).split(' ')[0]}
|
||||
// />
|
||||
// <YAxis/>
|
||||
// <ChartTooltip
|
||||
// cursor={false}
|
||||
// content={<ChartTooltipContent hideLabel/>}
|
||||
// />
|
||||
// <Line
|
||||
// dataKey="count"
|
||||
// type="linear"
|
||||
// stroke="var(--color-desktop)"
|
||||
// strokeWidth={2}
|
||||
// dot={false}
|
||||
// />
|
||||
// </LineChart>
|
||||
// </ChartContainer>
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// export function PercentageLineChart(props: lineChartProps) {
|
||||
//
|
||||
// const {data} = props
|
||||
//
|
||||
// const chartConfig = {
|
||||
// date: {
|
||||
// label: "Date",
|
||||
// color: "#2563eb",
|
||||
// },
|
||||
// successRate: {
|
||||
// label: "Success Rate",
|
||||
// color: "#60a5fa",
|
||||
// },
|
||||
// } satisfies ChartConfig
|
||||
//
|
||||
// const dailyStats = data.reduce((acc, backup) => {
|
||||
// const date = backup.createdAt.toISOString().split("T")[0]; // Format YYYY-MM-DD
|
||||
// const status = backup.status;
|
||||
//
|
||||
// if (!acc[date]) {
|
||||
// acc[date] = {success: 0, failed: 0, total: 0};
|
||||
// }
|
||||
//
|
||||
// acc[date][status === "success" ? "success" : "failed"] += backup._count.id;
|
||||
// acc[date].total += backup._count.id;
|
||||
//
|
||||
// return acc;
|
||||
// }, {} as Record<string, { success: number; failed: number; total: number }>);
|
||||
//
|
||||
// // Format data for the chart
|
||||
// const formattedData = Object.entries(dailyStats).map(([date, stats]) => ({
|
||||
// date,
|
||||
// successRate: (stats.success / stats.total) * 100,
|
||||
// }));
|
||||
//
|
||||
// return (
|
||||
// <ChartContainer config={chartConfig}>
|
||||
// <LineChart data={formattedData}>
|
||||
// <CartesianGrid strokeDasharray="3 3"/>
|
||||
// <XAxis dataKey="date"/>
|
||||
// <YAxis domain={[0, 100]} tickFormatter={(tick) => `${tick}%`}/>
|
||||
// {/*<Tooltip formatter={(value: number) => `${value.toFixed(2)}%`}/>*/}
|
||||
// <ChartTooltip
|
||||
// content={<ChartTooltipContent/>}
|
||||
// cursor={false}
|
||||
// defaultIndex={1}
|
||||
// formatter={(value, name) => (
|
||||
// <div className="flex min-w-[130px] items-center text-xs text-muted-foreground">
|
||||
// {chartConfig[name as keyof typeof chartConfig]?.label ||
|
||||
// name}
|
||||
// <div className="ml-auto flex items-baseline gap-0.5 font-mono font-medium tabular-nums text-foreground">
|
||||
// {value}
|
||||
// <span className="font-normal text-muted-foreground">
|
||||
// %
|
||||
// </span>
|
||||
// </div>
|
||||
// </div>
|
||||
// )}
|
||||
// />
|
||||
// <Line type="step" dataKey="successRate" stroke="#8884d8" strokeWidth={2}/>
|
||||
// </LineChart>
|
||||
// </ChartContainer>
|
||||
// )
|
||||
//
|
||||
// }
|
||||
//
|
||||
@@ -0,0 +1,98 @@
|
||||
"use client"
|
||||
|
||||
import {ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent} from "@/components/ui/chart";
|
||||
import {CartesianGrid, Line, LineChart, XAxis, YAxis} from "recharts";
|
||||
import {humanReadableDate} from "@/utils/date-formatting";
|
||||
|
||||
const data = [
|
||||
{date: "2024-12-01", count: 1},
|
||||
{date: "2024-12-02", count: 2},
|
||||
{date: "2024-12-03", count: 4},
|
||||
{date: "2024-12-04", count: 8},
|
||||
{date: "2024-12-05", count: 9},
|
||||
{date: "2024-12-06", count: 9},
|
||||
{date: "2024-12-07", count: 10},
|
||||
{date: "2024-12-08", count: 13},
|
||||
{date: "2024-12-09", count: 15},
|
||||
{date: "2024-12-10", count: 18},
|
||||
|
||||
]
|
||||
|
||||
|
||||
type Data = {
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
|
||||
export type evolutionLineChartProps = {
|
||||
data: Data[]
|
||||
}
|
||||
|
||||
export function EvolutionLineChart(props: evolutionLineChartProps) {
|
||||
|
||||
const {data} = props
|
||||
console.log("aaa data", data)
|
||||
|
||||
|
||||
// Process data to calculate cumulative count
|
||||
const cumulativeData = data.reduce((acc, backup) => {
|
||||
const date = backup.createdAt.toISOString().split("T")[0]; // Format as YYYY-MM-DD
|
||||
|
||||
// Increment count for the current date or initialize it
|
||||
if (acc.length && acc[acc.length - 1].date === date) {
|
||||
acc[acc.length - 1].count += 1;
|
||||
} else {
|
||||
const lastCount = acc.length ? acc[acc.length - 1].count : 0;
|
||||
acc.push({date, count: lastCount + 1});
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, [] as { date: string; count: number }[]);
|
||||
|
||||
|
||||
const chartConfig = {
|
||||
date: {
|
||||
label: "Date",
|
||||
color: "#2563eb",
|
||||
},
|
||||
count: {
|
||||
label: "Number of backups",
|
||||
color: "#60a5fa",
|
||||
},
|
||||
} satisfies ChartConfig
|
||||
|
||||
|
||||
return (
|
||||
<ChartContainer config={chartConfig}>
|
||||
<LineChart
|
||||
accessibilityLayer
|
||||
data={data}
|
||||
margin={{
|
||||
left: 12,
|
||||
right: 12,
|
||||
}}
|
||||
>
|
||||
<CartesianGrid vertical={false}/>
|
||||
<XAxis
|
||||
dataKey="date"
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
tickMargin={8}
|
||||
tickFormatter={(value) => humanReadableDate(Date(value)).split(' ')[0]}
|
||||
/>
|
||||
<YAxis/>
|
||||
<ChartTooltip
|
||||
cursor={false}
|
||||
content={<ChartTooltipContent hideLabel/>}
|
||||
/>
|
||||
<Line
|
||||
dataKey="count"
|
||||
type="linear"
|
||||
stroke="var(--color-desktop)"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
/>
|
||||
</LineChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
"use client"
|
||||
|
||||
import {ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent} from "@/components/ui/chart";
|
||||
import {CartesianGrid, Line, LineChart, XAxis, YAxis} from "recharts";
|
||||
|
||||
type Data = {
|
||||
createdAt: Date;
|
||||
status: "success" | "failed";
|
||||
_count: { id: number };
|
||||
}
|
||||
|
||||
export type percentageLineChartProps = {
|
||||
data: Data[]
|
||||
}
|
||||
|
||||
|
||||
export function PercentageLineChart(props: percentageLineChartProps) {
|
||||
|
||||
const {data} = props
|
||||
|
||||
const chartConfig = {
|
||||
date: {
|
||||
label: "Date",
|
||||
color: "#2563eb",
|
||||
},
|
||||
successRate: {
|
||||
label: "Success Rate",
|
||||
color: "#60a5fa",
|
||||
},
|
||||
} satisfies ChartConfig
|
||||
|
||||
const dailyStats = data.reduce((acc, backup) => {
|
||||
const date = backup.createdAt.toISOString().split("T")[0]; // Format YYYY-MM-DD
|
||||
const status = backup.status;
|
||||
|
||||
if (!acc[date]) {
|
||||
acc[date] = {success: 0, failed: 0, total: 0};
|
||||
}
|
||||
|
||||
acc[date][status === "success" ? "success" : "failed"] += backup._count.id;
|
||||
acc[date].total += backup._count.id;
|
||||
|
||||
return acc;
|
||||
}, {} as Record<string, { success: number; failed: number; total: number }>);
|
||||
|
||||
// Format data for the chart
|
||||
const formattedData = Object.entries(dailyStats).map(([date, stats]) => ({
|
||||
date,
|
||||
successRate: (stats.success / stats.total) * 100,
|
||||
}));
|
||||
|
||||
return (
|
||||
<ChartContainer config={chartConfig}>
|
||||
<LineChart
|
||||
accessibilityLayer
|
||||
data={formattedData}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3"/>
|
||||
<XAxis dataKey="date"/>
|
||||
<YAxis domain={[0, 100]} tickFormatter={(tick) => `${tick}%`}/>
|
||||
<ChartTooltip
|
||||
content={<ChartTooltipContent/>}
|
||||
cursor={false}
|
||||
defaultIndex={1}
|
||||
formatter={(value, name) => (
|
||||
<div className="flex min-w-[130px] items-center text-xs text-muted-foreground">
|
||||
{chartConfig[name as keyof typeof chartConfig]?.label ||
|
||||
name}
|
||||
<div
|
||||
className="ml-auto flex items-baseline gap-0.5 font-mono font-medium tabular-nums text-foreground">
|
||||
{value}
|
||||
<span className="font-normal text-muted-foreground">
|
||||
%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<Line type="step" dataKey="successRate" stroke="#8884d8" strokeWidth={2}/>
|
||||
</LineChart>
|
||||
</ChartContainer>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -10,12 +10,11 @@ import {
|
||||
DropdownMenuTrigger
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {Download, MoreHorizontal, Trash2} from "lucide-react";
|
||||
import {MoreHorizontal} from "lucide-react";
|
||||
import {ReloadIcon} from "@radix-ui/react-icons";
|
||||
import {Restoration} from "@prisma/client";
|
||||
|
||||
|
||||
|
||||
export const restoreColumns: ColumnDef<Restoration>[] = [
|
||||
{
|
||||
accessorKey: "id",
|
||||
|
||||
Reference in New Issue
Block a user