import { useMemo } from 'react';
import { Box, Flex, Spinner, Text } from '@chakra-ui/react';
import { useColorMode } from "@/components/ui/color-mode.jsx";
import Plot from 'react-plotly.js';
import VdapApi from '../../hooks/useVdapApi.js';
import useBuildUrl from "@/hooks/useBuildUrl.js";
// 1. Import your central color dictionary
import { rawWidgetColors } from '../../theme.js';
export default function ExplosionEvents({ settings, widgetID }) {
// Plotly expects 'linear' for normal axes
const plotYAxisType = settings?.yAxisScale === 'log' ? 'log' : 'linear';
// 🎨 Let's check color mode so we can make people happy with light and dark
const { colorMode } = useColorMode();
// Assign the active palette based on the current mode
const plotColors = colorMode === 'dark' ? rawWidgetColors.dark : rawWidgetColors.light;
// Generate url with input dates, default to 7 day range
const url = useBuildUrl('/api/v2/explosion_events', settings?.startDate, settings?.endDate);
// Clean, single-line data fetching
const { data: apiData, isLoading, error } = VdapApi(url);
// 1. Build the Traces (Data parsing)
const plotTraces = useMemo(() => {
if (!apiData || apiData.length === 0) return [];
// Array of distinct Plotly shapes
const Symbolway = [
'circle', 'square', 'diamond',
'triangle-up', 'triangle-down',
'star', 'hexagram', 'pentagon',
'hexagon', 'octagon', 'cross', 'x'
];
// Sort data descending by number of events so smaller dots draw on top of larger ones
const sortedData = [...apiData].sort((a, b) => b.number_events - a.number_events);
// Efficiently group into Plotly traces by volcano
const groupedData = sortedData.reduce((acc, curr) => {
const name = curr.volcano_name || 'Unknown';
if (!acc[name]) acc[name] = { x: [], y: [] };
// Map the explosion-specific keys
acc[name].x.push(new Date(curr.ts_epoch));
acc[name].y.push(curr.number_events);
return acc;
}, {});
return Object.keys(groupedData).map((volcanoName, index) => ({
name: volcanoName,
x: groupedData[volcanoName].x,
y: groupedData[volcanoName].y,
type: 'scatter',
mode: 'markers',
marker: {
size: 7,
line: { width: .5, color: plotColors.text },
symbol: Symbolway[index % Symbolway.length],
},
// Replicating the clean D3/Observable tooltip
hovertemplate:
`${volcanoName}
` +
'Date (UTC): %{x|%b %d %Y %H:%M}
' +
'Number of Explosions: %{y}'
}));
}, [apiData, plotColors]);
// 2. Build the Layout (Styling and Grid)
const layout = useMemo(() => {
return {
autosize: true,
paper_bgcolor: 'transparent',
plot_bgcolor: 'transparent',
font: { color: plotColors.muted },
margin: { t: 40, r: 20, l: 20, b: 20 },
xaxis: {
title: {
text: 'Date (UTC)',
font: { color: plotColors.text, size: 12 }
},
type: 'date',
tickformat: '%b %d
%Y',
gridcolor: plotColors.grid,
zerolinecolor: plotColors.grid,
automargin: true,
},
yaxis: {
title: {
text: 'Number of Explosions',
font: { color: plotColors.text, size: 12 }
},
type: plotYAxisType,
gridcolor: plotColors.grid,
zerolinecolor: plotColors.text,
automargin: true,
},
hovermode: 'closest',
shapes: [
{
type: 'line',
x0: 0,
x1: 1,
xref: 'paper', // Spans entire chart width
y0: 0,
y1: 0,
yref: 'y',
line: { color: plotColors.text, width: 1 }
}
],
};
}, [plotYAxisType, plotColors]);
if (isLoading) return (
);
if (error) return (
{error}
);
if (plotTraces.length === 0) return (
No data available for current filter.
);
return (
);
}