Files
Web-Frontend/client/src/components/Widgets/VaaActivity7Day.jsx
T

62 lines
2.5 KiB
React
Raw Normal View History

import { useMemo } from 'react';
import { Box, Flex, Text } from '@chakra-ui/react';
import Plot from 'react-plotly.js';
export default function VaaActivityChart({ data = [] }) {
// Transform flat database rows into Plotly's required "Traces"
const plotTraces = useMemo(() => {
if (!data || data.length === 0) return [];
const groupedData = data.reduce((acc, curr) => {
const name = curr.volc_name || 'Unknown';
if (!acc[name]) acc[name] = { x: [], y: [], text: [] };
acc[name].x.push(new Date(curr.obs_va_epoch));
acc[name].y.push(curr.obs_fl);
acc[name].text.push(`Volcano: ${name}<br>Flight Level: ${curr.obs_fl}`);
return acc;
}, {});
return Object.keys(groupedData).map((volcanoName) => ({
name: volcanoName,
x: groupedData[volcanoName].x,
y: groupedData[volcanoName].y,
text: groupedData[volcanoName].text,
type: 'scatter',
mode: 'markers',
hoverinfo: 'text',
marker: { size: 8, line: { width: 1, color: 'white' } }
}));
}, [data]);
if (plotTraces.length === 0) {
return (
<Flex height="100%" width="100%" align="center" justify="center" bg="gray.800" borderRadius="md">
<Text color="gray.400">No flight level data available.</Text>
</Flex>
);
}
return (
<Box height="100%" width="100%" bg="gray.800" borderRadius="md" overflow="hidden">
<Plot
data={plotTraces}
useResizeHandler={true} // Crucial for reacting to grid drags
style={{ width: '100%', height: '100%' }}
layout={{
autosize: true,
paper_bgcolor: 'transparent',
plot_bgcolor: 'transparent',
font: { color: '#d1d5db' },
margin: { t: 40, r: 20, l: 50, b: 40 },
title: { text: '7 Day Consolidated Flight Levels', font: { size: 16, color: 'white' }, x: 0.05 },
xaxis: { title: 'Date (UTC)', type: 'date', gridcolor: '#4b5563', zerolinecolor: '#4b5563' },
yaxis: { title: 'Flight Level', gridcolor: '#4b5563', zerolinecolor: '#ffffff' },
legend: { orientation: 'h', y: -0.2, x: 0.5, xanchor: 'center' },
hovermode: 'closest'
}}
config={{ responsive: true, displayModeBar: true, displaylogo: false }}
/>
</Box>
);
}