diff --git a/client/src/components/checks/ChartTiming.tsx b/client/src/components/checks/ChartTiming.tsx
index c272d0074..3eb3b1c5c 100644
--- a/client/src/components/checks/ChartTiming.tsx
+++ b/client/src/components/checks/ChartTiming.tsx
@@ -1,5 +1,5 @@
import type { ICheck, CheckTimingPhases } from "@/types/check";
-import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from "recharts";
+import { PieChart, Pie, ResponsiveContainer, Tooltip, Legend } from "recharts";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";
@@ -8,10 +8,10 @@ import { BaseBox } from "@/components/design-elements";
type TimingsChartProps = { check: ICheck | null };
export type TimingSegment = {
- key: keyof CheckTimingPhases;
- label: string;
+ name: string;
value: number;
- percent: number;
+ fill: string;
+ stroke: string;
};
const PHASE_ORDER: (keyof CheckTimingPhases)[] = [
@@ -24,36 +24,79 @@ const PHASE_ORDER: (keyof CheckTimingPhases)[] = [
"download",
];
-const buildTimingSegments = (phases?: CheckTimingPhases): TimingSegment[] => {
+const buildTimingSegments = (
+ phases: CheckTimingPhases | undefined,
+ stroke: string
+): TimingSegment[] => {
if (!phases) return [];
- const raw = PHASE_ORDER.map((key) => ({
- key,
+ return PHASE_ORDER.map((key) => ({
+ name: String(key),
value: Math.max(0, Number((phases as any)[key] ?? 0)),
- }));
- const total = raw.reduce((sum, p) => sum + p.value, 0);
- if (total <= 0) {
- return raw.map(({ key, value }) => ({
- key,
- label: key,
- value,
- percent: 0,
- }));
- }
- return raw.map(({ key, value }) => ({
- key,
- label: key,
- value,
- percent: (value / total) * 100,
+ fill: "transparent",
+ stroke,
}));
};
export const TimingsChart = ({ check }: TimingsChartProps) => {
- const segments = buildTimingSegments(check?.timings?.phases);
- if (!segments.length) return null;
if (!check) return null;
const theme = useTheme();
- const strokeColor = alpha(theme.palette.success.main, 0.8);
+ const strokeColor = alpha(theme.palette.primary.main, 0.8);
+ const segments = buildTimingSegments(check?.timings?.phases, strokeColor);
+ if (!segments.length) return null;
+ const LABEL_THRESHOLD = 0.05;
+
+ const renderLabel = ({
+ cx,
+ cy,
+ midAngle,
+ outerRadius,
+ name,
+ value,
+ percent,
+ }: any) => {
+ if (!percent || percent < LABEL_THRESHOLD) return null;
+ const RAD = Math.PI / 180;
+ const r = (outerRadius || 0) + 24;
+ const x = cx + r * Math.cos(-midAngle * RAD);
+ const y = cy + r * Math.sin(-midAngle * RAD);
+ const text = `${name}: ${Math.round(Number(value) || 0)} ms`;
+ return (
+