"use client";
import {
CartesianGrid,
Legend,
ResponsiveContainer,
Scatter,
ScatterChart,
Tooltip,
XAxis,
YAxis,
} from "recharts";
import { AlertPill } from "./shared/alert-pill";
import { ChartLegend } from "./shared/chart-legend";
import { CHART_COLORS } from "./shared/constants";
import { getSeverityColorByRiskScore } from "./shared/utils";
import type { ScatterDataPoint } from "./types";
interface ScatterPlotProps {
data: ScatterDataPoint[];
xLabel?: string;
yLabel?: string;
height?: number;
onSelectPoint?: (point: ScatterDataPoint | null) => void;
selectedPoint?: ScatterDataPoint | null;
}
const PROVIDER_COLORS = {
AWS: "var(--chart-provider-aws)",
Azure: "var(--chart-provider-azure)",
Google: "var(--chart-provider-google)",
};
const CustomTooltip = ({ active, payload }: any) => {
if (active && payload && payload.length) {
const data = payload[0].payload;
const severityColor = getSeverityColorByRiskScore(data.x);
return (
{data.name}
{data.x} Risk Score
);
}
return null;
};
const CustomScatterDot = ({
cx,
cy,
payload,
selectedPoint,
onSelectPoint,
}: any) => {
const isSelected = selectedPoint?.name === payload.name;
const size = isSelected ? 18 : 8;
const fill = isSelected
? "#86DA26"
: PROVIDER_COLORS[payload.provider as keyof typeof PROVIDER_COLORS] ||
CHART_COLORS.defaultColor;
return (
onSelectPoint?.(payload)}
/>
);
};
const CustomLegend = ({ payload }: any) => {
const items = payload.map((entry: any) => ({
label: entry.value,
color: entry.color,
}));
return ;
};
export function ScatterPlot({
data,
xLabel = "Risk Score",
yLabel = "Failed Findings",
height = 400,
onSelectPoint,
selectedPoint,
}: ScatterPlotProps) {
const handlePointClick = (point: ScatterDataPoint) => {
if (onSelectPoint) {
if (selectedPoint?.name === point.name) {
onSelectPoint(null);
} else {
onSelectPoint(point);
}
}
};
const dataByProvider = data.reduce(
(acc, point) => {
const provider = point.provider;
if (!acc[provider]) {
acc[provider] = [];
}
acc[provider].push(point);
return acc;
},
{} as Record,
);
return (
} />
} />
{Object.entries(dataByProvider).map(([provider, points]) => (
(
)}
/>
))}
);
}