2026-06-16 15:42:03 -07:00
|
|
|
import { useMemo } from 'react';
|
2026-06-17 15:36:27 -07:00
|
|
|
import { Box, Flex, Spinner, Text } from '@chakra-ui/react';
|
2026-06-16 15:42:03 -07:00
|
|
|
import Plot from 'react-plotly.js';
|
2026-06-17 15:36:27 -07:00
|
|
|
import VdapApi from '../../hooks/useVdapApi.js'; // Adjust path as needed
|
|
|
|
|
|
|
|
|
|
export default function VaaActivity7Day() {
|
|
|
|
|
// ONE LINE to handle all fetching, loading, and error states!
|
|
|
|
|
const { data: apiData, isLoading, error } = VdapApi('/api/v2/comm_coor_vaa');
|
2026-06-16 15:42:03 -07:00
|
|
|
|
|
|
|
|
const plotTraces = useMemo(() => {
|
2026-06-17 15:36:27 -07:00
|
|
|
if (!apiData || apiData.length === 0) return [];
|
2026-06-16 15:42:03 -07:00
|
|
|
|
2026-06-17 15:36:27 -07:00
|
|
|
const groupedData = apiData.reduce((acc, curr) => {
|
2026-06-16 15:42:03 -07:00
|
|
|
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' } }
|
|
|
|
|
}));
|
2026-06-17 15:36:27 -07:00
|
|
|
}, [apiData]);
|
2026-06-16 15:42:03 -07:00
|
|
|
|
2026-06-17 15:36:27 -07:00
|
|
|
if (isLoading) return (
|
|
|
|
|
<Flex w="100%" h="100%" bg="gray.800" borderRadius="md" align="center" justify="center">
|
|
|
|
|
<Spinner size="xl" color="blue.400" thickness="4px" />
|
|
|
|
|
</Flex>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (error) return (
|
|
|
|
|
<Flex w="100%" h="100%" bg="gray.800" borderRadius="md" align="center" justify="center" p={4}>
|
|
|
|
|
<Text color="red.400">{error}</Text>
|
|
|
|
|
</Flex>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
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>
|
|
|
|
|
);
|
2026-06-16 15:42:03 -07:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Box height="100%" width="100%" bg="gray.800" borderRadius="md" overflow="hidden">
|
|
|
|
|
<Plot
|
|
|
|
|
data={plotTraces}
|
2026-06-17 15:36:27 -07:00
|
|
|
useResizeHandler={true}
|
2026-06-16 15:42:03 -07:00
|
|
|
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>
|
|
|
|
|
);
|
|
|
|
|
}
|